unity-settings-daemon/0000775000000000000000000000000015172222611012214 5ustar unity-settings-daemon/.git/0000775000000000000000000000000015172222611013055 5ustar unity-settings-daemon/.git/FETCH_HEAD0000664000000000000000000000000015172222611014400 0ustar unity-settings-daemon/.git/HEAD0000664000000000000000000000003515172222611013477 0ustar ref: refs/heads/ubuntu/devel unity-settings-daemon/.git/ORIG_HEAD0000664000000000000000000000005115172222611014315 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/config0000764000000000000000000000175015172222611014251 0ustar [core] bare = false repositoryformatversion = 0 filemode = true logallrefupdates = true [remote "pkg"] url = https://git.launchpad.net/ubuntu/+source/unity-settings-daemon fetch = +refs/heads/*:refs/remotes/pkg/* fetch = +refs/tags/*:refs/tags/pkg/* fetch = +refs/notes/commits:refs/notes/changelog pushurl = ssh://aleasto@git.launchpad.net/ubuntu/+source/unity-settings-daemon tagOpt = --no-tags [remote "aleasto"] url = https://git.launchpad.net/~aleasto/ubuntu/+source/unity-settings-daemon fetch = +refs/heads/*:refs/remotes/aleasto/* fetch = +refs/tags/*:refs/tags/aleasto/* pushurl = ssh://aleasto@git.launchpad.net/~aleasto/ubuntu/+source/unity-settings-daemon tagOpt = --no-tags [branch "ubuntu/devel"] remote = pkg merge = refs/heads/ubuntu/devel [notes] displayRef = refs/notes/changelog [remote "unity7maintainers"] url = git+ssh://aleasto@git.launchpad.net/~unity7maintainers/ubuntu/+source/unity-settings-daemon fetch = +refs/heads/*:refs/remotes/unity7maintainers/* unity-settings-daemon/.git/description0000664000000000000000000000011115172222611015314 0ustar Unnamed repository; edit this file 'description' to name the repository. unity-settings-daemon/.git/hooks/0000775000000000000000000000000015172222611014200 5ustar unity-settings-daemon/.git/hooks/README.sample0000775000000000000000000000026115172222611016342 0ustar #!/bin/sh # # Place appropriately named executable hook scripts into this directory # to intercept various actions that git takes. See `git help hooks` for # more information. unity-settings-daemon/.git/hooks/post-checkout0000755000000000000000000000074115172222611016716 0ustar #!/bin/sh EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 NEW_HEAD=$2 if git ls-tree -r -d $NEW_HEAD |awk '{print $3}'|grep -q $EMPTY_TREE; then echo >&2 echo "WARNING: empty directories exist but are not tracked by git:" >&2 echo >&2 git ls-tree -r -d $NEW_HEAD|grep $EMPTY_TREE|awk '{print $4}' >&2 echo >&2 echo "These will silently disappear on commit, causing extraneous" >&2 echo "unintended changes. See: LP: #1687057." >&2 echo >&2 fi unity-settings-daemon/.git/hooks/pre-commit0000755000000000000000000000101515172222611016175 0ustar #!/bin/sh EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 if git ls-tree -r -d HEAD|awk '{print $3}'|grep -q $EMPTY_TREE; then echo "ERROR: Empty directories exist and will disappear on commit, causing" >&2 echo "extraneous unintended changes:" >&2 echo >&2 git ls-tree -r -d HEAD|grep $EMPTY_TREE|awk '{print $4}' >&2 echo >&2 echo "See LP: #1687057." >&2 echo 'Use "git commit --no-verify ..." to ignore this problem.' >&2 echo >&2 echo "pre-commit hook failed." >&2 exit 1 fi unity-settings-daemon/.git/index0000664000000000000000000013731215172222611014116 0ustar DIRCjgO.{LjgO.{Lz7H⛲CK)wZSREADMEjgO.`3jgO.`3z?4DxRQ#u acinclude.m4jgO.`3jgO.`3z@}?@6(t autogen.shjgO.jgO.zAS>$pBW NOCg configure.acjgO.jgO.zC 歯૬~-data/Makefile.amjgO.ȈjgO.ȈzD%dg ܗ*<Fdata/com.canonical.unity.settings-daemon.peripherals.gschema.xml.in.injgO.ȈjgO.ȈzE)a0'Oߔ}@M2YLdata/com.canonical.unity.settings-daemon.peripherals.wacom.gschema.xml.in.injgO.ȈjgO.ȈzF L3\Pf҇FHdata/com.canonical.unity.settings-daemon.plugins.color.gschema.xml.in.injgO.ȈjgO.ȈzG\-X/<ꎑcd [ٹKdata/com.canonical.unity.settings-daemon.plugins.datetime.gschema.xml.in.injgO.ȈjgO.ȈzH%.ζ)MCEr\Bdata/com.canonical.unity.settings-daemon.plugins.gschema.xml.in.injgO.ȈjgO.ȈzI0SVD ҕFt4U0Odata/com.canonical.unity.settings-daemon.plugins.housekeeping.gschema.xml.in.injgO.ȈjgO.ȈzJ³ x eN)y Kdata/com.canonical.unity.settings-daemon.plugins.keyboard.gschema.xml.in.injgO.ȈjgO.ȈzK$Z݇hwmM<Mdata/com.canonical.unity.settings-daemon.plugins.media-keys.gschema.xml.in.injgO.ȈjgO.ȈzLȥt< cOIDP<Ndata/com.canonical.unity.settings-daemon.plugins.orientation.gschema.xml.in.injgO.jgO.zM!qkAม7qh Hdata/com.canonical.unity.settings-daemon.plugins.power.gschema.xml.in.injgO.jgO.zNہi=ܓfL1aVdata/com.canonical.unity.settings-daemon.plugins.print-notifications.gschema.xml.in.injgO.jgO.zOq[n`R;oZmжEHE$Jdata/com.canonical.unity.settings-daemon.plugins.sharing.gschema.xml.in.injgO.jgO.zPl{Ξ *`YVZLIdata/com.canonical.unity.settings-daemon.plugins.xrandr.gschema.xml.in.injgO.jgO.zQ kT-Xrty:㽈Pw data/unity-settings-daemon.pc.injgP1zjgP1zzYK*Qڴ㗁At{debian/changelogjgP1zjgP1zzZtU*t W ƊRofdebian/controljgO.'jgO.'z\ fn+%\zf@3M֩'debian/copyrightjgO.'jgO.'z]7V84%debian/gnome-update-wallpaper-cache.cjgP1jgP1z[3kiǼ(U |^ B=A(debian/libunity-settings-daemon1.installjgO.'jgO.'z_g-vƟl#˜((debian/libunity-settings-daemon1.symbolsjgP1jgP1z^3S)BLwFeCdebian/not-installedjgP1jgP1z` ^e9p~0 debian/rulesjgO.'jgO.'zbӂ~u۟~ђ21 debian/source/formatjgO.'jgO.'zc|XqJ!`*&debian/source_unity-settings-daemon.pyjgO.'jgO.'zdFrunX ~fZCi(debian/unity-settings-daemon-dev.installjgO.'jgO.'ze$X/_(! f葺,debian/unity-settings-daemon-schemas.installjgP1jgP1zfPGk +*&o$debian/unity-settings-daemon.installjgO.jjgO.jzg1[?\XE-Tr=t$"debian/unity-settings-daemon.linksjgO.jjgO.jzhe ɕ7c)X(debian/unity-settings-daemon.maintscriptjgO.jjgO.jzi +mP'debian/unity-settings-daemon.migrationsjgO.jjgO.jzj(^n+/)rA%debian/unity-settings-daemon.postinstjgO.jjgO.jzk{' Yg8,U"1debian/unity-settings-daemon.user-session.desktopjgO.jjgO.jzl7RǘriMP j}V$1debian/unity-settings-daemon.user-session.upstartjgO.jjgO.jzn]OhQtu!S*debian/user/unity-settings-daemon.overridejgO.KjgO.Kzo%<hڠn>Cs)debian/user/unity-settings-daemon.servicejgO.KjgO.Kzpz+OHhRf2gnome-settings-daemon.doapjgO.KjgO.KzrDцQ,O_!gnome-settings-daemon/Makefile.amjgO. jgO. zsZd#cX(KGd-gnome-settings-daemon/check_gl_texture_size.cjgO. jgO. ztڸdlC{Y|=o= W$gnome-settings-daemon/display-name.cjgO. jgO. zu3OƖ/Y?m"gnome-settings-daemon/edid-parse.cjgO. jgO. zvW62B2ң]F?gnome-settings-daemon/edid.hjgO. jgO. zw3OƖ/Y?m"gnome-settings-daemon/edid_parse.cjgO. jgO. zx`uu)a:-Z*gnome-settings-daemon/gnome-settings-bus.cjgO. jgO. zyiW,C[hU1#*gnome-settings-daemon/gnome-settings-bus.hjgP1jgP1zzCqT#I]7>g՞{K.gnome-settings-daemon/gnome-settings-manager.cjgO. jgO. z{ iXs}k56.gnome-settings-daemon/gnome-settings-manager.hjgO. jgO. z|eo2~VՓ!AD޸-gnome-settings-daemon/gnome-settings-module.cjgO. jgO. z}AhM,íckQZwA-gnome-settings-daemon/gnome-settings-module.hjgO. jgO. z~?6LhC:Zn"UF2gnome-settings-daemon/gnome-settings-plugin-info.cjgO.jgO.z<ɱU2Ri2gnome-settings-daemon/gnome-settings-plugin-info.hjgO.jgO.zuM"Cװ,lk-gnome-settings-daemon/gnome-settings-plugin.cjgO.jgO.z&I+:eTa3<-gnome-settings-daemon/gnome-settings-plugin.hjgO.jgO.z}~`Vo*KN.gnome-settings-daemon/gnome-settings-profile.cjgO.jgO.z=ہ?'tH 㪀5A.gnome-settings-daemon/gnome-settings-profile.hjgO.jgO.z;;tdZ%4aO8p(gnome-settings-daemon/gsd-bg-crossfade.cjgO.jgO.z DGt[F+bbDZ" s(gnome-settings-daemon/gsd-bg-crossfade.hjgO.jgO.zcD dԚ} Tc)gnome-settings-daemon/gsd-bg-slide-show.cjgO/1_jgO/1_zHYQI{d4QO)gnome-settings-daemon/gsd-bg-slide-show.hjgO/1_jgO/1_z%>Ua< 4g{:rwgnome-settings-daemon/gsd-bg.cjgO/1_jgO/1_zRtFy)BѼB[Vgnome-settings-daemon/gsd-bg.hjgO/1_jgO/1_z%Dd\xQ0M\0gnome-settings-daemon/gsd-idle-monitor-private.hjgO/1_jgO/1_zkz{B:: Z(gnome-settings-daemon/gsd-idle-monitor.cjgO/1_jgO/1_z /r;b#'B$lEuT(gnome-settings-daemon/gsd-idle-monitor.hjgO/sjgO/sz&9#zWA8#gnome-settings-daemon/gsd-pnp-ids.cjgO/sjgO/sz4P&cGւ##gnome-settings-daemon/gsd-pnp-ids.hjgO/sjgO/sz cO24Jm %gnome-settings-daemon/gsd-rr-config.cjgO/sjgO/sz2  xap 7%gnome-settings-daemon/gsd-rr-config.hjgO/sjgO/sz{W5wn7]@u,*gnome-settings-daemon/gsd-rr-output-info.cjgO/sjgO/sz~qI^{MIfe&gnome-settings-daemon/gsd-rr-private.hjgO/#GjgO/#GzasErţ@΢gf"*gnome-settings-daemon/gsd-rr.cjgO/#GjgO/#Gz)f%eN`br}gnome-settings-daemon/gsd-rr.hjgO/#GjgO/#Gz4m1L[.21YR?Pk[ &gnome-settings-daemon/idle-monitor.xmljgO/#GjgO/#Gz:ՒC!* rXֳt3A Vgnome-settings-daemon/main.cjgO/#GjgO/#GzZ(u@ f }Km%#/gnome-settings-daemon/org.gnome.ScreenSaver.xmljgO/#GjgO/#Gz>i \1ZXwq +2gnome-settings-daemon/org.gnome.SessionManager.xmljgO/#GjgO/#Gz屘U5 /9gnome-settings-daemon/unity-settings-daemon-localeexec.injgO/#GjgO/#GzNH%] <man/Makefile.amjgO/:qjgO/:qz)JĒy~7~>rman/unity-settings-daemon.xmljgO/:qjgO/:qzH;<.V kBLplugins/Makefile.amjgO/>FjgO/>Fz`3Wۍ,A$ʆ!plugins/a11y-keyboard/Makefile.amjgO/@jgO/@z(6t^G$ to9*plugins/a11y-keyboard/test-a11y-keyboard.cjgO/@jgO/@zíR] T!plugins/a11y-settings/Makefile.amjgO/JqjgO/Jqz䬷VZ$ԍ"#$v!#bplugins/clipboard/xutils.cjgO/rjgO/rz?Cnх bNplugins/clipboard/xutils.hjgP1jgP1z3g)O@/AeE:ӑ0ڵplugins/color/gcm-self-test.cjgO/8jgO/8z@Y"!REyB=j!plugins/color/gsd-color-manager.cjgO/8jgO/8z '2rJ׉0t(+$!plugins/color/gsd-color-manager.hjgO/8jgO/8zHt/nZ|3 plugins/color/gsd-color-plugin.cjgO/sjgO/szLfdkJ&-plugins/color/test-data/LG-L225W-External.binjgO/sjgO/szE&&EaP /plugins/color/test-data/Lenovo-T61-Internal.binjgO/sjgO/szvzcԴT``plugins/common/Makefile.amjgO/jgO/zGB"bK YT!plugins/common/gsd-input-helper.cjgO/jgO/zIGJu,DH ]^z!plugins/common/gsd-input-helper.hjgO/jgO/zZ˘NrNJcplugins/common/gsd-keygrab.cjgO/jgO/znȄz}TI9^;{Qf]plugins/common/gsd-keygrab.hjgO/jgO/z ͦ VjP2U5A [E%plugins/common/gsd-settings-migrate.cjgO/jgO/zeY{MS[??%plugins/common/gsd-settings-migrate.hjgO/jgO/z=oSqZ]i=|&plugins/common/input-device-example.shjgO/jgO/zEѸݎTW^8⫇$%plugins/common/test-egg-key-parsing.cjgO/jgO/z3bƾ%V8c,aa"plugins/common/test-input-helper.cjgO/jgO/z ~c"{?q$&_15plugins/common/test-plugin.hjgO/jgO/z ZM|3IN"plugins/cursor/Makefile.amjgO/zjgO/zzW+e߁8Kn3~&.plugins/cursor/cursor.gnome-settings-plugin.injgO/zjgO/zz51u0]殥-#plugins/cursor/gsd-cursor-manager.cjgO/zjgO/zz J*s2z!ϐ#plugins/cursor/gsd-cursor-manager.hjgO/zjgO/zzޝt&[69)KD"plugins/cursor/gsd-cursor-plugin.cjgO/zjgO/zzarpˁs46plugins/cursor/test-cursor.cjgO/zjgO/zz3sؿkN{8+plugins/dummy/Makefile.amjgO/jgO/z8l\u=Jr&CK,plugins/dummy/dummy.gnome-settings-plugin.injgO/jgO/zwm'Tr9h26/!plugins/dummy/gsd-dummy-manager.cjgO/jgO/z63.)oߪXF!plugins/dummy/gsd-dummy-manager.hjgO/jgO/z !G Iy]])!W)# plugins/dummy/gsd-dummy-plugin.cjgO/jgO/z VCU9<Fyp plugins/housekeeping/Makefile.amjgO/>jgO/>z 3tIT`!$QM,plugins/housekeeping/gsd-disk-space-helper.cjgO/>jgO/>zX{8Cy}23=,plugins/housekeeping/gsd-disk-space-helper.hjgO/>jgO/>zK7{D3jgO/>z!v6M]o0 %plugins/housekeeping/gsd-disk-space.cjgO/>jgO/>z7W)(,ų%plugins/housekeeping/gsd-disk-space.hjgO/NjgO/Nzj)b r!Gv+plugins/housekeeping/gsd-empty-trash-test.cjgO/NjgO/Nz>n %ջx{?W =/plugins/housekeeping/gsd-housekeeping-manager.cjgO/NjgO/Nz \ڇo=S%<Ŏ/plugins/housekeeping/gsd-housekeeping-manager.hjgO/NjgO/Nz)r*5K.plugins/housekeeping/gsd-housekeeping-plugin.cjgO/NjgO/NzQ]l SLqH&plugins/housekeeping/gsd-ldsm-dialog.cjgO/NjgO/Nz ?6];l6U;ѕ0z&plugins/housekeeping/gsd-ldsm-dialog.hjgO/NjgO/NzI϶T ԃ:plugins/housekeeping/housekeeping.gnome-settings-plugin.injgO/NjgO/NzNhE:M5] (plugins/housekeeping/test-housekeeping.cjgO/ˑBjgO/ˑB{A[IbqO8plugins/keyboard/.indent.projgO/jgO/{ YnReIi^GRrplugins/keyboard/Makefile.amjgP1vjgP1v{dk7/>{#.g6`'plugins/keyboard/gsd-keyboard-manager.cjgO/jgO/{ RB`0z4@NxM -'plugins/keyboard/gsd-keyboard-manager.hjgO/jgO/{c)ҵo INn4&plugins/keyboard/gsd-keyboard-plugin.cjgO/ӶjgO/Ӷ{ Q^}`8zuRg plugins/keyboard/gsd-xkb-utils.cjgO/ӶjgO/Ӷ{8襔a-=x|7^|L plugins/keyboard/gsd-xkb-utils.hjgO/ӶjgO/Ӷ{.s*ǔ,L+plugins/keyboard/input-method-engines.gperfjgO/ӶjgO/Ӷ{rهo\7O`mzqR %plugins/keyboard/kbd-capslock-off.pngjgO/ӶjgO/Ӷ{ 2 JIYr$plugins/keyboard/kbd-capslock-on.pngjgO/ӶjgO/Ӷ{ !ő{t%z/(oݺ;XAP4(plugins/media-keys/README.media-keys-APIjgO/-jgO/-{ry hTF 4MzW,plugins/media-keys/gvc/gvc-pulseaudio-fake.hjgO0݆jgO0݆{5#N[Ы}Q$2%6plugins/media-keys/media-keys.gnome-settings-plugin.injgO0݆jgO0݆{6<~ >ypV0plugins/media-keys/org.gnome.ShellKeyGrabber.xmljgO0݆jgO0݆{7UNN167$+plugins/media-keys/shell-keybinding-modes.hjgO0݆jgO0݆{8'Ɣ'wXbG‘NJҍ#plugins/media-keys/shortcuts-list.hjgO0݆jgO0݆{9$qV>K ɝaTW$plugins/media-keys/test-media-keys.cjgP1ùJjgP1ùJ{;Vgi(Vg)> 7plugins/media-keys/what-did-you-plug-in/dialog-window.cjgO0,jgO0,{<TOJk27plugins/media-keys/what-did-you-plug-in/dialog-window.hjgO0,jgO0,{=&a$r//] ׷G_74plugins/media-keys/what-did-you-plug-in/pa-backend.cjgO0,jgO0,{>)APX¯j&4plugins/media-keys/what-did-you-plug-in/pa-backend.hjgO0,jgO0,{@~hy#%2jplugins/mouse/Makefile.amjgO02jgO02{A;2X!Oʣ,8k "plugins/mouse/gsd-locate-pointer.cjgO02jgO02{B[;&SSuǯ:;M(,B"plugins/mouse/gsd-locate-pointer.hjgO02jgO02{C–qH#Mn-{ˣf@?!plugins/mouse/gsd-mouse-manager.cjgO02jgO02{Dq;#a!plugins/mouse/gsd-mouse-manager.hjgO02jgO02{E uX&}0 plugins/mouse/gsd-mouse-plugin.cjgO02jgO02{FNFc zvފjQHplugins/mouse/gsd-timeline.cjgO02jgO02{GBo44QGy2!ǁ{n2Jplugins/mouse/gsd-timeline.hjgO06bnjgO06bn{H"O]1-f)[8plugins/orientation/orientation.gnome-settings-plugin.injgO0BjgO0B{PvhC .?3ߔ.\&plugins/orientation/test-orientation.cjgO0BjgO0B{R)jDY3Ygi3plugins/power/Makefile.amjgO0J@{jgO0J@{{S'~PâΦ$@Iplugins/power/com.ubuntu.unity-settings-daemon.plugins.power.policy.in.injgO0J@{jgO0J@{{T*JԝtBv6 !Xplugins/power/gpm-common.cjgO0J@{jgO0J@{{UIu,#++|M4\ctplugins/power/gpm-common.hjgO0J@{jgO0J@{{V&;Wښ니e?o$plugins/power/gsd-backlight-helper.cjgO0J@{jgO0J@{{W !KN^QQJ;}M#plugins/power/gsd-backlight-linux.cjgO0J@{jgO0J@{{X`{+'ѧ3@үa-#plugins/power/gsd-backlight-linux.hjgO0J@{jgO0J@{{Yb{.t]"ǁ\+plugins/power/gsd-power-constants-update.pljgO0J@{jgO0J@{{Zšh6f䱦hIfg ֞ F#plugins/power/gsd-power-constants.hjgO0J@{jgO0J@{{[P/1N1(&plugins/power/gsd-power-enums-update.cjgO0TVjgO0TV{\B\ӮҰ7bT"t'!plugins/power/gsd-power-manager.cjgO0TVjgO0TV{] 4@XVz 0om=!plugins/power/gsd-power-manager.hjgO0TVjgO0TV{^ `ۓE&t+]( plugins/power/gsd-power-plugin.cjgO0TVjgO0TV{_Z0(eKv*C"plugins/power/gsdpowerconstants.pyjgO0TVjgO0TV{`(DFJm}"plugins/power/gsm-inhibitor-flag.hjgO0d)jgO0d){aA3Έgp_'plugins/power/gsm-manager-logout-mode.hjgO0d)jgO0d){b* gGJpQb&tO!plugins/power/gsm-presence-flag.hjgO0d)jgO0d){ceʍ;ZK,plugins/power/power.gnome-settings-plugin.injgO0d)jgO0d){dŴN4tч1ؗ%plugins/power/test-power.cjgO0d)jgO0d){el{;}aeo.cplugins/power/test.pyjgO0d)jgO0d){gN䗃,>I"plugins/remote-display/Makefile.amjgO0u jgO0u {h8- )5ȊS3plugins/remote-display/gsd-remote-display-manager.cjgO0u jgO0u {i wm6 cb̸Σ3plugins/remote-display/gsd-remote-display-manager.hjgO0u jgO0u {j{oPKzȖ*b2plugins/remote-display/gsd-remote-display-plugin.cjgO0u jgO0u {kӓFX!v>plugins/remote-display/remote-display.gnome-settings-plugin.injgO0u jgO0u {lj]$gD:+* ,plugins/remote-display/test-remote-display.cjgP1ùJjgP1ùJ{n$oDDc^X#4plugins/rfkill/61-unity-settings-daemon-rfkill.rulesjgP1ùJjgP1ùJ{oյа_Xp?Eplugins/rfkill/Makefile.amjgO0{jgO0{{pipI싿-Hu )RDx#plugins/rfkill/gsd-rfkill-manager.cjgO0{jgO0{{qȠ0s=șZ#plugins/rfkill/gsd-rfkill-manager.hjgO0{jgO0{{rcᙓŌ W"plugins/rfkill/gsd-rfkill-plugin.cjgO0{jgO0{{s3yB`ԫH-\dWplugins/rfkill/rfkill-glib.cjgO0{jgO0{{t qG4Gm ."@plugins/rfkill/rfkill-glib.hjgO0{jgO0{{u'A**APoJӾ.plugins/rfkill/rfkill.gnome-settings-plugin.injgO0{jgO0{{v a1lm2NqIGplugins/rfkill/rfkill.hjgO0{jgO0{{w%18&[E6 Lplugins/rfkill/test-rfkill.cjgP1ùJjgP1ùJ{y98:,r'TRUi%plugins/screensaver-proxy/Makefile.amjgO0jgO0{zJ{sWWlis9plugins/screensaver-proxy/gsd-screensaver-proxy-manager.cjgO0jgO0{{ w)Y4\@ B(}:9plugins/screensaver-proxy/gsd-screensaver-proxy-manager.hjgO0jgO0{|/%3T8Fɮ8plugins/screensaver-proxy/gsd-screensaver-proxy-plugin.cjgO0jgO0{} (fB?bRQ!Dplugins/screensaver-proxy/screensaver-proxy.gnome-settings-plugin.injgO0jgO0{~&ڣ&e#2plugins/screensaver-proxy/test-screensaver-proxy.cjgO0jgO0{1I C`Lvplugins/sharing/Makefile.amjgO0apjgO0ap{d}o?N3~vc* +#plugins/sharing/gsd-sharing-enums.hjgO0apjgO0ap{sg {`߂< 4%plugins/sharing/gsd-sharing-manager.cjgO0apjgO0ap{&$ZvA ޒ.mt%plugins/sharing/gsd-sharing-manager.hjgO0apjgO0ap{Ή?[v߬j&WS$plugins/sharing/gsd-sharing-plugin.cjgO0apjgO0ap{l .^?z@d vN^a0plugins/sharing/sharing.gnome-settings-plugin.injgO0apjgO0ap{ϫ (lKKeʏ`Paf.plugins/sharing/test-sharing.cjgO0apjgO0ap{pGzMy &plugins/smartcard/Makefile.amjgO0CjgO0C{Ǖ:h!SZn_>$)plugins/smartcard/gsd-smartcard-manager.cjgO0CjgO0C{pI.@t3,X)plugins/smartcard/gsd-smartcard-manager.hjgO0CjgO0C{(*cR$D+kA(plugins/smartcard/gsd-smartcard-plugin.cjgO0CjgO0C{E-+U胛yw(plugins/smartcard/gsd-smartcard-plugin.hjgO0CjgO0C{H&%@w`nߩ!plugins/smartcard/gsd-smartcard.cjgO0CjgO0C{ rɛ_(<5OT:s[!plugins/smartcard/gsd-smartcard.hjgO0CjgO0C{gP)9!FݜN4plugins/smartcard/smartcard.gnome-settings-plugin.injgO0CjgO0C{}7`c/z"plugins/smartcard/test-smartcard.cjgO03jgO03{jOa]u| ]8]plugins/sound/Makefile.amjgO0/jgO0/{.s@oYnD!_ x07!plugins/sound/gsd-sound-manager.cjgO0/jgO0/{P/ƜTgUm)0!plugins/sound/gsd-sound-manager.hjgO0/jgO0/{C5t TRՌ$ plugins/sound/gsd-sound-plugin.cjgO0/jgO0/{$̐{Xθ.`,plugins/sound/sound.gnome-settings-plugin.injgO0/jgO0/{ŦG߁: N"hplugins/sound/test-sound.cjgO0/jgO0/{!@KesG0plugins/updates/Makefile.amjgO0_ jgO0_ { G2lKoW_$plugins/updates/gsd-updates-common.hjgO0_ jgO0_ {DzҢZܜQ&plugins/updates/gsd-updates-firmware.cjgO0_ jgO0_ { /CE&A:YI&plugins/updates/gsd-updates-firmware.hjgO0_ jgO0_ {W{? _gNJK+S%plugins/updates/gsd-updates-manager.cjgO0_ jgO0_ {"/V :FIE%plugins/updates/gsd-updates-manager.hjgO0_ jgO0_ {f7mu\`Wԣ Z$plugins/updates/gsd-updates-plugin.cjgO0_ jgO0_ {OwiOq>7G" %plugins/updates/gsd-updates-refresh.cjgO0_ jgO0_ {Wf{42 / ){4%plugins/updates/gsd-updates-refresh.hjgO0_ jgO0_ {e2kv}d 24V/""plugins/updates/updates-design.svgjgO0_ jgO0_ { ѼK -wzhp0plugins/updates/updates.gnome-settings-plugin.injgO0_ jgO0_ {>HʘR g N0plugins/wacom/Makefile.amjgO0XjgO0X{a~Yqjk'5b#plugins/wacom/README.config-storagejgO0XjgO0X{wέ` 2eC j;hIplugins/wacom/com.ubuntu.unity-settings-daemon.plugins.wacom.policy.in.injgO0XjgO0X{FN?~ (c!<<, plugins/wacom/gsd-wacom-device.cjgO0XjgO0X{! 3YEAܾ plugins/wacom/gsd-wacom-device.hjgO0XjgO0X{n'@.}a"fM|Gy$plugins/wacom/gsd-wacom-led-helper.cjgO0XjgO0X{i|Q\!plugins/wacom/gsd-wacom-manager.cjgO0XjgO0X{ *HW imZ:('ǪY=!plugins/wacom/gsd-wacom-manager.hjgO0jgO0{j߽eS 5ҭ-$plugins/wacom/gsd-wacom-osd-window.cjgO0jgO0{ al:Q3e $plugins/wacom/gsd-wacom-osd-window.hjgO0jgO0{1=",maە[ plugins/wacom/gsd-wacom-plugin.cjgO0jgO0{ rUO 5Qdplugins/wacom/list-wacom.cjgO0jgO0{b ]@HR6ZA/ plugins/wacom/tablet-layout.cssjgO0jgO0{ou|DOUVNUr.yplugins/wacom/test-osd-window.cjgO0jgO0{Ŧo.#A =N?pBplugins/wacom/test-wacom.cjgO0jgO0{#{k_ ԉzH,plugins/wacom/wacom.gnome-settings-plugin.injgO0jgO0{$Rwƭ'Ay?d!plugins/wacom/wacom.gresource.xmljgO0jgO0{ .7pG>mplugins/xrandr/Makefile.amjgP1jgP1{s{gM)P,1vӪx"plugins/xrandr/gsd-xrandr-plugin.cjgO01njgO01n{ʖT0ſ~N4j plugins/xrandr/test-xrandr.cjgO01njgO01n{eS@o8*iyt plugins/xrandr/usd-xrandr-16.pngjgO01njgO01n{bG4*ǻ}tXv plugins/xrandr/usd-xrandr-22.pngjgO01njgO01n{I,8Ѽ plugins/xrandr/usd-xrandr-24.pngjgO01njgO01n{B>Qm^.v plugins/xrandr/usd-xrandr-32.pngjgO01njgO01n{KyIoZTG/5Tplugins/xrandr/usd-xrandr.svgjgO01njgO01n{ςBō #ӚyC̘.plugins/xrandr/xrandr.gnome-settings-plugin.injgO01njgO01n{ uSWplugins/xsettings/Makefile.amjgO0PjgO0P{zbLʽ<WrT]"plugins/xsettings/README.xsettingsjgO0PjgO0P{[ 9!"W&plugins/xsettings/fontconfig-monitor.cjgO0PjgO0P{a©-Un@&plugins/xsettings/fontconfig-monitor.hjgO0PjgO0P{0t7 :Rri*%plugins/xsettings/gsd-xsettings-gtk.cjgO0PjgO0P{aa+ UwZ*%plugins/xsettings/gsd-xsettings-gtk.hjgO0PjgO0P{ ;|e߾cV0)plugins/xsettings/gsd-xsettings-manager.cjgO0PjgO0P{ ]ͺu9nY.gs/))plugins/xsettings/gsd-xsettings-manager.hjgO0PjgO0P{QJϡP_(plugins/xsettings/gsd-xsettings-plugin.cjgO0PjgO0P{?XcZ>C4(<$plugins/xsettings/test-gtk-modules.cjgO0PjgO0P{iZ@9>ǀF0O6plugins/xsettings/test-wm-button-layout-translations.cjgO0PjgO0P{M_cQuϗ"plugins/xsettings/test-xsettings.cjgO0PjgO0P{ʼn\I{p0plugins/xsettings/wm-button-layout-translation.cjgO0PjgO0P{LJ! it!C.`Tc0plugins/xsettings/wm-button-layout-translation.hjgO0PjgO0P{ ʉ jQ3sǴ<$plugins/xsettings/xsettings-common.cjgO0PjgO0P{  bs+ Vye^?Vsk$plugins/xsettings/xsettings-common.hjgO0QjgO0Q{+|[ȥYmܘQҋ%plugins/xsettings/xsettings-manager.cjgO0QjgO0Q{ HH$fF9%plugins/xsettings/xsettings-manager.hjgO0QjgO0Q{-Iil `84plugins/xsettings/xsettings.gnome-settings-plugin.injgO0QjgO0Q{o N[{Lr,$x+q|I po/ChangeLogjgO1 bGjgO1 bG{Iv 'aU̖`K po/LINGUASjgP1jgP1{ v?@U!b$\3кpo/POTFILES.injgO1 bGjgO1 bG{Fmi'vGE~%APpo/POTFILES.skipjgO1 bGjgO1 bG{9O זjF rk.A4dpo/af.pojgO1 bGjgO1 bG{} 8Y:s&ޜpo/am.pojgO1G9jgO1G9{M ү/"oV1( po/ar.pojgO1*jgO1*{NC֞P-GqEpo/as.pojgO1*jgO1*{[XП !?dN} po/ast.pojgO19!jgO19!{8_g~-SPlupo/az.pojgO1IjgO1I{p)+ޝ8 !l_po/be.pojgO1g|jgO1g|{s͐.{ ^po/be@latin.pojgO1g|jgO1g|{& hP .H`H;Epo/bg.pojgO1vjgO1v{t};vo,po/bn.pojgO1ZjgO1Z{s9;+GK˃|yA po/bn_IN.pojgO1ZjgO1Z{{wffN Ln @po/br.pojgO1ZjgO1Z{,mLX{ ,Lpo/bs.pojgO1LjgO1L{aΦyEC4N:rthepo/ca.pojgO1"4jgO1"4{`C Qڍ}QE|po/ca@valencia.pojgO1jgO1{PR̙w#A`X_~a\!J po/crh.pojgO1jgO1{ۻLu kp7'"HOpo/cs.pojgO1jgO1{UĕBB =*a@[po/cy.pojgO2,jgO2,{yc( I7։po/da.pojgO2,jgO2,{M;J&EXSpo/de.pojgO2nxjgO2nx{W?oܗ[k~^NAՎxpo/dz.pojgO2jgO2{H&,`ڲZ.Ќj6Qpo/el.pojgO2jgO2{nfWR$ў[h\ po/en@shaw.pojgO2-`jgO2-`{BNJp)TXmxX J[ po/en_CA.pojgO2-`jgO2-`{[7Ntxى?t po/en_GB.pojgO2LxHjgO2LxH{ÌF\[,rpo/eo.pojgO2LxHjgO2LxH{f(iS?)kGJJpo/es.pojgO2[jgO2[{% ͨ nwZaWpo/et.pojgO2z?jgO2z?{A}}C| cpo/eu.pojgO2jgO2{eQ68Ԝ'wpo/fa.pojgO2ċjgO2ċ{cSӏU_nfV;0po/fi.pojgO2jgO2{ {ȳ+))B&jpo/fr.pojgO2jgO2{isljp-#X )5%po/ga.pojgO2ƋjgO2Ƌ{[c!P p(zipo/gl.pojgO2[jgO2[{~ĕX-MWsr]Mpo/gu.pojgO2[jgO2[{NJcaΞamW`kUpo/he.pojgO2jgO2{rBp X>bpC ":po/hi.pojgO2SCjgO2SC|hJLk`C(RIW0fpo/hr.pojgO2SCjgO2SC|CH^+x, $l;1po/hu.pojgO3jgO3|MjAt sȌXWpo/id.pojgO3+jgO3+| s @"pkxsdpo/is.pojgO3+jgO3+|w W] LJpo/it.pojgO3+jgO3+|sɎ3H+(vw"VIpo/ja.pojgO3"jgO3"|ӻhG!̻*m1R_po/ka.pojgO3"jgO3"|yw[-_=wYǣgpo/km.pojgO31]jgO31]|!wq*-o ZZpo/kn.pojgO31]jgO31]| )O{4$AXx򠾸po/ko.pojgO3@jgO3@| 0kI#W08po/ku.pojgO3@jgO3@| ݪ(:po/lt.pojgO3@jgO3@| a̞JH'GaVb1lpo/lv.pojgO3OjgO3O| }zwZyWw߇蕈IM po/mai.pojgO3OjgO3O|a`Jq->,po/mg.pojgO3_$ojgO3_$o|K>*>T쥤A$a dpo/mk.pojgO3_$ojgO3_$o|l)-g opהc$po/ml.pojgO3nfjgO3nf|vv|-ÓEXchpo/mn.pojgO3nfjgO3nf|4~qa5)֢NG.po/mr.pojgO3}VjgO3}V|4dڟk $Puvpo/ms.pojgO3}VjgO3}V|,we:"*!B &po/nb.pojgO3jgO3|{a9;E| er(3 po/nds.pojgO3jgO3|9vd[T`=..8ב]po/ne.pojgO3jgO3|2Ϡ vϤ{eP㊮)po/nl.pojgO3.>jgO3.>|э1H耋tAU=ppo/nn.pojgO3.>jgO3.>|C󗙄"cs\'A= po/nso.pojgO3pjgO3p|SSI989<po/oc.pojgO3pjgO3p|cݼ0A,Z<po/or.pojgO3&jgO3&|Q /.%:6po/pa.pojgO3&jgO3&|er`_s5-EFpo/pl.pojgO3&jgO3&|XNL~4х;bw\po/pt.pojgO3jgO3|ء[<@d po/pt_BR.pojgO38jgO38| zv݌=3 Z3<8po/ro.pojgO3zjgO3z|!)$ƾ _8 0_ {>po/ru.pojgO3zjgO3z|",r8PIzV"_fpo/rw.pojgO3zjgO3z|#P}>Fg)po/si.pojgO3zjgO3z|$zJ,Gqo,po/sk.pojgO3jgO3|%Jfi>-ϩ|Sppo/sl.pojgO3jgO3|&XQˆfD݉tG9Xpo/sq.pojgO3jgO3|'.U>gc S po/sr.pojgO4jjgO4j|(܄X"[1aZ>b(Qpo/sr@latin.pojgO4jjgO4j|)Zǻ:i%VFp?Tpo/xh.pojgO4D :jgO4D :|3l;ko]*t_ po/zh_CN.pojgO4SKjgO4SK|4VBݶ-D6R po/zh_HK.pojgO4b!jgO4b!|54'& w|$C PY po/zh_TW.pojgO4b!jgO4b!|64}2^>~Z0ަAnpo/zu.pojgO4b!jgO4b!|8UY1RҚ*S*o(scripts/01-usd-migration-monitors-xml.shjgO4b!jgO4b!|:4M]q6`@Ctests/Makefile.amjgO4v`_jgO4v`_|;JDQQ̪B1ctests/dummy.sessionjgO4v`_jgO4v`_|<@;;'qٺY{$Ar2tests/dummyapp.desktopjgO4v`_jgO4v`_|= !YT :T*uStests/gsdtestcase.pyjgO4v`_jgO4v`_|>^j>0qcz!5Ÿtests/shiftkey.cjgO4v`_jgO4v`_|??RY1KT9tests/xorg-dummy.confTREE483 8 >atiA˸w+^kpo96 0 \nC-Ypxman2 0 ?V#T ;lCb4data21 0 &ա$8$tests6 0 %'fEBk[Ah)-debian21 2 Xf0{S(LT/'user2 0 0;ol?jcqsource1 0 ; 'ld5>³`'uplugins284 25 I,h㿝l1xV?>color14 1 %2 |1-Gtest-data2 0 GT/z'/s2rdummy5 0 R>a@XY󧥁\;?mouse10 0 /9Ty Ms^power20 0 0asCVjsound6 0 j{DKo1*^TQa_wacom17 0 !d automount7 0 ;aІ|X,clipboard9 0 [ӴQŀT&smartcard9 0 1785155580 +0200 checkout: moving from main to ubuntu/devel 4902530ad071fce5e14573d4ae8a07acc281863c 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155598 +0200 checkout: moving from ubuntu/devel to ubuntu/devel 4902530ad071fce5e14573d4ae8a07acc281863c 662fe0ab86b979fb022f4ebe98496c0305b082bc Alessandro Astone 1785155600 +0200 merge unity7maintainers/ubuntu/devel: Fast-forward unity-settings-daemon/.git/logs/refs/0000775000000000000000000000000015172222611014760 5ustar unity-settings-daemon/.git/logs/refs/heads/0000775000000000000000000000000015172222611016044 5ustar unity-settings-daemon/.git/logs/refs/heads/ubuntu/0000775000000000000000000000000015172222611017366 5ustar unity-settings-daemon/.git/logs/refs/heads/ubuntu/devel0000664000000000000000000000063715172222611020416 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 branch: Created from 4902530ad071fce5e14573d4ae8a07acc281863c 4902530ad071fce5e14573d4ae8a07acc281863c 662fe0ab86b979fb022f4ebe98496c0305b082bc Alessandro Astone 1785155600 +0200 merge unity7maintainers/ubuntu/devel: Fast-forward unity-settings-daemon/.git/logs/refs/notes/0000775000000000000000000000000015172222611016110 5ustar unity-settings-daemon/.git/logs/refs/notes/changelog0000664000000000000000000000025615172222611017765 0ustar 0000000000000000000000000000000000000000 28797e59376461fdbd00e32a2d96e165d25cc1e0 Alessandro Astone 1785155580 +0200 fetch pkg: storing ref unity-settings-daemon/.git/logs/refs/remotes/0000775000000000000000000000000015172222611016436 5ustar unity-settings-daemon/.git/logs/refs/remotes/aleasto/0000775000000000000000000000000015172222611020066 5ustar unity-settings-daemon/.git/logs/refs/remotes/aleasto/ubuntu/0000775000000000000000000000000015172222611021410 5ustar unity-settings-daemon/.git/logs/refs/remotes/aleasto/ubuntu/devel0000664000000000000000000000024615172222611022434 0ustar 0000000000000000000000000000000000000000 662fe0ab86b979fb022f4ebe98496c0305b082bc Alessandro Astone 1785155881 +0200 update by push unity-settings-daemon/.git/logs/refs/remotes/pkg/0000775000000000000000000000000015172222611017217 5ustar unity-settings-daemon/.git/logs/refs/remotes/pkg/HEAD0000664000000000000000000000023515172222611017643 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/0000775000000000000000000000000015172222611020635 5ustar unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/0000775000000000000000000000000015172222611022157 5ustar unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/artful0000664000000000000000000000025715172222611023403 0ustar 0000000000000000000000000000000000000000 f670167cc6b3365c22d99d86e2224bc0d0cef81f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/artful-devel0000664000000000000000000000025715172222611024500 0ustar 0000000000000000000000000000000000000000 f670167cc6b3365c22d99d86e2224bc0d0cef81f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/artful-proposed0000664000000000000000000000025715172222611025234 0ustar 0000000000000000000000000000000000000000 f670167cc6b3365c22d99d86e2224bc0d0cef81f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/bionic0000664000000000000000000000025715172222611023351 0ustar 0000000000000000000000000000000000000000 7a59e1b61af6de957765e77fbbf58787dd595e88 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/bionic-devel0000664000000000000000000000025715172222611024446 0ustar 0000000000000000000000000000000000000000 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/bionic-proposed0000664000000000000000000000025715172222611025202 0ustar 0000000000000000000000000000000000000000 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/bionic-updates0000664000000000000000000000025715172222611025014 0ustar 0000000000000000000000000000000000000000 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/cosmic0000664000000000000000000000025715172222611023363 0ustar 0000000000000000000000000000000000000000 24265629edb6e424b175d1b4601d6dfc63b64bb8 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/cosmic-devel0000664000000000000000000000025715172222611024460 0ustar 0000000000000000000000000000000000000000 2df71f1809b49864b7e9ba8e5957d323886a69ed Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/cosmic-proposed0000664000000000000000000000025715172222611025214 0ustar 0000000000000000000000000000000000000000 2df71f1809b49864b7e9ba8e5957d323886a69ed Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/cosmic-updates0000664000000000000000000000025715172222611025026 0ustar 0000000000000000000000000000000000000000 2df71f1809b49864b7e9ba8e5957d323886a69ed Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/devel0000664000000000000000000000025715172222611023205 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/disco0000664000000000000000000000025715172222611023207 0ustar 0000000000000000000000000000000000000000 cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/disco-devel0000664000000000000000000000025715172222611024304 0ustar 0000000000000000000000000000000000000000 cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/disco-proposed0000664000000000000000000000025715172222611025040 0ustar 0000000000000000000000000000000000000000 cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/eoan0000664000000000000000000000025715172222611023030 0ustar 0000000000000000000000000000000000000000 52efe8d0337105bb49293d6840be99da080e1d80 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/eoan-devel0000664000000000000000000000025715172222611024125 0ustar 0000000000000000000000000000000000000000 52efe8d0337105bb49293d6840be99da080e1d80 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/eoan-proposed0000664000000000000000000000025715172222611024661 0ustar 0000000000000000000000000000000000000000 52efe8d0337105bb49293d6840be99da080e1d80 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/focal0000664000000000000000000000025715172222611023172 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/focal-devel0000664000000000000000000000025715172222611024267 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/focal-proposed0000664000000000000000000000025715172222611025023 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/groovy0000664000000000000000000000025715172222611023433 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/groovy-devel0000664000000000000000000000025715172222611024530 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/hirsute0000664000000000000000000000025715172222611023571 0ustar 0000000000000000000000000000000000000000 d53bb9dbc145dc529b36c9712dd389b5b159c06e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/hirsute-devel0000664000000000000000000000025715172222611024666 0ustar 0000000000000000000000000000000000000000 d53bb9dbc145dc529b36c9712dd389b5b159c06e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/hirsute-proposed0000664000000000000000000000025715172222611025422 0ustar 0000000000000000000000000000000000000000 d53bb9dbc145dc529b36c9712dd389b5b159c06e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/impish0000664000000000000000000000025715172222611023377 0ustar 0000000000000000000000000000000000000000 5bc9dc4af4da1b756db0011523a5920e87c6deae Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/impish-devel0000664000000000000000000000025715172222611024474 0ustar 0000000000000000000000000000000000000000 5bc9dc4af4da1b756db0011523a5920e87c6deae Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/impish-proposed0000664000000000000000000000025715172222611025230 0ustar 0000000000000000000000000000000000000000 5bc9dc4af4da1b756db0011523a5920e87c6deae Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/jammy0000664000000000000000000000025715172222611023223 0ustar 0000000000000000000000000000000000000000 6f0e8ea50b75b073c4db7efda371eec5e501c97d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/jammy-devel0000664000000000000000000000025715172222611024320 0ustar 0000000000000000000000000000000000000000 6f0e8ea50b75b073c4db7efda371eec5e501c97d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/jammy-proposed0000664000000000000000000000025715172222611025054 0ustar 0000000000000000000000000000000000000000 6f0e8ea50b75b073c4db7efda371eec5e501c97d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/kinetic0000664000000000000000000000025715172222611023534 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/kinetic-devel0000664000000000000000000000025715172222611024631 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/kinetic-proposed0000664000000000000000000000025715172222611025365 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/lunar0000664000000000000000000000025715172222611023227 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/lunar-devel0000664000000000000000000000025715172222611024324 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/mantic0000664000000000000000000000025715172222611023361 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/mantic-devel0000664000000000000000000000025715172222611024456 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/noble0000664000000000000000000000025715172222611023205 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/noble-devel0000664000000000000000000000025715172222611024302 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/noble-proposed0000664000000000000000000000025715172222611025036 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/noble-updates0000664000000000000000000000025715172222611024650 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/oracular0000664000000000000000000000025715172222611023716 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/oracular-devel0000664000000000000000000000025715172222611025013 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/plucky0000664000000000000000000000025715172222611023415 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/plucky-devel0000664000000000000000000000025715172222611024512 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/questing0000664000000000000000000000025715172222611023745 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/questing-devel0000664000000000000000000000025715172222611025042 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/questing-proposed0000664000000000000000000000025715172222611025576 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/resolute0000664000000000000000000000025715172222611023750 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/resolute-devel0000664000000000000000000000025715172222611025045 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/trusty0000664000000000000000000000025715172222611023460 0ustar 0000000000000000000000000000000000000000 bcf1d099c28d98f7ac6ad0c00cd2271c18135fa8 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/trusty-devel0000664000000000000000000000025715172222611024555 0ustar 0000000000000000000000000000000000000000 ff8f712dadc9d9332fb203a1013acf8c697b12d1 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/trusty-proposed0000664000000000000000000000025715172222611025311 0ustar 0000000000000000000000000000000000000000 ff8f712dadc9d9332fb203a1013acf8c697b12d1 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/trusty-security0000664000000000000000000000025715172222611025325 0ustar 0000000000000000000000000000000000000000 7927f5e5b4f0384f2d8dfa16f619bfa318258119 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/trusty-updates0000664000000000000000000000025715172222611025123 0ustar 0000000000000000000000000000000000000000 ff8f712dadc9d9332fb203a1013acf8c697b12d1 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/utopic0000664000000000000000000000025715172222611023411 0ustar 0000000000000000000000000000000000000000 db4a3a51a94edf8ffcaf994b9048b3902eda9bab Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/utopic-devel0000664000000000000000000000025715172222611024506 0ustar 0000000000000000000000000000000000000000 a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/utopic-proposed0000664000000000000000000000025715172222611025242 0ustar 0000000000000000000000000000000000000000 a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/utopic-updates0000664000000000000000000000025715172222611025054 0ustar 0000000000000000000000000000000000000000 a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/vivid0000664000000000000000000000025715172222611023227 0ustar 0000000000000000000000000000000000000000 5c326b3491c83269cd4a5626b95866a69dcbe935 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/vivid-devel0000664000000000000000000000025715172222611024324 0ustar 0000000000000000000000000000000000000000 8601902a5268c84ba441f2a194faec96d75dbaf3 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/vivid-proposed0000664000000000000000000000025715172222611025060 0ustar 0000000000000000000000000000000000000000 46b51b71a8d3b7c8fca4726a8430825f6addc35e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/vivid-security0000664000000000000000000000025715172222611025074 0ustar 0000000000000000000000000000000000000000 8601902a5268c84ba441f2a194faec96d75dbaf3 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/vivid-updates0000664000000000000000000000025715172222611024672 0ustar 0000000000000000000000000000000000000000 8601902a5268c84ba441f2a194faec96d75dbaf3 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/wily0000664000000000000000000000025715172222611023072 0ustar 0000000000000000000000000000000000000000 39819d0a06eb08de7f48e6e5884e5831c3f48f20 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/wily-devel0000664000000000000000000000025715172222611024167 0ustar 0000000000000000000000000000000000000000 90c237f94fffdba051fe83bebcfcb0368cdb8a73 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/wily-proposed0000664000000000000000000000025715172222611024723 0ustar 0000000000000000000000000000000000000000 90c237f94fffdba051fe83bebcfcb0368cdb8a73 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/wily-updates0000664000000000000000000000025715172222611024535 0ustar 0000000000000000000000000000000000000000 90c237f94fffdba051fe83bebcfcb0368cdb8a73 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/xenial0000664000000000000000000000025715172222611023366 0ustar 0000000000000000000000000000000000000000 ff04fe463c18fe9988c4142b60aa810d3519b446 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/xenial-devel0000664000000000000000000000025715172222611024463 0ustar 0000000000000000000000000000000000000000 0c06606b427b1890311277821d91051ef3a4dacd Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/xenial-proposed0000664000000000000000000000025715172222611025217 0ustar 0000000000000000000000000000000000000000 0c06606b427b1890311277821d91051ef3a4dacd Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/xenial-updates0000664000000000000000000000025715172222611025031 0ustar 0000000000000000000000000000000000000000 0c06606b427b1890311277821d91051ef3a4dacd Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/yakkety0000664000000000000000000000025715172222611023567 0ustar 0000000000000000000000000000000000000000 4c3c6169349777fb0e36403f065dc3e011542917 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/yakkety-devel0000664000000000000000000000025715172222611024664 0ustar 0000000000000000000000000000000000000000 4c3c6169349777fb0e36403f065dc3e011542917 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/yakkety-proposed0000664000000000000000000000025715172222611025420 0ustar 0000000000000000000000000000000000000000 4c3c6169349777fb0e36403f065dc3e011542917 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/zesty0000664000000000000000000000025715172222611023264 0ustar 0000000000000000000000000000000000000000 5aab4fdc93c00a16104443b9a2947122f14b7a8e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/zesty-devel0000664000000000000000000000025715172222611024361 0ustar 0000000000000000000000000000000000000000 75b72c143b6774598759627e0cf964ffd45df2a8 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/zesty-proposed0000664000000000000000000000025715172222611025115 0ustar 0000000000000000000000000000000000000000 75b72c143b6774598759627e0cf964ffd45df2a8 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/applied/ubuntu/zesty-updates0000664000000000000000000000025715172222611024727 0ustar 0000000000000000000000000000000000000000 75b72c143b6774598759627e0cf964ffd45df2a8 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/importer/0000775000000000000000000000000015172222611021060 5ustar unity-settings-daemon/.git/logs/refs/remotes/pkg/importer/ubuntu/0000775000000000000000000000000015172222611022402 5ustar unity-settings-daemon/.git/logs/refs/remotes/pkg/importer/ubuntu/dsc0000664000000000000000000000025715172222611023102 0ustar 0000000000000000000000000000000000000000 438e8aaea637702af2c9adba7ac4cad3b78da62f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/importer/ubuntu/pristine-tar0000664000000000000000000000025715172222611024752 0ustar 0000000000000000000000000000000000000000 4110edb5cb1c8a4bb4752fffcd1977b12b53d9a7 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/0000775000000000000000000000000015172222611020541 5ustar unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/artful0000664000000000000000000000025715172222611021765 0ustar 0000000000000000000000000000000000000000 87434be575ac61fd9adc14d77468ae7f8a4437ed Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/artful-devel0000664000000000000000000000025715172222611023062 0ustar 0000000000000000000000000000000000000000 87434be575ac61fd9adc14d77468ae7f8a4437ed Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/artful-proposed0000664000000000000000000000025715172222611023616 0ustar 0000000000000000000000000000000000000000 87434be575ac61fd9adc14d77468ae7f8a4437ed Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/bionic0000664000000000000000000000025715172222611021733 0ustar 0000000000000000000000000000000000000000 701dee94195a6a6b8c8dc4736c3a5fb12708f532 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/bionic-devel0000664000000000000000000000025715172222611023030 0ustar 0000000000000000000000000000000000000000 fdac6c1ba597c17bce992b5377e49e89c0b42e05 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/bionic-proposed0000664000000000000000000000025715172222611023564 0ustar 0000000000000000000000000000000000000000 fdac6c1ba597c17bce992b5377e49e89c0b42e05 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/bionic-updates0000664000000000000000000000025715172222611023376 0ustar 0000000000000000000000000000000000000000 fdac6c1ba597c17bce992b5377e49e89c0b42e05 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/cosmic0000664000000000000000000000025715172222611021745 0ustar 0000000000000000000000000000000000000000 a256b4651d4b7fb339efc899508b496fe8aa20b5 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/cosmic-devel0000664000000000000000000000025715172222611023042 0ustar 0000000000000000000000000000000000000000 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/cosmic-proposed0000664000000000000000000000025715172222611023576 0ustar 0000000000000000000000000000000000000000 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/cosmic-updates0000664000000000000000000000025715172222611023410 0ustar 0000000000000000000000000000000000000000 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/devel0000664000000000000000000000025715172222611021567 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/disco0000664000000000000000000000025715172222611021571 0ustar 0000000000000000000000000000000000000000 059329a966e982c7fc0e29c5af6687203d6a5bf2 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/disco-devel0000664000000000000000000000025715172222611022666 0ustar 0000000000000000000000000000000000000000 059329a966e982c7fc0e29c5af6687203d6a5bf2 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/disco-proposed0000664000000000000000000000025715172222611023422 0ustar 0000000000000000000000000000000000000000 059329a966e982c7fc0e29c5af6687203d6a5bf2 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/eoan0000664000000000000000000000025715172222611021412 0ustar 0000000000000000000000000000000000000000 aa274a2ed2c2cc7476f50d58900689353523eb60 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/eoan-devel0000664000000000000000000000025715172222611022507 0ustar 0000000000000000000000000000000000000000 aa274a2ed2c2cc7476f50d58900689353523eb60 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/eoan-proposed0000664000000000000000000000025715172222611023243 0ustar 0000000000000000000000000000000000000000 aa274a2ed2c2cc7476f50d58900689353523eb60 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/focal0000664000000000000000000000025715172222611021554 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/focal-devel0000664000000000000000000000025715172222611022651 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/focal-proposed0000664000000000000000000000025715172222611023405 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/groovy0000664000000000000000000000025715172222611022015 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/groovy-devel0000664000000000000000000000025715172222611023112 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/hirsute0000664000000000000000000000025715172222611022153 0ustar 0000000000000000000000000000000000000000 7c905087ef3826d312b5c9681b52693d08bf1546 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/hirsute-devel0000664000000000000000000000025715172222611023250 0ustar 0000000000000000000000000000000000000000 7c905087ef3826d312b5c9681b52693d08bf1546 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/hirsute-proposed0000664000000000000000000000025715172222611024004 0ustar 0000000000000000000000000000000000000000 7c905087ef3826d312b5c9681b52693d08bf1546 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/impish0000664000000000000000000000025715172222611021761 0ustar 0000000000000000000000000000000000000000 c30fdce9ca1bb8aae46ea53e7555123ea221c753 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/impish-devel0000664000000000000000000000025715172222611023056 0ustar 0000000000000000000000000000000000000000 c30fdce9ca1bb8aae46ea53e7555123ea221c753 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/impish-proposed0000664000000000000000000000025715172222611023612 0ustar 0000000000000000000000000000000000000000 c30fdce9ca1bb8aae46ea53e7555123ea221c753 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/jammy0000664000000000000000000000025715172222611021605 0ustar 0000000000000000000000000000000000000000 1d911e0b2c85298cdad43b5610282144c03b266f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/jammy-devel0000664000000000000000000000025715172222611022702 0ustar 0000000000000000000000000000000000000000 1d911e0b2c85298cdad43b5610282144c03b266f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/jammy-proposed0000664000000000000000000000025715172222611023436 0ustar 0000000000000000000000000000000000000000 1d911e0b2c85298cdad43b5610282144c03b266f Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/kinetic0000664000000000000000000000025715172222611022116 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/kinetic-devel0000664000000000000000000000025715172222611023213 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/kinetic-proposed0000664000000000000000000000025715172222611023747 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/lunar0000664000000000000000000000025715172222611021611 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/lunar-devel0000664000000000000000000000025715172222611022706 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/mantic0000664000000000000000000000025715172222611021743 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/mantic-devel0000664000000000000000000000025715172222611023040 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/noble0000664000000000000000000000025715172222611021567 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/noble-devel0000664000000000000000000000025715172222611022664 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/noble-proposed0000664000000000000000000000025715172222611023420 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/noble-updates0000664000000000000000000000025715172222611023232 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/oracular0000664000000000000000000000025715172222611022300 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/oracular-devel0000664000000000000000000000025715172222611023375 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/plucky0000664000000000000000000000025715172222611021777 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/plucky-devel0000664000000000000000000000025715172222611023074 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/questing0000664000000000000000000000025715172222611022327 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/questing-devel0000664000000000000000000000025715172222611023424 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/questing-proposed0000664000000000000000000000025715172222611024160 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/resolute0000664000000000000000000000025715172222611022332 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/resolute-devel0000664000000000000000000000025715172222611023427 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/trusty0000664000000000000000000000025715172222611022042 0ustar 0000000000000000000000000000000000000000 a65ef112964724e5b169d2c5dd29dbffa000b0cf Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/trusty-devel0000664000000000000000000000025715172222611023137 0ustar 0000000000000000000000000000000000000000 0534e8cf748ff159459f7d722eafabde575dea67 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/trusty-proposed0000664000000000000000000000025715172222611023673 0ustar 0000000000000000000000000000000000000000 0534e8cf748ff159459f7d722eafabde575dea67 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/trusty-security0000664000000000000000000000025715172222611023707 0ustar 0000000000000000000000000000000000000000 ff5c937499aa60b84af16c3fb74007eb1b31ac69 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/trusty-updates0000664000000000000000000000025715172222611023505 0ustar 0000000000000000000000000000000000000000 0534e8cf748ff159459f7d722eafabde575dea67 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/utopic0000664000000000000000000000025715172222611021773 0ustar 0000000000000000000000000000000000000000 6fca73822e5900b051be84fc6e231f73459bb0b7 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/utopic-devel0000664000000000000000000000025715172222611023070 0ustar 0000000000000000000000000000000000000000 33b24fedf01adbc16ff519aed5ede636f43c44e7 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/utopic-proposed0000664000000000000000000000025715172222611023624 0ustar 0000000000000000000000000000000000000000 33b24fedf01adbc16ff519aed5ede636f43c44e7 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/utopic-updates0000664000000000000000000000025715172222611023436 0ustar 0000000000000000000000000000000000000000 33b24fedf01adbc16ff519aed5ede636f43c44e7 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/vivid0000664000000000000000000000025715172222611021611 0ustar 0000000000000000000000000000000000000000 2ec8c6572be035c690a34bec0dc124fa6f122ec7 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/vivid-devel0000664000000000000000000000025715172222611022706 0ustar 0000000000000000000000000000000000000000 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/vivid-proposed0000664000000000000000000000025715172222611023442 0ustar 0000000000000000000000000000000000000000 3c4733f85bc83c90703f95faefef46ba3c451410 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/vivid-security0000664000000000000000000000025715172222611023456 0ustar 0000000000000000000000000000000000000000 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/vivid-updates0000664000000000000000000000025715172222611023254 0ustar 0000000000000000000000000000000000000000 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/wily0000664000000000000000000000025715172222611021454 0ustar 0000000000000000000000000000000000000000 6b036413a54a0265a561ec36065529786dca4b61 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/wily-devel0000664000000000000000000000025715172222611022551 0ustar 0000000000000000000000000000000000000000 d639ba4ec35d3fecaa1af51cc059d55832e70c1e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/wily-proposed0000664000000000000000000000025715172222611023305 0ustar 0000000000000000000000000000000000000000 d639ba4ec35d3fecaa1af51cc059d55832e70c1e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/wily-updates0000664000000000000000000000025715172222611023117 0ustar 0000000000000000000000000000000000000000 d639ba4ec35d3fecaa1af51cc059d55832e70c1e Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/xenial0000664000000000000000000000025715172222611021750 0ustar 0000000000000000000000000000000000000000 7a88377c31cdc83a3fdfa9378b305123ffd8d142 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/xenial-devel0000664000000000000000000000025715172222611023045 0ustar 0000000000000000000000000000000000000000 75edc6735ce0b8beef515a0a936560ca716d5133 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/xenial-proposed0000664000000000000000000000025715172222611023601 0ustar 0000000000000000000000000000000000000000 75edc6735ce0b8beef515a0a936560ca716d5133 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/xenial-updates0000664000000000000000000000025715172222611023413 0ustar 0000000000000000000000000000000000000000 75edc6735ce0b8beef515a0a936560ca716d5133 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/yakkety0000664000000000000000000000025715172222611022151 0ustar 0000000000000000000000000000000000000000 4592ae2d51c94d313ba225149e0700d627412b5c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/yakkety-devel0000664000000000000000000000025715172222611023246 0ustar 0000000000000000000000000000000000000000 4592ae2d51c94d313ba225149e0700d627412b5c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/yakkety-proposed0000664000000000000000000000025715172222611024002 0ustar 0000000000000000000000000000000000000000 4592ae2d51c94d313ba225149e0700d627412b5c Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/zesty0000664000000000000000000000025715172222611021646 0ustar 0000000000000000000000000000000000000000 aac80b647a63df9defb4cd2ca190bba29edeb7da Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/zesty-devel0000664000000000000000000000025715172222611022743 0ustar 0000000000000000000000000000000000000000 cabf6621a0835b22ba17b4627e761c1c01cadbf0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/zesty-proposed0000664000000000000000000000025715172222611023477 0ustar 0000000000000000000000000000000000000000 cabf6621a0835b22ba17b4627e761c1c01cadbf0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/pkg/ubuntu/zesty-updates0000664000000000000000000000025715172222611023311 0ustar 0000000000000000000000000000000000000000 cabf6621a0835b22ba17b4627e761c1c01cadbf0 Alessandro Astone 1785155580 +0200 fetch pkg: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/0000775000000000000000000000000015172222611022130 5ustar unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/HEAD0000664000000000000000000000023515172222611022554 0ustar 0000000000000000000000000000000000000000 b02e4e32de28c646ff70088515d84a5c5bb539c8 Alessandro Astone 1785155597 +0200 fetch unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/0000775000000000000000000000000015172222611023546 5ustar unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/0000775000000000000000000000000015172222611025070 5ustar unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/artful0000664000000000000000000000035315172222611026311 0ustar 0000000000000000000000000000000000000000 f670167cc6b3365c22d99d86e2224bc0d0cef81f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/artful-devel0000664000000000000000000000035315172222611027406 0ustar 0000000000000000000000000000000000000000 f670167cc6b3365c22d99d86e2224bc0d0cef81f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/artful-proposed0000664000000000000000000000035315172222611030142 0ustar 0000000000000000000000000000000000000000 f670167cc6b3365c22d99d86e2224bc0d0cef81f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/bionic0000664000000000000000000000035315172222611026257 0ustar 0000000000000000000000000000000000000000 7a59e1b61af6de957765e77fbbf58787dd595e88 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/bionic-devel0000664000000000000000000000035315172222611027354 0ustar 0000000000000000000000000000000000000000 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/bionic-proposed0000664000000000000000000000035315172222611030110 0ustar 0000000000000000000000000000000000000000 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/bionic-updates0000664000000000000000000000035315172222611027722 0ustar 0000000000000000000000000000000000000000 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/cosmic0000664000000000000000000000035315172222611026271 0ustar 0000000000000000000000000000000000000000 24265629edb6e424b175d1b4601d6dfc63b64bb8 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/cosmic-devel0000664000000000000000000000035315172222611027366 0ustar 0000000000000000000000000000000000000000 2df71f1809b49864b7e9ba8e5957d323886a69ed Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/cosmic-proposed0000664000000000000000000000035315172222611030122 0ustar 0000000000000000000000000000000000000000 2df71f1809b49864b7e9ba8e5957d323886a69ed Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/cosmic-updates0000664000000000000000000000035315172222611027734 0ustar 0000000000000000000000000000000000000000 2df71f1809b49864b7e9ba8e5957d323886a69ed Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/devel0000664000000000000000000000035315172222611026113 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/disco0000664000000000000000000000035315172222611026115 0ustar 0000000000000000000000000000000000000000 cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/disco-devel0000664000000000000000000000035315172222611027212 0ustar 0000000000000000000000000000000000000000 cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/disco-proposed0000664000000000000000000000035315172222611027746 0ustar 0000000000000000000000000000000000000000 cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/eoan0000664000000000000000000000035315172222611025736 0ustar 0000000000000000000000000000000000000000 52efe8d0337105bb49293d6840be99da080e1d80 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/eoan-devel0000664000000000000000000000035315172222611027033 0ustar 0000000000000000000000000000000000000000 52efe8d0337105bb49293d6840be99da080e1d80 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/eoan-proposed0000664000000000000000000000035315172222611027567 0ustar 0000000000000000000000000000000000000000 52efe8d0337105bb49293d6840be99da080e1d80 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/focal0000664000000000000000000000035315172222611026100 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/focal-devel0000664000000000000000000000035315172222611027175 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/focal-proposed0000664000000000000000000000035315172222611027731 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/groovy0000664000000000000000000000035315172222611026341 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/groovy-devel0000664000000000000000000000035315172222611027436 0ustar 0000000000000000000000000000000000000000 7885e3b9a606920c6a55b53190c515c40131989d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/hirsute0000664000000000000000000000035315172222611026477 0ustar 0000000000000000000000000000000000000000 d53bb9dbc145dc529b36c9712dd389b5b159c06e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/hirsute-devel0000664000000000000000000000035315172222611027574 0ustar 0000000000000000000000000000000000000000 d53bb9dbc145dc529b36c9712dd389b5b159c06e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/hirsute-proposed0000664000000000000000000000035315172222611030330 0ustar 0000000000000000000000000000000000000000 d53bb9dbc145dc529b36c9712dd389b5b159c06e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/impish0000664000000000000000000000035315172222611026305 0ustar 0000000000000000000000000000000000000000 5bc9dc4af4da1b756db0011523a5920e87c6deae Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/impish-devel0000664000000000000000000000035315172222611027402 0ustar 0000000000000000000000000000000000000000 5bc9dc4af4da1b756db0011523a5920e87c6deae Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/impish-proposed0000664000000000000000000000035315172222611030136 0ustar 0000000000000000000000000000000000000000 5bc9dc4af4da1b756db0011523a5920e87c6deae Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/jammy0000664000000000000000000000035315172222611026131 0ustar 0000000000000000000000000000000000000000 6f0e8ea50b75b073c4db7efda371eec5e501c97d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/jammy-devel0000664000000000000000000000035315172222611027226 0ustar 0000000000000000000000000000000000000000 6f0e8ea50b75b073c4db7efda371eec5e501c97d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/jammy-proposed0000664000000000000000000000035315172222611027762 0ustar 0000000000000000000000000000000000000000 6f0e8ea50b75b073c4db7efda371eec5e501c97d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/kinetic0000664000000000000000000000035315172222611026442 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/kinetic-devel0000664000000000000000000000035315172222611027537 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/kinetic-proposed0000664000000000000000000000035315172222611030273 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/lunar0000664000000000000000000000035315172222611026135 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/lunar-devel0000664000000000000000000000035315172222611027232 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/mantic0000664000000000000000000000035315172222611026267 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/mantic-devel0000664000000000000000000000035315172222611027364 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/noble0000664000000000000000000000035315172222611026113 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/noble-devel0000664000000000000000000000035315172222611027210 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/noble-proposed0000664000000000000000000000035315172222611027744 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/noble-updates0000664000000000000000000000035315172222611027556 0ustar 0000000000000000000000000000000000000000 f223f8a37c17169dc539fabf8a4e104e0d4bc000 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/oracular0000664000000000000000000000035315172222611026624 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/oracular-devel0000664000000000000000000000035315172222611027721 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/plucky0000664000000000000000000000035315172222611026323 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/plucky-devel0000664000000000000000000000035315172222611027420 0ustar 0000000000000000000000000000000000000000 624c730ed1f0f7c058d3abd2830a7c46bb07a474 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/questing0000664000000000000000000000035315172222611026653 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/questing-devel0000664000000000000000000000035315172222611027750 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/questing-proposed0000664000000000000000000000035315172222611030504 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/resolute0000664000000000000000000000035315172222611026656 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/resolute-devel0000664000000000000000000000035315172222611027753 0ustar 0000000000000000000000000000000000000000 abdb145b64dec7e468f4f2b4eb6403aed2b0710b Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/trusty0000664000000000000000000000035315172222611026366 0ustar 0000000000000000000000000000000000000000 bcf1d099c28d98f7ac6ad0c00cd2271c18135fa8 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/trusty-devel0000664000000000000000000000035315172222611027463 0ustar 0000000000000000000000000000000000000000 ff8f712dadc9d9332fb203a1013acf8c697b12d1 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/trusty-proposed0000664000000000000000000000035315172222611030217 0ustar 0000000000000000000000000000000000000000 ff8f712dadc9d9332fb203a1013acf8c697b12d1 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/trusty-security0000664000000000000000000000035315172222611030233 0ustar 0000000000000000000000000000000000000000 7927f5e5b4f0384f2d8dfa16f619bfa318258119 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/trusty-updates0000664000000000000000000000035315172222611030031 0ustar 0000000000000000000000000000000000000000 ff8f712dadc9d9332fb203a1013acf8c697b12d1 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/utopic0000664000000000000000000000035315172222611026317 0ustar 0000000000000000000000000000000000000000 db4a3a51a94edf8ffcaf994b9048b3902eda9bab Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/utopic-devel0000664000000000000000000000035315172222611027414 0ustar 0000000000000000000000000000000000000000 a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/utopic-proposed0000664000000000000000000000035315172222611030150 0ustar 0000000000000000000000000000000000000000 a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/utopic-updates0000664000000000000000000000035315172222611027762 0ustar 0000000000000000000000000000000000000000 a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/vivid0000664000000000000000000000035315172222611026135 0ustar 0000000000000000000000000000000000000000 5c326b3491c83269cd4a5626b95866a69dcbe935 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/vivid-devel0000664000000000000000000000035315172222611027232 0ustar 0000000000000000000000000000000000000000 8601902a5268c84ba441f2a194faec96d75dbaf3 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/vivid-proposed0000664000000000000000000000035315172222611027766 0ustar 0000000000000000000000000000000000000000 46b51b71a8d3b7c8fca4726a8430825f6addc35e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/vivid-security0000664000000000000000000000035315172222611030002 0ustar 0000000000000000000000000000000000000000 8601902a5268c84ba441f2a194faec96d75dbaf3 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/vivid-updates0000664000000000000000000000035315172222611027600 0ustar 0000000000000000000000000000000000000000 8601902a5268c84ba441f2a194faec96d75dbaf3 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/wily0000664000000000000000000000035315172222611026000 0ustar 0000000000000000000000000000000000000000 39819d0a06eb08de7f48e6e5884e5831c3f48f20 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/wily-devel0000664000000000000000000000035315172222611027075 0ustar 0000000000000000000000000000000000000000 90c237f94fffdba051fe83bebcfcb0368cdb8a73 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/wily-proposed0000664000000000000000000000035315172222611027631 0ustar 0000000000000000000000000000000000000000 90c237f94fffdba051fe83bebcfcb0368cdb8a73 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/wily-updates0000664000000000000000000000035315172222611027443 0ustar 0000000000000000000000000000000000000000 90c237f94fffdba051fe83bebcfcb0368cdb8a73 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/xenial0000664000000000000000000000035315172222611026274 0ustar 0000000000000000000000000000000000000000 ff04fe463c18fe9988c4142b60aa810d3519b446 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/xenial-devel0000664000000000000000000000035315172222611027371 0ustar 0000000000000000000000000000000000000000 0c06606b427b1890311277821d91051ef3a4dacd Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/xenial-proposed0000664000000000000000000000035315172222611030125 0ustar 0000000000000000000000000000000000000000 0c06606b427b1890311277821d91051ef3a4dacd Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/xenial-updates0000664000000000000000000000035315172222611027737 0ustar 0000000000000000000000000000000000000000 0c06606b427b1890311277821d91051ef3a4dacd Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/yakkety0000664000000000000000000000035315172222611026475 0ustar 0000000000000000000000000000000000000000 4c3c6169349777fb0e36403f065dc3e011542917 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/yakkety-devel0000664000000000000000000000035315172222611027572 0ustar 0000000000000000000000000000000000000000 4c3c6169349777fb0e36403f065dc3e011542917 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/yakkety-proposed0000664000000000000000000000035315172222611030326 0ustar 0000000000000000000000000000000000000000 4c3c6169349777fb0e36403f065dc3e011542917 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/zesty0000664000000000000000000000035315172222611026172 0ustar 0000000000000000000000000000000000000000 5aab4fdc93c00a16104443b9a2947122f14b7a8e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/zesty-devel0000664000000000000000000000035315172222611027267 0ustar 0000000000000000000000000000000000000000 75b72c143b6774598759627e0cf964ffd45df2a8 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/zesty-proposed0000664000000000000000000000035315172222611030023 0ustar 0000000000000000000000000000000000000000 75b72c143b6774598759627e0cf964ffd45df2a8 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/applied/ubuntu/zesty-updates0000664000000000000000000000035315172222611027635 0ustar 0000000000000000000000000000000000000000 75b72c143b6774598759627e0cf964ffd45df2a8 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/importer/0000775000000000000000000000000015172222611023771 5ustar unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/importer/ubuntu/0000775000000000000000000000000015172222611025313 5ustar unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/importer/ubuntu/dsc0000664000000000000000000000035315172222611026010 0ustar 0000000000000000000000000000000000000000 438e8aaea637702af2c9adba7ac4cad3b78da62f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/importer/ubuntu/pristine-tar0000664000000000000000000000035315172222611027660 0ustar 0000000000000000000000000000000000000000 4110edb5cb1c8a4bb4752fffcd1977b12b53d9a7 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/master0000664000000000000000000000035315172222611023347 0ustar 0000000000000000000000000000000000000000 b02e4e32de28c646ff70088515d84a5c5bb539c8 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/0000775000000000000000000000000015172222611023452 5ustar unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/artful0000664000000000000000000000035315172222611024673 0ustar 0000000000000000000000000000000000000000 87434be575ac61fd9adc14d77468ae7f8a4437ed Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/artful-devel0000664000000000000000000000035315172222611025770 0ustar 0000000000000000000000000000000000000000 87434be575ac61fd9adc14d77468ae7f8a4437ed Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/artful-proposed0000664000000000000000000000035315172222611026524 0ustar 0000000000000000000000000000000000000000 87434be575ac61fd9adc14d77468ae7f8a4437ed Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/bionic0000664000000000000000000000035315172222611024641 0ustar 0000000000000000000000000000000000000000 701dee94195a6a6b8c8dc4736c3a5fb12708f532 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/bionic-devel0000664000000000000000000000035315172222611025736 0ustar 0000000000000000000000000000000000000000 fdac6c1ba597c17bce992b5377e49e89c0b42e05 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/bionic-proposed0000664000000000000000000000035315172222611026472 0ustar 0000000000000000000000000000000000000000 fdac6c1ba597c17bce992b5377e49e89c0b42e05 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/bionic-updates0000664000000000000000000000035315172222611026304 0ustar 0000000000000000000000000000000000000000 fdac6c1ba597c17bce992b5377e49e89c0b42e05 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/cosmic0000664000000000000000000000035315172222611024653 0ustar 0000000000000000000000000000000000000000 a256b4651d4b7fb339efc899508b496fe8aa20b5 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/cosmic-devel0000664000000000000000000000035315172222611025750 0ustar 0000000000000000000000000000000000000000 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/cosmic-proposed0000664000000000000000000000035315172222611026504 0ustar 0000000000000000000000000000000000000000 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/cosmic-updates0000664000000000000000000000035315172222611026316 0ustar 0000000000000000000000000000000000000000 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/devel0000664000000000000000000000035315172222611024475 0ustar 0000000000000000000000000000000000000000 662fe0ab86b979fb022f4ebe98496c0305b082bc Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/disco0000664000000000000000000000035315172222611024477 0ustar 0000000000000000000000000000000000000000 059329a966e982c7fc0e29c5af6687203d6a5bf2 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/disco-devel0000664000000000000000000000035315172222611025574 0ustar 0000000000000000000000000000000000000000 059329a966e982c7fc0e29c5af6687203d6a5bf2 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/disco-proposed0000664000000000000000000000035315172222611026330 0ustar 0000000000000000000000000000000000000000 059329a966e982c7fc0e29c5af6687203d6a5bf2 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/eoan0000664000000000000000000000035315172222611024320 0ustar 0000000000000000000000000000000000000000 aa274a2ed2c2cc7476f50d58900689353523eb60 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/eoan-devel0000664000000000000000000000035315172222611025415 0ustar 0000000000000000000000000000000000000000 aa274a2ed2c2cc7476f50d58900689353523eb60 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/eoan-proposed0000664000000000000000000000035315172222611026151 0ustar 0000000000000000000000000000000000000000 aa274a2ed2c2cc7476f50d58900689353523eb60 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/focal0000664000000000000000000000035315172222611024462 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/focal-devel0000664000000000000000000000035315172222611025557 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/focal-proposed0000664000000000000000000000035315172222611026313 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/groovy0000664000000000000000000000035315172222611024723 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/groovy-devel0000664000000000000000000000035315172222611026020 0ustar 0000000000000000000000000000000000000000 708e3d30f27d850495e004fc0fbfa3c6752bbcdb Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/hirsute0000664000000000000000000000035315172222611025061 0ustar 0000000000000000000000000000000000000000 7c905087ef3826d312b5c9681b52693d08bf1546 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/hirsute-devel0000664000000000000000000000035315172222611026156 0ustar 0000000000000000000000000000000000000000 7c905087ef3826d312b5c9681b52693d08bf1546 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/hirsute-proposed0000664000000000000000000000035315172222611026712 0ustar 0000000000000000000000000000000000000000 7c905087ef3826d312b5c9681b52693d08bf1546 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/impish0000664000000000000000000000035315172222611024667 0ustar 0000000000000000000000000000000000000000 c30fdce9ca1bb8aae46ea53e7555123ea221c753 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/impish-devel0000664000000000000000000000035315172222611025764 0ustar 0000000000000000000000000000000000000000 c30fdce9ca1bb8aae46ea53e7555123ea221c753 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/impish-proposed0000664000000000000000000000035315172222611026520 0ustar 0000000000000000000000000000000000000000 c30fdce9ca1bb8aae46ea53e7555123ea221c753 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/jammy0000664000000000000000000000035315172222611024513 0ustar 0000000000000000000000000000000000000000 1d911e0b2c85298cdad43b5610282144c03b266f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/jammy-devel0000664000000000000000000000035315172222611025610 0ustar 0000000000000000000000000000000000000000 1d911e0b2c85298cdad43b5610282144c03b266f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/jammy-proposed0000664000000000000000000000035315172222611026344 0ustar 0000000000000000000000000000000000000000 1d911e0b2c85298cdad43b5610282144c03b266f Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/kinetic0000664000000000000000000000035315172222611025024 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/kinetic-devel0000664000000000000000000000035315172222611026121 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/kinetic-proposed0000664000000000000000000000035315172222611026655 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/lunar0000664000000000000000000000035315172222611024517 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/lunar-devel0000664000000000000000000000035315172222611025614 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/mantic0000664000000000000000000000035315172222611024651 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/mantic-devel0000664000000000000000000000035315172222611025746 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/noble0000664000000000000000000000035315172222611024475 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/noble-devel0000664000000000000000000000035315172222611025572 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/noble-proposed0000664000000000000000000000035315172222611026326 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/noble-updates0000664000000000000000000000035315172222611026140 0ustar 0000000000000000000000000000000000000000 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/oracular0000664000000000000000000000035315172222611025206 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/oracular-devel0000664000000000000000000000035315172222611026303 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/plucky0000664000000000000000000000035315172222611024705 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/plucky-devel0000664000000000000000000000035315172222611026002 0ustar 0000000000000000000000000000000000000000 bac95b8567cc9ac9d345fd46203ccadfe607f2f0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/questing0000664000000000000000000000035315172222611025235 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/questing-devel0000664000000000000000000000035315172222611026332 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/questing-proposed0000664000000000000000000000035315172222611027066 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/resolute0000664000000000000000000000035315172222611025240 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/resolute-devel0000664000000000000000000000035315172222611026335 0ustar 0000000000000000000000000000000000000000 4902530ad071fce5e14573d4ae8a07acc281863c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/trusty0000664000000000000000000000035315172222611024750 0ustar 0000000000000000000000000000000000000000 a65ef112964724e5b169d2c5dd29dbffa000b0cf Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/trusty-devel0000664000000000000000000000035315172222611026045 0ustar 0000000000000000000000000000000000000000 0534e8cf748ff159459f7d722eafabde575dea67 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/trusty-proposed0000664000000000000000000000035315172222611026601 0ustar 0000000000000000000000000000000000000000 0534e8cf748ff159459f7d722eafabde575dea67 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/trusty-security0000664000000000000000000000035315172222611026615 0ustar 0000000000000000000000000000000000000000 ff5c937499aa60b84af16c3fb74007eb1b31ac69 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/trusty-updates0000664000000000000000000000035315172222611026413 0ustar 0000000000000000000000000000000000000000 0534e8cf748ff159459f7d722eafabde575dea67 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/utopic0000664000000000000000000000035315172222611024701 0ustar 0000000000000000000000000000000000000000 6fca73822e5900b051be84fc6e231f73459bb0b7 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/utopic-devel0000664000000000000000000000035315172222611025776 0ustar 0000000000000000000000000000000000000000 33b24fedf01adbc16ff519aed5ede636f43c44e7 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/utopic-proposed0000664000000000000000000000035315172222611026532 0ustar 0000000000000000000000000000000000000000 33b24fedf01adbc16ff519aed5ede636f43c44e7 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/utopic-updates0000664000000000000000000000035315172222611026344 0ustar 0000000000000000000000000000000000000000 33b24fedf01adbc16ff519aed5ede636f43c44e7 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/vivid0000664000000000000000000000035315172222611024517 0ustar 0000000000000000000000000000000000000000 2ec8c6572be035c690a34bec0dc124fa6f122ec7 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/vivid-devel0000664000000000000000000000035315172222611025614 0ustar 0000000000000000000000000000000000000000 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/vivid-proposed0000664000000000000000000000035315172222611026350 0ustar 0000000000000000000000000000000000000000 3c4733f85bc83c90703f95faefef46ba3c451410 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/vivid-security0000664000000000000000000000035315172222611026364 0ustar 0000000000000000000000000000000000000000 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/vivid-updates0000664000000000000000000000035315172222611026162 0ustar 0000000000000000000000000000000000000000 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/wily0000664000000000000000000000035315172222611024362 0ustar 0000000000000000000000000000000000000000 6b036413a54a0265a561ec36065529786dca4b61 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/wily-devel0000664000000000000000000000035315172222611025457 0ustar 0000000000000000000000000000000000000000 d639ba4ec35d3fecaa1af51cc059d55832e70c1e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/wily-proposed0000664000000000000000000000035315172222611026213 0ustar 0000000000000000000000000000000000000000 d639ba4ec35d3fecaa1af51cc059d55832e70c1e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/wily-updates0000664000000000000000000000035315172222611026025 0ustar 0000000000000000000000000000000000000000 d639ba4ec35d3fecaa1af51cc059d55832e70c1e Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/xenial0000664000000000000000000000035315172222611024656 0ustar 0000000000000000000000000000000000000000 7a88377c31cdc83a3fdfa9378b305123ffd8d142 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/xenial-devel0000664000000000000000000000035315172222611025753 0ustar 0000000000000000000000000000000000000000 75edc6735ce0b8beef515a0a936560ca716d5133 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/xenial-proposed0000664000000000000000000000035315172222611026507 0ustar 0000000000000000000000000000000000000000 75edc6735ce0b8beef515a0a936560ca716d5133 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/xenial-updates0000664000000000000000000000035315172222611026321 0ustar 0000000000000000000000000000000000000000 75edc6735ce0b8beef515a0a936560ca716d5133 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/yakkety0000664000000000000000000000035315172222611025057 0ustar 0000000000000000000000000000000000000000 4592ae2d51c94d313ba225149e0700d627412b5c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/yakkety-devel0000664000000000000000000000035315172222611026154 0ustar 0000000000000000000000000000000000000000 4592ae2d51c94d313ba225149e0700d627412b5c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/yakkety-proposed0000664000000000000000000000035315172222611026710 0ustar 0000000000000000000000000000000000000000 4592ae2d51c94d313ba225149e0700d627412b5c Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/zesty0000664000000000000000000000035315172222611024554 0ustar 0000000000000000000000000000000000000000 aac80b647a63df9defb4cd2ca190bba29edeb7da Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/zesty-devel0000664000000000000000000000035315172222611025651 0ustar 0000000000000000000000000000000000000000 cabf6621a0835b22ba17b4627e761c1c01cadbf0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/zesty-proposed0000664000000000000000000000035315172222611026405 0ustar 0000000000000000000000000000000000000000 cabf6621a0835b22ba17b4627e761c1c01cadbf0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/logs/refs/remotes/unity7maintainers/ubuntu/zesty-updates0000664000000000000000000000035315172222611026217 0ustar 0000000000000000000000000000000000000000 cabf6621a0835b22ba17b4627e761c1c01cadbf0 Alessandro Astone 1785155597 +0200 fetch --append --no-auto-gc --no-write-commit-graph unity7maintainers: storing head unity-settings-daemon/.git/objects/0000775000000000000000000000000015172222611014506 5ustar unity-settings-daemon/.git/objects/info/0000775000000000000000000000000015172222611015441 5ustar unity-settings-daemon/.git/objects/pack/0000775000000000000000000000000015172222611015424 5ustar unity-settings-daemon/.git/objects/pack/pack-5ce4060d767fee0af12bbf440f06f6c278661f98.idx0000444000000000000000000025074415172222611024530 0ustar tOc /9GXdlz *8BMZbs{#)1<JSbmv$)7>Qmt +4@KX`n| $+:HU[cnz)7DO^gt}!-4=HS\fn} &3=FOXdq~   " / B I P X i u |  # 3 B Q ] l v    - 7 E K Y _ k { Stxfnv fK|*—- 3 "8ǂH[ܧs``sɎ3H+(vw"VI&;Wښ니e?o%V+D㬅w 7[DžxGpYlWo;W 0Lf+|5),ΰi,b~!"ڤGB2Zj3pєW CLɦ& ȴ! sZg R\!4M&$17bucf ,7`),9 }Ye9Z.bp&Ғaa),}< K=[9P`3# P.seI1 T7 :Rri*20l4nɨOit4ճ Io06~4ɴp݉/0EΡ]H?9/ʲ'$a_CpfU߆YR7 0Й#AwtMCCrEW D&r[*S~]4Q_\ sc 8Y1Mi*fv[qzAo0_fD _9bEE>I)l4CGo>5D 0, cCeuS3ã} iUNN167$k,&{ w;gqĦG'#.(Ki~Z:Uv.>L7Wmg:%ڢkN%KH:fb^BCBZ7RǘriMP j}V$1'se&7YneQ68Ԝ'wYJ̵ ̠yR"5<($ƽ67Y(q’ʢ -oʅj:JDfAvv|-ÓEXch*|;OMN![hT ֫׺ LMu:*bI*#mx*{z(l*+3xt?w񿮢XU<~l(< `EܯddkA hЛ{)OÚҙ)u}<4tYE}r.W]g82gf>TgkTf:`Vd~A-^okh$d}0S訨#uX&}0x%% L%ZyD'tPn|l(UK7xԷ̀LP渜{50)f)ůf =j[J9#{Ygg[%o~3GúlȾwSǷLW%/3-[3{P f ~]- 7f:%]Y4d.Zb8b cǍV%G$Hia`MH}D>XO 9!⬧na,v/m4H¾ P?Ar]  YAyIoZTG/5T2YGׇTD@΂ e)2s_b:N_,XS2N10Ƶ;DW:5fN?k|lVO,670Ǫ6h>HG?b( w.uAgRi"hsݪXt[B2Y|wM*w (c5{= Z eHY9n%zS<( (4:rht̒! [,3E2vbN N[{Lr,$x+q|I ck&ЗRmY)^bRa d|Wz~ ʏXe )[ӏ؉Y 瀎5>YmƧSiit ɴ~ufTz?( ׍xnA=r"<0„SQJ @"pkxsd 1A A) X6Xf4#S>$ %{g X,"AB?G I*G~1q O[lVetί4nͼ O120Ej S ǎ+xr~/$; [  :(%6 Pu23śD~:k6btpe"Zk 8}J^B\3+؜_<O!NG%,Us8%U I (_ hE#mk_fq+WD(eōrU' }c-̹{LEɌF.=-Niښ:-(cX2YМ$4eʹ $nUC·'1j?T(\42̒b X.u[7Adi$`w%h\J2>p;ȴʙLeRZaƣ(6bT=EƄ:]N%hc,^q5}x =2ZI waGI~0`#SO$V݁fVAdR-L2j>l2PbßڭՊ nÀU+dBa:g56 wT.7)Hb:2@ҘCKE$id)FM4Sڞ2~r-E1ҽۅ W'mPVfDdۺT礟x5UX;@)6527Ъ(D Ȣ8ZȅK,>,FM>ܣ>e R1ժ&Ȅ^<9eCWTAmN6H• Hs>W%9h%yC>Z@έ` 2eC j;h$qN 9ɛL1-] f@f|(iS?)kGJJ]'Gγ4xfe/2'>$뷧8#kowOY32p9'`9|R<>,0XgJ;nfWR$ў[h\&b&\b8ՓMZKt_7Z}C*>hJ6(yp.uY_zk+[TJ6jThP&MS"fj?yI6ЪDR*8邓Gx@`3Wۍ,A$ʆu@H VuٔO\W ,);V(!D;&oV842e+Hn)Y|" W?XS,Dg *dQ͋VFQK}%iդ@F̿|\Xt#$|A<ːZZ+ wߨ;nʲId|Dm^ yA QH|x |`K]dɚ] ZM|3IN" $*EFDj} [G $HI"e.xp'- ү/"oV1( "Ev;eNX 4.XSvpw򯙽 humRuOmX+ §Ifo5:! G{HBř'!2F ,z!G Iy]])!W)#!PԘEG Y^~!d!vum)ɽp]! D6Z&{ !ő{t%z/(]Fo#w3#C믢A\IK$&V)$uѴ`mcK$3faw 0$nW꣡;Q:5=$qV>K ɝaTW$T‚: [`ak&$H `s?$c[$ƾ _8 0_ {>$$[z:A7R;K$fi*2R$C$o6v Ê[% 3gm)U%18&[E6 L%c5z7MN5 %qyr/e5X&V"%zg]qs}K '5%Ap%8\%T`1r)|`N%\SzXd2O1%Y3躎NƮ2%'fEBk[Ah)-%4__[yGB& q=t^$S.QB&,"(njPWt&E~1wkuJR^&XpݩZ1y_<&suՖT+( #4&m?/ &$ZvA ޒ.mt&ty}`S<7&h)a':O t$X t'; ,0<3"Xz'U\yJ_nU2'.oC4y ɦG.'2rJ׉0t(+$':. #0VRѵ]'A**APoJӾ'G$je Iu'J:b^ "a']̹L!>4Ϻ/#_H'dbxr#ScIF']=8 mU'V8~!`߶ab'|g&u,D}i'+Zg1XBa/'k+@;\,2FOx'+_Hh12ӣ Jjc( EкD5~ [(%'M3OU?tS(6=@xv'NE(H:줒=ڡ<,D(y~Y7da*-e\(n$<'mab,+(?՚M9|Y$]q(6t^G$ t(߻öLY@4y~$(嗳"?].'(:׍ mF 6p)N~l)+} qMBӦ)$GoB# DyH)6XzAN6Y!)6G|Ex4XQТ)G"d1B!AP-rN 1)T έK݅l [uo)T~kq[wX)[](24>]%iW)wO)Fq5a)WJ')o Zn]ad:)oO}/Sz7˾dicNjmٷ5/\S--ZՠX7+/qtz?> Ng9y/r;b#'B$lEuT/Bf"]ؠF B)0fw&#MXA^0kI#W080sП"MK0~ L3Ơ&~r0g%*I^3tĭJ0bɩ ZDW0'Oߔ}@M2Y0//DI`wf.0/z/ *;Yh1=) bɏg1 ~EqGY 1,ļ/ؠ߈ƕ14ي_ϙ- 1V]Ha&ɩA;51}ǎ;:kĦ11~@T o5UeDR91ݘ>*:?c?1~Ye|er\ᰠ2 1Ҡzo$1[?\XE-Tr=t$2>"xQ!TEN2hYn7eO-S-Ak:2pEFoq_ 2xCO$ZjG2`.L{xS2X!Oʣ,8k 2 ";y6;%4l2 JIYr2 ~p"ٗ&3%8ee`3#2Ԣmbh(' u331": P#>373b`BTգ3?AAPI}y{n3JJ#C714<3YEAܾ3bƾ%V8c,aa3e.VƊONv:UR (@3|yakcPT3xQs t.R3Oo6N{T)^63.)oߪXF6IgU\aڅF*Kh1J6];l6U;ѕ0z6mB/4Űf~LLE6~5$k./[U2F^6,Hp份O@(6a}PMhy/'6jd ݵ[7"T%g+oUb#G|72@eܘ- ڹsq-,7<#EPԚ%L7S>Niʭ7U9{ 9UY1&ڦ7l((PmO7r"k/mB[#7!f5@b L7ă``@9#U:7sYs$ڋ7V\ n/7*;*7:Ã8\7z=+K/gLWo8g !$ׅ.&t8>:8mb#8U)90}x8l\u=Jr&CK8k^shZ>o99I:ijtYn/99nzrKE[q.6""B{|9qZe4 n-]9}%Y꨿МK9 HNX1 9P"(aN0f96àRQ9-aOB2}>JJ:*O)6 = V%j:2ZT07D^u]iGB:S}ؕ8Ijei.:Y'SWdwf:TT@N:h!SZn_>$:_`>:yDEa1t:ihL3,},i;\qxiuca0Qי2`; 'ld5>³`'u; 8 `]/5y;&SSuǯ:;M(,B;.QL׌rf<4 }>DFS-.7кuWWHgl>w z5,yJ*f> #tbe<f>_=/>$pBW NOCg>7)瀫P)f]ȔS>Xrty:㽈Pw>.6BFreSua>aH$MP?`y१W>Ua< 4g{:rw>ٚY mh>~\ ˉ*%5->HʘR g N0?韹2k擇?oY"B^K=0{Ȯ?V#T ;lCb4?h>_0ʫy YW?TB*򵷣!p!u? A7? (N? ;ZmQo?H×p v? M?uyM Z(?)fFV:? F?oܗ[k~^NAՎx?dgT8h?[S[)RP}Z?뷝 7 CƇT@NEz>G YvK)S@bSQLQhչr6c@3e4Xx=K@A|$n2d'ٯ@E/:L1 o@HH4j'%@`8;^xK@yzqӠb$*8oK@44R!'}@Ԃ*[LH/@ZҰ)ZHRkO;r}@66zz@ãʼnGrto*P@9raG/ŏO@3\@7^b @׼iD(3AKu/w+S٧A!_ߓV42XW~QAnjgLA3Έgp_Ay{N7(:츕ASd}R?BT tAgwĥh^.RA \PS%ڟA-H)afGAyK9IBN:qu2hЄB 2pX wjѿB4ll~3 w˘GB蝶_&hoW? ~ZB؆iy~~%ڒdBp X>bpC ":BŋJɛ$B"bK YTBܓem끆{bAq>B`0z4@NxM -BcKЋDoM,!" }BE)7 neC ȳf5Kb#}XkJChK k/VCN \9?3C7p*ɭzӷ/ChlЉ`D-ڠ[H;DD"V=.D dԚ} TcD,u r Б; lD6=Ͱ*5]|dZDB1"iIe7;Dg!|s{SHcZDj^ К1Dk0$|$}/Sz6Dn`F^1bN7 T>QDy' &2יDJCЯVR/{Dk5EH#9D`W.dBSx rڮD! \039|*ښEd Ctೂ6W򉫥#Ek!dpE-QM1;%'A+\E&&EaP EI4=iӂp]EְT@9v!E6Q!h|yŕEAKF>;XÕD7ÝgV|FACY Z{I)e]OFZv/c֧ a :(q^FZ1W`YU;mkF\ =>zC4FjTlq5#F{@ݯKs$F[ڡHF @vUOA:F-2ԡ(teF*IB*[չFqӷrj0_j^F_fG;A]6FrXY(o}8hwFҶ^~0]) j@F&'ypWӅF {+X {` G | zVCJG (lWKl E~G"Wxd wl_NG4Gm ."@G@4\]zl~<,hR/GFRB o-pU"T˟Gh8mDJ*q|è53SGj[6wT:,H'9NGlh HӲ?Gpv򿦑Q=9BoNGt[F+bbDZ" sG~ѿF G~[in]6YGgBZ$-BvY"BGT/z'/s2rGdMIKE{W.ugGr4I+l}?$2/G% Oc2UGgWQ1/GsO-m.B^G- D!GwK%C@GJ w[a(G۟ОƑ~<ɲ+VGނbI`ɞAk,XG6lٺ`qnxq0,DG~OgNsЦTKoGy^൥E:Q!X?HuIZ.*iaٚ&yHS8T 7nNդxH_ŋsӿII,.Hc"@>. v@HA~'u';?HYQI{d4QOH&Zmx>?eI 7 96WsҏEIS qEsԮsIbO& e`n8fI#:GiWY@I#9BfDXDJ|Ic ÆV7x8JeJ%0? AhtN"JJ%d:sڢ;VJb ,'e 2I!]Jr(H5P>JLk`C(RIW0fJa=\ckz!6O(IJ)RmGkꉮ_M:JraWr?ÐJfi>-ϩ|SpK$E99)0ϖ KI4>-iUKbe%c LmAKhIڔeB`hK]Bn`K֒IKH' (6NK5eg1ħ~߮kyuJtKD}zp5ML: hv4/ЩXQ`Lz%  l&wbL3\Pf҇FM#ۄi<'(yL: `M>Hf[s _vfMmhڣr+xtXtBMf.q|FMGseNBYMh5]%?H"قMHBۨVB3T4MDn!3mN)oȂس#%.NT}|ҧi#ދ\fN?~ (c!<<,NH%] $v!#bNJr07S J!T!,NL@k|/67VNfVv{O3X<0w0$N`4fs{NJp)TXmxX J[NCǍud;j87vLNPP=΁Q6 N=$:PwpO. Tp@O F9"ÅTʻO 7",<:*O SyN$kfޤkOhQtu!SO&J:& znnQORAkICb,^8eX#Oi{<`67F3O|VMfT/)oOBOvkՙLMG7Ps0THN0 YP J1 )ޱP$ѰDr9$PBcioW6tIP_%44;=>vz7ѰPn IL)$yC&he#P|Pnf牵Ǫ^dLPpxM݂^*rŊ(sPq{atSƈE,xPiF+x?FQ Y@D/QCzfh*بԸ|W QE܈G MZ6+)= Q^}`8zuRgQs_oAX|6cxQJϡP_QˆfD݉tG9XQAW"f _e`Qw͆ӊ&?R*JJ QPZfbR4W!2\RNoq܏qT:TRzD'r uwtWR4j2DfIt26#Rޟ= * N۳ORj`v`"q%kRtFy)BѼB[VR3qI)=h@RRXbJEUȎZ1oRqz546Ut^kmSk#y ai `SWyS ڈ@Z}Q S/2'uW17So$RG[}~ S|NcSF]CKW\#>8jY]F=NTH6x7ejgNZ?T`|Ex>lΎ^Td5Jw ݛTU7-dKT/ ]ef)GT]y,x#TĎgc S Uѥ>oݺ;XAP4U@:WŇGeAѫV C|% YQZ`VDl,4V⥄ lV-sDL?iWVCU9<FypVSQ[kCa&! VVs`%$%/V|dEtz,nVq٭DSx=j=Vb,&YR]:dsBp.4zY:Є P~ݸYnEpttIcY}tsúfz4EY𨼙XwUQIYd]{I /Z 43jpZ<<EOs];ZN濭 ,ӪލZ%is- 3ZOܓ DCq"KzZ@9>ǀF0OZiZʾ \KfWZ݇hwmMN\R<g\(}2vNC)9^2]ͺu9nY.gs/)]8t1(^ qd*;r+^i< ~k9ڒt^4%-k{Xn^6ҐՖ,|*y/!^QyKUʊ^ce+fZ쿠%^wq7{q2ɝHr+ ^H7*%A@#^)WWOZӁagB*~)`al:Q3e aHSXcg&8XKa9;E| er(3aÓ1Do~4{arpˁs46aFu_`T@cZb0TtҢq(%88b1310c/pxb&3E_MrbϤse,cibޡT\;b/~`SlRZb2 ļiπ)Gb;bX4! oګpbLsXӫ҃ |FtbLʽ<WrT]biϞd^42byfMIt9[f7b}űij"+lbqghqײMbMӁ|>G3-berQ8O.{b=rnQ *)\bWI}l&kk7\鯷#bꭆGlDM%|?bָ1-'BYw*cF uu@hcSӏU_nfV;0c[1[h#s8(cv.馜2R^@?-*cᙓŌ Wcw6?QKW~dclZo őd+? xTS,)dXerx\$doG،Y%$DdzA&&pW#ƒd[T`=..8ב]dt3'hVρd}K^Yfd.)o&+3ܓ7dtLsQ Xdܪ)Z%fn5*HJ2dg ܗ*g$55N?tLg))2,BuOm\Yg.:\:dTzggcf@%AM$gP)9!FݜNg(*)!0{~gZ-N k}􉵺ghp⒁yݿJZg} 9K9g?|%0xj~<* YgyyaFAbGOvCg~-SPlugےzlC&eg<#,(vRٔ,iBg{{{@Q6gmK5_7ZJ]3&gk՝d37X \lg_`|4:HfhpFg4Pcp%gp έg9)h"` -PbG+~+Jh#_GE0?(kh&`O5ͪzy y&h1nJ+;>a#h8Ld'KLFNhBJU{jsd 0hNEʰyfM`zC4hy 4"wh+0Ct1hP .H`H;Eh:lL垥h݄NH:4Y͝i)R+S:TXh]Mzi;Eo{MiL$Ih:&J'l,piU`*MaB z&m9Vi]V~N:,Jn8LijEk*>lY(iu Yy*H9wIii| wϾ[itSst"6iO:̷-\Y,-ic| CI@iEل4qZc]&i !NQ!`ikɒ(FL6rG4oUj2s[PL8@j eVhNB \amj;UȱUAcctKqjb\:FNm*yr_jhc2p \Esjsq H_j{DKo1*^TQa_jgϹ}O<nkdJea6U)xmKako\pl*ؙ4skE{^Wb# ]la?e3PY{llehdS'N'0u礭k/znȄz}TI9^;{Qf]nN>cnr&:EDn񡐖&8nԠ&Ϙjdo us~q}oQa*wDM- '"oeG3NbvO}#QooVNW^o@0yLgf Duop_<(c?obN8#v9`)oPKzȖ*boj* =eyo#ͽG,oߕ Ww(5Eos.YQn#sEo<!8ߢvox@e%>6lo}Be 00)Гmp,N_{8FMpn˹^_$-p Պ`# -n*!/kBpr P! I$hpZjksl:_'2p=0}u+p)+H/۪yԑpU -qP!RF#pe1210$p5+EW׬v-lphTIW|<99np+q=7/pGzMy &qp2);X=gۛq56T*wَPoq/~!Bm7 9qp=aJ@FPi{zr!qh(JhqP~uq?}٥әr$9u #T*(8Mr+Yu(&odOCBfr;.a [~V,r@g!N=W-ԅr8PIzV"_frunX ~fZCirF]yKb][H]sry hTUvs;()1h  `@ lPs@oYnD!_ x07sAN|,A|astM9S TER>s*ǔ,Lsn ~4X7s[ŻHBm desP6% PWnl$_sb<%c6ڧpfkgt89@[b(=ާ nt<>mM)0wd=>t>pFڢrbIt\Q#mV&tgi?sQ РZ=t||^baߘltFH+fA t}/oԌdt19x)VǑmS>OtřvқޛtAݽF#M䜪B`tKmv]jWu QF?9?J ujVDu h}_E["J1|t[luX%ә%Gn;ht;wZu`u㸦9tunad&ɥ`_p~$uw/N3_+_Eа:Du,;gtYYb~ d]uZŒ5 JOkP3us\฾QZ e`qmQ3vOu6D”*CvZÜuH8ػYJ"vhC .?3ߔ.\vo8' i5&ĸ vzcԴT``vjV= ͏v~vΝt*hCyѵ vzG& DLvF$"jU jGÍv 'aU̖`Kvy[]Ju#^q>kwvj ! wDcG9Qρu_ePw'Gh5i2"wGlj`2> [wH DYv8v͎wH#RO]SNwOArbL%f_oL>+ fwe:"*!B &wiOq>7G" wq'6%kNO`wVz]G)C\Vzufw%t&85?wyFyC,nj6#wm6 cb̸ΣwGLyBZDOd-PqwUx0nE whPvտO$ދxt6[%:"AxQIQ-aX2x#%8mbM%SEx0F݌V7Zxg{bs^eL+3xvbyIA{x|hջ)RxĹFx㹦 jU11x{Exưo%Zt,y&Er*hy'8O-%y-EJr1ZOfy8B$xj8T 6n>|y>3O-yC[yBԮQ߭k= LVyL0nb&(@fy mO\T.ƀQyc`Ͽm)neyؘ?*:';/I+(yNgia}}_~cNz!hiDE"PWUs[zSqjg3Y9=esG~wzYޕweY^zgwho_g;'fzmb a P(|Sqlzw3l_YzwZyWw߇蕈IMz|tQLC_4DoU2NzDp;B{4j{<-Oz7|1:?ߩ70Q#Bz2Y~$ꋚ$ zxODzqK-o0'z6W;AD,"9{ ټ/{6)P0{j/lw2jh ]{H%3e?2¾{(oF& 5cO'{+u$@U?OD֗{2cs| t$=e{> \j0Ip ^ {[Rgs$= %5{`8Cb$3{m2TA U{N1{a 4| uBH U 0WL|$8/y*?EzipXt|P9(^bm2W;|W:{}x-ق|k+G-äre|P8&hRi=F|m@x"8Q<o|AWz{O#'mPy} < '͙EnI_%}~`Vo*KN}:ٔB:}vM])jXZl; }bީ#[0i'}2;֍=Vjܱ~es?r"'Z~}'7.ng~Gh׏15!#"E~Hb8xȐ-\_yB<~P4[^s>'Q~_1N43$1~r9r6}Xc8V~qI^{MIfe~rfk:&ݽӾ~uh낾ȎՃ~^+UW@ܩb)n"Y𣬄}uD\YBN;q'%ava >\22X9a~Yqjk'5bV!Ǯt&ո4#HH'qk [} { `t%VWL;qgYDjZ'B |ؗL( ,0Մ(d+?R*q[PXFuM"Cװ,lk%<hڠn>Cs;C qE|hv2>\ltf].3.;mb]:zêpFj99gcL R})"N5`x-kѶ6%X{O!r,ݳ=AU=(@aQe[/P=zNgvagb ӻ[ 9!"WX/_(! f葺p[ڥ @"D;aІ|X,Tk IG%uy l7T"~c"{?q$&_15هo\7O`mzqR N-,BFg)禃_a $c)ҵo INn4&: :-&%L߶;1`x-9Mσ}}L=̃9#zWA8g-vƟl#˜(Ʉ?M!j˱,ruYP`YHiPEw4ԝVSj@k*MG4/Up@ބ}uҀaйjDž ل|#|f"F62B2ң]F?{Ξ *`YVZLCeaI;,XĽiZn/ء^̄CA ?9 <Z~%<yHY 3u Q7`Y|_XKCK籅Xo3!YBg/ U'Aiz-=o{@:{yf '"j%Ab8䅙#PNaD/օ01g[iknLfzp#4OI{ȳ+))B&jw(XʲnGoϝWyj6Eo\Z1#cx(vmrҜ7׼!1{]l0zvd ܅7"*b:r=~}5*RhKA] q v4XY:g_q(3lX8E~bJ4{zsljp-#X )5%ue}5zu $Ʃ@ǗWh<&rRfaǟYXghR ;V̤ H50Aevo<"_nQRc ?fCKuathD7KT?T_hk<33Z(u@ f }Km%#|5Q춇j1O 8 cׇ%3T8Fɮ*pSOW+!w^߯5 `!w9{3I싿-Hu )RDxoDDc^X#Έ %Yng\h7X63 teP!چuk6IC Qڍ}QE|=B9=Qu:dj?_巇(шO}$RqIN%^6OQ yH0~bp~W kz+OHhRf2։3Hz|y;b~2~}_49_Úvqnf\'҉IZ/-+HV @XFj#""d|X?Y-_j%#qDC_ꆁ0r8d, AnQnzEe|I(Qۺ>>PȟO ey Ӊwm'Tr9h26/?[v߬j&WSk ,ZT>"[HRE@hMp#vj{#LI aO Q?%,|=:>nɢzҢZܜQ姊ʚ@{$T"Ϲ,AjhdMnrF+(qݸ#‹k pƕІULGtFD?pDx>~YIʗ$1E&޳vi&HaB.hDff9l˭x25F$+]zANHpd֋ WB@v!8|fZ c4騹|BN2pgEu f㻌Q!|ԁC|eXvu zJjSM|,X&v^\SN֙T(u rDv|ӽyωH6} ~[<]cg)Wl`-"UP?H8$,j>/:E 1H耋tAU=p0u\@rC00L 5˳R"j,o ""sP[/8| FWoJ "ah5:{w+ fGtzI8nsRnВD~ F7AP /ҸPTҕA|Bz21/ĆV0ˑ뽰/ "m q *Tk; 4'S\hLklhlyLv;ba^wۥn( 4A56f}Ո锕ώ|MRFbR J\$6Zu|DOUVNUr.yĤ1mh Sٔ!iX=wϴ)hD/wďX &}w8<^3zD!uǑMs QKx>Ε:NHdü|x.FlG]ȑ2DEq%&F)~ο:[SOO-]L]*G:7&CDld_gn/=qFʚz=(-AcpvήZ_Z B9V̒NFbRX$YVIА yC*M w"ʐ BaS gn&>#{k_ ԉzHА&ա$8$++}8LnD.$zCύ"\/T{WXz +Tol^PV s^0y/Hn93ϼ8VFաqLs}PO75rM5nMA#ʨ/JNE gU5z7O۠Q6ۊsST!ovl&#`EW/R  .GБDцQ,O_'& w|$C PYvLX$r%˻!&lw&mɌk6vXّ;=AK?jh-X%K(NfK[-&eLDeE3pDŏSW\\TX܎'}s37]a5)hMkٿ6>Myy0ߣۻ$˒JN&L?2 -W|ؚC!* rXֳt3A VI?^e4t UR>a@XY󧥁\;?Wb$(NOXmnț ]\)K iyzNMB}7ן㒏۶H|lr7 PbO`q`o(\@(EĕBB =*a@[0A7nbM Β+;3@ٶ%쀣Q Xy[bk#3]6x/+5GS*(e@Rq7-}7=7H˔EOQ~s6PЯYEu l_hΉ,TZ Rtkp/2؏~k)-OWmo"KPOli)%^# *pA!,x%<ғr} ӗ"&2 \œp-cFY蓥0TGKCoaWAմMvͧFX!vL EMp5JӔ<풬lM_=|CDxAcX #櫔Q~_D(K ax9u] 5x*9]z ->3 n|[ȥYmܘQҋsctHyu`4z nprA GʵI.@t3,Xq_mԒ̚j>|hM,íckQZwA/#Qm^.v7 LCL\l`N9]:.$Px33&qz+:s)^˂H'7\-_wF]0XhH3H{K7q1iT0ſ~N4j VS aRDfç_3 x_l#^0qzxI|vi9Ռ84Gz|%5ڛlTnPv){OXV>eCɫX贉"{}ty[":I2~Nx|+-+Fl([UqXQj?%jEBX.j="GlZ*{QGكh|k E#]k\ L 5ay1*՛J,Gqo,J*s2z!ϐ&`S֜gڌE2.9&3bF:o/n[៩_S9f—?4sPc>Ezs,MoR[X"[1aZ>b(QgHCy״fSE(RDiJX3zH9,Hݜmlp&VU 8oaG1Ag#t~*xSМsStRge@-(|* Νxy8fƌ92T̝])қ­4IrPxfpw0 w`1O&ϱT>7Py|? pntiҴHNh|շz4uӇQ_^=8*5(mB}/v$nF&Ijc

T쥤A$a d3m4>{wW#bRF^"s9]!tuT4żaGҊO~zz$Nubv?_[|Thb ]mdNsuhtKv(iw#c/qfQ$C$uc;EՖSQdQTKjUҹgcNS6ѥ* HuUwQ\Vuf|d'vuĀqD k=\yOri{+'ѧ3@үa-ֱmLT$bi?2Ig"e,Ycj>0qcz!5Ÿՠ<1hƥj{*Ȭ2Bw|$'322*#׋1C5t TRՌ$\<~"d3_5`fh6f䱦hIfg ֞ Fn:b6`zp VuJ'JV=<ʡ` R俆.' ;3WBQo۸ |9K1 ۡޭbGʓޚy>ħpmv\Ԅ;VeK9șPIo cK`w%hڵ]>if^ch ˆl>0݌nϜtT|RO8rc@ʴluA!?]3/ w d+=>tTϒ_)a5]ף2gF폈>BR/|!4c,*.MrݩṆ[n`R;oZmжEHE$zK֚yWbm~&< :|@BssyVQ?B oGL/m)wrk>]ҟ& e\̚`#au,ǂigl^_s!6Vw ;cT~g06 Tu81 $d{71KQzJiN+$VTs/a[s,#HRzlf_NIX+[箺(lW(/C49j B_Ô=|K(o@j%u(g@0m?_[Uå'%wi1l@ҥ0NzX31zq 2e_O<;jl@ h@;8Pe?7 3Rոv\dXէ& 񡝚>DA1jlh;(ҩI %=Ƭ]*(E›XbgqBe>x ml̬Q̪uQ#l2ߧo+t&;e/RZM7=ȡs*ǓjnG #-z*ŧ+f%kyPL}kQ^T'S\NjFlj]QGWiXѦsj2\k,m0^G]}%5#=*o/^ӑ𝋥AY୶3F٦m vW<2eX5?%h*f=,QQ1 NuhEÈ"O c֥I[߸WxMƣg{3n].Q\\AGv5o44QGy2!ǁ{n2J&*"6Fڝ3Ш:Sk!Jı?q6sbVjuiAٿ(L"eHH$fF9̞JH'GaVb1lTgZfH^0w [(~o2V0`I6>q/!< .NlȨ/ex˿` {Qg:7OAmz R}9Rk=1ĩR%w< ,(&%@w`nߩé)+ޝ8 !l_YY-SЄ"Y8 ]a2bhFxvjl6¶O#7J.hZ^WY0n<ة2u8h|; 4;l)sp75n G2lKoW_!HJQ-l{SPI'J.tv X55#`1ț0`ӔҪ3ETcꛮWjj *р4{KD3*RRV?la 6]b+0`XfW`ߘB"k dzcߝ,޷ڪ FW9k-#(ˌYvY1g" ֏RJh).SD@3-ߩ}W-@vK9 (lKKeʏ`Paf.}?@6(tXП !?dN}8UԷcCE=k( 6d[N~LPV*BWl׻*NGdp֏M\OjlߞA/dl2N\3kA^>F 4MzW;mS-"'{!ka1lm2NqIG[dhdҰq cR$D+kAnu;P1AA$t#Ѹ]r`-ikpc/9 &Ē yt0fɈOu)T^U[O.b4yZNUuL1B,ɬSj4M$2p%75SooVZ$ԍ"#/ =6XK训lzk-iz4n~R] TQ'Q$^BIN瘧aK2S bjteN^şF'y"!BRh˭EQET/HŬ➮"O]1-f)[AjrI52q\.O|p Yj$M^Vd*Ul&4D 4-^ZV*®7v w)ziI|_Wλl}7)6=yCj]p['<Λw,RW74uh&N["[Uy@hf,'C ԯmFUt(;|Revuu)a:-Z话/RF8>уSJHeNQiHSX'C{ J1w˅hŤl[rag XPɅ^铍.wN;n9\K;w(GX':Bi{R-EA}Y':3" our'~PâΦ$@U QZ()^L6KDձ-0d˺ځ"/V :FIEpy~ZGxíW/uNC;Q*rPGחŖ`9~0+i:(L99wz6gfbFĄO7HtM+[^c~*s_)Gbhc~)k픱ro)NB=Czvڲ)n|yb\AO DCV쭵I1!*y/oʱz sf-x17{Ʉ?zD m_-g[H xcXzN@ x eN)y `-sƽܨFc(25H_t,Дi:ypVB\@ ^O?*zTR$ԗ[3ba~CK/{ZN4tч1ؗ%,B6e8m^Ua7#/]sHD:%,?Dm"o; @ދkIrSJMݳҎKnw'`2i^/dVo)Y4\@ B(}:39O"Χma牎j6&AS7ȞNs6S#1F/4^X{8Cy}23=}7`c/zXw +OQcҵ0*e:!Adm߰OBt!%8chRC2{rfȜail/'m_5A%FG뒼1*>Ѷ%eN`br})SR/.͝e,a7.8xiwQFhY ȤSU#I;!KxW0jj0nrCv X"|^@,ƥQe'7~gCZoyrWҎ-&=R0 FR@\xA&kT-{}>\uqXaPg dOi&V:%%u3Ý 돎훷3sؿkN{8+#v\ֱcrz;+GK˃|yArU=dlC{Y|=o= W~:g:'J+v;tdZ%4aO8p׸Aթi ǸFC`CøFYKtx.iɸR7 &hbXUw#I<U)43b2|lb9~ 6$r\xlEkܠz Dܳ H!Jq[3S#ˆ1g3=]y?͸]8cE\lj4(7#HY6akke[C֚fe qq:2~69ioJ|qn[ ^L%lVP;nqPŚה~Brblϡ13Grp\w~bvL/ @u'Wʹ~^F3χE*~"W{Y?1^/gJt=*޳p3L) H51cc1{|L~[]Őp\΍ڼb@¿3:Йj '_M4+ \M=߽.7pG>mԽMGv2'@T웽fm/p kQy.J)#';qCluU z2cP/1N1(HL)+7hφϧ.ζ)MCEr\yC؏vBFn'A[IbqO8XϑnL#YcF'ݼ%S]|/\ iXs}k56#P@H1 5cM-,!| 6 =kAม7qh  c,= Bжt^ MB6k:nXC N pH:V&k6e`E"3~ml'+J-J \ jg iOg䏷C9F.35֔S79HZiLNʉp7][Lر\moNlkֻаDX.ߎ lh;r\G49Ub!H,T(ſl;ko]*t_/ƜTgUm)0) ,McWQ8t\Guu:Lg۲8dB@(2ϦH՘/Ey송E oz;vo,O<2m&$^أ3ikXh]pUjR{>"qKN~tF;S^\.q]{aDY=n@/S/G? ҡdE ԥ]C5ҞD gn3s]2*̛ 6E+ BLJڨZ .eM}G$*@ pʜSt0~ I%~[Z3=vmc ibIgf{MuDJծ43M_cQuϗ|N|/{`ގM9&`0 B99TZǻ:i%uU>!S'1C6ЋE<-<Ҥ1HvM!ѹ|X2OROi;~&;ɺEWz?y'PD6\$Wwêfq76mYդfH !IǠ4Z%Iפ* ,Y2m7#Qdra͐.{ ^ SAQ(?vW &oq;Z+Ȭ# T 9'W vqxZ"]'5vgDN:.0;ol?jcqDFEJn|[Dr `Ts)TiQn,%l_VEĄm SD'GĕX-MWsr]MĨj/-xѿϫU Vyyb|J(C'Jk+*0*~ͯ֒z8z]ABTR9n^޳W9 IڹV=DȠ0s=șZȥf,6 Zu|Ȩ# V6T;;fȫ>gM)P,1vӪxעg2L5q Mp0Hʱª'!,T0Z7렽8kLPWOBwXWZ5fA#gނa!8 K-sGd]*aHֳq.B"Jd]uY7UdtGRt1eJκ S`HaǪkDx{Q?gn|ymx\osNQ] 68b*ɎFV:?f((ɛ_(<5OT:s[ɸڎ܂0 *_?n߾qUbM#N]g2|bա4KTue"Q>l36$\xE?aՌ{H%rYFoO1%Y8A+,2wcz@`|RD=u`戼~~UHzjrW읺i|sQ'-c%Oʕ;9d?ʴуq:ܭ<]ʿf!["b~v`/ Pk&&` =0ed!Iݩ$LoZx;5CBZcuQy:W,˘NrNJc˝8*oNBr 79%˟r\@T=PU;o˫|6B֖1$,˷m4d Q,9ѥiט=",maە[/0{&TůG4*ǻ}tXv̐lj>RQcvJcHM"Ou:i .P.as;v⊤q%9KJĩ":zo6/W"=3-í8gA{.t]"ǁ\͘5Td4r͞NsU>:"X=wZLͥ>C۠Nuŗͱvn_>'3h|aЁRY2>UXD]]Oa7 o!%4Ƨ1"-ǙT0 iXLCb[Y;x)(X͙lCO!Sv8Q J2L1K˯%|EMs~ǩl? (mi'vGE~%APtw\e^]']|!3 L*GlrCD,olR8jܞ|a~^E!,9J0goNh[!'0dn{؈"ճzlL; _moZ/r2h;ym' h.ia+1 eO'Pʯ!h.ς! ^ O\z\ςBō #ӚyC̘ϔ=Xe:c/ޛއϠ vϤ{eP㊮)ϪuH|U:ȧ6P_M@kW[U&Wl~hy#%2j o-+M6 bRof̩kVΜM:wb9.3'%C@az4h'E:~b`b$&w$rH I#cˡ1Tg0H.`e}isPU(C?I]wݕSM\#rf`fuyЀ,%-{O[4z KKз9E[Po~\(r~\+eص>[`te4Оf3=,g\C=`^Yݻ^ͱ~Ev7&q+]j8&%sAiY,ޔNH'g{ժdsQLYz_ltyƾ{(aa'pOvd|KR0g>BZJƼя6c0DljnѸݎTW^8⫇$W&6ގpxG L.Hz>ytmH$7jz% :oYQfҽP/:Z}z*3+qʫΚkN;r o X])1Ff$̐{Xθ.`@xV&W$?EMNKHpQF;{lf@8 U g)aDq3&wӂ~u۟~ђ21 88->()vBM];+f_鸂rk@-Tl3 Ti<I*Fc~ݩ75|zq#ѳY("~Q^Ԭ8z<Z&<H7wpKGh3f0݈Wy1<k IX&` Sqcˀof{aQO3&aǐݜmڬ9ޛ(M2ߌj3;ER6q-ӉYnd蓍iq!&qxXYQmP8t,|R᫳n'@.}a"fM|GyҢU$(!9ɛu&ڣ&e##CK18ک|Yyt-yNu!9N]?YX2 sa8:z>Dt! \N֒,+o\Sn֓++B7} U,{֠FNiL4M=jF4 *N:-kl;gEZz˳y׿o6{ԄUlj[F3jh 3s` :@o;գr 0k}ڈ{8grӘ`Q\ *d+DS]3#`q$BXs3iM{4DxRQ#u>y^pQXV*@IWg9LAO) aA|؉)gVLR*eؖ($Ra6M\>ՑnطMh)Anb3^c}"ظ_N#,r*5Kc Vn:DqRK IדOM!@KesG0)ʄh)*R5Q|8-/UuP-lM=Y+[lTDd\xQ0M\fkb)F2}05پ{xܜ^ܩ'I{fٗ< OH]/ß$(2֎)B*-́wʎK~rdWU\3vDr,j\lEu~9֚>pGwnM^:sC]5;Yړ ΏSnY`ݒ8H=YdDcQqO#Ձl?ڥ.}UА21ڭ,OI\گJނ4V+fנ][m.lTmxe3?Eף 1PP@<4wX]G 7!Jqj;Zc2Mݓy#Z1Yٖ<'q7dqb;x2Bpo(J:QNߏKH.ڛyw[-_=wYǣg~ܛ 8XT/)hcu6<#Voˆ$v'BB9KIC\]B;tQ)쁥snMFc13\cH*J7W5i̟Wf]&ZBD'XA)E8ʮ.'gܚd ?>B͙jh<SEP8UOv7 =n\~,zb׀&܇g蔖18 5ByTvܝ0I+k'ۦXԌP(6o2~VՓ!AD޸瘿v%/zz}_!#2r{~Yo"Uw4ugAjtSW4g @>=Y 0Jo߭ cI1IF;>Nc/@9L1:$ZV2TpP9Y]g`:dvS!jΛ80ROjTE HaUZdos[32"[)j56 ݑ?ۂ؂I7w-JV%*,rGi00H̭KA-"6OC&b ]@HR6ZA/ d߬COBO!5e ɕ7c)XBw˹ VGN@ߔZm@2v/P@a>D"3Ok\rJ0$$7`]b&HlBWi|Q\z`DhΔ*N*GfD)zd%t]5ޝt&[69)KD? [ʹ[eEgd߯otMbZob_Z;P'ysEVa記O9Dޭӊ-זМ+vP_!!YT :T*uSH$Q@z' u-Ac)TH56~l .^?z@d vN^amE{>~Ioo_6)0V_ݨu#ZWU/i05?Xv:\!LIetSpW~qQqeRe&ߜ}HjKWo$ߟ (\%_R\`;T߽eS 5ҭ-{ bqX'nZbتXJb$*qh kN;eq13y/!nC`d/ ʶIVa' yz醁_]Owd`Px#!v6M]o0 T7o9vA(X%!/vlKstcES%IیXߧ(XwE}o0T @7\_?oX@dϡn(P񞿗?nQ-:gzӁe)wrBi62^ lII*wsm~;K ,ύOa]u| ]8]}2^>~Z0ަAnְg s@'@:}׺}dVC(vw /gg8!ͮ3 -~NK1'v]KM)->w TEY Н] )$I3)$+/ \[,’Fc zvފjQHPT?r 1H S,1?ABa+ UwZ*h7&Kr'$Kn] ObAePJo/[2MVhVɶ!oG%7ǕJVG㎉}*UҴʌ¯R) >,bdS "? K@:AoRmRG0D LgT$gDz זjF rk.A4dE>G~pB=%7Ntxى?tږC=6PL֝7a m~9EWf{42 / ){4\> U8*4^el=ε%l824*}N>VFp?Tf2QŘpٿƴ  +mP襔a-=x|7^|LL[>\IP W`y8來o1DyLENw.u,hHݪ(:Q(R(6ghXW4-4`} 6~1Y0_nl!"3E`X囊,Nu ]KOh4s^㸙`~wN}o?N3~vc* +*_Lq%ճȃF#nLaմ;{ď;AI϶T ԃErߍeiXA}}C| c-So@\WJ/EUa֊꣌`N:KZYYJ_K ۃ0gI}$[c!P p(ziayCbi?F8ٓتfL\RcX FZڶ3jZ[)LE~,HisһlrkP7`]c7Iz?1 ('=[SfO(0’vx#=bZXvN>wO n\У/i \1ZXwq +넮7b0@5ڦ :֫S+PHyq;?f_Ə2gbMί #oQ):eʍ;ZKq@hp !Ӈ]Ϧy7Ox_X%8Q`XD/wCRDf X8VK>Yϳu2Y_*S\yltG:ط|z\:wwg^ޑJL:*cQDHk`WcU4@n`c~U Vt@bv L@4Wt!!ua5tޠ9R|УtuNʤmsX}좜xM!l(TRJ^hU3EYS|.F\ lʡp{!zHLo~a+1.HfHa!xqJA8Ln8C4ׯe.|=72n:x49f%N`ơ$:#S{@Wχ#ESAu~sTF6 S[ӴQŀT&cL˜O*r17oxfhecoIgyB`ԫH-\dWvC4(<Sl9\ɩKac{OzH̞-\[ tl`u޻|NSWT٣̣_]T彩\GG\泗0 kӐm]K" hO5{auڼܴ=s8Cw.e[Čv݉KuwV^bb? SY0 jMdWHg[tiC+ !}#0YO\洆z=J2^#-ML_䏛~tan}ۛ\ڡv_gAuTn9<vhLfdkJ&2 nɄl>''KeF"% k| 8;zo lα:GšZLt;J5C*ß!о*#$&3(mdunl }[E-+U胛ywY V7щ#u&Va8j_->4uU%kV˖&2=zݪU,d>db;R*ve]YK#I7P`"`C\bkrbt4_(O Fdj:'UK!ԟLjm#|9NN K4Ng_^O;omvX?rUVf謑;DT[}SP:$%IZgZX_ ˩Owo+rvEs*2u`p@=XDvsbGvhvÔ%=k'X-% \opaIz%7ޅ@"dK?_"}|d ͒n RJ\s=nPaexMbMd?`sWpdܞ@W$]K-q"a3&!xSHv݌=3 Z3<8|ZB`QtEazvb^ 2l%SեߊWHƦyZՄVb2  5OUx{dQ[&~&c4w+P]z\BaR 3L+^QYuYC3!\ۮ?d ''X mV[=ĭiI!YPsg՟F _c%@sȏM(hg)O5YmJ z  Rpx&J:7?;,|DJC~o1S@o8*iyt{(|vU@[ly?,VTPKE_U!6 [U%)YB-_R3Do1՝{ˋ B=)b4$ 7bI D2wpVUyva:d!YEo {AKAb> wZϚaNkg3&/ס:A.;0+oWVj5r5ζ-k8o5uMq|ƥۃ*:pKfyIGJu,DH ]^zPn)m U uV6/k,Oue= AA#*@18\0nۊjIirm=/$Rwƭ'Ay?dtj. YW֣6]S{ 4#.1ޤ-3 v{MO;쾃rg] tiRЈ<@][ U /u `[!h!Y[Ro 𹄘oDuSWi,d;8Όab?}< w5̙w#A`X_~a\!J `I>ՖBoء[<@d GC'/Oֻ|> IMyܗ/}:++ 4QZS'BEzfu^);MDt9"(XdBlUN`/Z@7J4&z{B:: ZP~+W2G^CK4_ _e?t{2eem'mZ7fS;+9 5ƌ g5š4pѧƂv! xNԾwHDqFzq~Yޖq_F/I{`00B.hb&HH$F˖-&2Owrk/e\[vW~xW@hUt'El éJrN:{F*brDL Nj7xjrc#0Xj)VS͝AG o ֜j2gy-97{D3^nSQ_a奙 98cW`t3J0׭¤X91/(3CwqȘByF<+` 5FEKUt r8"*^[ |iq$^&uzKTo;C y4t\t`Jl?@1i^p~zz޲mkGN|U /QF&(Lg =ہ?'tH 㪀5A03Z]aq$q-3/:όi{#P>qZGt||tɌ5c4~Je1o ma@3 ƈ+R2Qẽ[ i"4g\3FmHJ? 틑M4OU67#M;lӾrJގhF aM>WU^~\1wy#, vZ&6lͿ@l:/CPk쪴8uwkQJXִ"VU)  &t_!:R;STYN|aK e0w\{V"--p6l[݂}Q'8 $ {PJ$y OU9bPRar>Dž7R*4?YEwmsڼ wQv3ː_#*6>;K8>1ބUƌ\^9pNpa>vK1lWpSPß3N 5 l8ZrAFnX}8jtLjz&hmθW3%Ch_شC>>ޖS>$D)߷'G++Ux艑E?@v;7l&i˻z/m[! U®hz(Cyveũiχ=ל6y|Hw;*Y9ʳԶ1Dninj?[phg d!&ywO HPz'W|FM8m7L]Q[oql58~!f%֗{2C"NDCsk{|G-- -IC&DqG׷IncEbnˬ]hGd*t"1 5.Dz !D*ZG2]]8Ζ8l8⩎<<6M'͡bIv@O#VO^uVjВE`e <jc$(84pa4G$-RKΞP:F\H<,inf4 WW-S@|j$S1{PxĢΰ‹fX ?LZ*ppߖ%jڤ yaMipWfч²ʫY_yM)ڢՂݺ$|+@?_6>߂(>swngƅ!,@(Fw" ˽9'l9Ԋ.2tJHbQ@!C!:lظU'tE2X.wDo4RЫ]C g[oMu{HD2UgS Ov/}jX}X F;&`o>_ *~k#p!дr<.nL Unzyۧ٫8IcyhoI^m+z2pfVgbQS7t{!eGNЖREN8Zdo|4Uo"͋#Nd77W`{6?m i%nFEV Uk4oF|4Fd*b,J!:LQ aWWNkV:C}$=E 49jqX2ɤ1jMNC_~M[E`B$O|Ֆ˥[ G0Lvmn}}b_hR>[l{0Qպ~gjiTI|*H-BIJpx7`;%MGxCc*̈6<;)-ZWVzkwxP4 . 'IAhW5&I'mg~y5sh ϑNb u×^%}-*irK6#24b /C70~kv95+aU#{fXA,++X/ڼ|HqAyFaB7ٓkfа ysc&g%j_; fؕy ThTq4bOs̪{Ny2(@C%u^OD7Jn2T~QKh(w}0ne+<|]?}Ni/̵~XmeBs1:D8 ~Ө(VM'e=gx? 0́Hw}J! $pk=eqamW+7!N͢^YKR[tbt%TvioVVaAE,Ii5Լ\*ܐ: uŁB4lxRto]>y[$1,׹֭c+(;uƨLFIJAp0.`ZʾXTHU14SSeIO-_/g V_/ Ȟɓ6>| /wfi^l@j[]φ)R.Vs/tzb=ɷ-"[&-v*j(#MUiϑH*@匩3BBMTsgBi-Lj?=FbBăwn.F Pn)Lvy*kGiT(n?Sm- ~\pdLh7&MEo960[~ .Ҧ B0`@֟>lKG[01#(w]Z 0o i.QX`[Ϲܷ!޲X|t<}xԘz_MS/Q~L>]zAQDyy]ɜ0}?쮷dYv\.#FUK󁍿ޱGep`J|, X͆Grkp?3 V/L,&ndq܈=\1y2c3%a@6??T ^V  ?$ ]71Pp:Xc]tHgZ]aa;7DklLhbм ~EՖn}Eav_{Nz6cQ`1_ x|llʦ->X $.ax*ky@R 0FF)5gޖD JYzkE>P!l'^"Ψ )4*̍Ss谂UMZ4`OLD}9JzC+TX-MarzUy,L9mZ4ʏ6Z)Zh Z9v Ӗ^n/sC3Z4ߖЇ 'aHQ"qcTB(A,v;n)vG{,RqrJ,@cN5ŧi lKx{=")p>CUv*ۆxNԅ|Xb%pU a 1~~}[}ݶUmI^cstWg ~x 3ȣs4K8H85yC+-&>=όLd |OKHn: BULh&w)'LkpR^ ,`B_V1΃-S[\9= -JIf*vNI,xEHoer{|4]ov*͜RT4M+d2jTVfMHӆ".t0ldB)pTizI/̎OQ|`ٞ0X`4;-`bi.TN ŰWl@,{Ny/{iƢ wa|+Ҩ:x2ȠP50~e%~jcRw~ d1OD짩F5ڼj}gێL5;sC_u8ʆB&^\rmt 7&bZe-XdeJ;43b|?$GIc?`~ɳ\T8.`TфzqB剚HÐ{>*o>=u<*u|KJ2*\y%w̓% J&Rc&/Zn0hԱ+\v;nw~+6L0@X2+,vFzruQu::#2-pa]yGq:IRVADQ:yl& |Ɣ] v7{./#1͐1ct*F.N629$]cO73Q-G<d n>zZm2ڌf{nѦ;a/7~1nqK T|@كo ZqQ>o gpH ~UJ Rʮ!X%ʞi:5'E޳{gyw)~(Kч&_bEoF0߫ṕ{E(u6嬨P#]7?2;<:ۢcq@u<ɯ&:ePBd)o4"k>Lj+|;D|&9tMr,V/ר4EIk4q mA )&s6 Gq4G Lѝta$!y v6Rpf Ŋ7guFS3SҘ |&tziWVh„_U!<700j{ui.{ " eZ?x;+jZer8'#>]Qu}BIpwT"yAcUe=d|\&PpDk9j_ MG= w؅Ŏ) $,}03u>wE 7 v+BgY.[|7JOfs,b HYp z\|3Y`0L,=Y^ڬޛ2c|"[iInMEe"g|q2'Pa[QYr輶ns~>\iL!FJMxi;sXWj{fθkoxыNR]hd %b'mHDR|{0*^bc%.B}ƣ\KWm{zheCwfs&ڷL/UtPdɑ4[Nz.$ Nu AP<n/ Lw䡷dktVB`'̌vg;=>Ż !, =5_ =tXzC D?ϑ3f6+9p39_)GXLA,X+Y'@[w$ "*xG fzKK:M޹`$)4tb5>2˥o[6Ʀ^37Inmn-NuWJFi"$JD}޵Ӗt%iT-BM`=6 G 64zNBB UQK~WܿEM2^u*N3̳tW*MLkNRT/"EGxI=FXNߖ E}4"7"Qp14ճuCgƫ1 vJ\7 зs/! 3c(6RN;g_.z㐁`EeqHf@tuW0}L*%BI&O϶EЛGpt-B ]\N4Y 3\".w*l4GWUP}v t K}ӗu1݀|mħZ|g(wڶZλ_ c2W-r@,li}r=tgMZwOtWF^Ji5(&t aJwԪc h=qąײA& 1.-^?'$O:gY ;JTh[ۓNֿ>"[15e 4׿/HJeqpMy<)2{tL d *PvX ).z# =GDl>բasgV El+hQfm?Gjr?|'-/h$O?d%4{5 3L9&:!N[7R 9N*˥%AκlT1q%JCCǸȗw͕qCz,6lOqd%#=_YyU[iOԹ!v7V4T Ss>Z#f!ݶӺ1T*)3 G`?,Ŀ W: UOhjdtΣ^_!،[o~1O7vCTYAPӿi5GRLZDom鼺<~:0` ݆S_he!KN 9pMP+6zcgy,˿@I-?%X§O`cU15PAV2PS*%2161g״IEF0|dlʅ]d7XQ#.9J QޠM"}490 [hc>IhxwFIGmd KM{8:`D>}2ff{ZGh{hAPIi>ypm8]j_3͠+T] OЖAF8p Tc?NxyY7:SS$,l0/xIƸ T?P_ZLrQpS5<.͆gXDK╊0q Q7NIl}LQoݽ;P a3nv)ͤkVtsD.\RS-Z١ jc}na'A 3tb>llNCv7%.gt 1)"~x~;({H&<>~r>>O)%GҰ}?\!rcEj5xE\L߷3X@ u61ԯ+|Z3@df EӬfY;Mi* "BƇBs&x8sh+ oIuȫl+{"zEȉ^@sk̖U:&%5Z9R@Z. Z] .8xC%4v (X88oAHѩ߈`d#oe`d:[=M5,֭9G g|c<3kSUzF|7NL oQ\c"S}߈@jW!洃~FoBF&*Dk(+#]XQ?[XKkq1QH:yy>S̾a%g_G ^fY9Y_pBWA$+:_m>`{-%] +qe%t :Dkڷi33QXso/DR×:Ko*GFn]b9wH!Njk" ğ(טl2uQ~;yrkR4wI%cbm"'GbݟWV*LQ^ I!T7u~kWSmlEt3CA, F0صQП׼3$\up ,]$O?\{@ k<6Pb%d&}JI|:`e|+MF  VU_if{:VHlv :r3opV n7|l?`D36d/$ErJ*T?x͚ \CkxPڥT_ЋQ\9dCѢ-`@H^[[?/3-?kKW*R;2.CDT>!+v*p.:X=f"YZ{5eHX# &[BWrpB4Lc d]^  r/%m%OA{Xq1ȝ)s hK RYjZl0rI %h4Gi bIUp5c_! ,#؅ po9~fz.h|s a:P *=eM 5j r$~ e|K-L4g( %n Z"0+ *k\mV&m^46J<lC/ D6 ,;{v0[olJx m& 9 1ZEt!v 2;P2muzIEq+4i;C!2suLHx\ 'RHVCuDA"N+ y$yEp;2}*Z(+}MrbV ?oxNk. j\|?V6/[i)e:R;6?`c `,ݡ7Hhfi%>& 1CQ@<'w@y7m r7xͽ6\h5{GjV WXNR _T%D[ݓ& \F$G r cY-4a'2;s" (Vy0Pi4 \<Vc B k g  kD=0w<(R@>|LO`Fi j$h nT2H j}v bExri$ " E3o (o-#zzfxȬ!Npv] s+wAf{# }&EJv8bHco9) {F9F RWtvGXnU @ . ) Ǐ +8 d4 zK">h2zNM=s q 1dtr2V@&I O+zxN+!Rg+q+/6J x ; z?_ `4Z|>C. d| A#$.)&+ \#Pe *I;JI25 $H p|R' D^|e^FDt] Iq u@,@udO q9"lCj[8o tjXR4h(vW#RQL<Md Õ uAԷbKѧIN q" G[0/r AE e:~VW'D #V2`7pd F0# j_*Nj( "Z72 [2I/ k Bo  75 p/ s-! ^P}f7W |G+rkrQ~5h mU8yS=>r R|LiޖrN?LΔ b++ {& _l TX"SVcS$ gc }[; LNE|Hv TWJjǸ zGNW^r r55e*+!MH "h|6_:mǨ1,6b8a'Z0^~h $6 k$*r s`xh @}IZ /+F 'Q?ld6vqUZ 5v;{IXe{prOK/P>T*o4:3(yaR J9 D~jgX[ Im.'8d-+:7 p}dP J^8kbDo[ O`V] dop]9kE1+R/{K@L9NaR 42 x!7c;@w5JpH= B'" p|lKZ57- H\3mG~RRr%1H!D L(6b:S KH OWCq < LV $vr G?87  +mN]F 3 lՈeT1#Xg0Dud7WIc.Pr]N87$O\UElFc1U{z>ش! ?(F|]b U b*u+~{{TQ-MbP9sT9  ^%u[IA~[')Dx }C98r.rQ-?"޹,|z 9qV 87].oP {aC>UR/  ʾ  pJ6fkxdQ,#_z=2sic;P yӓ\%~ T:^^k; o&nSl(2&\dpVX%8k'^ 'b9:|L}P[Ee#iV3* D:6I3<h{#a"wq3be v  J,';Z<$x?$ if~?/$ <Jj]at ʘ;:& sl&f;YaQ@I~jYN[SrJn R;B4P|[(zpv.(y w4P  q!GulJ"n#}2X;YP (WMNoqk.d{Q)4 O;-._$̋{ɷÈAm ^/ ^ F8 ) n tda qFb"h[s' Q*@ <Oi%/ Byi!0s  R ju) E M|0z:~yX7:G/< 95&t ~W zSLJ0x7Aդ6/<>˫U4+r_gslz#U R3wr mGcXZ, 53wi!MsH˫ hM^ c LZt6*lP3t3*77/5!86.hNH:>yIi,;lw j&0 z -b8,o`Sj/t KLyQ]"ba scH96Ygܒ|7lc$D 0"C  6o 8{%:3MCl"91',`-( rCB!4T!/w0&=B*uM Iht#S q l3tc$NTa]q2GHEpeiKң#YGA6?*: lp6r3_g#Ga0$G("3F Q,QT - ję  K 8`tGIe>]`!N*1ifI)9}_ hXP7c8GAqz L-T6O[ m7!tqR%-"űcV-M0Hs ((98 rB Pz2 {Ihf[>l4/#v^N5rus9 % e 7 OLm !> 8a l[< w:xTVdrvM%x3s$!o< qwK$ N~'& OiP'P JvC7hTnQ 1Cl Λ c ]879`|OGh •2:rNBt'X&, f<z n%s}q`<?W 3y^g52 +ʹaDF2@kC o, y j-A 8$[;bg9'@YZ{ N-> YxQQ'-!ڽU(,ۢV +3D_:] Y2K91 F,`^HQS#F.D2j5.F$ӷ D_PS8U |w3#l9'rʩ!D|X9b4Kz)a:W.-! IWJ{h0n  óVB l,N?QFRf0K zuA?S =Beq Qq׫ h{ 5#+^I d^W> 4x+s$"MRyb2gsw.1.4ڐ  "U۔t.+g f jY vH^BNi=)r z#% Z: * 1 O 0'x5.w3CYb;c3h ,=TM,1 ~h܇8`nB^W=؛ l 2}5$U$ drT$@Q9;b7*= UF JW#7 *) (@-I MEW2Do U 1.n1)*7J]qT KT@LIxJm?d>?D\sfx(  Ky9{. jV]"*-^0^zk}n0@D} < y{*?K D@~:u |jbq.+v +-`}S~8AUJrTx:,6'oFk;d [; o;Z.<xA0( RYbmNu *MP6l| bE7F0dS^ vE w 7HSs&4׉F4G?ݫ}<pWS ()`Q\ +o(*]^sN +4l<#WWU)HN jA e!u$2a4..^_wq.ґ oB]5VpLЁ i#&cɫ x hL;3w>>\2GO.0\ v +Dxfn@.:4hKunity-settings-daemon/.git/objects/pack/pack-5ce4060d767fee0af12bbf440f06f6c278661f98.pack0000444000000000000000001666207615172222611024676 0ustar PACK xKj0>e,?BZm} }Urrf@MVc#dnQ:&g`O~\fTxKJ1DYE揄{ X\@N1ٿkV58UԚ"hI-ҋ2Ub>HahN*xL.Eixb TJV~צmѷ>*>ڟcy>;C;R裷HjA ȕm0K^ޟimǵ5&#pB`v `0xeMN0 F9Q#'4B#vp3ALդHSp1*6n 3: QEob~ ‚ăRqsXj\ՀKH>!f{ []0戚YFʐ fO"z_>3]by뭭2ݧ'PqG2:4bSi*i/?촃.;].5R[c,p+!I4R Fѣp߲0\!X8? _ͰrG~ȲsExeKj0D:E/ CKnOka1ȡr\,%QUu#%kmPN~Pޛ!iM%Zbbh]!{STFb $26?+L7w4ߖxx/ 2СBd;s5B"}нVK-[ݛ)pƄ樸8IrR′j@[ܺ3gގgxmKj0D> ` dHG?,9OVIUUwD"㉻Z,iiqn;.Az2H71`1!>xp: X(NQ$ I$ם|VF"oG8zPX7-o= 6]sw2ڟRmz>Qmʥ_5؎k)gT0!DN&/pBMk׽_#9J^ƿ}wDxmn E|VÀUV_c%:rvѝ3SwD*&m4ZqCb q4Xg: }@epJ)o/^3o-6FZC:ZqcYyɮ'!Klܦ\jaiMЌ+ 8\nkcm6eL|wm%/ߏ/iYxen D|VRTZU [)sۧٙi+dmi8X$91Q B+?419)coѳu78;x i9^`=D6> Bw}/hkyڭP_\Y|/[ܞmSi~|Hp>K4h-v(*uU2|.O].5m^R[U챻QpBPjD5v2mn\%-T8 yfQ6s=xej0 E /[IÆ̶~b+3f8v)Yvp*踧`uvP0{tqϠ6e-$?P)| vS?2Zi?\#rsʢ!=ӭu-|jnj.=lig4A~enB̾|c.ټZtxvZB`5pZqɺms׹tq~dffxmn D "]ʵRo` XیfL]E2`1{icbr=7 %aǖrI[)1ZX; FID K%t"²iޏV[Xvxmn0 EwR,  #/XRv.Y -!:2; $ \jn6ǥ0QB>AAnkR;)0r_w.'—]FʷR*9.xLs9wSi*y[' pjCʾ|R.mH2.!9j-[m{PmSi>ϻjN# hxmn {?eѲ])]2-_olD : Z謔AziGp\D9AK7~ PQ~ʑA)20hЉ`qk6DzB>|5O}}Kaޘ08 vrwT mJ{FYe;iqmL9Ԝoc%<\G@ e%<(3c4gkd5w`u-xmn0 Ew}, NKׁy.,Xu0x sΘ`H}|m{s4="2{o@=Z& FY|:2}HZN-XiZh.r9_ƔKViiv 'JB@ J%9:ӺGo5# igxmj0z [J֏ ڷXiWK.C\>fv2ȡwS1'B,\֤\'K1p&fN4;<̉ sZ2d !dt&#pk*?y[tAyƧڦ}~ڻ1x-;A\ZGedt_ Myl4..SM-Bh'dJevQǕ θc*4$%iėxeMj0>-F3'Ќ& q%Uq[>SVU3yVIq"'D%:1=E!#`nbKy i #D\r{K9t6AncVos:y>NlUSG*T5<_mo1er>S.{Zm:wp@vh=m &,=i|o}5--txej0E -[h%%tu@I" K.Uwfa&"01c$O=ƨ٧@ B*|M Eg 6 >]|sf^ħOŵpPho-6C(F .p;k=\*OSr۔K-v I $*px|=^mSu_nHnfWxeN0 E,AO9,_*b7JJ؃I(^;,rPhnTIGg(]IkN rRzɩ Q F"`^2eyG*Bi+cN9-+;<<^0U mYrkGnC}me/c+C5Zfm\-r..# řbiw-LbsNjĽҾuƐxeN0 E /AO4i`*;|}}k,BXeq?$2Yk7UP?vGkEDF&%[bZ seNooKjBx61-ęrDuM TfV/a;,OŵR:B +q8vl/B((q<;?F.8<9h9%LǕ롕=DrkVxKj0D>Ed[-!Mv9@"IFfrԦxj` Ӯv5d,Ӧ-yobu:lW噦k ഔBII)hN8Cv~J/s|*/;̹9q9%Gŕ b3$C4_Џ 1[p]M%/x/_˗xKj0D>Mc C.d]j`$YNMQ&p LίQ 1jv1z@ NMJW ΉC-"h,:_O~{k<˜Xj3+S%1=&EyhpVu+EsOzQ~&շ#r&px`oOaʗxKj0D>EnY B.d] K-"KFgrԦGzc5eK)&i+FE%Ia@߸t@kqAsPFK;ɳv%Zտk*c?j:\jwoZrw ݲL:;}nge*A7rPH$Nlx`xj E?Ԩ(ݕn8H7 =\Nop@:M2nnvJ+iCtƥj h$[CdqQ )?ѿjOxKQ[q99Թ>gK-c_@jM\.S:;}}ong-B/&ݳN(~"bFxδiYZEijZReaAeqyYXfSskBAdF=V CC##xKj0D>EY?K0B6VF@(^o̠- q(i (YBRﬕt`aD.(f [K“BF69FAoaѿj0J:磶 s[ss}ΘDXXWN:# ĕ983|s;S-mzYo{zU,axAj!E}T=0B6a!M::w"7݊ݴ,9<ܤt@5!1F6.Z퍰Z8'6o{k685:Ԓ?P кiq<34twћpoiG-h{Br 1`xAj!E}h.j":~z G|zcAŦAwzlҖ88G* l KJ6Hk4{aBih>JpK>^[q99ֹ>gJ@豄@:m4\ę9'؏ޘ2<ȋtF!@y_`xKj0D>E]&@6$#K3׏9BjU(D LRQix E/NK`0%%n -'kA#)AA&n}Ydyr>y55oVsw[yeĦ\Y.Zuw'9:u8r.-]`9xPj!W}K-[>іVM~?.(CFZmhe :*I*A grF!B\E8ުKbqk}>#uGmPR]z{WjI=6_p36onN~ago2P;S-3O7L'_FxδiFjZEajQjjiaiREYZX_&ˉk€dFfC =xAj!E}h Cn&lK":~z G|zc(E`&X]4mD>"T8*Bivj\:rBZt#tQ^WL4wmGGk605:LQ%mX`:Tpgͩ>~ƔH"^Vj)V+_,alxj E qL£tWH7 =\No³Q@`!-#VU)*/U7qv 97(wA&7Wmӏ҇xK]磶MPR]z+$rj~rʠA WԟN#q.ong-.& aPxKJ1D罊3qsI'}[p ֬DL;)I'`3hC0u~PL8J{JR$In-AԁPd,PB)KR& ri-mM}m}m[η^_RvWke:׻|ғ1aeG¸n`9.XqK`ڗxKj0D>En},]&-D0,%׏rԦZ ZR+6&;9!p3hv:0k T`DiDٱ kp|LW:, ~9ٗ96'Wǹ^& n827tw?ϫ Cb[P-tك^ `xKj0>E_Cمl$M#@ڽQ3@h74J䉈7`UCDO{\lR%քM*U5)u:N({냻x9uk^\ۘKj9L 4xсtْo'?Źs(ȭ^7 Z D ЂE]*_֗xKj0D>E > !d.h`$Y~RGFq*D(9nxصTIɘ$q9:{"j6cS*&A^5q_h:&h}/ k[khkmc-ojӝV^.(w+EK. 8GT[n+7r&8n|CY`ۗxj E (ݕn:RE17 =\ Ji HƮZk9:7S:a#m^cr YH2պ gx+Co{냻GߚSkFZ"=ض!_r[Oz~δoGi-ylA6`xKj0D>EnB.d]OF!E :y"QAH#4`6s6iRT#Jɬ/!6Q4;g:NxOGslsmc.._KhHm Z /MW[x|p |q?rluG $`pExδiAejYbIeYebaRIX_&Ck€dFfC#C}xKj0D>>-Y!d.h[D0,'׏rԦGFg $RБԘLI'2R&ӎ ^QDmZ )-Y=cD?9Zoy>yМLmmujlez ވ2]twqE|s?rmrR9T,axAj!D} C7Ն!d7d]/Fml\?MQGF1(1p@%- 0:t9\ҧO"(cш`Eh&u*F}(}{#uj6ΰݻRKߘjA Y&ͩ>w67r=m\m"% PbxAj0E>͌"]覻`, ,ׯ=BתX (7o2;m̺x(Ur ^uNYo֭ELRd޾K|&nXƵ1q|%)dթ٣ Nb{9;|hU8SK>o.d_ ~ `#xMj!} C7>چ dn|jmN哞lWo=]9۸6&8hBa—xIj0E>ElA dh(A[2\?j7z#RdJŴkQVqaG=tJk9Ơ16%/E4iǙlrGѿjO?J;gmXRzx Ԓ{l/;7S\ܟ.z#w7+2oʍݘ~:GC p`:xKj0D>EZ-BvC6mM#qHxx1A5nh hzVjJiƥcÀ^UDA9ouhcoys8hu.ϙ5P%z\C/ ר* qf:ߜ;؏ޘ2<*^~W i_xAj!E}T=Bv!r)0jcӁ!MLDF&*;Ui&ՉjG"3GAģ_~>=u{m]65\j3[RK |_Bͯ@Vm5p3Is꿎N gxH;R-mAlE!~Da\xMj!} C7e!d.($¨3׏!oUfȖ ®ƲrtR0 fz6;:[Wډz.U|ٞ[ﱉtڸ~9ٗ96'7G辸^4qی7ƚbuw*SW,yЋ JX L"axMj!} C7Om B6IQ9BjSTQ|ToDLk 1HqG@∤[NߨtNX;EUfGtPaƾQ`侀|֩q55ԵԾfoK- }Ú_WNZ1_(ve9_rOzq^AJo9l`xMj!} C7/]&@'Fml~:#6E}DZL"@T)&Hnw\ߩF۸G#U(Rt`n}Ydyr>yk[Z|E_[߷+CF;npeh哞l {P?smj*^_xKj!E絊7oxZ~!B&eZ>jaic Kȝ\PVim$4(,bEQXNרtKln9P!gGM.F (}{:5xWX_ZC]KkvvRK:};j~&nVJ ]> z#AJۆbc 7LI`xj D$x5R+t0*<5}k 3̜VAj=7:an7Qa{xN_97𒔱Ibfb1u0Cq]*|=G:Km\_aieΥ\r$_W@픕Qnbhm铟ϫU \X-b]6"jp/ax!D}ը,{[rm?G;up4L~E7fp& i:C]OH`aE4:HkDR^C,$OkL4om|ֹ\j3WRK t;?AZc=Įi_s/r ?`[oLܶT H}D<`xAj0~X,!KnyHJ28'/MM&fπPd *lF6쇝|1͋]VA -Հh$8?ٿkS_,T恵֥c[cc}̜oK-)} 5*4n^m ͩ:;|SћpViGM']0p`xj D$\5FtWp*<5}k sVr a.x.$bN'U D$-Ę*ʹơqV 49?Qoߥ—ux >Yj / sKs(s.mNor}%лhaCӠ)ߏ> ZeJzŒGmuB[ `xMj!} C7ϧ]&'Fml~ MQUjWÍR \sA1tJg1@;)1J;YQ V#q 7wm:gm{WX_ZC]Kkv]%yw|ͯVR#2ۜ.dz#كڕjr6Fo`ǙxNKj!)~hyVG!B6~0jckrR>5z`@i :Z /SD=!b뤥R&ɥw> &%s8)ÇuLx^l~x[[>oHc rKo5zbrP0-&dI:`x1n D{b/[(JI,(H0$׏#dьf^o72:䠵F}" L4觃Eۺ V?1n9ŚvY|Q-un404:LԒ<_3Knxiڜ靿agoLkZWaxj y_t&¥tW0ё W Fׯ} ;YȒJl*= QRIk*FQKhX8Wm6RJ6Rux ^Yj ~9ٗ96'gG豸@jM M#M|_ϫU\X-B-KR %7`-xAj0~HWܖ\r҈V֣[jvaLk u,s%y~LP+-Z9zwc{𔶧ZۄfR&T5/b xMIJ1)t2'wƝx04DoDঊ=F"څ!NAf%>AcDIBL$BYk2:QJ=i9>Z'n1K䵜}^ajmmcm5{|'Bif 'ؖ[-~y^G,3+j~`axMj!} C7ե5* !Mv9?5D5~ zY;$ Y ,\׸+R&;I!ze=@FMQ/|ֹ8Zj_KJ-)j~;IU2לqۙjj/]~TG^ƗxKj0D>EV d"dd9~#6E=7:3hB$6JETZӦGi64s <JYh-9zQ rrhY /yk[~qkmmspc <0ܤp+EK?No~ή'#zԋDaP `xj E?MtW0H7^.7f*sf+ɆIћ0`q:q頭B'5S;D6>FV1脑j?jw7J:棶 skss}ΔϞJ-c5?nH&.kͩ8;)'3r.xM)pRlP`ʗx1j0D{b^yet!M`-KD%YJfZ=:= ;;6[F-LF>7x pNeaE\xFY 6Hos+o{sicxvKN+ YgYM].bqwx_ЏU/ >}=cmR4oFi`xKj0D>E${$BvC6H24~#6Eת`P#5H9xSHbvڵptP Z({]`444a>Kuo( ~9ٕ96'WKhؒ^7#B#xSl?N q)3ޘE`bD-::/!Ѹ0qBPR9had,z ǛUZ0GmGC.^Q[&sKss}!=)ZB5? z)'%\6__bgovZf_W aGxKj0D> B6`$Y~RI@FPZHj'!+}Dp`h u@'P#jqs|ξc(}k:7xWXZC]KkxTjIC717_0Ϋ7 _ܮT HmaxKj0D>E~!B6-M#@xx1YY^HhWp:qKrZZRAjW8ߵxO>Q[/s9ֹ>gJ@辄_ͦ\"ĕzs꿎Nq1exp;S-zWoעX@`xMJ1s?f 7<@OK2dQ-un4LԒ<=6_3ɻ0h2ל/;8ޘ2|qR- o3w ?`lxMJ1}=T~'A܉wJc`4Doǃ)ߴo74$tr +e&2>1 Amm\h=:&eo}yh6B#='+'W.xf9ߒǏ['*[xF`S`DxδiiEYYIybjZqIIEXf KkBAdF nC=#C3SIwxKj0D>E]&@j`$Y~RUT-^o̰( *;G٠Y-[ź ]fиtV;bON:vg7KJ9@MߵWJ=uGm\65ou.9RKp_W+'[n847_O7T mEhQ{`xj!}_fUXBn!acH!EAաޘA+fbIy+͎!jk6ߌ YpKxQ IdIu1d7GmG^R|ֹ}qMƺ9RK q 5?Pj# \e9] q.'37qo~^_xKj0D>E-Y?.hIm"IF&׏CrūD0bd-1iD7胟vj\:UY-t i"VY:蟵oys8hu.ϙ5P%z\C/ 8ip3 ~ƔHPW<{]BB -a xLKj1)>LxvP+t!^* R̠",U܂OF2Jj&EiʹԖ>V])Ω G0Qoߥmu >^j ~9˜K\rtt?@Hc 'Fb{|ſU?\X2uơ% W`ޗxAj0~/3lIܖ\rdψV[xq x[w{_skJ񚨶Z=/ LP^Z \tk?NǶδ“^Zxyߩ`xKj0D>Ej}-BvC6-M#qHxx1CxH7h-EDmکq逊䐬u"(t(UMDa>:彶 nXGZR)=^#ZR5hZE7__07 OnGP_JZHi+`x=j0{bje!]H.ߟqf Zε_&_0ct>U }ӗdH阔b'-8gmG[>j6θƺ׌Ԓ>zNm9\2iNwqfxR;S-Օ\~[07`xAn E>+[` ).à"^#o[<}nD`!dyahlvlT &ʸ!JFd!e J1Z"+Sܷ^gb{mL .cz1ԱT3c%y|L+HO+ pҜxw?0/#rD^4xun0 D [6(j"~خ~=e [!b 8Gi*H/6!DGGpɓF0#(tK" $`9Er0ًb }^/[BzLKWVqv qskTؒC_[gocLE1{[NG4=1 Wȉg/oJ}eJ~&k^L6xژxuj0z [_Prc-eG?}:ҹ,̰L+1Rǥ2Vg- e3ioנ Hv,17,[+8qg}0 [ Smc}̬iv@/pLۺbsjC{nu˻w\k-Έ+~k _ئGg%Nh)kxej0E -[͌4zA(zK*9s,FC,JŚɌ9;79V0f $ Nb`^y0Rd!Z1PڡhG [=V1Vx!xlq6Cv)t{z/@E/SKM[VWW@4IsK ޲,Su_,Zky^qxeKk0{l 6zY!sJZ':ecvfN$[+ ͘{#"lÝ >Ó6>Zt| DE&6Ű,5_õP[hKm}\).;k=\ yŮ'ԥ\b+>RKL =׽HKΕ?|lXڂ6eJ} Z}QKfsxeAn E>VÀ1RTEu 0$HcR7~ۘ@]>a`l2ِ.g&*Vxiѐ3tkTS`R?4d&6r3iB.!8@{=7́j+O7Ĺr=_/m`g'J >Jk]6(?|Sqr/UZt7 `2N%(x5Hx[Uк a:&ײ\__qsxen E|V) 0$Hcוˣj;P6hO:R06ly3Xf6>!i4Hk"8Q)`|Vh_kjE|-7vRΎz~ %;RZ;҆˲v=!{V{PG! i\ BI+cvmsxe}?ڢfޗxej0E -[X5J~D8ƒu1]e3޶)=a,C1Ev UKXenz ga2q9 =>e ͌N˄{_dv{[bȬ?CɪU"lqfqz}P;}vZZw<Ƚ˥˽Vk,=v?p0` !@&":,˽H~Whze12rAxen E|Vc(~I Kefyt[fdbhKmA1L` kӨ=q@!z4`z _k;O>īŇfNu-UmI,M"/%T3*Ӳo?sS5r]K]ӶZBPvpH~쾴Y8~ }>?yNexeKn0 D>-$E]=Lѩ1, pf8mQތ&7YgtL9 @ݒVb: "'缓$ЄĆ1ɋ5OI{d͚[&L! FF]cU2ڊ=\eD.۸mqSH.3DV`nڮ_KUX}oTjJmuxu鯶Cx8 0BÑB*-˭H~kV[-y%r?xen E|Vc RTEu/1$Hcו]Wۉ8¤l"d%68`ǨΓM5#3A#䐽]6x?}|ίC_[|p@Q_!vХv e{z!C*5ZosZkZ)F Nym/+߶PzgMײ__ifoxej0 E /[2ہk)ә$ T+\VS6:bcTu-ZO*)897:>&i$etpB,Xb]#vt(BDϸf&ܩLrkK1EvD <@[iMgxeN0 E,AFv4BD|E4$ϧ}N@&%9@ b`\]=ء^iT T*@)vd;D^*~1E;P&2;dgvHn:~6M|o/ F;{vuS)[*muu)y[w=6'MmHלf.#~{TӠ 9^<4Gi`O-~MsӼ՜7wxej0D>& -ɖlBr -oh hp%}i~U%B=!sq%Z=~36V x M7$ZFhN3de|59x[ %n{q{%"R(- q= 1scy U6l"ǖ(7ux~).ϔn8Hᙱ39@qjxeNKj0 ^|Fx'8> _I#xeNIN0>Flǫ4BpDM&/Q }iUuuU6TIqcYk gI u4F͌CU,.r`W;iJ0_PAR6LLG'Aro z#t}qϷLD^_#}]S![Cm 󃻞gXktRxng}b$|jjz5CpK 3Vvgswx%˽ 0@ahRR/-X }EYĢTM؀HtO>{ђ-I1 "y2&dvK"/ϲ6لVK8ôpg>(hDz#xmj0 E /[[K0-O 3;f]GW2I:)؉=&&#B+]qvIX$ϱtED)*>֘__Y c |I\X'Gj,)}*ύp6mLjcQ';wZpޗd 6V[o?&ڎʌAiTpPȗ޲IZ[*5˭isdxmj0z [V,-zO։XR >{r0˨H񎼽\@A;9Oљ0@- *xe1z+-voKU~C2^C]Km`-(PJ4RJwZeZx ?fgg,p46E$Q&C 0f9*mm&| NITgY$m #'@`R&;G#avz$7ymr['<.$_-n׶ 6 4:XDqtw:x*ʼ;SKM[VX_lf=C%E=[(^jUвLk}Wj rBxej0z [F؂PBo[hзo{\~9 Qr@i Xϣhd79#G1ȝF ר1N[!~&7z}CoͶm%59 {y%2ڝV}'̝OŵRns*/k . 4LwL}MuS(f;!_箧QTexe;n0 wBc)zAC^@D_d߫gT.$ȲBKԆLd@(&)Uhao^n ca]g`w; e"W: ~bZy޴^E9uBxr\j[RNk:RЌ1l%7R!v=*!vO^u,+K<-Oz[k29KnQ^X!_lm g-dz<)sUW=[si~:wuxeM0 VTUbvs48m$(?k0(ol?}v `;I2Q'vFʖZ#('0m4AlÒVP[,tN9f]|gNڍz%tjP%Tp- 3OK<]*#Mvz+1GSQZRa j*]߳@RDBxNN2:Eq G?~'hjxeMk0 >nCvv/e5i]6]^mA<% .dbd0}QʹԴρ,aIزǜH #J@:& `&d4)Z/IT[Idѧ˚֩=?gmh`}6(mnWuyN;|˽˥Z^jXg}D[6J`k[0"+fj[˪iER׬Z>txej0 E /[I1 e~ʌ!/b_ٵWGR+y# {4=`Q)!"9: =фV6L8J[Ws;7{KU~Cr^}]Kö|HԊ KV^DK*tgTeߎsS5r@h{P=^p|mvp^ mw̲n]o5Q .g.xej0E -[FoA(#8$~LWG_%fS0% |QVMJGeWĂ+]Zҁe ڸJ"CORkrtv&c**[ cߜʳë<7Πeܷ<A{@(%v^{kÁz_S;@˷j+[k[m/ƃ~'QN_+ʂQ˷I\[ez%:__dtxeKj0D: Mܒm]9>XR/6 *;8zHbA5g(K\OJ{hfC7v1FeGþF׺_v6ċŻgvGuu)%Q! :R34o~<5!e_s~L)ܾv{H-P7Ϋ Ucؙe]Mç?Ws5mhxeMk0 >nev/l3iѫ" #O1]@1 G7ĉ%27}=Jf-w`<%2L9@0=)i–:(&LO[y[8VdV1ȪUulmY5Y^Zkir_득g[KM[[/YG{>]n; skMǕQoKl{˪܊:f2__ %rlx 0P%fT}aRܙ(SEL2 K9u" uJ3Dn5pԎ*חm' t9Z\SfX&wsL vx @ P]$Ih"weD,AAeشwM״|9b 3Grg4Bn(iʱ3Jks`Bc (ֳ}o]W?qdx;tI(5U!9,,1%158"$0"8lNV#ssˉM& 1xej0 y 7Jر evH4Ξ)aMǧ_[E'F(h1L@HBM)ۈ|$7kd`سG O8zm1hu`]3fhl@}=V)L;/Yչ mC|& 4@{imׯ}yOv>@[n}*5n^n:Ec:O8=p\iP[VEr+^V|g&tWxen D|V]l*~Kd;~|k2씃Ý`"2R^qdtɍ0[ ӨCԓ1Ll@sTyovKM~!V]Js0jRfPk*Tiݟ˻F.kη%?[m;!P0xARhvp|۩Y֍}Iޅ:Ysϥgxej0E -[͌'_(8~ ]9sFĽ.ZɣS(A+SDC &Ǡ-[FK+G49eLǍ!de5))A#Kݔsi(0s_|m6~Pc|>.Gi҆>Wv>!7C*5^R[h'FtmP G<}mhA4q#շ޳rs7,tٛxen E|V iT_ÙAJ2Q~ezcփ{i\gGqɨd)Re?h|LDn7mLT^vJ2yo LAꖽжD|$t͵vpNfD" c]‹|7y=Kq X<=:~-m8PYc{f#mH{[jzm!0skP&e8|Yu*i]oӫ$Z_lPtxmAj0 E>-Cdlj C'meƐdBle,9'b4! `H!)[`dv:C#01h2G5Vjy<$'򚹥ڇ!h@ҝQy]^r9ߖKѪ5m!0xA €JɷJkehߗ]o5Q Bf͝xe;n0 wBc% (v H { X@r ?f"f"`h `!ڄ@EPNyY}2 A!Fg% OBz4r02xV{)poEQҠz zn-Ez[2鞊}-Gv|/3fo F?b'iJRfT-lsX%?.41JxaXtU'*8X@|w; :&Ǧy߯F4_wxe=n0 wchK EzSl'z&qrx$?2Gky gjM'[ңxF z=2ЄFV0yLeKZ#|+|Fd^zb|T$C4ԣ*^,n>ׅJ]vvrv>qI:SGj5a+4 pxV4vڷ% J6{qǪz:(ɇ_Ӯkxej0E -[͌'kb4%*qb,пoUV0fڸ lDfZڔ``l%s>gmI~V0H3qCtmQ ICk\m6)4蝶jwݝN5Yԩ~2ͷ|˥OZRjSC3p#m[ LRHzm5 +txej0E -[͓B ݵ!?=% P7eup2qB=A*uQuϴTf(FH6Hc8! 5F8t7eg»gǸ뵍mmu`\qkƲs'S-4ok} RS* / ڎO*[\p8{|;mSu_n`h!fXxej0~ [jڷVD%N%up{^>ff-B&fLD7hStIQI9t·&F@ZGdRb!{ˈAZmINYqk 9 ]\很O^x.QCOkZom> i;qN5^Ĺ~2;3ϥZZjsӠj;iЃA0hv(X PDc D36q*>+5r|osdOo F'ا)ʫr_(ZڅcK˘K-? OmFxB'tеpl)Ěn\D\136qV|svxmn E|V iTͶRwNM^ oF]=>vىxPC-XM@Cmj{ Ұ[tv>yZmzOv2_}w_~}g+jK"_1s*v>ҜUmݟz`ʱ|R.YKˠR  E+V6_2߶)3yE^sZƿ_ЯjpxeIn0 E>  H l@'Z'S:!jy~hǼƙ}O3>7T{5q\+km20DOڔKJ  Asqp jT_!S:7Vtu xe;n0D{ C.6`nSHjm(+gŢDHn0;fj&bk?`Wi@o%9AJ)U-/ƪ-y6B$pc\9w>2s>x+&ꍡ VHvj 4Z)g}-ǻF?Jc?Z)1Z~`%v9(' @ aq5ܲc׽k%EOhrxmj0E -[͌$$!tu@q"pc: ܹmefv#) cJ y<̚J6Xs;vc>1 GF)ү6A{uDh 0(U~q GHw^rD[HXJ{y v(Pey,2RVu*X#=Oh_[Z WZ-- 2B|_jo?L{sxmj0 ~ [ɿ1,e>]C 篗[]F3S"lIP0rc0# 4AD=YN~5 5PKM|)R3mZ(n-1>'5\S?`HCːrےK-? a j  /v_{}ɔ:so%o_fxmn0 w= S"C}YNlXr N-ǻ6"ĨARvMY'.XMJ:$c2[FƃRho!2(")B<5BȤY*<8P4IEv6W,l`.F%}>폶iqRJたu^Zkia.S;€M󀥦\j?XDaLQQ$<aGJ5^s!|e|qgsxm9n0E{eCpREEl% oxLĝK26HGaR!qH 1}AOHJR%P:p=ztDVvbǖg2ƒ5,6>lR/ ATaڝ<-_z.]L%Rns*Ģ#c{н#\Kcfm>'}E/eߕxej0z [wJ7o"ƒu0{5B(,  08N`Vg_s4eZ 94d%f.%it1YIP #Z0єӁrvZaa~y5ռ92?9~G8߸Є* O N=v}8ޗy}4eo-)${~ 3IS%+h#%>q,S镱k[=6qxej1D  ݒ >k@mВܒ<"pƣ&DcCrI;k%#)vZ@ <;!^Ez meBo%7,Z僣24i Fj{aiٷb !yVuNodjK F3BgVs᝱o୤ fpxePj@ +l$ˆPBo_hwdKпS2hED ,D!YcY̼ȭ*̘#C000 #ш&x92q;#0Bk)L?= Wxi 뭮]Oo @G)*:V<.Iڦ\ZK-Sٿm~ҷozƋ|͒^coMj-v~krxej0 E -[v ݵ!ʌпoB ]I92e(d"RV1jK"7:Gyya϶TQɏ57G3i[\5\Įjsș#CVƃ]OP{!m )%VN ^?\ ZSoeem:z(),׋?jfxe=n0 wBcgI@PdQ,CjRP.{$Dzz+d`i`Q ,ޣhV\ Ax,G*P(KEѿd`/B 7l^1[Wvuwp^D8vL/+u`;;RΩ׹Tuq7؆|S.GX F 6\w:~pR+ΞV,tẎ)yS9t_6z.xeMn ehc)/ -]x^MJ]t6O{S`G%^ʢ^ɋ0V 5J.q NwZ JI ۼүveqٶyۑy:Q# zǐRqTZi'; #]HŷRc*}k@++=*kt_qoЖ)WB@[I# gkfxeMj0:-f$YBH#iXr_'Pl{ueK{t}R L;j` VV5@uHA]*R0h 0N1:0zӫ;h,o@V*fkSq-hhlH=yR@#ʫl~&cקv>&7M%l\\jiџft{ l ]N=v_qZ%EҲo[Vdvxe=n0 wc%ْ E:v N8N(9#kfφ䬝h4iGM8OhăeNg^k39[KfqP./]ŷR.K,c֌898^BAb/IԨܞ; M%E a.5>>6*MKbA =z-,z /Eh3iRR H,_˸&o1~C]J:= (Wfs,Ҟ"ۚv=AKSK1mom@w"҂BlLIF΢.~ۦ4.rQ/dixun0 D{  Ym!#/TAX %t-!jiޓyifGmN( ^+'4`!aњ}p$BBvB ha$A2EǞ6Q.|OPFvsk,biPRY\==%hiC̾Xb._?XZ۠ 9Ps.5t-\?Sf8Hiޯo yxun ~ "#^HQkDg4LD,QB=Mѡ1V9CfJEfk9#q҉mgmL=۴Py4[| o__4:o[2[bRm,nǞ_4zOߴ>Jψ?'V1H. {q;֒=5s׳VbZ>?qmxmn D|V RC)v,ukmFof21QSv&ZmH%`WњRO@CH`>bdL,riYFĭݟ|k+(#Բ떶m*?31ȓFN;ī,\atğԼz}ڪ6v?!*m) 58!tH|Ybw2.ˣ0 v|%2Q_txmKj0D:E/, aYr}3#ˤwUiF-ڬ,q~=s݇x1,79mة탮іkeov>@ASmLeWJmj'nnqeG.T(v5}+ t xe9n0E{eC 4s"6p1GR%<#qbҰAF2+#51kUvq$0\Ġ4`.HĨQ [L>T|M5>_(F #{;葫1G%iٷî'C|ƹV}NW{7$eF9 ؞- o;V?Bڊ>޻ >DfƝxeIn0 E> l@% %A]t eCܫgŚ 1ļaID@BMvvbdތq4i-I(& Q˙%`ҐSS+ZkO _!0_#" +{Ne P[(mk,²w!un?uO9b68tLtxBҞdaa)Cv@4{CShxeKn0 D>  %E]t C$^=C/VNW劘aDdh5t`2 dLsed@@@kT$owQNc V;G;;(=zݸ~,鑊w\:4g3R)² ӄeR=v\7u?HۘJJ'`ArT{k‘BvZ] T[1Q<7V|*u9xe;n0D{bK]Q(ܦH & Q?Wΐʼne ͖ ')d;I4ڸޡ}ıyz6dxdbWjl-5M !?0_" QkuYB)J[5 awuu!O5rbªG6NsU-ӝ3hmM:9AEhxe=n0 wBchEz٢%^=C/ִFrzx, vmSFب;RWQu9ހi:T[p1H-k"-F ѷ [ˎC-[y̫k?ϕ$Nk>p;LJN\l !1«Ro6Mq_zu:o9߆KJ>Yj [A+pdՑqZ|_!q8WĖtux ƻ 0P%Ba2gߧcHq\PE,:(z|(h%j,:id"?M+BmUЛ"K!{)Yo;5y z/ur_S;oC*5^n:fҽhG0#_R/kh}ea]oӫ5ɽb0rNxej0z [ͮdB 'XKD?,_ڽ, 3L9h=XS;3J`xNE:^;4誝5TzjTs;7KU~Rx!oGT^Ǻڇm8XрM]R)H;2-v)txbʡ|S.5hzz}}h[ݵ3N̲s.ei}_fxej0 y [ˎs@]C>=.h3 Dxb "``%;lR!F&<HF7փ3RJyk_aQG8y- (#9^5Xc/{%"1GJ<@|lXYMi~ί$jN=O~buxej0 ~ [ɉe>]CKiu 7`&ͳ"YgG&*t2%)R~:6&DN+W|C[}W]FWq+ s=E)G8/J8;sKn"˼>qmڔKJ9 X^mt;<}t h.-[(񝋠e2yݯ&<]}evxe;n0D{eC#p+[+D p^)2;;5#R֣ SO)Ԛi*cU  c&DmУ086y'%*!3՞YAۚWCy\cW3Թ^<5EsrL.%֊^ck6mOv>@.[)9Zc(%\Lc/TB[m#WBޏkTxej0 E /[ɲ2R~3I~3nZmVfȩa=i=;#ꐭXʏ&Vs ) lt!ج>3k]k`aPo6ӷv+ʏi,i/[m|<Kkkiݡr_ԥRVe*o, s+@ Jɗŷx*Lӫ$Z}1r˕xeKj0 >-C80ٖC821!{zȮFD\V 'I唓bcW+4"yTd 6IBjxv"s߮9̿Bz{VjQi*~`:#x @?t!f_s/1R6AxA t gʼnnߗH᝱ϳ7Q eIxeKn0 D>-R %(r&OnVfHQ$M@4 m\,qL ZG[8)3>B,xaOhP+ ;^G JΩ2aaGvP?+Ԁ8p\!{ۨ{(mNwpL~tHxej0 E /[?3 e Ŗ3oj#qn͈4@? >Fe r睹_LvȘ*5W{iP aFkt^F[3XG1X[~BBzx2 W2-O=?FI"n[X+f:ڵh\-o\:kܗXja_aL\Dꒋ 1tmf,%%'q.g1xej0~ [V޵$%s@?D?,_ecfv,md U:2ֈIrMB߬n㹊^9 GaAޫ8(R! 1hi^&ٻR3ӅoZ؃2sݻL4@\qA\aڞVuٞz6m%\j^jmOR6@.09 \x;5X3 qM 1}vZ /5 T?)dK[n6%Rd="fxej0EY dMKBq,upl.޹SV"V㼑*8鵲.p)!.dIhg:d[i* Q>ΫhG;k Cj'׈A)\uFD^qcZbn+gSY|?oΏi~\6Me<~**‰vuZJue^Hwrr )\6X6-8ߠOJ)[!Q|gai6']txej0EY ^!,iO8-cI!w\8ǔվsC'wr:ϥq!{NB;;4b)؏FMZ2'5)XiZou-|*+<#Whk,ali@79_KfwA͸bxBTQ#e#'msOnHi5=hxej0 y [[O=ڲN>Bu=F¸(xPSK&4)LHqK#*ycwj0C<9 Č"Yog(W1٤dnTQJ PazpN<v]1mw~m7te-2z! 6 0B[;m쾗IoЮ01䊽ےk9c{Rc; &yis X۶%< gn huxe;k0{ ̮$@T)Y`Fl3 3H腗"(`9jr4'-17*AAᤍg'(@k8fP@۲}uckŦn='oE)'-DM/8[j-zOus4m^zw\YHZokVr8pDD= 3/Ҟq)WB@{Muhʗxej0 y [a)Ko= d[v!vuI{iucf4mc9(m eY2[JVxiBy>.c9ݗ¨:~*HsT&̑)O;$c‹x8W(e)>/{#Ng^Zki!>ov>oc*5^n:Of=_IG8\(VjeyގI,}/txeKj0D: ZC:'hI=3?*Mã,CHѧ18w, ֤{fF&KA %ёChPs#H6 jykzЖoE㽓uHtεGiy]O%KVmʥO`Fc^.k:@lTEmʜ^8{l%/ot@fYxej0 y [Vs?ʮ!N^ҞV >F3Svfѫ`Y*!x%bxC"5h#8DF27RT=Q`(GY T'ݸ<]|w$^ħ 5Gin?rta?i#T:RJ{JEu ?<1p|R.{%϶y%` Jm۶)q|o35#ڧrhxű @ P"LA }>1BV.QAd)Jwvg7_cN#=jibZ k8v5&? ( B`gBH~xeNj0 +|lY,OX[ْl~]^Z!40fm" Y:IdgH5%m#P Y +n4rٰ:SFBgxfSv &h#cHlz6u㱉wX[EbM+GP}iZkkrAdZ_K(}s?6Rir+鏭c;dӁJ j[oY0=ۑJbe3}sxeAj0 E>-C8r C'meƐdBluIW|~9H#7A1F`CtլNoE`sDdh Qʲ?@3qjy<ɞrIw >57HOVjc "jEM]S) ҝL<~)txbʡ|[R.c86m^[+AyeRfY7%q|eiO#(g#xen y C !R5Zi/aIQ$ _`[v٘!4EgǞ c㨴ج\D785D EGtl8{nE7jx=ZA v:Bo۲+Y|l4O*\IP{ NG3›Ris"=e·FGS5#1;P?lWR2 jmn#q|oq5  >A]t P2eCܫgݕ37,8[8nlNk?hݬ8 k|"ccZvHgj_#+dp>#\f M0J\1]'IneC)J[]B%h]hG~Ԏ!m d[b3A?lVH#mBI(QrO!V*juǦy{G97|ixej0 E /[;0"O 3;ݴWGn"*D &=&1E#Kp$ &b݊,UYHG6vL1&kyDHb @Su䜵 DQ7{#Gv׏Ǧޅ,zEM6Ӿ}Eit&mFQcf|ʭsὔ-ZZg Զ p\ibm-ue:Nu,xej!>DŽeUa Kn9 iwc<&LNI]>Dx RtG2*edii|Dp68"鍡d&ȠlA;HN3s'_[*C_Zq8*F  !vйv y[v;苦!{VX5*07^ $F;eXYy_M+cgo⽖&gxej0E -[FH_u"pc]e63wn]!Lo2tI)a 5_1WVlY ʧG8o[0 cJI!8@ykfc%ڎ [?WK͘Ňw\H -lsݺ|\ibq4;}Zwk{"?h1)rr{ؿ؆ӾIvJ޲,SFzok[O%txej1D:&`-|-4<DL8ojI8P'OC" 02vLU!26:Ifa"[}nKʹOtkho-6僁vhP:]ru<,/v D?4)J͹_c?vŅpG Q_v_}ΔއM>^_Xexej0 E /[Y~E0%O 3;]6mbY3 2NOf nMM(&%6 y!!00"}F'^4Z& vtaLd%;!cXէL"zKVu2i/۴m vz/PU/г|˭RVVjSH_lvЧ}k2q޲,"uWV[-r4s=xej >ǖ%2F#,e>:fWH!js盿)qp@fFrI )9(g43ʃ8Y4j  *CY Do] :]s=~u8- "eɎvͪ+3䛩9F6 !hփ,ḧ́QR)hTQKeH(tAx)hЊuYp xa%hl Bz[3RZ'-Ӿ^Lwrky`;K(''B7G5f67ߖXzlk~jCC>2R.Tjw PsPODPÀ Fuh) q3xeMn eQ$4f;R/AIP*DŽKmaKyrF < M$EAǿT͈T[V3"Ȩ䄶&R6V) g8)18 2Gf`lOi`Li2Ķ37,m9a.v2_rom~_opc&В'NT+fHu84ǞCO\oܗTj g@/!Fr^d;]'jcI^ y?[m%m__x\xej0D>& 6-Y+ a䐏Ҟ%ISVxmі[g3ܩY)]ZB} QVͨu*ϝ82YӗTKRdLCZs}.%wnFtͭQ{niî'}2\c笐b(0切.Z2\CPB"H~C=t{H(F-SmKN7^x@xej0 E -[ɏ&aE7]#G1dQhp{jf@k E)KSv$m}vcϼVZaa::=GmY(|-ç޹̾Ĺu9~ɽmMmC)thAT+gxڝ}?zn/)Jϩ"*4 #YFTdERkxr}OB|7kGxej@ EYyhPBʾ?ɀ_x& Б,(Y@ܓd T8h7@4xֻ^yebdCRxpݗ=bmt  w$͠C{/ ,ޗ*Δڸ ̙phބ'A\+ok}ӺlOv>@6B{)1Zcg46 :QTVm[yxYҝu3צWKoDu&xej0 E -[ٖ2!ΐBEWj%NZT3}ME8 Nsr 6nJH E%RRyNRFH',`zW,&&x .L):.oo"pG B[l۞Z<̇2^X[/vBz8B-cn =}_cp=z5GOfxen0 >WJz:s˳\yJLcMiV`jTJT6˼>u/2o9_ƔKn_lp6`:`uQ9vDŽ620 2+6+lI!~<ͥ%5xe=n0 wBcH@P:D'ǰ䞿*.-{dۘ%S98{"Α%2&A'K6i6SHِu] w 9E:֓)DM<]}:~+m8PYs.0dyȥ\jXs@;tthpeu._8fײ4~t3xen E|VD6HѨ_Zo,]r0K8qF1dt0(`PItZ5W4hb@' =x^|[f=k}ؖD=8@Dp @4RZJwFeZetybʡS.E6oӶM˹ {o;3˺Ҿω(kNh9xej0 D [vs@]n6N.Z! oFSt83#B qGn$J[Z>bd baql J&Cv-mt6a y4A^oM&RsZ;[$F.;K|љO`TSֆ_sT~!tҽ\^K-XŶQ ]mO5</+ֲhZ{NU^rߧArxej1 ~ [.xm!s@K eo>F3SCG&PīOH]ef8i)$)k $96 2j+:*5ǕŃJt(̣6msT_@N\k?sN)˾v!8!Jy̹2EjmPr^@m[V9x+y}o4'gixeOn0 [6(i (vD*؆%-: ;XWf21}`uL$d=@J5 r[,?e{H_41rre8FǶ=p5e9J>@pܺNk]%Ϸ iuxen0 <*";@^ 8ND=|;o"0Gno-O҈'5+j76mNt%? >ocpPTOKK lg6G=h8^N!gr]s\|\tCIҟm@k[QUt;Hx6Chuޫv$;()cjZxeNj0 |Wq$ȎPFٞe5I}\`!twS٘uZD  Cz#XP͊ETyvARYQ=#^19fP7d=`DJhGfhp/eWaRęR[[r!9N-7!r'NP#›a.c]'v>6OmL/S%wVւFt'OT k*+)^V,t,p]iGj{N?7`0uxej0z=,2S}O-K=:eegn!6R-YN-j~7d+m!UNar\k1 '.RNZ1j7F1Gpv^wy( pk w>r{)9Z䱒-ށZuZj%Ҡpiۊ5޸\93wq^rcsxeNj0+,VoBȵcXR!_20Lۈl7)VZa&j,,O&4M45l4S Ny)Ɍ,I%&cX K~ykolpR{0Cdxh[iC}ic}no|C_\j^R[lj8Z-pƄ㴳@.QhǗ>ҝ*%\(2u$g,Bd؜xe=n0 wBc()%l˰䞿 ܢCH#{ fԚKDɁ&.ح~Kc*9MA]cHo#*PH{CQ. AkE<Bh tZ۽l>7^;csCiKY2i21X+=[a_)~ũ\q2pd7?NGz~|{Y}{̯#vp%׼uox 0 @J<#q?F`>Ll?Hċ: #pwQ5$lͪX%)[w+ ׌ ,:Z\5ʍB̅KBҲ$t<$Ξxej0 y 7J߁2v}/JkH;{dc"ӧOR]!*k5*b쭓=EBk'ֹ4 +`PZ.QIL(s}TQ:)Qjͨf m>qϕR9>v%Ps 4ua~>{4;}Zy[6ln˼>m/ژJJL?[+mPwtdcNB5ܹ-˔86a+)_}Ǟs1xej0z=՟eC=J"%cI}:C2- 9 ^kp"4p R 8VTa)]i ߉Z̶|k1Gps^M9Eo\ #Q a;]baG]s-qYbtQ,rc?N (7qݣP\;qx[mP%s h&h%hi xeNj0 )|( "CeVl6 Gem)Icf㐵MLά%˙!tJ㤽XÖ&jkg#9FZ"@3g~aB&7et{рL]h ^ݞLj+iaMkbTty_>ǛD# z裴҆*c}n?}{{m'" mf*@Jɗ5޲ʰGj{-nrFxej0 D [[ve~˻$b_Z!-q^q`ޘZϵ=TZJmgeZ葾hTk:q 3p=ӡ Õ=?{Yc;Uu,]w="ko޹vR[xƻ 0P h2}|l)R"e2 # ^ty" )2.9p4-[<8UDw(ʚͱ1@GeZ1Y!kǿn{KN#xeMj0 9-C0];PleƐC͐R O{+uo,a}$`] CYh幊D$D,AF@6R.S*t菭ՏmP h@jBP w.eJ_zF4}.tdx ƽ @ @a $ g1 pvPENT,Y{阖}3= VBJIe>\ZVa2sdظH4YKdL96 3}ny'`xej@ EY{B *f$'~aM0BFHWueDm\O&W)3'B [r͂+OULњQuD;s`iNAc"=9LFܫ{c懐,{}^U|X&9WqΥϮMsdd<BJAR+Vj}(2Ov>@KCKe]խ;Fl]peHہ -Jk&pY4#ľ2]umx ˱ @ @ $ DZX /ȋ2 #5w ǰ[(LIMRVQf&40I d2;_߶k X Y͜Ĵ'u0}v~>%xeMj0 9-C8t-xqBzj#=ՕYDt:c%1b h$VUTҹQrRQjHe7#<zv pmib@V*ݖ&K<1祴7))Z:Oy"PK{5zO*.Me^!?yjC*~+a/AӁtt h@iBPW.eJH b+)_}|xej } /7-QpRMqV&ɗԝ/bi2qeAE%-Mv@2*wF*'O4TGYh}%/xeMN0 =EQ+;͏G!$;:mդHܞf7gUDYsL( R4hRdvPg bU v{=0D X{k8 "^ k27 [}WnC*"겔]<1Zy)]oO z =-*n4ߖy.в|r.i+ct"Xmv`:<} jBޤ,c~l#VtO zx 0P p_e&H/%BQ2 11E T̓ԽHiks]R5QQ\d%&'I }Ly RO%xmj1 D 6ֶaC o3hq"xRSry0\",cJHg50rQm2lJJ1ۜfwD<_x B CIK+lN5Ne!EjEhu︷Џ?m],`ao+F;j'8ܡGiÉ2o]Oc3MC,5ާR[eĎzlBf\t$ p^qa T)nTR|%ley}$t.xmKj0D: E%Y2 aYr}gGGIo*^Wu+!PQ[t 1*rV p/1J$ٔp4Dg `A ZDcT\ZB?Li頟5zCܺG=7Ţrz  6(M{~z_a|zRm(cA@0fpBMsPi?L[ ^qfpxeMj0 9-C0n{@O3NBo_tP!!x1=inEE(| 2a|<_j,#z aD`L, CWw_+frul'FFm|Zpyщ>k# c!-BJ{#xa@nxeMj0 9-CoPzٖg<$!v }SB xJČV[#DaL0! iuDGsB\ij,i'ht )&$ dHd9e͕Ж"@:䨃Mv[vWm,aJ#a%v^jLu,!4O%8¸ 'b'ث{iVv)h/OIcJ[}+A7q5ާ}r ñӂ-^2\Pzjb[-?75w{x ˻ 0P%H.g>))X*P1㲭NG e$rS6jCM90迡hKU@S+y3<Ψ(b ipiEnHdDb !beIr{}sm Ҳo]O>[)g* g4?@mP) 81 qE#D疄VmL޻4|d!xej0 ( l]vo$Ξic0!_VXyjȀr4!LA"[]qmTL@B4i hWb4XiH1tDid~=0R41&~./ٻ7/snp8Q@Gn m~c]ʓEkV0`Ƅa^B1mu-ܩrSq5\uxej0 E -[[#a.'o:*.{T3̨Td)"C8n3 Mݤʉ9rz>Ydks+|$O}ٻiKۥz!P8Vk ]oZoܗXjџ؁ #bLȞ]|BT%Ky7@+1=LixeAj0 E9-Ce'ClI4)MI.*UVF4:ѣtH#2jJ*,mڍ3 =ZBdcߙ1 N;1&zGFS\U-MӗZeE\$}Ĕ_Knȧ9ESCEA `ޫ{,EVuh/fiaa[@_lm>tcnBW/He.i{r x @ P!EbT>`HqS"e(3Tfs8e[(fY+w&~5 YтAo{#EqJEĴu4{ }_#*#fuMWrS&{xeAj0 E9-C,۱C[qqBzfH.TWfalLj ңV5ؓ AhZ9W1( G-xIe"G3lPs`I;1ڝu^庉@i+OLy)ϔJ--m)W_>m4!XGUouvr^Zo^8<YaùQc @v>IeKkѩ}nl/|C_| k-C_qlz V3%tU!%}JB78'`)rڄP`x?jqp׳VXO@9IԚZ#ѧ ~ڈZ8 jʎBsFc7.8'P &թRi#jK<~]\2J0Jhfx[3[Gהo-nLk<"gxeQj0 s ?n9qb(ܺs;~Ya0!%},$ȞNNʛhfSxAluF(6ݣ_2N0ek+Gc&I=+^&=]8 Kl2k RZR;_T 4h 5URxPl?Zǟ[|bQmF ]1%J^9 Z=7۱Չ=tO zzxƱ @ @Q FHl(DRa7I )h#d!*V0Em'R{5ub&Dٱ7@TPx/D% x 1 @EBNFBٙM#Zyf!X}σ{w>P1F(1 PP98X`: cJWNVSTw/-6j]\xHF`!jHm}16f&)q% x P%Gyowo` {Hj)sWwRY밨+݊fb&}|>x>oS48zL3xeAj0 E9-Cq ClK$!v }@(20XE#9q$ج~>DXA|`k~0 dc48A-z \w>O_jI|u^K.GK-]2..'du@nB5*4_ea,2K|Di6@訁4ߤ(S~l*zx 0 @Q>GGHl_0a'D $w󺸏)W*6$rQE`_޺kUR,t nLE#bI|?d%Hۑ"m\&dxeKj0 @9-Ca(=l+3f;޾)E@$=D̃ONI*h%mҠFi\4fEŽ1H! !h+dxG1E Jv)D7Jt )"d;u^{JX<}&JF#:%G8_8'4{t;he2?|>'M}5na>ZZNI`Qp lgO xpYLގm5oqzx̱0 #T04$K`6Ha[vq, ,Y(߇}ץтycT):'bE04K _iu,9H"04V~)vBcz p@}%:xeMj0 9-C؆txIBzJ'ՕYHhdT&QF{Grj\y!ѥ5U1 MӉO1:}҆7-(!@[HV*6M$Xyd,,Kio<}䩼N ǎ^y8=]Zy\2?ğ<)ʃ|`pL':]I0rV.O Vr,c4o$oB{A%xǻ 0P*ؾ`6H;%BQ2 {O˶6իq0d^ f#7N5_emm& $5J+xWUjpN)0<z&8xeAj0 E9-C,; Cd˙)MI kB:;IgAҠOA]=PBkU&3"B `,iu&cyD`~%e! 򾟬VKFf ޸zW\7ӗXC T8/syMysRZ P`fWְKv@}|-ϐZoA>V=-}:&Ԡ[8xZk(%MvJ̗t+x5x 0 @Q^0|:;N ؠ'qU]$ ,YxxtӺXTV$@shNR t~uY@KR%\]%5 9Vt;ѯd#Bf!l C%'xej0 E /[)~0̶e0yG) J:ҭke"ei &XB:1($!JvL[lB( B au)Z=MzrZsiQk2kT ou3J+l5ω|](lA8ӕGF1PV۪۠sEab7Eqґ/o hR:w|\o4f'bxeMj0 9-CPzْg&NBoߔ0P=}Rۈ"Ee ҈`!Q.ޭQi&.1+筵ޚDX&z/Q'cJ+#  'EМv_6voDP]P̥N:D(K!. jIe,#Csk[n~B.ۯv=鋦s{}_QJ.4Wt Bw uʄ]v^E\n~.z`4x%ǻ0 #T04AK+ RȶTr\.䘁2 {󺸏՚n(`tS ,I:Zşhr6$CB)!T*n%L,}nޗ&xeMj0 9-C-PzŖg<8!v }SҁB@$}ODl$c>jMRh"ypѻnJcFŵ#x*& u E"GiQ&%t5ON nO`(:u^yb+MyG.uʵ!`K8 a0!4܂wv[]r˼hC#}\Vb;ǖ`O ppYLȶ=7 yCx%ͻ @EQa"(;At`!BYQM,n6R&,ȩ0$f52B_qu̍BJ PR1ޕKO} },N ?`HdG%xe]j0 s ?nNeud[i%Nn0>IT7fa5ZC !-ddTރfs^ hP%hc>9# 8vWH=z]6\w)M_b㉩8qHNKN.,@唒`ъܣ9ʛ4ȟ<1hjï{*{rhBR W.uJ^R yoSx%ǻ0 #T04AK+ RHg\1Ke ^immmf]ͱ(N#@c:|mm{w( ZPKLIAFN\ 2y 2#/@%xeMj0 9-C,d C,[8!v }SҁB@=Y$ *5IR4`XArib(PFJ$i:mL)ypHFdȎ>mYoF8YvUV&ӗXyb_Y\ڿsȥ>O:_撃0ߞTN*q]x2?ȟ<1װ;XсvRRdǝo፫2e]rF\?ytyxe[j0 E  d0v]ʌ[1~B@pnD I.8|B#`f 3 X3EсT%i0iWqngjZ9'HbT7>K-q0}{b(. Z)cR=k Ŷk?Z<+?G8 GwNS 0ώ &mXxe]j@ =<,J2:=@ٺ*Xk @K%eQ;jaO-G !kV 2 qV;9Odvqf>wl`4Z!w 4zXVm*bJZeʢKo2}))D)E8_Cg:u=S)K*vH}v>@)c)-?Gj m{-h5[**YѲIގoWzy\x%ǻ0 #T04A[Li$[.9.E|R׽c:u QPn T+em6n͟,"[TEd5k,Ǻ\P)9@ {?vZ~e&xeMj0 9-Ce;txqBz =O'4E7 xŮ ݂+ƜN(=CP6xZցz;7Xx +ipkye~+mcSb+eJF#SmuX! ˵VSkKjv@}|}O}L5lA>ZW<UpP\iT.KNVSg/{ixDZ @ @*wA EY$ ,Y(@WݰXէjjE0.Q/@UjiIRx@4BAв)V`μ$PzĤp&exej@ E -[ͣ}% P_b`fxej0 E -[Jq0LlY18NtEB{{`ZFqY%ߨ08XM/!kuEl xe >`jDo$ĵзE a" aUNI)\j J㞎9蔶Wu cƋ)O,-kD֬.`ο\̶|bܷ7 PK;^?OE{ xxQ??)+5D!8)2$((49)4)%(4h1` ss$@ xeMQ S۩0ƮR8UvuYP  qvyG/4h=icIy'~߶XH~Jiz1p85 Rp,U|k t57B`_9טK-*##!k!E xeM {+|/hW:߯CB dsNxJF)Q8崝@кo*vi^qmK0SWAr5͵gm-͸9U֭v|B*r_Rep<(d1p'~qE xxQ??)+5D(0$%8<94(-,-%$y)fs $ϗ! xe D~b&(k$D-kz鲰0˼cyMԸ8FvE"3@78#K@K3!lU}#^RRk#d^3e5t'Q_ ^ )6ՔWmJK~e}/Ed5xxQ??)+5D2$"(1(80,u)P&KÉ$R xeM 0{W]c-_IbO9 {YqB+3P"h3KahxI3zݾm [ G?{!;8TE-[T[ZHm~RևWX[+9֘)w5+4je& >LCxxQ??)+5D8<%)<4$9(,22$808%9y1Ĵ $NWxxQ??)+5D<,1182) )801h90FÉ$;$xxQ??)+5D!)902""<1,1 904-bP&#$ϛ9sxxQ??)+5D2(022)%8LKJ32olf`61=d^) H xeMQ ۧVa]GJna? @B}z/7;c&n88VJv(Hm!<.iSE xeM {+|ުدX=-vz!e!HHOHR[/kBy=!cX5lD?k 4ۖ_h~ yM{;~Tr:'V--p%!ko^"`e1PK`Zԝ7*F9:酟 oI+ xeM އ cUhW:Qe!HHO+ֳJ˄r^n&p-x0wۖ*niQ1KW@hS{ƾ%xIo_O+ V}MzF?0v4ܘQ t m1E"xxQ??)+5D2$<(8525H1H10I4KJMHoh21=`>I0n xeM 0{W]A_8*+k+V$`Ժb;POD1h 'K;# ۺJiZW0py*WB1 DYf*;…TB+嶤R ?"ޟTڳ`=B>E xeM 0{W]u r6*+[bu9=ƨQ8cDDCxxQ??)+5D4)41 %1$11$,(dl6Qߔhbz(} xeMQ ۧVQcW,v~~${4*#VS!AFH}g~߶TIqyMF> ya'B0h=k҂]Re`_oTjh7ʕF5@!kcFb xeMQ {U1v8U`@ !:>R nt\o@`+GcԠ ]db'nΗ2;OMqҎҔ6>e1,ba6JUlWg[eQ }DCxxQ??)+5D!%$80$5%"--91$"(5%2)1i P&sˉ$ sq xe D~qդ _&XFz[fv2Gcl{Fo`BP=gаݾm! [܏LG1| VMuPR+P%T3-t%dq_ @xz*|Ht_CI'Y8t07cmeFxxQ??)+5D$51 ,%-5HZX$Z$Mלdj<$} xeM 0+rn,+y,%lHefvg ,/MLɣ=:l8~ga[Ă,Ӛi?D C7䪿v9'VP^JܗTtGԵvQ!}Z+B xeA D}|LL^%7XFzlf7}+ }Sn:$fr鴜L0;,jv/:z73o[BҖ\k8͸bo,\qCyU0-p%!m⯄\@#`1PK`abmG#ÖD}E xeM }&JUy ޾@7  UNPRF/@KìPNph֤Ro[,؅-G)C K Rp`,3`_9טKg6r'3 zM>E xeA E}ј*ҫ$: ޾@7 ϼOr+kza HץЩ f ,#qo[, [܏LG7Ƹj^!5Ti/!')ɕkH93Q[eyu}SD#xxQ/?)+5D %2H%[&L3e1072baia>q$ xe 0}%nhD|lKIJsaY݃}6w# @hy#My'~]Xb'n֦4G-j`H>KhML#!d2k9Q&PSo:j?bE xeM 9Q(W1j%i$joJ|+U4̨Tx1"v#벤U7uq]sGvEJ )nlJW.!C*rSEؗ iPVgumZD* xe >O5PJ_6XFM ҹ 0߬B:KVR[ʁFVߙxX%UVӒ׭DG#@ < $AA۳6&jwD?AEsS ۜJ-|h v1GD{$xxQ??)+5D!(8994 ,"5%<< (| P&$%\/xxQ??)+5D!(<9<(1%$-2,<4($<-9%l P&S$LxxQ??)+5D<5 0)"($9"8, -<41yĴ0&3$6 xeA D}$PJ7XFzlf7 WG|&C] gVމ5Vƙ5m{SZ"Vp *uR;is,~~=E1}dyVxq4]/p?eE xe 0D܋q7FMJWIZ"ҹ 0or v}>i'G;F'IuY LK^79ω[Fp[a򮿣69%臐3z\ Ľ uVxIl]c ]D xe 0D~Eb5(bh fS"ҹ 0o6 €LBvFeɺ,AUN$ܶ+f״L{;D-j pj4Plyrh]̑3! O/Z+9ߗ9˳M6j 5?^CFV xeM 09E^b4B)J$޾Mg30|gpEԣf5 -4^z-'R>)Pk,5m{ {kRZb-*BAU*9t]AoW|x]\2*~<)Qj1"(!Bh_s>E xeA D}MJU~%iBz&lf7b us)E#`[ 6V{ogEyhye#ܚa]#U'p* TEш33! D7N"j))*|`\kF ԤE#xxQ??)+5D(90$)<(-$"8%"04(d1Ĵ0&Cˉ$ : xeM }*ϟKHBo߄@7 Wj5 +09^) BE'GeIThZոba¡}H`M)ntJAgB|ǙT|+>R ?+?( Vdډ]Ѿ*D"xxQ??)+5D(2(0259$9 01<8(-9|1Ĵ0&#$8 xe D E*_q,I#Q &lf3bdckMNHP`P @ 4;xOFeIn"iVq]s؃f\1pA фRgCЈoiL%Rs*b󝀶 R u/ED xeA D}_F(Wh%i$joBf`yg Jx : BA:&&jK':n )vqM^ٔ|AϰAu:ThZJs4αWC>ǚcdvUxSF `/h}'"D2xxQ??)+5D!%11-5%5959)5%$1%(1",(l)Ĵ0&3$1sxxQ??)+5D!-$-8"-"( 1 2l)Ĵ0&s$ xeA D}*`IZ観alCvр(@XD0@@7 cHHöfּ5yI{\(ӥ#L4^s4ǝΩ+! w\Z)%ZUNAa&C;q?oErxxQ??)+5D,40"-00)5$"4<10R ?+?(FHivG8Dh xeA D}PJ7XFz,0o6 _8Y-wf 0@rS1=Xy'~[XXf״vJiZ$Av4*gʹ9q_N h!f_s-1,JWUcgZlAEQ xe 0D~EbMLPJEh fS"9alӃ1n NNC?R3}w"u\8mg1%oH$h%T,T\;isD?1}<+y<A_ԠT՟E` xe >q%XFM 9~|ME&0w@aLuHd= N,f״֥D-Jw .0( 5 5NY*|G3r9O!'hxiB̾|_b.Y:oz2 ȋ>"ğEH xe D~PJ%>,I#Q ,0g6R %@K`ʙ`h 5URǙ5o{{7漤:T$ j-ڳ6qsD? V}I~VxQT= !aE  xxQ??)+5D$8<- 84%8| ĴPf#c$$ xeM 9yOcPJo$D-Mt 0߬\%WhAW^j@.8ѱ[%ծ%[ `rSJ#PBU)ldJAng@}xT\+1R ;+? J-\vu E< xeA D}F*47!Mg30üY3bc+eSq8x BhR?9R\%URDӒ׭ƭs9)4RL4^c6ōN3A X8 Rs*{+G ]ѾBF xeM 9=F(W/47!Mg30|g(k7sn \J)hv]H,vN$-yjzbA1.\@48P\{hRgCq!Jy̩Ίwʈ *$h_`D#xxQ??)+5D4(8< 9$--4%(b)ĴpF$E xe 0D~E%1D@)u5п"ҹ 0oIhh9rHBghي?İs⊻Q9/+Zw9OFip[xc4*~q=Ib*V}J:+?4MۈUU/yE/ xeA D}51 *F%i$joBf`yOzkЀw8^R59GtH=)o )nqM^po]JKBEǡt)`,uR9qs,~z 1cd~UxS2ʡ8D IdF? xeM }hҫğKHBo߄@7 W@'p54JMpH'GeIqiV֍9)N\h./BZa$2\{զ7:臠3`!B*rSߟoT@H/b!/@D5 xeA D9_PJ'XFz,0o6 _ؤ 6k0hRvCOӀSSމ53kB{;D -:4AH@CuY*~G3l`@/ZxלK%ao :v#Mg9E9 xeA D}1*ҫ z,0oAr{wdz TL2ӝ:V+sy]J[uʔZ4: Z E-`gw4\ʼn~ ~9HI\^mʥyVxr4^;lR8D xeM 9XJUyKHBo߄@77+A0(s%ȕQ u50Ʈ~2.K]IK^[os$# ګ68jndJ7Bn'8Ӑo1TU+t }2΄zOFeIT?Ѵuu>9ap9\.8A1 8 7:3`8JhTjg3('^.Bh_?E xeA D}*Q4!joBf`y'B`S8v>MhA!IlH,2N4-ۺq愡 ͡{`DuU*py& ޮ|BʾS._?AY9(i#GDF xeM }Rz47!Mg30|'JX9`.&V@V{Hda]TI'n~yN{0\hå'4(&o1pS~z=3V}N~V|Q0rrPh'vG^jE xeM 9(ҫh| ޾ n:?q,Di ^Y+?ΠzRHcz[ M$$㶮4$i Ki:Ќ+-? $W͸9zE?] ƅǚcdvUxVaCMGdE xe D~yW|KHB n: u*`&4${\[g;㔕NiC/b!/V'D xeA D9Q1B)o$ooBf`yMOHLn0x.G;DzG VOuMؠIZ#yI:WLž.\rKy 8G3dNH +ްАJD xe y AT(6XFM ҁ0߬A2D9v`ʓ'D8{0QcŮ3.K]uKK^JrZ@VJVͷgm;hcS~v9E3VmNqTb20jzhfD xeA D}D(W,I#Q }t3̛Bw)@-BE;Lga哈m]caey\Ӷ1%ԢIlIy8RYis,~~ 1ћ1jΏ%c8=oc/D xe 0yŸ@)}5з"ҹ 0߬Ip $E!Y$%hi9+Dܯ +vqIVhlJsС l$.A(RM)~~;6Л6kΏ9YQuF7?Eu xe >Y5*W`IZ{ef6ҫ3vHEtR?9Rkڙ5o{`s^R @# ǖ D͵Wm0qs~z;;.,[)%Z=NGD xeA D}|5*~ ޾ n:͊*'k=aP`Gタ*Md\d#벤8uqƜSVB/E4V@M)n|JUog (,(Jy̩"Jw, s}-Ec xe 0D%iZWHkCgy9ʍc utc@4wfT@!HX}ga]TYuOK^J[r-P"H a@# 6>*SD"Z)9ZQ*k;`cE xe 0yŸkJ~VILR"aN37{/|F{l2 +Do +vqM^hlJKI#@ ()$0` g;is,zm-mלK%AkG7p?E xe 0D~ExoLB)83a" -{ 1zpJ.K%~i]xжP-cKojSa :+,̧<՜K%vEi%hzwD xe 0y%hh)k eao=' A`GcF3֠t ' {o뚈4APpnSUjP\yRof~ RR%ے2嶞񕣲JI _D xe D~bD(K҄Mz0[fvs֩~Wfu!3؈dۺ&b4'1WXĔ/9ߗ)7Ԝo\* X/pcm D^xxQ/?)+5D2$(,%0Kgllh01#l~Ija xe D~bFJDK҄tXa}[u@glƠIk81zwa[Du£o:*A@Iex9hя/-_r(9ߖ)w+ikOPWD< xe 0 }K5ih`Q:tM{9 YѳШ h HΪ&B?B 5ޣۺ&nxEZxh:8 P+O.sbYѯA\+!"Cʾ|_RSw> t1Xs&D xeM ދPJ%,IZ"݁f?0ޏڨ4r60"ƅX7qt<ۖѼIxM;Yqi'񅋈)}IrSOƥh/pcmBVF5 xe 0 E}jU0~Ŷts2$pϽ{g9 =EDm3jC . (ۺ&<2v0]=:4-ԭ 4 +O.t9ҏ UP^/9ߗ9՞7;Zв9kEG xe D d]&PJŨ q-kz鰰,fRXxt< `Aa87 ֏۷-RCvaq;U BKB!OIY|p%я5>}L.t_cS[o eFd(j? D xe >b1+W/4!}S^,-3G 8H&4pvQ<1*göuJGL/u^* 'Us&Я_1"b.r_rҵSw>q-9}1D xeN }+|/QSkJRZjs9#,ĽQCu%j J;k`tBg˱+y\Nb ezHF@vIY5kITJ^a>%tbW[otG@>N*C xe 0yKt'W1qb6}-^,-3F>:F=zJA6B7)#ۺ&b4E?xxQ??)+5D<,5559$8,4-"-(()1qĴ Vc{%4 xe >PJ_%5X&ĵзE74hAskqQ*!j`">}c?ξ^.tuKF\eE}8钐G/XYHٗkʘy;Z|i'}bE xe >IJ Q }Z^:,0~h&:M4+Lpf L@T,m1E%q7QRM eao># jgMoWf2JjF;Z'AZh}mдIliQ ({) $QJ'e,dK$^ѯ]+>}L.t_c$I7Sf(4mD xeNI 0 ;JW-$MB_C/ #f[3v=Iʹ1?aBLqb>t hAC>¾mO SjhuרR_\̷P%Ր3hs̡|_cԨ9nљ-:uBoA xe 0EKaT(()ZL lf89wwAm 9׽C }7Y:Go[$Fv'GZ V¥lR S~RVߟ%|$*+DŽ9%Y#Yo(_ cD xe E~1W%iBBfssAp 0بvE}T^O!pa߶TXc? C?4KMP,? |IEt3k"ҋVS5rɲGxS: aC xe D~5F(&X&D-kz^faӃ\3)3h9NN2X m qa;3VEB/{D5S~ߟN$j#k ‡r5ed4h c9DD xeM 0{W]֝klnyIHH;*`4VQs0kَyF-.K&F~y֝7ѣK@:'Uv)S׬4.j)9*E8r@Op D xeM 0+zدT*:>9 ,$%).CqFr\%`?ɴlδEh5UBV1O>ۙhSbU߂CzѬB}N.>oMb[pB}pE xeM ދZ;a?Ѯ`oa咐ds  Ơ f@Ҙx†'IyHbg}; }9(.gۙs*Yzm …}\2o?oT(A_}(F xeM 0{W}ӛ cWzS:tm9 {Y^l}"RIkmF3Փt "Z!GuM;ӴQ5ѡ8^ @ %Tvx9֬6 )}Id"~(*aQJz}D xeA E}ЌQ *qK҄޾)B7 3o0& d{d,|Ompґ4=p5fǙuߎTM( Z9ŗg.31~~@PxEPLXR/1$k$W{ps}d#Fp xe 0Ee"+m2)֖f"Vn 2qV騜)mR mӈ87a]Le[w½oG/#m҂V蠎IU~&k/K\ƥQ΀ aEO xe >ٵ(W,IMz^ve?"ȸ8ZkDR֌&j=X<#m]SaeyZ(ѣ%vm+@P@Y*~=sHm+c?Φ,v u ӓ,t%,֏ ŐhSb!rT%R&5Y jȪ?_E. xeM އk cW}G!\A 5&v·΄Z0wqH^p-F2˒X0ɴlδ7U44Xg@:ŗ'mM)oC^FzѬƔC>YH7t-"opEA xeM 0{W]ڝӵe8*;)b^qEklwP~xnp#&@ddb4NgN:eJA&DNk[gYײމm]cfyy\t4U4I/'#@2g.mt9fQVCz"BLt_bIH7ZuF/pBzD xeM 0{W}ڛޔbO9 {Y^lR7h]-$;3hI'j{O4l뚑i^ttMtBsP\\N{l OۙA猬Yzms "~ߨP=*NJE^ xeM ދN71+VѮ`a咐d ¨DRD4!8|=+_%VӲ{oG-AIFF@Tv&ho_!h!e_s),[$GuV+>,E xeM އl-_V]K~.%!!fe,Ch 7o~F85fǙuߎ쏦x9AL[31jb/)&WR/1$k$G"@ _ck;QD xe D~5&&PJEK҄5t/agfw0wh`Ԩ5xgLsz (c9m.'-k5Ĉ/\Ęr,9ߗ)Zs_ >D} xeM 0K{دXb_9 ,$ȢCpZ V"KLS-k3D-"j%ey| 8}E xeM ދ=n1+>]K~-.%!!4fAor{  =v8 ,X?q]Y&m3m- Zbdh (r3ΧE~ V M1%SNF8s^F0}-D| xe 0y܋1k~PJ_IVI*fSW ҽ2|3b 8xUt,hMl4h h T=φ<˒ci֝poтR =w'ˋ w>%jckor(9)Gֽ;J/h_!E- xeA E} ҫDK҄޾ B7 3I>s!ة1n|XP9MK4˟_%flje[L{[- E+u~M)fQ@oEɗsL9ɣQA_z8?azD xeM +kvR+U74!jeffOvIP5 ";עǑgkaXuYBca=^Q) .Оl4@ͯL)$Y߂Cz~,}.xCLQH7HZ N\[!Di xe 0>EPJ_%?hUta[fvsOIPt3)S%NosoGC-@ l\* +\t9f^ѯ*޴/)=r$wJr9M5E/ xe 0>E?[(b~b6}@/|̮=q0RS>:U΢ luY54L,-ۺSܻ*:4%ȡgf;~ VgR%ǜ2eQOx|gR}i/DD xeM ދVZ[c8ڵT"\l!S7!jiG3w^L+@n& $va[טIv3V.4.!;!A2Q|yWgƃ1jl7.l)KL9N6Z)PCOq/E@ xe D~5j"_f Q &t;[fvO wlOY j{ezapg'uqqݷ#VӢ%6h/U%Lc1ћ1JJ%d=6ZSy0DO xeM 0KVcR#:Ŷ.%!!6=DRuVsà fJO$<ɟkM63]Ja==T^ՙAi~ V /dKJ%Xy|'( $iD}TTD xeM 0{+>Z{zcWC~Ja/KBBu|FOYR#AkWw!tg̯˒abi֝Vт;YIpRI䲌EE)lJī[`jq!e_r)S5q:0fyi־uD xeM ދVcW>]K~-.%!!j2Џ7VA_,  ]?^˟[%flje[L{[EZؠ940 (r3ΧE~ V M1c)'Y#y9*s(x[;E xeM K{ cWjqk~-.%!!: h NՌ>[~]DӲ;C%p@P\yQgg ;-[51܎)cN8Q=ock_e2E xeM 0{W}Xn0~֛t{S {Y^ݓhOG-E1?)@XGbzBk|q$J Ӵ̫ZQ#h :lW=$[bT=y}LY)ُoM >־UD xe 0D~E%qW&B)5I*&)k 9 3̛m|ypk-yMޠt-i=;5[JŴkHUf};u15j BP a+!2~73bIGH/^ q1ޗSTRM`G78UUES xe 0yKݚd-*DZ[D8afu 0\FaN"벤ŠxZu/qQKP;4A jgLqS*E?@)mNd*y_9*c@;82FD xeK 0C>Ό^ſ 7Mz#zqJ;cmmN8)d#ۺ&bdg};(M5  vA*WTDF?@)}I: %t {93' (2ω"qܺ*: [k@ Fk ʋ *g>f$pq 48c4R`ۺ̲y\tմ`2@ Jv BzE, xeA D}cRz&X&D-M鬆6>|f2j,3E"p&Y~m]cf>F9j :ց  d$h^uǴw`Bq=`0Q}}akJ;2~zmN3Z} o?o=c}E3 xeM އi0~Ekqk~-.%!!C c0`40k7b ۫aِuY1O˶{SEF*-VU-tBP^TL)oߪ!|,c1LYHwloS}E xeM 0)z~ cU):Ŷ.%!!3Qmo{g ^ A73iّّm]c&4vd<*Z\( ;F(LW^ՙs̬Zz ƅ|IĔ?t(8A2D xeM 0{W]Z _t[)^${/eBc]p1oȷ5=YeSaeye+՗J0+NVvʎHS4s~L),HwV#Z+8$UE xeM އgVcR_ߊ]K~-.%!!?;0X\@^:GSQIY?q\%fe[L{SEV*#ZA BP^gkO1j6b7b KJ9dq}`vmE`o PE xeM ދw cUű~kvY. IH 1pR>Myo0HgK4˒0Ӽliᠹ;YpbPC}aggN;3flLdc.r悅7*+@ZO;8@WD xeM އثLZZkvY. IVP(Xur· G}0QFPQ# /") iX%RM˶Np'KP RٙpS*YzmƙŔC>\2o?oT-{e[kE( xeM K{N1+jqk~-.%!!:<'c]*J8DsQboeeIM<-ۺSػ*:ЂK e(/*LaSZ~F;w1e_r~)S5VHcԕ7p/aE xeM 0{+.=0~ޤC~Ja/KBB>C2Eo|~DvRRz7 Fs1쁸m]68$v`8*:Ќ+- [^X sBZU )cI3; F{MY%D xeM  B,ai!eivO=)oЍKҪLK`ک~4(hىMۺT%3ۑhh ֨/n59d_)ՙ`sHXv+wc 1EQ"qRX 'o fD xeM  x eٯ ai!eiv%$Kxu䴝;f4V=wۺĒyXHJU)A 0e`@yU~7s:ȜG И^i1PK/`abQ@ ?uEP xeM 0)z֯Z cU):Ŷ.%!!3UZXg h5Nz2a1%#ۺLi\xU砸h:@ E\:̪[jo\XɗKL9NE?JE8AM@D xeM ދov0^gqk:ۯEe$$$Y}TAA6  ks>8R>R.K*M˶^N$AuU8;tJ5@o`89?K- 3)M;8@{`E; xeM 0{+>ZOOm0~e(:ŞS {Y^=qTMPi4 `(ugluY5XZuUR 脼 5ʋ )lJī[`jq!e_r)S5I#Ձb84k_C xe 0DKݤ*+IHkK40oVepCOq׳#0 ,d\uϼմH:A IA ~7rYG_<1PR1k# bE\ xeM 0+r/IwilA_i9 3ѳ0"Fp䇞)Bc@DH xeA D}|$PJb'X&D-M鬆6>gn' &w09"5foGUFA%HD|sctIExuNKn sl?> EUwQ`L,~DjOM4<Ϊ68Jn4W+)b!T uhJ54ejW=n@P~ Ρ Hp~S_M˅ӻ\roV70vy=Gk,]`O;%InxQ??)+5D(-<9<-,"55050 }nxQ??)+5D2<$8(%%524)5-HMԷe664Xlnl2 K,[xQ??)+5D<4% 21-<%9$ 9,-(d6Qߚ`b?ăZl vaxQ??)+5D! ,5(9$195)1 1)r-|f uX<.I($xQ??)+5D"02,(,,%72632NKolb`>1ߟrA 7o xQ??)+5D"92",-59-,015 42i-|f SuX<.gMxQ??)+5D!2,4,4<228 55$(h-|fKSuX<.W`"xQ??)+5D!("98(95559825"099(t5|?sSKˉ\8xQ??)+5D4",,$<15-8$$"y=|f KÉL1 xQ??)+5D!("%9 5$) 82-28,p-& uX.TNS|xQ??)+5D! 15)(<1-<9($$2 $41`) dn0q\Ѐ zh9xQ??)+5D!(092,8"8(%8t |?s3YA|.~G.xxQ??)+5D,$( 119"2)9)$5%% (lnf1Qpb?ă \ gxmMn #ؖ*(EHT7SWpBrtjf,j;ä%Z>3z\I)#@Lkj֍j0oej8*rB <#_ߵ%T n>?dK uř\rtO|(ᄻ u%IxmAn Eb`rȀJV{;bтiMѨi> H^o?wPR,ح^*S~p%[+#QKuRT(TZ5gRo"v,[J w5\r n (3vpG>A%7?JG9xQ??)+5D0%()($ N17705L51JM2106omg`gd`hn`617hA%>$QCK.П8^xQ??)+5D( 1(51$"% ( 9u1<&sˉUE-׉K]xQ??)+5D,<85 <(liajhbb4QߔDbb?1?pA=&s.T)xQ??)+5D0,2"$(8)90<9--80"-x5Fˉ<.7[xQ??)+5D0299$)24(8(92,$85"h)|f##UxD8xQ??)+5D!1%)10,$1 4)$45)x)|fcKUxDqz]xQ??)+5D "$< %24% 9h-|f#SӉuX<.9QsixQ??)+5D,%$"2$2<0r xQ??)+5D ,-"0%45<<8 41)y |&ˉtXA<.a]uxQ??)+5D!)$%<$",-0252i |fScYA\.wcKxQ??)+5D! $ $ 0$)) .O]xQ??)+5D!))0<%990<15,),,%<`5<sK#ˉ8 "\7BxQ/?)+5D0%)8,%$-2248"$51)q|fKsuX<.P{xQ??)+5D 25,1$2,210)$t)@fUxb\tngxQ??)+5D4<$4--<1,2 ,05909"q-ļ@& uX > c1xQ??)+5D 40<" 1$5 "S-'2L `644xP 5:xQ??)+5D0"-,"25)-05%<-2<$r-ļf##uX TGCxQ??)+5D4-"(8)-<90"((5|)|? CSˉUxU!xQ??)+5D$$( % $1119(91m)|? CKÉUx<}(u.sf,C %I:D\oRuo-QOB,,Ú2ܔuLhT"ۚN(Qerp _o|m՜ 5zFއ˛O? /H xQ??)+5D8-81" (5205%%%-||?f sQ%Kv^x5ƽ @ PA)S0,: P|KlX/U^&6օ9!kXǼ4ެkIAhT\87NL"YU_A0/$xJ!} ?sDuqIoQ W~/9O@R[Acq Gi ic!BѦ ɠH-Xs5eq>GZm.Z';}2"Q.ZxʱVse$[(%',= SJYp%6\lP$I-1$qh2=}A9FmuPWmBo b w*>3}'wdzT o/1G}}ύn :'V`Q)q=B%tT{Ffe0xKJ1D罊 7|@DPn~N1ٿkvjpș-D֘ ( ZJgK^4r,J]ҮdP)<9oFk~>js:ycWxOS[tG&lW{_J=2+g؅n@(D.޾5`xIj1h,!/V"/UP܈8',n]gLBRD҆N#hMD%%ނDT[4-Jd?6,0NPGmL ^bMMJtgzR(2Qo2u)Qyc#t{ 3_duxMJ1Ds?:="Гt00|]YPh0gkv#WkFzS:DΞրLH&;tBs|.>Ye.WdmCTHPBY7\Y`/g8oF+ ʀ10? x`/xIj1ƴ6K|hԭD032Z}Ա Wf$G9(o6Wd- /P X<; 㬖MLRڙ4oxq  cgG+>JJ[ogr蝳[x2_G 1yc (dxMj!<zT!0!ucBU-'"Gp(>eMh+ZC =mM` S4m.h YXR2,8g?GmLZ;xUDstGK.s?rw&lKlG?Sݑڬ6 VVR\/5xofC`xKj0>eBV }Urr"`V ehVFŲrh}1-J!ox5:yq)R+7.0!-~WmYha4Ě5GtWz7)͌qpeeڣ_G%S.8{ĆfexNKj!{kul!0!$BLRPUd9%J͖7k݂i5Lq9xkm9m|l)\g20g;cx-ގG;;4,L&keZbUl3hgWc9 S=J^qA.;CUhV!z$wSo$`=xK0>EDzÐ A-m50\a޲Q\@8oSQ qBoljMr<\!Z7Zh']΋0RDˊd)\g.H<6l7H+_0m VuK.> RJ8O}C{Ŀf[fB ^}!tX[.2Pfxj!D~EiM;:B!`(ftq3 u:Shq"2PΞVGq=!0CFJd ٰ畲oDuI)ʐǽǦ_R[S uIJpv?X h 4xwӈo` x5ƻ @ P% Sd컜f>J, d=*^cXHt\k5O`2g" uױTFe:d5Pd#B6q+1翟ij? "xMJ1Ds?{2  Z<@~10|ݫū=%9zD:Xl rw=!2P[d{{Ԍ6n03l]|YeH]<̯(dmCOVKp |hȬh4W=qwyyI3n BPI|_4x[j0wb,Y1t AQ+ }UǕQ(tF[$kf1Px\E\BZtNoSVBje37*[)u*>3;Y*SW#}>Bon @ ẌMeH\8G{J!eHxNKj1B)P.=fFHIsL5hѦmqZZP<:!/q6C0Ʃ1@28Q A ExT}Я\Nqyz$VK>فuz-rÝ딡8ANFK3-g7Px f~7Y_xAj0E>Ȓ-(%'4 ҨW%W_yRAFDS\VZMqbv2.ڜ _o~&HjV7>-S㙋p#>TzSz{qzu5\#__Gc.8;{Pa/|_fzxMj!} M?BYZK"t!)ރzޘZ)SԚ!(0h `'d\ZԸtLF{ wqCNG;!!FM|!s罶MGOXe]@XC=kܦP\`23g.7"Mf+/ [͏@++avY_=xPAj!+/Kl &Œ.?nҗV[:e",C$vn|qc3:o(hëV 9e<fO1,n {.U|=.SFU\#d,2&OLk\r x̡/BYo6~7 LMp:?fegXfuD (%v[SaxMJ1Ds?&twDq- $I>bݫū#gś\,޺N̙$w*bbM=ܦg|ʘ-G!|ژ hp>G<G\m.Z';}2ʢ%h}3)[Mᐩ i5op]Y(|>I!I H_@_Λxj D~? k4 Rht]7j7)fR d0E93v !{xpK]z1m8,Q1&xEyuU|o񨭧eK2VYj9p%ާP'@#g M'=r:W~ͤ o/'^RM=i_xOKj!{ BB!xO"t` 9BjST-34;dDN--?xC9ɂ6%,{ "hN.@zk$_Շ6|S>&JZ꠺?'jD$&` {y\"KYsvM_ty2BT~;͆~`xKj0D>L>@:- !yT-j6`u iT0΄NQAi4){ʑhr1&Kug>{#uv˟?\_5ㅡ&i.pj9ӣg.o7˞X>?^AxAzR wS.?q_ǙxMj!`O?CL drup 9BjST-SB)$Kdk1qdvciS.ר ִevhuL^8u>(I&j⠲@qڝ+"O=x2>o<=|~VuQOR`xNKJ1o?y/I`AA\#UU5GU_5ޙk %$KQM╴YmI*JJEpFb~ͯ>36 ǽwOyѷjTpt:^?^=C9?Pmt!`P~7|_xNAj!+/v K$ry@-ft1̆72_5@Y@RwRjF'J.M4VPL!zP`<-wߩP6 &)eU>)$C+ms|_a1 8p_b;|_5v.xj9ۣ' r o+_~@ g87A `xxj!Dn؅s8NK]fC>!u)7Ynø@+' Xz('ˆX]tGrUJg܌@VL?__xj!>E۟B]9<@-ftg6RU8dM+fdbh1$ A6@w\\NlnHLșP_8ۘV~ >y~gY]>Nu{Mz%wEg`/W>PPeVE#48axJ1y/:?=& "x󇁙dwV|Rwq >akYubFJ*觨Mɞ0,|6@BCkt:CD>+Y0:s|>lc[1;d!wk[-/Ou<:W>Pꖡ-huQCi`xMj!- !0uJ-ЭrԦxW VI^{gJ&m.*!w=Z3q$bwlT:HB{q~Hd6$V G (}{qk:?cv~b>^Zrc |inæ{\y4;Kȋ\{~b\ߛnbxPj!n3 Kl D KQUPUto1[ޕix4VRrN-Wr6YcJjU"i)^yFQ^[_cR8)J-9бzp4NYirTܟ>o!]RVrߒErCiH A1[@>9Op8ٵ;,ώ G6 ø,#sG|>+˥ޒ(UBUdsSzz%'OޗEqnp8[u{'Q))-T|3HS3O3/5m}O nxNKj!)6>φ!&9U"t!)>DH B ΃(aIz##N-μFJi"xZeLX$eɣ7:Bƾ(}yƮxS|$UHj꠲DHxW 68kŜg{_x\v ^Ae&o`ҙxMj!`YD'GբF'1ePvRlHK4 >:zUc:QUlVFRpVf-a@Xu:&/u~,ʟچ8b_S%ㅣ KQ bgz^y[ىog4 /螔,wS_MxPKj0Ja 865$_OPo1rvk<) *z6&eW!vKΣ&٤Q$J"nAcЌFms罶.{vqR>^Zrc |hV\&tܟ>o<#47Y@/xAd 8UQ^xAj!D!&9JnzBUW5zJ`wfJrf #M9R:˔ {|Ԉ@Rc&mu;)h08n¬c{q[u>6^m×5j~_b;^WRN:.;ۣ' E/h.Za~_kxMj!`Va C'up 9BjST-щ8&*E{V7H)V$NupkRX HQg@cXܶOʫdXug?{:G/DmCjþ`;^\viN=x2>o?uȋOW -M~f`xKj0D:E~a C- !)j`ݴAĘ)M&ZU9Iݩ: xk*a6R$* ԛ(9[/?^|Gp_?쯁j%оvM9锔pe<eo7eOht)pJ:.&<_ޛxMj!`m!&9~[G#6Eow%X[D} MfwTb$fuk::t@6H߭8 q[u>6QؚmZKj )8(_.{\v,f>]\A+%`nEO`ٙxPj![gԁ%6rD :U{KJMh#Y@`I%9vǖJHHJMkC{2;[p;8u<J*J|,a۵S;ylgόeo7Na[쓕+RBN`?$awxJ0E?f&4AA\NS ͣ&o?;wqmg LGYFň!#O.58=h@Lk'qa#8̪ z܏4xlGflOzMպ?, 72\^ڏ3e˰^i-H,e$!Dgn U^xMj!B C#BF#Uj!xr^)*QKgJRθGbwM*'5b6s>HiW(Fk~aNx?}Auzv huS2._l:׏g(g4BjPs~7q`xJ0E-3igCq-~ؙ6y'xw.νH9 (ˢ0袺 x$20R-7'i*Vfa0eQϢfAz,սܺ{IͽRUw_:??nKNV]pGj?oOvs3˄ a woM_}xKj0D>Z` C_- !)jY"M)|VhJ2J|)j !=9He2!*@as|ξ¬c2qo}ήxK<5^/kv00NmrB8QƓƨ* O@\MX~`xAj!DGnG!@!8NK&!GH^-^0žɛmt l0`mعɰ:r [0obW'읈s|.?Yǔeȷ.׮چ:c9R(Ҋ.\W{_xy,E FU07Q|_VxKj!DCB$2YUDևTAĕ!T쎅t(f.&c2)Xg"EƜ59U w*g0\W{X_Y?֧8O [o5!S?9A{~SW՞u8^ޟyr}#.V,h&oaxMJ19EC&Aq- N֦Z|Us̯JOJF)# (dw?r\PFC:eEd),IGE̯ ǽ$_֧8|ݟo-㉣qJR bg{`/~Rz % '`nJ_kxj!D~š[G%6ruz0ِOH]ëYF&ΚئHP'Hqqd8ZoPCҥQC4%x6K2i!YaW8un:IUB%O/eN=r2+>or;vy k@$ _=xMj!`S_+ !0ul&B?NU덈 Gz5{  jDQa+)l ^FiCY6ϝ:5~$R8C>^c(%󅣙9ҁE~)6gOr h ^>0]әxNj0+$1N`)-K?OjH%kP]Ivm!0:%1&6 dȠnXùb([YKAl}ܜ\%jAA]Orqg'\#CKmam%{//@zXQ1\p`۳{GHc3B' $F4c)v1^xNKj090JץxQCb͔ !i&YTЫNuuY nۢawONgR%=(OA)W2{huL^8u>(J&j⠲@Qu8N(sg /h,Dw<_xNKj!{ [?B!V0r4 EuQU=zJ48#Иzp)e,aƐzP{<{I$q'~guLV}?}~GV6񌾶ZY7Yƕr$ϰo\mp}9c|v1`xNAj!+/Kl 0lRu(U[J`I΅KddtJ *B޺6i>ZbϑzR+ƉFM|m!sǽGXe]@hC=^7^<*qQ'3=rvoy$ 8+;S V `ΛxNKj!{ {n?0@!8#BF#6EEU {2)Q`͎@OOZ'.됔1o1F<]YM Y9ZYǔoe]^wROTmC1VK $qڑ+ {^"Y/hL"U?`xPKj!{l|:`B!In?NRjQUDO)fR err7{rFZ2{T,&K1Xj%ʐ F/'_>Vu˟?C9c- P{Vp lge/AfԛnxA`>AD!_ܙxAj! s3: Z(] jŒXmMx7fl6R3iO${Qi˝6wmQY;Ш蟵xޮ{m<(R(OJ-9йz=jYuL4eW?./ϐɐϨWx$j 9~;q, aWxAj!D`W0B!POnzBUW5zd`#E\c(JȐ$v=Wrm 6G&Xug?{#w~M$&jeMZRؗԎS/;ۣ'Ʃpf OW@BM`?K_xKj!EÇeG$2Y@iDև|wpNNAE[K*;$9hi!a쎝I%vFY: hH)"6s|c2yo}PDmCXDŽՒv>p0ˬW_ڳor Ϡr* $(! }`/xj!D~enՅrv0LB>!u)jh B.)D(׈! D{ `@޻Pu#TWD1>?ơ_oۣI6K[ͼιoj I_:ۭrfp3^NG !4` xj!>EnGBB9"b3 yԥ:|U ɥU%d)!3m]9r M<|u%T6&F5\r1D/GuLx-ގG#wx_I$S yD_[-Kl3qUv g{_`+{LfAtE!BE&o{S_xMj!`c?0B!:8z8!GHm 7"NE{L~݌rN\& l@=4*jM!nϫ\%xQz):RRߵ8J=wqkuk^T!yRl a19Nܩqig!rL%w)fwˍB(}kvka|"9qTQj)R%G:XG@ nrbO./ϐɐg4+&\DRwo__xKJ1D罊i `;ydIQ58Us13BdESA)6HiP 2"  ]@%81cI>A[Z^do罏I=_'?S=0*c~>2i;M\ڮz+giwavy\] iEԂ)obaxNAj!{ F(BoIXmMHIzc>!!y h,a:,Zrs z܌7=!{Y|L3EnA/FP %``xN[j!/.vk; K$rg!Œ.F8B zch n)E aمՁEc%Y!O;uHH}y p"Q|_GC._{mϤRR:c>Xj[<[=$P0$/zBL{ۓr^I^4xNKj!{ ~ !f drOЭIrԦb}M8DJs%)a'[,<n`fdhpH316G郿{m=64H?%R81/K-9ౄz>sXoJ`=sto/_yGi~VuQ_R\rlEobQxNjD!g?80Jץ}|BC $$ j璱6FEPɢfs`RzG Q*$R*PHɛhT9>[8ZGpqlPj%n+NI,e|wo/{y=ҜWVxe?}axJ0yRv&m@DPl] OL*>sfLo:b(8Qn%ѢxKkdŋlԝ]sdAa%1I@vBΡ ϤhGgtvkʦ%9k7)YϒhR=50ovu7(\netYg`na)xMj!gF!@!aFFrԦZ|UqHB8uHw@oc&Ի!vNupAyq 9< 0cI+塈29>[a1k>DK"5Q)bmD<خGor*\s9& 7%JN `kxMj!`a C'up!)_Dmo^gKA᪲ȫLBewTFQ0$$qVoWoq3ufߎ{:G/DmCX爵q_b;8M{嬴"O=f/x.;|~Hו+BΟMX}>`ԙxNKj1oC(Jץ0cǾ#T4:3p2Z9ǎVmdSVe E+sYDŽ2m>u>,N&kre{ZbαO "8ҽ/7ecgx *I _xMJ19E33AA\H: $(-dU8h .~;ވotiW2:ޝUJcaڑ2(蟵Gxޮ{m=5x_Q$cvy|>/dzNj3 ĤW?+^ޟgc~&Y6pQH7&o_xNMJ17}mg@DPG0w`FGCm\ytl{6l&vw=с&)zçYLQV ss|?c2uo}WODmC\OVKp zo r2~:?\ZI-F@d_xMj!`󞭭Y'up!)[TD:޴)O҆FcqENfv`(aܒCk0)jl0 v[u>(I&jeZߗ؎'ڭV_;Qwe'ϨP ^~]jP`̟Md_`(xNj! |+~$ RaW_[ IzK NNB6FO;)$\c-Qj3䜢f4`PG >Q|Sec2VYj'%p%>Pg [.8KL's{>g ξL$\V$Ms$ߛ!_xNIj1na Cc?HB4zJUր1g'sPy'*IG%Dzd-BKȽC+a:I_ˠo:GdOXmVKpDڅE#X =^~浙 /+̟|l3_xNKj!{ 6 !0u<Э!EAQވq fOYm;b@IlBhpkT:'pH`{+Q{6ʕ?k~>k֩xDU\%w,O̮,nJ)~lg^oC$C)Lt]z?Ԑ؃Ǿݟ#t#}k$6W6бZـN~QvnkM=)"#Rq4E%lou|;略P?˔KNggscv|!M13/7dqai4&/a-xNKj0RB35$sj!!-$,-9c CHpy=4.]cZ?P+EcK,蟵ɏm>kֹxDULԒ)I[͢g qG+^o2e:?NxU Q0~6Q|`xIj0D:-hB!|k [j GHmū=%18lJTf>IK),xN=F ZhH43:fߎ{#u~(_چ8ρj%оv܌z낗_Bs1~:}`™xNIj0}dX !0s- q'.E2zJ rIFԑg%rԎ'#hRRA+{77Q:|YDŽ2>R|DV6\mO@ 5i XN({'gR+ʕ.̑jg/Z_xNIj0}dZK2 !0s- q'.j@W2IQ9Z [iZRBT(*EIvsҒsFe(=kddn:&oǽ:\#xlWj%} xAr'ؙe|wo/{yA.{|~^% -Ϧ`_!`MxKj!Dƫ^?B! at|US5G\ZKGME*,D`Ȓ;&w0JcƈR1I;rڛgG\NzyL%h}V#[ +2<\K3/gM .$\?_xNKJ1)z=N& "(kb`&yF֦誢z)JRqtjTɃGkmô,K>"3piO.hgbG >(}kvk "]"TQj瓷z=ُM>T:wyyin&^QxLnHpG'-V`xj y ?F#J粉 >}-#tXf>zLm8+fiTKt9)m7c%D陵ɮA5 htzUK&Z)vv_ڈ̏ kyÇZyb0{(kg794da/w:z>) ; HL4^;!oWI0R) ZϻMMsm]x 0E*Pf7o)'rkb"wM pْK(\91 ToSNQA e'%28,mӥK׿_|`XoẉӤ9'xNQj! $꺻PJhT*kKPdfA[JJIWn{l(ͽU]ޑOiKG0JNZI3j6u+d./'v\^@wp9(}3|FH3'n dhI,`8xNQj! Sb.RhF*kK0̤7f`k#ec cKɒ>$' /w߸tPRRX vL'NqH-~#o׽ !Gvq|>E_jџk#+GVO./ϐɐϨW96J5NoT^xNKj0=(0jH!_!-$3g 7-1Btie 61]=N9dd5#ڇ|-]v|ʧTs*5U[W/Kv2svZ &=pCwngqۑŭ<ݹo<yerx zq@b٘{,>\ϭkjvKmCsK/s.m8O¹$|.RG- 754Jb:ıYՂJg fa<xNMJ1)"k0~V@HIFOAh(HbNH=T3E6EHH/Pp5fkUpْc1k>Rgxsm+)jc0h5¶ҫ^ޟY.gby}zR07 ɝ`xMj!Pv0B!(˒:c~jGYMœcxm9+lpⲸKmc" a : .{"Gl!_KoyʟSںڱlτBOVjy9b^ҿ37Wd.~umS0~Z|>)aaxPIJE1yAA\{'&7G)(UEρ\Tb[gd% ošVF1#QxrR`jC\u;L&gW ^넷+hIPϧZo5Hztxa^udo.yyRO7suf~ӔNAB`xNJ1+t8i "?3Xi/ @HIF'6Ge`*:Ie`Щn(2؀Ph tLѣ+,:_o׽A?̯,ʟچB9R-둣yoVz$~Ϩ7X-E$`&xPKJ1?2t3AA\H $(ZT=:J]YuHGH^Ƭ1h=tk1Y%Tz7'tY"E/s,:_o׽A?/O l!PΧj%sKzz}(w8o-*'s3\X`X¦@p`Nɾ8a>xOKj!)zc=B!h%Œ>?s4Eբ!8h8f4Z)]NKrKrٓOYWbKyBIO QQcESb.NcRK|\C=@MjI;ytܿ37wy~{inVx_^|  9~:E_xNKj!{ { C$9Gn?sEբFO#8P dpȐ4 N=u<ٵv9M*fmv,FFs|c2yo}o3Dl!N*cj t\C;8j4,[Yw'ˑx^qW%&/:`wxPjC!|+|qB)P^6T8Gm Yff鍈_ӊ*8)"!tHjA)`"8vJI'%iBD)J"xc̏S?s_N=T"UQj{vuruj!Z~9l^<^>.g~c,0!`gJ @_xKj!E箢姵G$2Y0RΩщ@y"ܭZo%9#B"T'֩=T)1$UlNULh9>Z0Ru_?}9klmװ՞e|3˞ߞ (4jS/`xMj!` C$9u0z#(xQɓe^9Hfw!Is@ 6Jol)nvEERT; s|c2yo}osωچ8C9Skj)\Vz_.{~{TU*JRrʵ`xKj1 D>m C q>GH!P4zJ@BKhR.cG!}F!SOu@TBfQIe6tNy-`:YDŽ2>R]<6^'1Pm: SVnp%ҳorr$g% RZS/l_xNKj!{ C$9'u0zRU$]9hDdE۞Rvꀐ#a4NeAfwaWH+ux /eyo}PL9mӗ1jv>nm lg˞ߞ B]qB)5)aěxNIj1n7 !0sC=xY!A)Q:sw ( |6*Pgg]OuP49-R Xu:e<+:JA? v[|DV6\mwlO.,ךzҳ%/7ˑh^QnxU(sܐYESaxNKj1)>8)S$7FrKJeT4pfǤ( jdo8gmoǽ Ds"UQjG3RKO mlp‰eGۻ`;6?Ksӯ*Ϧ\W_7xNKj!{6 !@:|[OsEբFg~qf#,h%dT[kGN&::D1aNgk]$H- >HkJEux /eqo}pL9m#BmPدԎPv[^C qG+ߞ !˯jT$ΟM%`%xMJ19E%Lĵx~I3#&7GW=g+O{0)%hl6'h%FZܹ:FDh퐝Ƅ>ygTm 9>[۬ckv[u~%YH&krUbLvvڈȏ1V^4۲*ka/b`nI"',KU3=4),>O?YkxKj0@>(RdY aF3j)UkE$֨ua2R@ .*qz`H;"# `Ș!53U=?SxKj0D>Ef< j%V \!|UEq#+04DBi||E0 R-da:K'zI;Kpb jxkoT:ҹ_n+6 /bf(WQ"QiݱQ`@nY_fhxKj0>e$YJ z l+S+t300C-GWrzc 4RJȄJXMO,|6 e1Do -ل[* {>S{g됎g. LL^}O+b>A~q*ӰGjNq$bq=bal|FP#eJxMj!F}"`5BN+ j?>B{|O*3dSf˄.xk1"⒑Ub\pFG|dM1OYyo#@A(NiSuV,2PY+>LLVS]ӹ jt56 Kkv8"&?p1=Ua+q cfxKj0>elc(%'>OT+t30\Wo)YR2MTB&:ZdV!U:"%[PQQ~QQohP$: ,K̑icnvsv{[(;jVX`Q)˸?c@=/]dBx 0@9Nl wy@gUEY$] ^e;]ZO37Pbwj'LpUGx+V,P,[,J2k ex ̻0I58wFBahw ho{O0 *#{#R(Q9eI e+2$l.D@}~=@ xKj0>e$(%' l+S+t300x ZYU^nHYgDmCP(/|6`6JVưMF IH&.BO\3~xҸK߼ϔk勇z{ۖwXVU"\q0 {WDL~2sV7@,=/!dwBx Ľ @ PA)? SR8SFb-Wk3' 7VRٚ;f5^=9₀DBpLuiEw=c4x ű0 e`| SR(H*s9ElX7]J뱻϶js#ѻDQxp-P,Q}|u1[Fl Hz.¼#+65M~ $x ı0 e`˲4C%DZ-/NwZ}PHFY E"<97 Fjq`Q@q^S;Mx xAn ~rRUB"&uTB8# 7"jGmT^699JA - YgEV:V#Zȇ)U|x|Bٟ15x{零KOgtW4~qʭU aNC@$q=Rt[#_merBx ı0 K, Ԕ)dK"9`_U{>ktcrPŔi4@0@k:VDaOk˞ld[tnr~?"? Ghx ı0 e`Kmi))$,DZ-/NwZ}f}4\C.h3b.]@l+=S`jDWwr> ԗxAj0~rk˒%(%/] ҪW%_g`0Y@z2sX)hrF'Z(/| 84QsDƕ¨mjuf|I) EK߼jlT^vVkW I>pO.8{^[)0ehhx ı0 e`[Ҧ qplX/N˱"գI(Z,#ݿǬ>" d9Bو\D$u;|M/ Ex˱ 0 @Q`;g(lǔX`;(=üo5\,Tjw dLl*攵O6_ZC߳hc:) Jx ˱ @ PA)g SRg""([dփuqݷ<,Zz%o-*hYu"O6[Z( Sg.̠:~zvHd֩.}.lPL{ [x Ļ0 3e`X>!}: %q,B=-9WDBj)H* ΍+3ۑ9A8࿈juN*Kbx Ž P2Sx`)]eY^Y{WvcBsUfLG+4}=FxL`T;wH{w's{.:Wx ı0 e`I$3C$DZ-/NwZ#bQA< QTNUsqȔbdEiu_;~ib\ ` x Ļ 0P2S0}>iܷDY+ޝ QnQɲPA!pt z|vΡX[AҨBYk}',;M!OSxɻ0 e`)X:%mq,e `@w+1Eh0"֜ 4?:5Q-} .r?2;JF﮵Re <%An qx ƻ 0P2S0}?|3NIqJlX/4ONwZ}13t`e0no fb#8]KÚZ }$f sxKj0>edY_(%'>OT+t30TA*`KFƤ4 xh,g ֦䝲FEdZ Qe\\g4wW>bs ']Bٿav5ܬÙ aLNBň/~ w R-;lُ3^e?x0 3e`d:d>"dLzyi;`Քkf=!&0 횼W}|N1z%Y|.x ı0L͐: @|^ė-s+]i;Ug,PwT@RH&S~|tlfʂg @*=S]v!Wmx ˽ 0a2S0LJ!m:χ""([d֋xNwΣ9R3+Pnb%zy|p9+\bG Xj)k{&N Mx Ľ 0P%Sdq?3PS8(DlY^t#8z!̅2{U9& eTֽ:ŁHgY` x ı0 e`Kdk))$#DZ-/NwZ#b:7<2 (u䦣X_Ѭ6uЬm^TAF*Z }Iz, %Fxʱ @ @e`췍=C/B,E`$Uw,9 %0#:QKkk뮄V~~vfbN1cשY" 18Y{ k 8x ı0 e`KHCt4%DZ-/NwZ}T)$x!m@c`0;K Xk÷sF B 7i8Z NSylV l`x Ĺ 0 @Xe!uJIA`x#[d\qWv;ѹNC` ڲ7&O}͆A@9:2yґܞ{.K x0 3e`e$͐>,}"dLzyi?`f7:H"tUJtT굹s4\\l Mƴ \Fg*-M!xx ʱ0 e`˲> SRXX.s9ElX/4zWz:JʶptXAՁǧ>T#n*ݴ/LDu&A5|{x ı0 e`_ SRȒ\r"\G^pJ0Cw2y$ RRGW xx ʱ @ Pqe`C|Ct4?""([dփU,gY-buvbۢSKLk[|J%HjH\@MCX_oð\"YSx ı0LA@fHTr>/Y%_]GC#XCP'|/sRE *9'*aoa]F^۫\g 1xŻ @ P%tLriSξ(DlYw׼{RcQ6D1yM/ou,=fCơdt8 Ja m&&3Mݵ!d&x 0 @A88OnX}y=% !Ru4 N%KL:۹  z/l ^_*۱Ϲԡꦹ0<}ca$j#:CIWnj^Qzs{=:Vx ı0 %SdYWLDVq,`xWrcL K&AS3 >mxS  fAu 7m:XtԕHϭ*''x Ľ0 %Sd[?=e$\r\.- +U2;0<**XHTVHlJlX/k=rPfޣh#&0Zu%FcERL@t# 2Z^Ua 'xű @ P%tLξ}^6)H,y| QI l":*H6ڔ;^ņjp6f H#D^!q3k3Mx Pho?+ܫñin\黼k3'/Z#Żtq/L m1ʾxq=ʬH0@qS!gx˱0 Ѓt$Y֗gMI#]rp" ^Uq9֦$pNQzeפ9J,WyLlTQ]2_̩AN2`~~`_G[x ʱ0 ЋL֗SRز\r9EyջcwXY)b{{1 T5¹9w!>t5ds<^r;xŽ @ PAL R2lX/k5^z$IXHHڒ@xS-*TebAi*$g\7v~>? !wxʱ @ P%tLwgyj+H, k9oHe5ͰRr+0-_b.y3|t:ϋ4Q!x̽ @ aAL~[!uZ (B,E`=H9>(.D -SAb-,I>E{%bEN 0DϵȒw uxŻ @ P%tL9}+Mq(DlYw׼{Bj [bVHlЭa/"wu,d "ft4DQ\m}LS6 #ixŻ @ P%tLlǟiSw(DlYw׼{梙V-Ӥ)؝E<zc*`A@Zm 聽s{d-3Mާ!dx 0 @A8OnX}y=ES/ Yj`a`k` ۹ u0j% F]=tWi)!+xŻ P P%tL]6\EY$b zӜk؁o)&ΙCTKo-h uXBEs`@ YVkinB3My"@0xű @ PAL}R2lX/k5^vBYm)q'Bf)qc2P]T j̥5kZޛ7zl3 ?!$xʱ0 t$˒R-Qr9ElXP}xEL;iIƂM[ąJwRK).itT_9~0r -x ı0 %Sd˒)Sȱ\r\.- +ޕ{2e*~v.]hsICrkjE=zsA׃)]4!B>JlX/k=|OQ FqeI*A DsoJXL G#"-!C| gYEDJFD5Ya{N7HBx ʻ0 9W%HGrB!04]Pd}oxr$!bkA(5aM@4( vӔsĂbVyY[)0]{-xű0 Ѓtd+NK!٢8ElX/׼{<"&ndN^d] VbT 8[4q Zf"Z^}  xȻ @ PA:`VϾ2lX/IwG,HI,)qQ­p۟0!"Sxƻ P @AL6xƟ2lX/Iuw׸{Ĕ32(Kt-Mݤ͉W$t1EGD.* - 9U yOŹ.t~P!2Ex 0 PAo86 {倓cU!Aݢ ^[Iq=v`rV¦fEgda׶yL jA]VVQPJD=  }5!<-xȻ @ PA:`Ҧ}""([dKR=]5Ǟ9(r!5%txɽ @ @aALVNK""([d 's  0x̱0 Ѓt%{Trp" ^uq;v) ġX(63iAuIrc"ieNʁPaXmIA"[xű0 ЃtLl RKrp" ^k{`0P!e͓Bk* Fͪ02E֌Lq0ޫ!B.xŻ 0 @2G)VHօ>a^YE4CZ*V=2Zf0^lEE"\=(,ą,+$? !8"x Ļ0 %SdK~+SZed=wVpDØE0RB8¥9GLW&X!CIShyJ 9{xŽ @ P%tL+MaߕEY$b z׼k؁Q0Q3gH&}X%H(P.rg`{h0A[t~>Ti nxŻ @ PALgW"Xe,zQ^Ȝ[Ʌfb#h)U W s#sR)T_jxXs4uJ$ 6k]x}>@? !xŻ @ P%tLw@M`D("[@C9'}hT۷| WJ+*⊒h-\va{& FSxű0 Ѓtd˒fMIc8ElX/׼{<"&7@Akib)TzJ3zvNB%4Ґ{SHWLԤZ_׿07bzxŻ @ P%tL;=-eߝS"e-X !^c\ (T!09Ծ:y`cױ GD[`EP2tZg]rxű0 ЃtL$+P\r9ElX/׼{<"fRQ7 OnZ3o6iI#s( R lth} ~ Bx 0 Pܘ#8W̵qU]b zIyݷ@HPUhA Aݬ^_u羄; Jrx%srTzK)||T{w w xű0 Ѓt,!+NK!c8ElX/׼{<'VQQi$ɤX(UUs÷s:s)[)l&v)~-3 ~ $Jx 0 FaAop++8UXu.zғ>snr|>Ð!x @ K.aw~X=C0nĤ4kގMaP%\DYT+UoXFJ<F y!S? 4*!yxΤ[Rdbinjbdlbidjhlbhd`hjbijahhbl81֋|`0=x}YyO>e(R(T2g} B*!{TRHK9-%HQnE紜ϻXZ?~={ "8"˘V*!tE)ҐjJLI+m;7nK~=>*q 53Z&`7B;"tJhY}VC^M~UguzBSCX4BTȝvς41gҬ[O+02ƃ³sci(4Ԑ#d2OF_p6zq%QmA+dt$P2Pl cϋqFʊח.0ަs`9S2!OTW>y\>Lދ 4ee"q2nCJ1HUҹAs໭='#U./0 XQi󩐊D9p5)I}Wg&~3:l=ayβ1Ra (YCpܻIw?Pmm:A ]&zYOJ5N)Iy~ .ٚ5KoF FADI}J-Ye NJUdﺲRA3k<~M\\Cɨ2yQ)|E":jIK{wiowrxG&PkȥBQj9xm͟81TZicx+ m/MVGtk½4~#iPO.j3Vw-?wsJne!婔Lhc h$  :]?UO~`rC1b"2xw`HƿXu!w5x0iS{>hAB 1wû$2 7+|~dz?|} &!-22v|*R pâGdR1>4c/Vv;- L(rED]meP+YFkHƝK^?\ytk_^Èeǐ᜕YSj$ɂn*;Л;;Yo_",`0 63O̙\$;;p-]GI+CQ+RfAӳ֩gH#ɤ| /cUqZ`쌁 E&)ϓ(Ʌ6}k59}PM}߫ˎcp$lDLj R2xO ,iO՝6j?#{:gtSHa4EFD CCtMν˿]E=GE_8THE&hiȊ~o{O'n7D&04B9 lB0#pL;}QW?1믇v*0 \hAElqJ!18(C;Q1" yFSh"4qAr+]D]e3h\wMN֫|#5h 3KBwSZ׮? v;ڔ+ $utZT/X<0`05H.#~soͯm_| 2io31`QO M1&XٰZ37s*a#bb5vpȦΖ h=49wuek՘hl:=xq Q''[@jm- DbqVyX"|ʐ)34jJzfCQ6rmCiL|n: D4ud2UG<-55ɫ2dxXxaJ Mђ@dI)zh/|Ue, *E9ꋾ*joɂS?^ln٘U?o_3P1Jb^GR,PE?䷅}ZWqʍ;G%jd5gdĔ AWg\2&,sC#8 a&Y]|o.*Ɲ5(bAv=GI lA!{ L.ir/uuU^sqHFr Jp9p:N_YĨ놼߿{GVY3L"AB,Enky:~tsN챢Q*RQ@b !;4~skl5`_}-%T*^Z(VjX@sfF:  уe&o`(ePa2%8`epkToũLMz^,߭PIrUuO:2G+u.սsxC AE@!1.lݵԽ7Z9F"OG@*Jm4:D$gO ^k7vzf 7kHM ;2οe< >wItE˯*PhG,d'({)QD?=jqo[s6;k:kg6*[)$ұ1}L 2%ɿhKsrX׳Īq\x{8T[Ġ(T:$f F5jиerRE!E-""۔|EIw)DՑo|vjϳY]q |7}qx"k4O xx3 k3.뒡5H ~A~UM͡T#e$LWZ~vnD 5_XKós 23rjWIsb^P}. S3_辰 ϛ,OEJ q|ݜ-gpY,5] {xi@g߱qa%g cKJmd1Z22xʬH . Y+n)S* _tg# ˭wޗ+|kR-l7/1^qlgYKwhJ $KUڂ}Y-]B"AePAk;o=42D" q8lG1 +cR>OD VQQ_2a[ꨪ> yy$4 jEC+ZSJ‰ԔREBx%yLcN񊨲0Rd1>;?`.+A~Xooyv/ȭp XSHKΏvMW>j6Idةeg-T~S$Z.NL֦U =r`5/A"3c#FG̩s1_y+DDf* ӘEcHtG-w ѣDrQ'2 c'ͰY,Y"̹*K(C#^AAߓCFCE2DݳCͧ%lhVdD6#j=꼍MltȅG6XIkOKWq#+I10z/} 5,7@`wƒS&agֳescL3N4cZjgT*Ke׌^ =i40:pfRVEyXrp7l=+4r*dx ;‡>dnL/`ՃUv]'2ܽ&" J| ;K?ڕjN"!7nA?w#D6-?M!;c:nTx4mY7)>Nfg! `@Qd .aaٺ_TLZx&¹w:G>nRpRm8ZO2M6()AIB~ޠpwH|tG4}_ubX BV촴]<5^"!qtQnErdf" `z-FqD%80I6 Jϸ@J7;ϕѝzHYC)cղ{V?+ՀXD]ͦ7_9lI@y:_8}h/WGUp.t43K "!sʿuS7bIC-yERǻt'1lK}z=%mTQ" ,n{mqܵ%*\$^ѩ{g 5<<('ۈ "!^IG*=W];>; YϗZ gcře[%H,tv}2~őT#?h{ Z:ULxRLٓg{k^;zw9c$N[)=L8+j 6jq)ikJʟ s9Jc(XIQN~ԋ5Uwu|o EXe9{)>4p~" = q1vɨq2$DY<=\'(?$wd>d 볢Dz|J"0bLvQ?{'_&`.ZJν KFJdöٗngHiɣIA7I'yC'_F"A@at49֤?rciIdCrQ_>^Qڪ!FYpgP(4Z̠1x@~%X jCztUP*=eX핂6)G|x{bY1}\~_ӂ7NDZ0τnzN|S[ Q 7O뿄0cgkH|fe䄍 lq9u|=b<[i&ʷ%r oGɋէ"gI=C"A N}z)c*akNoq;?x{SvI%wOoB>[H.R諚=za% m*HeT3>X3|+"Fc.yA{?A7*I\;v6-|K}ԂD-[F}Pר:y-Z0fܫZ1GX_-,D]q$|A"5 T Յ3u1/|Qx340031Q(,-N-)K/MILϋ743"mmd`hb`dhkPTWRjRྨsoٯb?b<Dx340031Q(,-N-)K/MILϋ743"mmd`hb`ddkPTWRjR-aIT=/>sgn x340031Q(,-N-)K/MILϋ743"mmd`hb`ddgkPTWRjRQɮTG}-v?ڥx340031Q(,-N-)K/MILϋ743"mmd`hb`ddkPTWRjR%ql |C;j;^x340031Q(,-N-)K/MILϋ743"mmd`hb`ddkPTWRjRoʚ~?Z kRx340031Q(,-N-)K/MILϋ743"mmd`hb`lhkPTWRjRྨW'oh5 p_ԥx340031Q(,-N-)K/MILϋ743"mmd`hb`lhkPTWRjRP~ RMg4zqIihx340031Q(,-N-)K/MILϋ743"mmd`hb`b`kPTWRjRr S?X`l~Ix340031Q(,-N-)K/MILϋ743"mmd`hbIy%z) G^|{8uB.A*^xx340031Q(,-N-)K/MILϋ743"mmd`hb`b`kPTWRjRbDЩJ_1}B h)x340031Q(,-N-)K/MILϋ743"mmd`hb`bhkPTWRjR~g̚?\K~IܴE_Yx340031Q(,-N-)K/MILϋ743"mmd`hb`f`kPTWRjR 7}aro4 jNtx340031Q(,-N-)K/MILϋ743"mmd`hb`f`kPTWRjR 0\ܵKe?x340031Q(,-N-)K/MILϋ743"mmd`hb`f`kPTWRjR j 6nz~Tz&gӥx340031Q(,-N-)K/MILϋ743"mmd`hj`adkPTWRjRPUnoC{nfxp݇H>x340031Q(,-N-)K/MILϋ743"mmd`hj`adkPTWRjRPm\f$w|T潯U^x340031Q(,-N-)K/MILϋ743"mmd`hjh`hkPTWRjR`s%Q:&GʙǎO.I@x340031Q(,-N-)K/MILϋ743"m mhgd`hb`f`kPTWRjR̐Z {[#nВwxx340031Q(,-N-)K/MILϋ743"m mhgd`hb`f`kPTWRjR3Bw=WMJmDx340031Q(,-N-)K/MILϋ743"m mhgd`hb`f`kPTWRjRӡ%5[7 ڟZq%x340031Q(,-N-)K/MILϋ743"m mhgd`hb`idkPTWRjR2ѫ/aALT/tbx340031Q(,-N-)K/MILϋ743"m mhgd`hbh`hkPTWRjR̠ڎw[]?lkx340031Q(,-N-)K/MILϋ743"m mhgd`hbĺIy%zz) .t8܉q!zg7ux340031Q(,-N-)K/MILϋ743"m mhgd`hbĺIy%z) /Ҍ7Qps-ܜS{Npx340031Q(,-N-)K/MILϋ743"]ҤҼRCd߬!˯Nw?WڎE{)x340031Q(,-N-)K/MILϋ743"]ҤҼR#dۓr,[㬶O\~-Z x340031Q(,-N-)K/MILϋ74303҆zF&Iy%z) ϏO sg}7vXo-nTDx340031Q(,-N-)K/MILϋ74303ԆF&FIy%z) \{L*d[_Vh{O<x340031Q(,-N-)K/MILϋ74303ԆF&FIy%z) |9_)̞Q \x340031Q(,-N-)K/MILϋ74303ԆFIy%z) .:\ Egd.L^gz oC,3x340031Q(,-N-)K/MILϋ74303ԆFFIy%z) =6Des?dڥx340031Q(,-N-)K/MILϋ74303ԆFƆIy%z) 7 ߱YXv}wi,x340031Q(,-N-)K/MILϋ74303ԆFƆƺIy%z) n(T^h'-ɦAcx340031Q(,-N-)K/MILϋ74303ԆFƆIy%z) ·e%xњ_8N]lbAԧx340031Q(,-N-)K/MILϋ74303ԆFF@]ҤҼRCd=WxzLz3֮~=x340031Q(,-N-)K/MILϋ74303ԆF&Iy%z) i5 fn~}!nx340031Q(,-N-)K/MILϋ74303ԆF&Iy%zz) j5~{@oXGx340031Q(,-N-)K/MILϋ74303ԆF&Iy%zFz) Ry 1~vx340031Q(,-N-)K/MILϋ74303ԆF&Iy%z) Ni IxEWiOh[cx340031Q(,-N-)K/MILϋ74303҆zFfzIy%z) 4N7MPo-̸9͘)x340031Q(,-N-)K/MILϋ74303҆zFFIy%z) >ᓬ}l;X{cx340031Q(,-N-)K/MILϋ74303҆zFIy%z) K܅.u\&;ty]WAx340031Q(,-N-)K/MILϋ74303҆zFFIy%z) z;#mb]>/ N^vxx340031Q(,-N-)K/MILϋ74303҆zFIy%z) (R?=3+֚hAեx340031Q(,-N-)K/MILϋ74303҆zFIy%z) Sdޔީ٤mhx340031Q(,-N-)K/MILϋ74303҆zFIy%z) v"md/!=ia{x340031Q(,-N-)K/MILϋ74303҆zFIy%z) h4"ԽEltx340031Q(,-N-)K/MILϋ74303҆zFFIy%z) қ/rh\bv-kx340031Q(,-N-)K/MILϋ74303҆zFFIy%z) [owUop;ۓ9j7$x340031Q(,-N-)K/MILϋ74303҆zFFIy%Fz) o'Eoߖ_yn_FCoz̥x340031Q(,-N-)K/MILϋ74303҆zFFIy%z) bR=Uc5:CJ}Qcx340031Q(,-N-)K/MILϋ7430364FfIy%z) K?~g,i>G]Yx340031Q(,-N-)K/MILϋ7430364FzIy%z) =tHn}45~>x340031Q(,-N-)K/MILϋ7430364FzIy%Fz) N\;/S˛Zx340031Q(,-N-)K/MILϋ7430364FF&Iy%z) U!6pޠudx340031Q(,-N-)K/MILϋ7430364FfIy%z) lM~h͉C%_~tfx340031Q(,-N-)K/MILϋ7430364FfFIy%z) $~n.`;^x340031Q(,-N-)K/MILϋ7430364FfFIy%Fz) CLxK]߾utx340031Q(,-N-)K/MILϋ7430364Ff@Bנ44P/8zvN fotezZuzsqݥx340031Q(,-N-)K/MILϋ7430364FfFIy%z) {C 2HJܥx340031Q(,-N-)K/MILϋ7430364FfFIy%Fz) CK~x$!bKWhx340031Q(,-N-)K/MILϋ7430364FfIy%z) >8ueQ Q iwJiDfx340031Q(,-N-)K/MILϋ7430364FfIy%Fz) )j'e[ Cix4.x340031Q(,-N-)K/MILϋ7430364FfIy%z) %$I&Y罼X]lENx340031Q(,-N-)K/MILϋ743036434320430345(M*+)5K)NfY|@癅>X?={q"u +x340031Q(,-N-)K/MILϋ743036434320430345(M*+)5K)NfЏ|DW7j "̏~fx340031Q(,-N-)K/MILϋ7430364343204305(M*+)5K)NfƮ|ǩSbVnfcx340031Q(,-N-)K/MILϋ7430364343204305(M*+)5K)NfXq?vV[s~ߠcx340031Q(,-N-)K/MILϋ743036434320434005(M*+)5K)Nf\f-uGe[ޚTeFx340031Q(,-N-)K/MILϋ7430364FFFIy%zz) ;/2^yuyf9f)x340031Q(,-N-)K/MILϋ7430364FFFIy%z) =J|;3.@VMpx340031Q(,-N-)K/MILϋ7430364FFIy%z) |m> I-[%a<Ywx340031Q(,-N-)K/MILϋ7430364F&Iy%z) p=@{cx340031Q(,-N-)K/MILϋ743036FFIy%Fz) J[*V}|vszb!\x340031Q(,-N-)K/MILϋ743036FFIy%zz) c:mmkWz?}x>ӄ4x340031Q(,-N-)K/MILϋ743036FFIy%zFz) l {ZҿkP&&ɧx340031Q(,-N-)K/MILϋ743036FFIy%zz)  mѫ* xb̿1;wx340031Q(,-N-)K/MILϋ743036FFIy%z) j/O߭fEAa?1,Gb$8x340031Q(,-N-)K/MILϋ743036343204425(M*+)5K)NfjwED^>rČlx340031Q(,-N-)K/MILϋ743036343204425(M*+)5K)NftYu9n`X/o~lx340031Q(,-N-)K/MILϋ743036343204425(M*+)5K)NfМp=߿9v>n)^,#x340031Q(,-N-)K/MILϋ7430362FFƆIy%z) w^<=xe]uݥx340031Q(,-N-)K/MILϋ7430362FFFIy%z) _v*J:MqrLx340031Q(,-N-)K/MILϋ7430362FFFIy%Fz) 75OdjqvImx340031Q(,-N-)K/MILϋ743036234320240745(M*+)5K)Nf _/Sp,Ihx340031Q(,-N-)K/MILϋ743036234320"s]ҤҼRCdV+]ٹ\Y}Z3Yx340031Q(,-N-)K/MILϋ74303623432022005(M*+)5K)Nf.|瓊{['Y:zx340031Q(,-N-)K/MILϋ74303623432022005(M*+)5K)Nf81Tdov#bvx340031Q(,-N-)K/MILϋ74303623432022005(M*+)5K)NfX=o޿ۋ?(o;T3x{Nx340031Q(,-N-)K/MILϋ74303623432022005(M*+)5K)NfQvnsT|GNX> ox340031Q(,-N-)K/MILϋ74303623432022005(M*+)5K)Nfر?vE'Kg; ?N{s@ vpx340031Q(,-N-)K/MILϋ74303623432022005(M*+)5K)Nf۫#YS貚&5He3-x340031Qp  f)Y>R_|e3|*u bWR{L1Y.S|3[eOnS|//]U|Tkx0 3[O{uq[A. >5gnuQ7= USkpdKŲ@m_V>O:sSSҒ< 2mRD^W~AvF Դ"T6\q o;9Kr&@X0ABgT,.Y5qEwCS23,6xi^fD`=yũ%%yź)yz) UߵMu#zciF b%qsB2m[+,B`|8dyo8'1a䔦g30?3'/ _[._ Up۬] Wg3Z-1̂bWWW~h꼬#)DEIj1P^z;f0k~Y$mx340031QMNMIKex*ѱo^S3GO!DYr~^rb^~^frb^i^fI^qjIIf^znJbjn~^AjQfAFjQbN^zqrFjn^En^f1?~I < woÆLA:00X.[?\u=u(+rJ3sXkNO|ik.tc&ĒԒT,6Oaoobr g7o͝d؀ioz6Gk/KkQ gf%pKm7|>fxdV&'`a Ά9qCW?J^2lMMLڃ-g,(_\g|mDRBڑ_WX ôdo=%ߋ?s^$K S%}̎v<ر|ƅ _W_T ݘ)`{grڣl>D ,H$ò"jqt^Bu~ ָzrUKEy)Be˟k)Hj%E61qE-!|+=eɮ}v"3>cP+sSu M+K-*ax4緕̇#n0ͲHI0)y| T_*+Eb;;DoAd&ݍaEA2eYmR*y4_>>SgbNty%99)P#fDp[Կp>YܽKI-./M>.YGSګ^Nzvv|E%+иզ@x340031QHHKOOgPQ:#wGRMM{B$0It1#hPg*JsO}Y˲RHp%E% yڪcdI{qﵕPEy)%99Eɉz ,7˳N3Yݏ]:s2J2K*uSKJ2ҋuSSs 2K&10S >fӿ.Kdi-Yܤbu|Do5N5*3|y_Q{{ri(01ҢTknfSC$PVj=DEu%wz K@ecU5<"XWgi10U-KI-./`>r!O:'ŕ:N)P/*a`>z< 11Ya*Rp@:_BvKԬe7o}/| x340031QH/M,aTWOvqs#Cfx340031Q(,-N-)K/MIL/K-*LIe˘x&YZTР[ 9-zY~,sx}PuA94ATN %^ Ay;4\vnw=E@B 5E#QW0EPxI Ҕ4Gn6Y$ c #BP>.ioW~YaaP3"Plfxhۃ!@|g G O)0Fq0A@2\^ɑr哮S$c@R[ڶfinL(ϜU=Wx:v(y?*I Rha0BJ bXˏg}J pK]GxG_~cՌ-n^:m=3/ PP\BpBFuAڧtVґX '9EfqwzIE{ƊNvd,QzUΪ@fii/Jcq3+rb#$$*ﷀl4ëlE|zs=eӅvN=r 9)l`6kZy-:_^]f935sA~\ tl[r\3޺AB9Z'vŶo?Yj8ҮVvvys#AQ1RD4-,7e`qm4 ZgKLT>bSm&A4X(6Oiʹܟ ҈S~ðnQpsΕ030OTHYg^B5Yĩ3(ҫ$I[v)߳!j,l8=6cHdTu{í7_>qm;lݛX]1<ɳTRd2ģhXM^~gkiYmh9! UzE؈Ǎu3( +KC7;S[s+%HBNv``?tQPcߢd Q20xbwV],#g7Kw{GT[jzViοު]w'zGt>N4 j,WY Hm^STbeΠ@ RpmHVݝ1W$)F2˺!n[bxS QeJfG:JARRdʄ[! Anu3W< /j:b%13_cф?D9%ή9x340031QMNMIKe~`Ԩ;lkb ٩IE) +;n:_0|3$uũ%%y u/ㄴCfYk9JKsKJ'~B[ˊWk"֠Q^T0]?KcV3/Iy(QYqh[2}yAYEP59E |}GpyS`y ?6\Vzsߠ J&<ўȣrosq(H)ͭdd'(yosX?gfmߛIV~l<? sM]|p夶%)(fڰEЉ@1)n9͗K'ݾ'[/L+I,׺o'?WrqoS3! S /:s0yūuWBRsKRuS2 r+v4јc_[YbXv_j4TaZvfNôoV ȗ^~t׮@''WT2Z9Y?B%%&gd䔦ge1HM9o^3r% ҡ!zJ RKRusr  Rt3R=ffzbeq1WQ'0)usSzʦ*&~+9Oz2_qކ5yfϦJ>_܈]W s(F!6OJ6:$IP[[Ǯi4uVgfsx340031QMNMIKeXhyM=gp;,9' )?(E/=/?7U8$3/X 4=3O/3{Vi[0H?e'՝^ 7A771/1=H/!bϳ;Y&kN/ ??J+e{A_j:,akU}^OexTGNfq P{ݫ3b/<"cY$ ɕ'Ͳ 5u{P%9@S6~̎(5%3hԩP}.>]SUfUe0/>ee;u"*(\$(hލs$Ko摐2x97N u] .]tQYR ?$ũ9i%%@Wa1{rZW׭)-Nnnb^bzjPBŮkA>,jmkmN FRE3~Oy+ m иJf$?N0f;c P9V7%$}U5(6PRx340031Qq122 u(I-KKc,Jyڵ)GvX!5/,_7P3I뺓W/[.v!jbG"'dx340031QMNMIKe(c_]r7EBh!DYzqnf^AinFjNAj^2u[Iއi q`%t݂t\y(U!NL/JL{z*9S2x340031QMNMIKeP5}_O,dQ\ZT_[ZR^[SFy}60SjM/NхhMKLO-Kf-TRG-]onn ]y6I[OS== 斨6B@&>k1ca6(K)ͭKM-N-)K/-)Mc9'tmW+?;zL/NMKLO-KfR #3?ǩ≮MoW56_v'rcݹ=Mb++yV`2gZ+x340031QMNMIKes=' ;n6(K/NM,-.HLNH)H-Kfl7.{&$abJ}Dj`LsO7k~؋]KIjq Ў7]\0 9zj2? 'ľ}o]m|^ׯ-YYHjSs J*uK3`.گ;s/)9 ^Ƅ##85;5 3/]771/1Fyl~Sd)NY`}lnnU5bm 4=3hՍE/&kyo|H9sRsaT@犉zxzm]? XP_;.NyBUbdy0e15?! rnJ3Pxw~^2juW,Ӄ)32x340031QKI++(g1GX{K*2(MNMIKec4IO̸|_+*K/NNLO,JMKLO-Kf?%Pa3fMħ#QAl*|o >¦ 4=3hEsg/mdkGf$ I%9@q3&H[T5M?_*t8}2 V /NI{VIyOCf榖d]Z^ZPܼXKm2ufnTWvRnrbAqN~rn~Z^A^:CSϯ7c^'VqaUVng.;i[)Oד}D{ZXRf𶏟]OANizfК3=͙T5훣VB+ i)N.JM+/--)8:ޚCݳfVt_ rMEͷMq7J+XV˒_H-#^uQPKM-N-)K?3A/ ֮ b*T{~Q:D^pFjNwj{QbR0*rsi.ҽ^/o j,)ٛO77?%P?ӆfYw|*p=E%ɥ%ź(=6E|]D{~nx\ꅪ-I-.A `m~}mW QyFbnJfne~)ۺ@OYW`:Ō5ێNuuxvNx340031QMNMIKeHv~pJ=s_g~`lQ^X[PYX`y*3K$RzꚿyK7w̷ĮI/N3=(%H\R= G5fFڔ;G@RYZX䚇)b_GrxzbtQB奔fȈ`v-5h:6vW$笩RÖmNOuNtҶ;8~9*|iU3vA~SAu05-HS"]cƬGnǺ*l`X0/Lk79[]߭u;̼l̼'Z<0Gʗ/`/TYep nΑKڹ墪<5L}Z`Ӕ||E<-U=ҢTgK<Lutrr/tP&)wVnƭE;*J]dJM@+jes0%E-R'iP+mhJL%EH)og89o*."obR~6+ ť:o&}彅[O8tCuinJjY& m̭DEp3ѐ s62Fn )H JsSKS2uӀ(g;ƽsױGL|p_ x340031QHLO-K/Kfx'.卑S/6 !N)^S?n0*-HMJLNKȠRġv}xƦ-1e0,si^͈5Z#K #CAx340031QMNMIKe\77o2U*Oyj,8E7'?9$U ?3$H/hEfSuV> k57XYNЙTļtӾ}*q\7oTisq*`?1[wE\\bw 9y@YKOE ߸3CR] T-YTkezt2aEO@J#OV2ۮ[ZR^ sLf:i_ؿIED[pf6TgIjq @ܬ3gfܝ-o:=d=൴ޣx340031QMNMIKe0d}I|ٌ'N7(K/N/L+I,MKLO-Kf8hz*@C#);JuK*ߟ |1!T$I:⩸䔦gpBӴ $=ӆE/=/?7U8$3/fBf䫲O-6kDeB(I-.AhҌ;$NgUIw}LG o-x340031Q03MM-N-)K/MIL-J+*I-fh /򯸸w!B!Դ̜T\W_ڻQ<[fk| U^5R771/1=H/t=>({fKn '0xTى~~뚎 4=3h|r3'˿z"p ʡJs2 >trz•Շdr'MХ[ZR^ 3$34cߗ^0rRP ]{eYu5i hݱmeSl:T/Cلy󏰜0V 'gǯ8d?!VPeyũ%%y0'e1 x]ͣn/;$Q[k'2jd9ĭx340031QMNMIKexU?:/&Լ0(K/N-/KMKLO-Kf(vؚ*?{x 8g0?9!7jv|(e 4=3hBg'wKr= ÷eJgjJTԒ̼b<*g&T8CJlR_WN,I-.XaV 8+Hm!x340031QMNMIKe [pej?o_0!DYzqniAJbIjnr~nn~^*F}9<-x,2rR.-zs'w>5r|:29lu1H"Xt&%tﲽBǻWGCÆ J.l)a1 9y@ 景gȽRs-B %9/JM+J-j(ϼ_hge%E ggѐ"|f)gsi6j)NI-L+.KgH5\&]hICi}%>Tzyũ%%ypd1p^٩[.A $4x340031QMNMIKeϩA ?q2z,U/9?/-3]$(1=>N ©Yݧnt !9?W44T4/R8$3/X7%157?O 4=3X< ?'3R/3[+G[FRyZg@M/NMI-LNKfIjUYJFgf\3#]6޽;z^[ 9)9E@SwЫMTJ۳iwJ y)n̚3-q+18g0hXufn"m1Xy)@ ez;RzL/;> 9h,߽PBy1t@h1vI'nR=+x{j9P9%@u.ϛKVTz; w8R7tV_T}zq.!%@_z6>fjT?z$z`UocB."9yo W+#.M*-)I/--)J+I,ਥ n}ow5~jމ6iү8?}T->k:\:Yzkgt=`hWΜzK+:CAu".9?7lӟNu kݾ[lp`PHRHrQҸa?仅}ѫO,]9Όہq*`Xq^TZCƃcv4BnX+KMEOy fgplݷᝇ ,N܄cx]y44&5YB!$Q%&!&Ԙ3fX*U)j +EATH:<}]^45uLVTO@.9ʿTMi&pG_ZWEgvkb4)(UG[{9q=4%6ZXix }tX,֖}&{gt7 NV`H MCybm~r!CFE\uJ,:ം?YBGuyM ye 3 !GBҝsqQԼ5rU #]q]0Iκ`)fgZqGϓyCa~[CO_֡q!PEjuo6 5>y\p;ؙ޵}R.W1aO'48AO DEN$f,B{y6тծYu//1CSZ8TT϶ڑov% R,4ey95(9_6GWH2UF|PI]\- HЯvdC)^l0˘Vٯ ӬXXp~xhe<Dџne^C%St@p)f[/o iAN3W a6\iy 8+.oZ4X}t_e(p߹ug}pݞ:;n0j>uی^1BPe-sN7*dwA@HNTLyK(wa~s$> * bb-{kfط o^*hUJ͗jc=NYU--#zacFV+e=z:2ӫ~wHk~n  u|8(;O2]Vr in ;N3rY]POwɌ 9W__;Rc-f\M@ .dw@.Rv_ a#Y;g)դ{/Yw(N%²c:@=0xV?i@9~06L^<`G_zf e\-Y_JxEg+h''+U lcN/yٺPP.cT (a}ՋR;l)f>N26n .7Lx}vIk廽I*mi4[z\nݚ"j 5 N"廋]@a5/J.4V hx6"YHpea׏Y1R??h&ܽo&(S8W(&:eYSי\dt98J>$b(cg&nmRFt}2bDKYOO{pwDL2mhAfLɜPX94 #oC9aNtz^3?۩*x340075U00--NL/J,,/*֭+`bti'D~X+X+wԧx340031QMNMIKek6>B M  !RJss+S3-\xfՇiMN+ Ld0@/%8$z¾"VUXdU^RZ\XWPp_1^USxجB~2=,L+NKfX5L;Y%90 C!AOogtsgֶq;@aeKwn+5t6P$H_~Q{%a^7T {ϑƼնp]t;@zo2177L :H:!#a.1Ape \h;PY*i1%K\L}kan@goS \ΰBmGzOt:BfQ`Wxgw}'K }egwӝ#!pe X骑߽eFmiYCĂ'mdLi>',F W[:ݣO-_r)v+Tˮ%NX!jp pe 8`c!x=x]IY6KHY=m0ZyU /&811/v7>Yd{%n'2z2LX]}Pީ.ʬJw"* : 6$M5Mw&'L%܊T+84ؐ0Ki065e_8`+ ,KѮ^' =*2O@dhγ>oaˍYFC ;\6̪d_ٿ*˴˚w: 6cu{ϡ88ȿ2W.ڝf"4_O,VSÂBpXōҌkq深l/VN4 ٷc[hR9Bq\"9bG􇏫X@wI~7~T=k&OxB, ZRf)9cȷ#5"\.<8l;q'a9ٱI6ܡ: Dh ]l^%AW2L C^Y)i+YyfsуoxDUϖE,`)!gOIq'I)hG,3o\zWQy G9k6_H 2;{Ai l3˛y{Lf ݵ:]9pɼaY9`'((Ờ WK=.5/6-U|[W|=Df0C]4< &ލe XF…"]GջBW(i_Bf:X~3sQR96XRcѽ)C3s '\j$Xr7Ym?iQp]K zuo,hc-#O]S|?c`ÂS%:6)S2ۮn!•"DIPɢ3\9F-!*QkJ)"$}MƓ_>j:4}PS(/. +7Q6ߒ&g0rb W~Pc>>%OX)PYE٢ׅ1.QH2 N+ \<֨)4"2 ~%؛&>K7ѷ$@p}7Qc,_I 2{ڻ^6]tpe x3#PY1G񾳰HE2 C]l+}<ok0•o( LhZ0d}0d& i4.W|sڜ3e[#x;K*IۺF}+1pC;%h} ޛ˨cnΡ@7V3B"UꙦDf?YWXcMG,.M9G`:YSi"Rx@t7K@iI30t|;?.-i5kKYlp@ k)AӴ@\ "QˈKtٲa6Qf2\&s׷8{ʇ N4@XЙVUuʩ>GC$ƨ\/qv:*,ëY<{.ѡ"*֗$ɟ/:w7 xK~: 98*HLsϔ&g c ,$Q7iAU2YG_dcʗyu_) +1,w*lnwzn7*w2daBtH *)6F W^{Mj DKLP^b$c~ H93WDoX1"oܗWX@ܔ .W|W20~FeOu06t,z׆+rOdaxR\bj瑄_|<,U_]k,+vxҾ9unl9(=!jPY,M2u'IgvuQ뱾 3M7lvo.KJ>ͫTn/-z;JSJyB~"u레\[=:*Qtޒ3kƐNZx?q(o7jGC0؛GYbŬ>|cc}<]@H\DF ÕNOg\~t%a9͋Tn,`Q(йx<_˽7(WP&x+*W@N\"msM薬*BQ3?X:Kg%[E+Od X}|I]3s^hU]I{?B9x340031QMNMIKe~`Ԩ;lkb ٩IE) G.(oVǶ*pLTDRWZR^pU4E?O QQL6 "G~L޼4[)_!Ey)E -ӏז.vAfiЯv.& x6N\qPDy0z ,؀x340031QMNMIKe}*=wS97Bede&'d&%%3hwMzuNp(=vS6X9/éG8&9y@̮fNoYRIART6^ k>K6 }]ȼUTԒ̼t}y ]m+nc^w݆kF=Ԝl׬prNYr(۰8x340031QMNMIKe{&LBu%6"L&@hhXZXpBlulD%K$uũ%%y YLQY3$6ҒҼU"ҚO 칓p.!jӋRN9n7:^\azBk͏E9GK}V\UqD߾'@1\vD}4y=M11Lל1]g<{ebҢb 7GvGK2) ӕW/v&_Wm /-NNM- j-KNZWDOḺ  (>;3Gk6 ._(MMLD1Ë孶綪̱0cSq2T:Gvz{aAԏݶԼĒL%DNδsN@>r S|Oߐ^W9?F{ћD:r2J+vd3(xײsģ!R2Msxl~b|/P)X8T>+.I+)--HI,I+Jbv+<'Y$4mZad㲌kOx^dz CCj^i.ܖdGܡ/oᖷ50&%.d踝2v /SyïaU76wpl3?>rHp{QW15)ᒹE>@+Fx@cOԩޫʴ?yܶzoAj/<$M3^*(m@\̼̤̒"ݴto?tqZRf-YsͮERnN~z~inn~J*P:6Mzv9?#i*(J-NKN١ŝի 0ZIlS!y%=/?77u6?+zJi9ebP%%薯~&oJ./ygxşmnLW=:PZ{<ݲ{y?B/.{bx_wC 8;J~x}Wkqo7p@gxFsMg.x[}oag?xuLm03gPx5UuT! gaxDyAgrx^i gxOaCdgxuV~Y~Dg'x5Gn ? g9xKz.^TgKx) Rqg]xuCbCr gox\|rn(kxMtC;d | !kxuTd5 5k-x5Ex*d |NCxXpq-9{o_xI`k'[p2kzxȿA}w>kxuwC"d |Ak&x5g]k d9[]3K] DInjJf"(&_+rL-2@1\--i;gO4`/L+I,Zx9uHؽx>cq*/O-bޗ*NbzgBRsKRuS2 r+v4јc_[YbXv_j4TaZvfNôoV ȗ^~t׮@''WT2xű 0@M&o-1-eyG4Tl!vO "#I*$ $-,; ͮȚ3EBɑ\:#:{6=v)[nG'Lxű 0@2U&~;_0%]hY"b 6B삸ݧf6(U 1j"!1KUDsV< SF)Rr%nyӸ/^(y@U[`'Zx˻ 0P2U&|>W-e  AV*XTzMkSRbU`e!2e1I (*KFŇ?c:X`)+tAxŒJGlͱz$sy덳3Kf̯P(ixȻ 0PR1B&ΟR| [DF]Փ޷tS Z`#>Fz)3xHq Ej Y]"MLeu:Gu؝zs4fy?1&qrx DZ 0@aQ`L`?-]hY"bl iNԪjh(ed pt<#D̨(IB'ϳ:@d#DA) : u~ϧ>ۤ%[yx ı @ @QeL]0-] F4^"b 6BWܷt.TSBR'5w KTՠh:(N208 ]jIdE";%*6:91@c vU[<&(x ˱ 0@QeL`_0-]ǎhY"b 6BB7|Rj#Is!pN=T-%Gy|J+>9LAUd}3EaIS^v/s}S4,GK3kaZ( x˽ 0@a2U&|_ti9db5 y_g{XG%O }B%X y|&>E^`+RJ1]`G|c}:NG@+@kZ(%xʱ 0@2U&?_-e mG4Y"b 6BTܧ{ws9,G<F;(c*Cͷ6&$eX Av{D^?tt!@bz]L , r'4x ʻ 0Pa@ ;&K9db1 n^~DD  1c6` b!2&36Y2{@(RTKBKydu zQ}NZDc$s+}ӑuq[nyt_֑(' pxű 0@ zo`Zo\E]j$gWĐT)zV RE^Y0/F^5{T-$y.\Gg<]X0lXltif{O?q)Bx ̽ 0PQaL`w>' -] [DFY4|{wK9YP%MKۜD#)+5?X=O$p!٧ :+~=kͫ>VPf&9x ı 0@QeL`obZ@db5(wtG7m,h\g2R A_gP1ij+m1ٜ12R%X6?ӭ?<qXܦ-GE(3 xŻ 0PR1B&9ߝ'Lq [DFY0:A9@ fC,*`㪲/iZ}(TBJ>.5䔊G&(6_y}NgK3{'7%xű 0PR1B&|gO@EIbG4,WlekjCVVr40u%:[,Pm<.(><!P"V6]i}Nٍ<}5 լ& x˱ 0@R1B&wޞ2~G4Y"b 62@uMkS<1 p˞Y+S!IyRI\lGB*Ŋ zDt,>U_%x ı 0@aQcL`^.ſh \Ele;aTP2Q` y̙"R0@"V6nc8eN,0g=/7?}j;7o&'x Ļ 0PQeL`ҥsw D+X 1̽L pD BQk ((ƭ4y Jn:%eWsA%f%m?X мc54c(2x Ļ 0Patl jg\Ee+ޮv.23r#J*d)e1񘘧7wy"xWr (5f9ɱY6rS{>]/Wzpg8$&$xDZ 0@ұA&*Z~G4Tle:mݴ4"X&q A-e%iUTRLP! Ǡ{"!Xe{d]??t=mvKjn~_2p% x ı 0@aQbL`m=-] D4Y"b 62nTB3#wHQ*1\" kicD>rʕ#<6 w?O :\l/.'&x ʻ0 KR1B&Igjdh s9`,~xKoOjBuJQ(6G3iV}&"A&V/ȚJܗ>4\ψɼc5Y&xʱ 0@J T)l@db5(ˀ;RF#&̈E1B2N9yIĨ-hpA)X%"YB1%!}˙,XN-i} _L'- x ı0 K2U&IVd+ PSl%G[ |GKfDB)+"1PŊhʌWJm#l?D+˵{s.gv2ݳ7Ru{M%'xŻ 0PR1B&lϟ hh)S +[DFY0]u">`KV(AR;Uqu}(1. .$Ebk.,6üv)֒0 p,5#9TϘ"lk(7c AJyPm9r`m]ܾr<}1+uy&tx˻0 #PcLOY2%9|"leUoaMuCRĈJ\RJ3 2e(37 T=dZ7HPKDΗ=&\??|`ͣs3k''xű 0@ұA&lL#,Wle50&20NĊλQ9ՒP 7ya!`!A_! 3՜\vs:\ϖ\2k{,s3{(/xű 0PұA&L;G4Y"b 62׼ٛif]4Ǥ0X_\a-ܾPvD# gG Sce3t;R{9g7z(M6x˱0 #PcLl˒L&G/[X P}[ujBb6Hhy ?2hN>ԳgKQ~JY˟aw:GnW%G>xű 0PұA&.پ[29|G4Y"b 62׼ٛq@!6H12S4=de,R9ׂ4EUI!IJmY3%On٭Vng'>Dx Ľ 0PaL@ :KasD-"`,C^vi" -yq\uP0H $Ò֑ml3c3޶lrQ8otS~=d@Qskz &MxƱ 0@2e&mޮX2G4,WleBuu[7:/V<\\B\&K*sJUmp=1+g$ d3qGa|N<}1-U(M Xx10 @QHخX;8iRuG ۛךsWz!@JfdSZ&1QJe5/k9YL[LEUT!t$Y[?(x ı 0@aQbLvޞ.h \Ele;aT(B$b.9U"\F>)H`u "'AU t8ӫ=֩s&o xű 0@R1B&~;~O@CKG4Y"b 62@sw{7*2$h4r)Cp OhCp*hԙgUgLP(m舶tѢY}1Y^/,& 'xű 0@R1B&v򞀆2h\ElePt̵1;S>(Md>tl4j2NؾcɯYBʆY@stDC ad TFm8^N+Я5~'|-xŻ 0PR1B&Ο;M@CK [DFY0V k U])dJXK[y 2rJ %Z-sZzt.lۿp9;@ltmf}?%M4xű 0@R1B&mߞ2~G4,Wle5:yVrD$DNHʁރ;OLAIfٕق`.2ab)m1{9.g6v_MfS%;x˻ 0PR2A&|h)S|爆 [DFY^aD&)SL)GZU)YO4>sGbMmb@ARlhtjmE&Dxű 0@R2A&:ZhY"b 62knnll$:2BfRo61 \ц9%EL 1 5q(eY H6^q}N˙)gw7$ xű 0@2U&;_1%]ۉhY"b V.knnZ[јa )jk*"K[}C9Sɂ%d16G%#3*X6]q}Nٓ c [()x Ʊ0 г/S0,}IDTe.DZ5ۑW+_y90gJ}$<*_HLx 0 @HH)<HʅPe^Wގ=beBE;:M^Dp+*1m{|UP;9^qԦ&bI2.7~-Px ı 0@aQ`L`<-]h \Ele;aTGB<9-28Ț6iuf+J@nH^"Kׂf}s>]/ξc]]n$Vxʻ 0Pt X}PPS8w D+ P1,1϶F)…d!h/b  \ ?lCVo,Y'~O@CK~G4Y"b 62@uͭL^1[%##I$R7| Uc\ĺR (>_8m)ygz_LjWM&&x MViҦs&UF62wCB0)E,w6{7sgmX3gJQ*,Td})L>==6sgR&,x ı @ @J ހ.#@Ele=LF2H(hT*GZ_x&F5Gvcf"Ŏm=l|]w}.C:,k$/xű 0@ҰB&?ހ2G4Y"b 625w{70@C%Ӫ!럩:+Ȩ^ *UgKzd}:\YS3V%6xű 0@R1B&?2yG4Y"b 62knnjl8H(1h.saFjWlU)XBaF m׳Gpk},w%=xŻ0 #PbL?4)dY-8`,m6̽N8 DH 5 6(y\Y! ܿ:*#j Ƞ+$(qj@z s:\<}14`& Jxɽ 0@aR1B&|q2? A+X znVsfB5a&Rxɱ 0@R1B&۟2yG4Y"b 62@uMH%ƈl_6dCIx[`~t_6l!p{kx[`>t_6\ƴ}H; 4xx7DD(DCΓCDD E D C E C_{IDCXDCgE4DDDD <&.l.x`zd.Ex`a!mjR)\:;bx`zxC:l̛S.nggl#x;b`g ?<$cz9x;bhC <;7IVx;bpC <;7g! w l"xapL(%g8xa`L6ndMlUxa`LY6_.qwxaBƎLY6_. l&x{D\&lDx{#BlC9X# o[x{#DtB˭,^`?Qkx{"@tC \6N0x{"zGd3vWp<Lx{":CdC6LSX7seapal!x!rEx  _d7x!2AxB7wpL`>Tx!rFh7wpL`@{lx;#!a>nj"3x;#tDp|ɏ]6g3=d=mlx;" }s9/#2x;"G`;nL}=)Nx;";nP*l}]eox;";,U72Xl"xoC4l!0<#OxۡF} \8'>C_lxۡB} \G8&kwL"|\l!x[DmC\!U7x[@mC'X6/ca>1Tx[~GuC%̛x7/caa8vx[>CuC'gp0o`ܼ l&xzEe.a>njK# -lx;Ԡa*曼",x;GqZٖmɛ IkGxEa vN}]xA~C %̋+9AoyxF~C %̛+ط3o.fem@'k#x[#Bn/ 9x[#DnBOL~w>hl]x{ ;GvO%ux{ {CfOm86pհFslx!3EfC  "4x!sAzC5[7^GTWjx #=a+x@o1x }Bj„W97smd7Kx "5a+;7_`f,ϵ`Ql xk: {s F^&6xk#4f~NE%<Rxk!Ais.Sf~NE%Qysxk"Ais.lw7s*2m.E l'x"A|3v\f"=lrx={g "gx}kC+ Bl(xõys F(>x}sC4370_a;q[x¹!qcP5W8-wx}cC4nj0O`<hgx;}f{j.x;}B˚WkBx;mBfqƧLSWx;mBfqƙ0q06sx;uBfqƙ09OfnP=k x{²eC4Gm!x{ry33-:x{2y33LVgCgx|iC# &wj/x oxdLvC38M,xdxHlf28? Jxdx{i2/b|5_kmxdxuC/䯬kxde$䯬kgxR \LgOxR]a g`xR}!M gqxR]AG kgxR ugxRݡa Wg&xRN = g3x;ХK YkEx;pN~N_E g[x;0E~~ gmx;pKnC? gx;@n? osx{&Fv'|\{"2gx[#IfC g+x[#Cf gx;$@d ggPx;$Lx3Nqbx;$FxC%d~Vͻu2(kx[#AhC!-2x Mh=d~V X3lgx&Gpg,x&tHp! k=x&&7dsn0olxk<#y=;+cmgx;#0I` QIg'x;#p5v(Og8x;#0v lIx;#ozͯY62&gx{o; Tg(x{w+6+9x{wi\o37)gxgC %g-xg  xg>xij gx;ǽ g*x;}kC+ g˓o FVF _x!a奙 98cW }x!4ճ Io06~ Ax99$x`,qoRkKڙ^67vqS> IxzuF1Qal'58g@ vxzuC c)jތZ_i6($$2,}3vvث3T:5)31KI'6/U{бPYA"Xd%o/|qHQkd;&_r.qx_&1x@x˺ubF.4G1hef. KxzubFӳ.4G1hef(&e&1LbYW-X#+#jW x˺uC cHڍ9Ɩ ynɋȚBJbI"ïǖn:koLZMҩIy ޤ+q] -CSo7Dl_:`C0d;&fҪa.=}\݇# ]V0y/Jkx!d ?>B͙ xq30bɩ ZDW40000 dataM|,X&v^RBŋJɛ$禎, f@f|]_3xq3x0F݌V7Z40000 data|ƥۃ*:pKfyRУtuNʤm,1Aٿ(L"e40000 po[kgDgl"8)܃[ zBPC{xRf؜39 >q1Yٖ<'qԓ,`1O&ϱT>7Py]_^R&ax= +"_nQRc ?fq $HI"e.xp'-,1% 3gm)U40000 poHH'qk [} ̓z ,-xR\0I;t*p77|pPq{atSƈE,xғqLNӑe4Џp}j&ax:u'Hy ^G/~kumAC'Jk+qW/!mg` [ wZϚa]=Gx Iz8z]ABTғ]=wx:u'5'wuɱL#x:u'ȴgk6FvR͢%cl Px:u'(~sM{ɱLm }x:u'[VHN_&y gh↦ɱLT X*x:uj њP5ySX&[Ʒ Vx INɓ$ɐh67]= x:u'&faœ7ۮɱL x:u'H6ss *oC\kr,-Ż Ex:u'Hw ezZ/}r,- urxV7<#EPԚ%L1 2?ye.-40000 poP`YHiPEw4ԝz N''xB5d ?>B͙40000 debianeXT/Ho¨u-|iŲ ayxxs5M|,X&v^40000 debians(H:[A>UvR@yzqӠb$*8oK>,3xQs t.R~_0x9c[1[h#s8(̒NFbRX$YVIГ~_Jxk0bɩ ZDW,!IkJq#.RBŋJɛ$禎>, f@f|~_h2zxZ5|ƥۃ*:pKfy40000 debianB 2pX wjѿ*ve]YK#͓~_+Ahx!Șc7G ?VBTx9`o2F*t0Nf3io<!8ߢvғ~_EHx9VɎ2i5%jHRУtuNʤm>:rGxox0F݌V7Z퓘, P6TI6Г1;" /gd |!40000 po[kgDgl"8)܃[ B# 0}x9'k+@;\,2FOxAٿ(L"e~_GxzuF J>1\w;VvN 7Y txRf؜39 >,wq'6%kNO`Yj$M^V~_#`x!(:6mgv x!`Y" G[X?x9{I'$p $+r Hx^\0I;t*p77|pZp>C'Jk+,DY=n@/S/GRfo{I>,1’2'Lˤt7e40000 poPJo/[2MVhV _Fwx!aQO3&aǐݜm'x9\,O\YFyv``1O&ϱT>7Py~_'x9)nSa}(RW/!mg` [}Rzx Knரϧee*)x9PL}kQ^T'S\N~:g:'J+v~=֯UHxͺuFW'&MY-p3~޻ ytx9%֒i,0PX#*V{^qYj})-xw>"_nQRc ?f, \TQYd68QH5R $HI"e.xp'->,1% 3gm)U40000 poHH'qk [} ̓ 5^xR\0I;t*p77|pPq{atSƈE,xғ,H:fb^BCBZͪ$ax9HuIZ.*iaٚ&y`){ J^/J֠_5~=[#Gx Ed Ctೂ6W򉫥# GuxwZp>C'Jk+,XLyelՀ+!&%9RW/!mg` [,1XdMr);(X;40000 poPJo/[2MVhV J7 x9qXaPg d& q=t^$S.QB~=r5SxR%Y3躎NƮ2R,|4M~Z;sN `>,quMxG]΀u|h~=5&!?xR:֫S+PHyq;?R2|bա4K>,(g$ y`W8$ H~=5$ax9kytiN?+*pQ+h~=(x97ă``@9#U:s 1,TR6nx~=}HxͺuF?~/'̛;A7kWc txͺuF:ZيB"lˣLb  x9PWOBwXWZ5fA.dz&Lׯ0I~=khx9gCZoyrM>Hf[s _vf~=%0x9r8d, AnQnzɻr{ht6~~=<Hx ;Yړ ΏSnY`ݒ8vxRj1O 8 cדRf2{RE5c]3Kr;c[>,Ĩj/-xѿϫU V~==S&`x91~@T o5UeDR9N@ߔZm@2v/~=d 'xͺuC cR7~wN<9-ZS($$2?p)&u J=cNMLcȚߧ#].piVƄ&7D&X7 ~|ad;&W wWF6yRCZl?GDxRi)R+S:TXh]Mz“Rua5tޠ9R|>,Ab> wZϚa~=!& ~x9i,d;8ΌaUaYea-'44{_~=Fx9jR{>"qKz8z]ABTғ~=~x9XUw#I<U)>w z5,yJ*f~=Vx9 @>=Y z M{ݍm.x9Ѐ,%-{O[4z KKyt-yNu!~=Śvx9kѶ6%X{O!r 6cu)r~=: >x9F>;XÕD7ÝgV|CN \9?3~=px97 LCL\l`N9]:FjTlq5#~='Nx8p(zv湡!oCTu0?{(|vU@[ly~=x97l((PmOucf ,7`~=9]x9\ L 5ay1*ՓNɓ$ɐh67~=[P%x9kXh]pUߓ!6Vw ;cT~g06~= Omx9L>z%  l&wbhXeTwynHhi~=5x9eֱnz%S,}\My"gp έg9)~= }x9! D6Z&{ 垓G<[cC֓~=Ex9u`u㸦9tYݻ^ͱ~Ev7~= xR'" \)1E(-ҏ̓,r]  YA WB@v!8|fZ ~=# nx9cK`w%hڵ]>;C qE|hv2>~=6xR(mdunl }[RFA_},|>,~J1.oeӉy== ~=i&oax9|W:{}x-قsn ~4X7~=f(xRaÓ1Do~4{דR9gcL R}>,GwnM^:sC]5~= $ax9!YBg/ U'A(mB}/v$nF~=;4(xR'" \)1E(-ҏ̓,ijEk*>lY(p5+EW׬v-l~=\/#0ax9|U /QF&(Lg r$9u #T*(8M~=5(x9g$55N?tL*fv[qzAoӓ~=Ϋpx9zd%t]5؝1g&[ ~=&mS8x9wGlj`2> [&d ߶6~=Ճx98^v@V* WB@v!8|fZ ~=ܷHxR=J2^#-ML_䏛~Rف^<^e)%[Q>,/"S `'.?z,~=UI )xRnN>cnr&:ED儓REKUt r8">,sAN|,A|a~=#%+axRyNgia}}_~cN,9@Ǩh# NT}|ҧi#ދ\fד~=5o'`x _ٶHGdj4A xͺuC cR7~wN<9-ZS($$2?p)&u J=cNMLc8dgH³m=tR.5|1HdYǁu.^,`OcykkSwuL;e;UBx D]]Oa7  &5Mx  u:Rʘ./qFHLt5|x9DG ]L[./:]OF*lNDs~=Dx9/ex˿` {@΂ e)2s_~=X x9R@\xA&9Ub!H,T(œ~=mTx8('=[SfO(cL˜O*r17~=_}x9PqLb'5O_v re^wq7{q2ɝHr+ ~=rcx9vo8' i5&ĸ ϓ q v4XY:g_q(~=Hx 2 nɄl>'Dvx9(e@Rq7gzӁe)wrB~=F=x9 $KAO۔. gBcg]ȧi|{~=Fx9j^Dڞ6y1Ŋ,^.VmN>~~=Mx9{3Cu;tLo{+u$@U?OD֗~=x9.4uZZC<IQe[/P=zNg~=l]xo7<#EPԚ%L,zo6/W"=3-í8gA1lh;r\G440000 poP`YHiPEw4ԝ [J/n~x9rkP7`]cꋓ 2?ye.-~=qx_%100644 changelog?h>_0ʫy YW%1l̬Q̪uQ#l2ߑj.ي`od>dT *oxP540031QHHKOOgܲy 4ITpysf~)xP540031QHHKOOg`^gu+[^_mϙ~dxP540031QHHKOOg09ۺoȭ2wcF6xP540031QHHKOOgxIaM΅S ,c^g"SFZxP540031QHHKOOg`it; "s7>gyxL%100644 changelog CLɦ& ȴ%ڨZ .eM}a0w [xF%100644 changelog|32%q\L&=%1k,&{ w;gjSTxP540031QHHKOOg5᧭2=غQ93k xK%100644 changelog&m?/ ϑ%1lKstj5;\ .6<[wwټ,100755 rules%u3Ý 돎훓d(.gsettings-override8.U$)Wa[DOQ}xP540031QHHKOOg!I]6>gK8xF%100644 changelog7V\ n/%1Adm߰OBj0 x_%100644 changelogANHpd֑%1Adm߰OBjhkTvX5Zs$铳d->nx_%100644 changelogiU`*MaB z&m9V%1l.[imQfj;\ .6<[wwټ,C:'dmxK%100644 changelog7"*b:r=~}5%1R*JJ QPZfbjZ;@dYx;~]D!9#1/=5'?wԯ4@U˘9x;~]D!9#1/=5'?aCIv\+Nͱ3~ygߔ˘,Nx;~]D!9#1/=5'?Apã) ^HawJj2f{E] x.%100644 changelogעg2L5q%Fx;~]D!9#1/=5'?KA-o8f/[.Qu3}lxF%100644 changelogl#I:d?mܬߑ%1]p['<ΛjaN!1Vx_%100644 changelog&q+]j8&%s%1N zR(Nj+f_鸂rk@-Tldg(cnx;~]D!9#1/=5'?洙I"wڨm(x;~]D!9#1/=5'?A6I9/& ?y?{FePcx.%100644 changelog~rfk:&ݽӾ%m x.%100644 changelogf,'C Ա%]x;~]D!9#1/=5'?aYInKr?N٨_ xl%100644 changelogٿ6>My%1o"Uw4ugAj%jEBX.jAlinkschF>^nSQ_铱(~o2V0`I61B>x`%100644 changelogla?e3PY{l%1Pxfpw0 wj3AA#*@18\0nۊ")x¾]D!9#1/=5'?ОOS,)+;@nF~f*x~]D!9#1/=5'?|*sSj eKX.rr:fcex~]D!9#1/=5'?ٜw敾loKl O˺=x:fS xH%100644 changelogNL@k|/67V%+(嗳"?].'dowx~]D!9#1/=5'?AXՇE~T3u^/4YQu3&2xb%100644 changelogoj* =eyo#ͽG,%{3(~o2V0`I640000 user0;ol?jcqS?(xqxg%100644 changelog3|yakcPT%A%jEBX.jAlinkschF>^nSQ_鳱3(^uxF%100644 changelogԝWqܺP;%1o"Uw4ugAjJ|Ix.%100644 changelog{ `t%%d7x¾]D!9#1/=5'?^@Cر,W2 0'{j?3w AxF%100644 changelog9-aOB2}>JJ%1o"Uw4ugAjJaexF%100644 changelogH̭KA-"6OC&‘%1o"Uw4ugAjJmPkxF%100644 changelog5-;^܌yAЊ%1o"Uw4ugAjJ@xF%100644 changelogr(vF=T%1o"Uw4ugAjJ{ xg%100644 changelogǛ5a=ʹs׽S)%1'BB9KIC\]Bjc>-'BYw*!')Ic0H=F~}3Lzd\U/΂rB('D;bAc='x¾]D!9#1/=5'?H`޾:w~~R^Սbx¾]D!9#1/=5'?aϕv2m99ب g5x¾]D!9#1/=5'?awl=<0F~frXxF%100644 changelog':O t$X t%1F'ݼ%S]|/\jJz-xF%100644 changelogGgWQ1/%1F'ݼ%S]|/\jJdxxF%100644 changelog__}}SrÙo%1F'ݼ%S]|/\jJsWxF%100644 changelogVWL;qg̑%1F'ݼ%S]|/\jJY,xF%100644 changelogwGLyBZDOd-Pq%1F'ݼ%S]|/\jJ^}xF%100644 changelog@1iq%1F'ݼ%S]|/\jJVxF%100644 changelogH.`e}is%1F'ݼ%S]|/\jJl+xF%100644 changelogy.b#ot)Z %1F'ݼ%S]|/\jJixF%100644 changelogB$2whPvտO$ދjJ}x%100644 changelog1/ĆV0ˑ%1۶H|lr7 Pbj%V+D㬅w !')Cde-pIM@4FDdrunX ~fZCiA%0*e:!Alinks1[?\XE-Tr=t$37RǘriMP j}V$40000 user0;ol?jcqlmD $x\%100644 changelog|AWz{O#'mPy%1VSj@k*Mjb755 rulesMS"fj?yI6ЪDēdPSlQsBqՄQHAL+(qݸ#‹kAE VxF%100644 changelogn`fLd.a7۰t%1b9 Dކ`59jJ +xF%100644 changelog][Lر\moN%1b9 Dކ`59jJ˄xF%100644 changelog`w%h\J2>p;%1b9 Dކ`59jJ&UxF%100644 changelogAS7ȞNs6%1b9 Dކ`59jJ|*xF%100644 changelogJa=\ckz!6O(I%1넮7b0@5ڦ jJjx¾]D!9#1/=5'?A7{GVYS(bz:x.%100644 changelog=Y+[lT%wxH%100644 changelogq$^&uzKTo% ڭ,OI\둳Cq8xggW540031QHHKOOgXTuyBfc~wj3m\sxH%100644 changelog.3'%C@az4h'E%+%u3Ý 돎훳d+WxggW540031QHHKOOgHN`Q fXEhlTb^CxF%100644 changelog љsT]I*lq %14nɨOitj%-fxF%100644 changelogS ڈ@Z}Q %1lKstj%<F xŶMD!9#1/=5'?w:^7#l{ﻴ#`FUQfr[xŶMD!9#1/=5'?A`Ϳ?5 yBxŶMD!9#1/=5'?azޏ βw>Yqr-QxŶMD!9#1/=5'?AWgZꁰ-$NؘtFUQft xŶMD!9#1/=5'?U~|v-]6z(3A#GxŶMD!9#1/=5'?՚[^K9n>kY+[e(3JxŶMD!9#1/=5'?P΅C/VKiybz:H r=xŶMD!9#1/=5'?aAnt\azHՊUExxŶMD!9#1/=5'?~)rUC48l>b(3z!3xŶMD!9#1/=5'?KϿ}+q(b/a(3]%nxŶMD!9#1/=5'?!hY=iٓyAjƍ1)xŶMD!9#1/=5'?!=yڃ4 _t<#ợ_e(3p<udxŶMD!9#1/=5'?\g*\c (3$oTesxC%100644 changelog3hhUkطۜoPױ%xE?aՌ{H|^qxC%100644 changelogt0fɈOu)T^U[O.b4%xE?aՌ{H,%:Cx[%100644 changelogKv̧?z_Ŀ(%11}ǎ;:kĦ1jRD=u`戼~~|.-vz7Ѱ%14~B941yOp+pj[B;xF%100644 changelogu. U?kg1%14~B941yOp+pj1xF%100644 changelogDeE3pDŏS%1ʱª'!,jXxF%100644 changelog2e+Hn)Y%1̒b XٱjJPXxF%100644 changelogRj`v`"q%k%1xy8fƌ92ṮjJݧE$٩w_?Keb߼)Id΅9Jf~PO2rz+xųgȜ s !t#5TɛeX .x) H;Mke_RrmW: ~sex) vG^9G6=fӓm 7xs[D71;5-3'U/1N{)~63]t2Ld 9&0^N"=/͜Ql:72g%3|Buw%TjQcyM$gt;7<ڔ IIL".~ -ASFx}{Q}54x`x% 2 ";y6;%4l,x% \`CJ&mReB^Gx% )T~kq[wX/R{xw '100644 Makefile.am2=}(7A Pn'Z.cg(bF@ h6/k,Oue= Smain.cO`q`o(\@(E?֚9 xUD71;5-3'U/1zołSD`֓˲OH1^R0:$fFMɒQ 4Ux{wBW NJ)2^;dF&Tj1x! 2pEFoq_ '/x{weJ=jC[[Xi/XdF&RY>_x{YD71;5-3'U/1k-oʷ~ '32Od1UΚAJ֡u-Yk,˥5'8E754X/A[Y-m偉1~/3;1"xID71;5-3'U/1#ϼl֬۹dč*=x2'100644 Makefile.am:}׺}dVC(vw'gȲjxN_TƆ%ЦJZw!(Α)奷: V}߳9f—?4sPc>+'6x!Ԫ[#;<X3x[Ͼ}9efo :\*ձq99YQtwK-|K_ɝKު`]v('9я 9~Lx%0Z'z-}͕oۦaN>mx%0BXs3iM{aN"=2x[Ͼ}N*I"֚IO& 2nNdc! dx%0SM\#raN;cDx%0lzk-iz4n~aNL)ULx[Ͼ}H1Fc}sfadAF͉~LG ~xW?DZd<'&o đS{t}/oԌd94, AX\haNv'fx%0Ek!dpaN"73x[Ͼ]D71;5-3'U/1-sd/ɜvvUO/lT`_*X Q TX|C麕R])i%U7C2X^qγU׎ vLw*/L+I,zDx79f?=E`Ę"/B߾\Nsޘu9FN}0Gy։/XQRua{/ ovg8$3/ӯ9/-\i\p-ޟV#xdd.RWdY[مڣ"{X 8Lڥϫf>/Fr U&2^ܮUv_>+E$BvjeR~bQ آG;oGԽd{DInjJf.Pa1C~kĪ7fE|)*/-Neн<+VqO4:w*/L+I,c`bs܆Lf:E[K]uS_ZPǔZ,`_4Si_꓏~5ٚkF;zN̹!3E_T(1/b&LA휢6x3q TAqjIIf^z1Á_s^ZvI7)Z 8{xdd.RWdY[مڣ"{X 8Lڥϫf>/Fr U&2^ܮUv_>+E$BvjeR~bQ آG;oGԽd{DInjJf.Pa1C~kĪ7fE|)*/-Neн<+VqO4:w*/L+I,c`bs܆Lf:E[K]uS_Z@Ф]*$(˭M({8ٚkF;zN̹!3E_T(1/b&LA휢6x3q TAqjIIf^z1Á_s^ZvI7)Z+Wxdd (bx҂Udw|#r*UC;#7LqM)YBvjeR~bQ % mlsٖ U%)@ f ^6_jqN;TQ~iq*Uxdd.rpOrwytl !jxdd.RWdY[مڣ"{X 8^_eRTO^Ar(dV&'0hя-:|޿{DKJ@䦦d&3ԨXWjٻvO:YpC`VėT݋ͳxLn5D`@?Ev)w~I&QO}ٚIb&LA휢6x3q ԊԒ̼bO缴p풦oR|sdjzx:2 xNԾwHDqFzFYR]:dsBp.4z;Nxxdd0Q8j:gPIvAFWnnƛwFx:O&J:& znnQw pƕІU;NIxddpQ5םQMk^e{*FQvxR; _moZ/r2hR"U?K VmmB.;cˀof{DEJ$`x 0泗0 kӐDExO$qN 9ɛL1-]w8U)90}x;:Y:Є P~ݸ^%^xddߠ$UkM r(xdd.RWdY[مڣ"{X 8ޮ0+x!d.)o&+3ܓ7Zx6Y8 P->gHCy״fSE(RDDx!YJ̵ ̠rsxdd0RD~l7^#^=UrSS2uS+Or(T}a 2naRxddP(yqW}1wՓWܻ# -xddpQFBR޵{bՉ̂"lʸ7 -xddߠ$–Skʡ}l Lx9~r9r6}Xc8V&2YGׇTD,F)x:2&GBH[j4i VFiL$Ih:&J'l,pdz;NkHrxS2 xNԾwHDqFzFVv}ԫndU}wYR]:dsBp.4z;Nz"^ bxdd!l瞣"JK)\=+ PHc+zAܙymo%o[UPZT_pS_h`ht۹ݜzONvc  x6DB1"iIe7;ӳn #+ zQZ'HK50COxOŠ201RSfVg\[8!ͳ;:6F2 &b覊$-x6Š2016F2 &b)xddP,-MYsrU`oӵ uax8~r9r6}Xc8V!PԘEG Y^~e$Ӎ7GxddQDbx&[M.=8<毌Sl3x'100644 Makefile.am)jDY3Ygi3'k;JԝtBv6 !X100644 gpm-common.hIu,#++|M4\ct0helper.c&;Wښ니e?oܓ1cKN^QQJ;}M1{+'ѧ3@үa-100755|ӮҰ7bT"t'H};}aeo.c}nGx'100644 Makefile.am)jDY3Ygi3'k;JԝtBv6 !X100644 gpm-common.hIu,#++|M4\ct0helper.c&;Wښ니e?oܓ1cN`4fs{1{+'ѧ3@үa-100755|PT?r 1H H}Qa Gxkʮnh``fb˰f֞?.,Bύ#ggOT϶^f8Ʒ]NysYXT{zAnr~nn~^g釩:j_k|d"GʎrjwM$9كvG&Fn<hxkh $⳾M!t=:/WMש{wvf gx9C qݳ?8HyOK-vcnTa&cPHx~}4!_짾-R8g( yf^F xx~}4HSУ;/YǩR9'=$&L]{x~}4HSУ;/YǩR9'=$&L],x~}4l؅n$/+4IrS/#P ]x$F-2ԡ(teH$N3x$ y`iQ1) exv1б#DJ ƌFƩ@ǗWh<&rRfa1cI0 h;1?9/ʲ'$a_100755|Y2&ix~}4H?7by$&L5x~}4lM]ܙ_e<`$&L >fx~}4ȵn~3fnY~dn۬IL=z*wNx~}4PFڞwX,59pf^F+ Hx~}4"V B~}) 9cf^Fyx$oPjdϬ{@H58,x~}4Hv7LO{v|/ϙ$ك 8]x$x#%8mbM%SEH#[x~}4Ȼ-N[et-nL*]$&LWg;x4lPxۯۧ8 w>#5g%x#ZfC6 gxkq"Ckxaybɹ2#_gpx{jdngx{jlYgx{jzp% 2g%x{j` g7x{jAoC8px˴ID71;5-3'U/1AkIem+6[25'mTcQx˴ID71;5-3'U/1AZC×E5ٞ٘k#pxddV740031QMNMIKek'䗬óvK5+YlTObs@ x$Sj4M$2ph 4xED71;5-3'U/1!e07lӅ</mTdf$100644 gsd-input-helper.h?q6sbVjuis!\x<9D71;5-3'U/1vgϚL2eMӒorPe)y%9Ez O}XQdZwf ,oN m )Fx3'100644 Makefile.amۉV|Ԓ5삤'@BxMABҢU$(!9ɛu100644 gsd-input-helper.h (m\7/1 1:rx/'100644 Makefile.am1ț0`Ӕґ'?xG'100644 Makefile.amI3UW/7bfi 'Wz  Rpx&J:7?ʑhx~Oi{<`67F3Ax4iB:K'k eL::h wx{QD71;5-3'U/1RWGa'ڃ{IMT?xOox;|⑾h-]L]*G:7&CDl:Y'SWdwf5Z$`x̺uZ}% l;"/~n\ ,x[ömBa 2Uv".d/4Ɔ5L E-x[öm)9ՙEn[^P5ҢY.x[ömB&N:\Z"ȱ kѥ +x[ömBmE/YoZG%ޝ\a < Vx[ömBct 9+AΤύ k7xl]2zbnUر/x[ömBH''p1\ba  [xV:I %=Ƭcgn|ymx\jvwj4uA瑞ڌ ͓+P*h@x[ömBꔚU{zNKHyzc&Plxl?2Ig"e,Ycmxl88->()>Hxl<1hƥj{*Ȭ2vx=:m$PpƖ˜5.֑c!VΨϔ_ixH>ˑvGgx[uB=;tӣMY[&R xl{jw[\~ IAx[uBIKXjm)?elcC mx[uB+k5;DDf0Ir Lҙ x[uBȓQzkOݽ{[Ksrw狆 LG^xzu$6F_Niʭ' >x eڶ3jZ[)Lޓy\.x*"m,Yo~ -xzu)ЎwsaL MXx[w[=έ^NYxx =2Z}[3x4x%% L%ZyD' ޻|NSWT٣PdCx8*|;OMNM{`8Cb$3MF xD 4-^ZV*±q7xzufmIҮv9&ێ;شq,w  x+qʫΚkN .$Nxzu{ $&WXcEӴ;d zxzu~'vδY:E|Y&e &x4+'y%JugsjTxN+$VTs/ao .xzuC*HKM;Jmӗ\ڑ ],x47af.^s ^vy^ S{@Wχ#E-nx]'100644 Makefile.am H!mg!sWN'}Q8t\Guu:L S{@Wχ#E}'kx5D„]%^Q&aaUxa'100644 Makefile.amMQ-e62UQKFSjrđ'}8\7z=+K/gLWoT>\#>8jY]F=N'8x$H{+4x̴ID71;5-3'U/1!bJM;) Խ}κ{.6qDv`>x$Hʨw!M|ʻYniC*>{)upx$HL;H :d!>{ ^ "x̴iH;9}72;)a+9qD;;^ Vx2'100644 Makefile.amA-H)afG_"IȖ0Bx;tiLS&cs! RUxT׭¤X91ޱhi z!xtID71;5-3'U/1Dג/&gȴ;]_};}DxtiHa;YRzTC4l\ى!xsȨ# V6T;;főq.x;tID71;5-3'U/1!:􀪅)F)<.oQ]H xȼyjrC{m<[vi+-jQd{غ /x!М+vP_!7x4ID71;5-3'U/1! dzGSٿJgʷj&YKx:C7Iz?1 se!4M&$17b-FJx7 ma@3~f_Ə2gb~v[%xhDdXerx\$Xq%qyr/e5X&V" D.B A_W %J Ϩ嗀Vl,xx;vMD71;5-3'U/1d~ ?8xHs7Hڨ. >xC8UԷcCEWM-xyJ-ALA{p F Xx9D71;5-3'U/1!ڎR m~Z>jrɓ=7ҋSt+RtsSvދo5֎M6/d7Y'AxyHT1I̯ g1|!#I mxCD Ȣ8ZȅWexyH:6Xm/\cBF oxyHf0T-,t ~xC֒,+o\SnWIxy7Κ {%WEּj}K{Է uVJd(䦦d&fV3X.,}{;9 L6TGvz{aAԏݶ2d%**px>}:Z{gr?˖zչ.j5S2# ?xɮnh``fbpLJm:E}2l?''XvJ6e^ya' PHJLN//Ka8! ݮ6{um.-xI̟63,|Дߛ.ԔDboNPq9%?ZN䫌AN\k֮Pzk̼ݼ̴Ēb} yXU[l{ J'w3Nc#C/9k4~u~3&5b\EqjIIf^z1aXc,5wNtfmzE/hxMD71;5-3'U/1AʨfV@P)_;)Ӷ^Qݙis70#Bx!FrXY(o}8hw k/x4'100644 Makefile.am6,Hp份O@('pWBxvm:HM#EKfh[*'pL -x8'1C6ЋE<-<ҤcQ!|ԁC|eX7$ Fx c4騹|B-x6v@ ؤȽto4br_fq+WD(eqx6OUx{dQ[&~&r_fq+WD(eRDx4'100644 Makefile.am0A7nbM α'_ +<x!<~ jIm{슳N'0xvm;aXc,5wNtfmz (xvm:H~c2ڹ"gϰ.lͤ ]xddߠ$"M{6-sœL~Fcx[!BrBUf)ev~=vc% 7-x[,iCŴCo9 VZx[g4Pcp%o9 !x[!BrB4]]S.+ܼmsɲ-yB~Dxtimwpl9ZyU,x!3=]y?͑`"%/xwrk>]ҟnQZ,x!)emN@B9|F<` /xtimwpl9ZyUx[ƸqBHi^bǓKH Lڹ;!`i: :,x[Ƹqd7 ygόN:=e‹ U ~x! 1Ag#t~*xS:6>xVq٭DSx=j= x-A @ ER3t+tgB d޾"2BHŢќѿinm'{qpĈ!%Q8'D3ٸ:O;̕B92vӛx_>gH7 s|3XI[ K 'Nj`ljCN E~o(8պxSPVLU(MTRPRpJ,LVpK,P(.-(/*S RP6463645<xSPR(/WH/*JM.QL./KU--IULS RP64005Z x5 0D~ŀ APXbJD $`c9̜7[W)u-{W| vPS)OjGYF4Ɔ=9AX_p @遇 T%9mclh./WB$QXӀ3֞;}:W0 &_(/tͦ7E xMjAD~E AAC3 v/ӳ~}fE[S]o47s xCKs+&M}Z)RCqXqeK$# <$E [l>%_ͩ)g!-BF.7Y%KE7rq2)5$8φBH)u5p|m?ZZ?x]JA/*k0DēwCgғv{E˃Q<磖RvS>WpA14%;cnwaXCĐr&5Rٶы.h[S}"&/RDIy.9rIlZ~f5}E<*ۖ=WfwxǫoK xSPRMHKOU(JM*IQHLO+.QLJb#=]3.] x5A0=]vF70n2yzÃ̄q=ʈkNu8s(<;>SA'a?KF˽q̛#ZoFMKL1;CKV7Xi sj: x1 0XEGqM<&NCL<(gq/&2d,YE Cˀd*r:bIΎ(2^gߗufJ(^uS d6uvbmv~_6xSPRMHKOU(JM*IQHLO+.QI,IRy)%\J0xSPRMHKOU(JM*IQHLO+.QI,IQI\e< xM @|"ht6V ząn;C{7F\S1<$2 pĔC%Ґڙ&N'# JfZ@ ѕ|W ӚAuRLELq3Cݹ89<-:xSn@)Fꡡ*nҴJRR%TzX0@x>C_k4%˲f1:CFq,Ky</Jcv~_,n6Ckx`kXYYPzOX;p3dtD0JZ1$*צe(j!ǂ G4 I^2 ƨ­QґQ--{xD|&<]W֫ʽ=Q:oTSq(WatCqZPaQI%P?bܦ6Fɠrd#R"£&_s>HTjnڒOE 淐Zu^:Liu/TxUMK1< ."A}G]C?Q@ =lK`s3brkZhh-R]0bJ.  q2L .IbqxswV18֤3ɤ(5Å4 Xzv@4ZLEԖL)S}<(W!:OŰCO·(tJd#qx+zr qΉFbQcpJ\)Ļ7poyNQ fsMÙb]^ $"cRR%m+a^8,h'm+5ȵ}@(-MR,!%N# TVf]nS%?qquGW鶟Ud10I x-̱ 0Oq! *MQ (4I&ۛ|@3&{O 6On |}h@_R]29Pi'}%* `,u^bE%AM0\7|c.޺xSPVpT)JSp/QRPRMHKOU(JM*I K x5 0>E&n:NAa7ZphU1$| 0Av'`ĝXhbxdCp3, e WOrZ+qĬtPo4Z8^Z a4X>]cO-*[7Y*`I.SHAI Xn<r9TRWs3]n T\:F78֔ + u+ۄd̞.z!j/%ج$eq|%yJc_#0_oh'{|2ϯnVxWV xuA @yEIq0h5I5L/[x1O1 _I,TDLH-Nl!s&q;{Bۅ̓>@YEK Æ)rHWNM{X .*,d1B\D/8PQ*d NP<۾f]z>5mݭacХ䏘"sELR_]?-esr7^fJ~Z̚| 6Rr&x2]?Ix=1O0RP FĐPpq=G>;U=nu{{w8&ߡa/N5 ~6=.0 *#;[VSmG|<Z8eؑ1 m9ܾ?q?<wK'ٳli j1֨2jN\؞1rqzFYA-Z;X+UZuL qN>˦y3NM:8//+Ci z|o xm0cb4>JVa~: pCSCxM @D{b"**("jg)X؈X\.crx߻*{ 3N7B\z[0]DRh)j hRT'j,8&PX'{YƮ &JyTi;oYihEè#ݳ$4`ؠ?z{Vϻx=@@)Pl(X2q{#9(Z(۝LP/+"doOT}17E-Lc<\x= 1 D~YE?CI<4- oɼ7)*.ŅlU .Q'SP:ny@jr8YbA.mF_lҞE]2j xkҋR! +4j 1[m tu /tbj]Y@WxSPR-HI,IUH/RHMMI-./P01V((MKQp THHKO-N?xN@yz4&4w T@zwlٵ'b]pUR{9Yn`mq'p3}-ӬD;nF>7 Ff% pLC#|=֢c* hN.)epx8q<0lr9FVjK8kxlFOSYm"=Aa,Tl'uIt\,M,/]EԎ.~ tL uDGL)m(P.׊fKw5>HC^jJ̌m/oZ_ry}~_~TĭّF`R((\E noaUV׾u;&jsʌ6^3/vTHchZ}/YaΜ*g[Au x ~SX5J.[2OcVm ZK"+@6s\BR9F΅,E>Q0]4gFv˂ I 'ge.z[i!x0AƓ,.}u?Jk/G9 x5M @.(A5CQb ďW]w߷FmְRd=-Jn-vĦ&B{|,E%)\*ytlo0Nzfͮ s͘_e,QU!(rXֳ>`QѣOR|2n6wv-N.5VYꈭ3Y::U_ԴyʱD4v4_ qbt\R!E/cRQLp]zô2DX/S7Nફ眀,lOW'Ňm* ZDiq퀞+Ϡ35< "G@,,Γ0ddUDwnȊofRxs PnyeYX,Mjj,QkK[붧- DX;k x]N 1 .nH>ozp&*8L㍝#Ԥ/^u +T`W%}D)ܾxtnvHp<h+ynt<}աGz x=A 0]*,2oRx:l4fѿOD|{iu5";ÿ`ӽ)$m B[c"8>"xˡ !lKEzXǍ$`jZ ~gBaR36}d=yx8xeQ0 D=~;ޠh4[2s7yθ@X)rF\j`-0'W䵨a6cišBi'崐Y]FZHu 85SDO $Ι}C{m?OovgpxSPV(-*LQpIURPRpLIQ(H,KW()MS RP6471402hx-1 {^MX!޴ x-= 0E . HNA␏>jX7빇{WQ XD#t=!*År=a=TZZ&(ƌzNY7tEe&^*"}R렃%z+=@K.xE[o1+Fڐ* -R RXŗ9Vڇ\sl'z(VxU[f:xyu(_863rӑ ({Aw7XiH5x!Q2nno^po~}lWzYpzG݉YH DB{!L ="}+{U#AyٌtVF):+.N[)e?Quft9ѨO28WG{B g1ك8\.3TC` :T|ݫ{ơUzp5OtL5ՔL#vĽ޽ !aoO/Ojbػ2وN׊BMamZF J>srdF(\Ly|u"j)P4ϝ+r]fdj0xxSPV*TM,/VRPRpJL./*Q(-(.)JMUH,Q RP644335, x}K0=%Xp Kq.$d0ʧ ζ_8$gT7%;2ʗb3^qݯgt2Eya#2SS _G1fa,52I6f Jo^:qLUn 9bCܯeޔ(DZPjտg*Iս x̱ 0FO j:C\`ŷ pELDrc.9JokG * ыجL0:Vi:LN,d`# hKmIim @7xm0w z)$Ĉн)mW ==S5" @؀Q8OeQhh F{NīSSڧ/X;pęfW`lN[!2C P8SJf\ @W^R!wTȲ:xEn EWV?@( )EYa\/7rњzՙlyk ɊP9P>G 5f?Kqv%<<=5͢#4[!]WdXdJ% q9<.h^^Ftর{rH+R\3̇ꆩ2x !x )hR! `cG` =bE1ѱ:`%7/s<֨ w9E*_lm}+#xSPR-)L,JLT(HUL*J,T(HLNLO-9 xU= @D{ŀ(b'U@JL}q{gߛFef[TrzN¢ hR9E 0w A4U-#OPja<$ȿJkxSPRMHKOU(JM*IQHLO+.QLJNKJ-*JT(13sx 1 1@~OF-aW3X؉E6!b[xj{%QQ3kv[%兀Xo y&[EEJ* /l 8~.#mxSPRMHKOU(JM*IQH/Rps5202564 CxSPRMHKOU(JM*IQHLO+.QK-WHMUL*J,L-2pxU= 0O񀋊D)欈8ڄ6\ q8akSlZq9 ܶʓX6ꠅ .Tq T=@5Eq]pbi8Þo˻<_^1EA]6HQ:o;|~ j(x4/Q[xSPRpˬPHNI.I,/RNLO,J1*S J2JsSup)^JjqvI~BQj^bnO&4 xMj1 D ?{ =T[xEn[("i_Zfuq<9g 3Gь(ZPBH݌[@cnqad#{|qi̙3&!Ȓ(Ԟ6ЙoJyQ#zt*?im[ O6_ &NkpvaO94dPxEN@ }9W[ܬCOv(}{י> (`N{seS6 )O׊evwK`a# @?(^xhǮ}՘Ұxjv8 4B }*e Wqihd)*0btT1x @{⁍ BDb&]X.k݀)`@GA8,;fEM8Oib' cvd-z/'o67o6Ud6fy{Ox5NAc&5^i@)T-BKXȌeWl߂іD(``HH,]vke'.zӵb \*^E(?Q)';f76KHLWo wv6J`ZfxmJAy/*dQs!x fg{g 3&;橡-FԐx{5Ád&(;oE'aNyܮ?Vy^O˻❓`sc$fi+54CZp9U·tBǜ%АRr:(Ԍ7ɊC_(! 1:\_zQ7M\o$h);ҏwhu9^s[qȎ2~ x-10 shܱp"0E$+^y wfi.FN=ԼmfJvMP;b Ŭv%/K~EPs@IXS]sA/0> Mk65 x-0{b$@()(B/%Nj֛|3~(0C]\䪕Lj>'Sx0u@qKfԢʵZ!+zQ`r8n1.j)C3)[՞h~JO?xt!O.\(1GixSPRpˬPH,*IKUOIU(.,IP/QH,(HM,K7^x10>qJ@(6'Ȼ($'QԸے5xMp!#m7\AYK|;cQ,x Œul8RP$xSPRMHKOU(JM*IQH/RLJMMI-./55oݰxA 0Q7+AJ $J=gbDk(4JȢC3{x1@0>B2M&NVblw75z}DTK>zN;8afcÑР9u"ܹxSPRMHKOU(JM*IQHLO+.QK-WH/Jx=10 {^I@oŀu9R~+Z͎r.7#&KS>6%U*WqǷM\ʔ:_q" eja22kMw<ѓ( 7e1«vxȤ_ 8guài]5g, f%</Xvm)LxUYH}W8U Z11X ZL$I*,ꇉ <{/q7;3g=0~m[7cpȊW/,Nĕ/9$KnۜK^ (5N2֫ z4N:jLpVEvhUY.)N_aYu'YcW8uq)51:]Gs K\|f]4i?YgOrysU-ů"ףp,d̶ǗOs6qv +ģGw ^4BhHS],to>rP7.Ut$MpKL+ѫ~__nu\;^Wԅ(GUd^- ̵;yvQXq~f侓Ä~!$ABG<S7$5z`,+ɬHkqyn, ^u`ưh"?XFqӡ`LNkƯE2:OzQpy&Wd0ՍIxL-I,²y uz]ͩ Iqר V; _-!jEh<~^p9Od@:E2dUJ4|L h/3'r65SD lHi="=[2A] #wGD^if㍛s~*zqHnlӜ5 ]f2MPtTy ̟ywi(6iKJx]һF`)EtJ 3闂 2036;B}DyqV9O~ ~  0h*, ,1(MM%M ۤd3ob/e_j^sh"mnD$sj)q" ,’gbM?`$Ԅ&GJD)* Dʱ$Z)`GT6hJBSIpJI"  ŁdRr PP}~\g"2A @ &i-,b'sAJ>JMO-(CəL/x߾Q8eEp m@ka7 )7x`ڼvt|ɮQHx{ yy&oKQyN;U pt%joOAr`9l̤WToGP _ȃH_顽EL"ʡ7aKm jzl~T͝]:c*Fcg_rm}I=wײɜP[  oөfuK,|+dTc47ZLL~f$hSr(ə !j/ ˶C֞^ꮃ*>0v!jr;eKn^qǡ9=OjP:7[xɍ!uB2-w_z^Kޣ^?@瑺%BZ@O7#e%NZ#(쭓Pw3@SV`UaiܨbkwM(=T?bVUqߑAՌ^W$LYYx OOsPCx0oAndͰRTˇZ:K06fO#VkHpxV[s~WxHDh/y9t7r/1w쇩ږMko]ht?~ l3H"ַlI+Է2P5iV4r'I< #<+r:^r*NjNj$-y%"o~;+ԀAThMuuխxۓ{\l뢔d/i"j^6UZdITL(njH6Iʔ/yĭLY(~Ȍkן9΋+6VH[J\oVЏ[VHSE7Foi*2ULPv37 z}"PEޱ?Djȋ:NTK4e򹌊> \p|I"gDz&#p"&g3Jcx 0R7fS^]ųUZEŮU47KJܴ+\m@.wkx:?U$yې](q}>a]D3E_޻09/jQB$};{E<=-&^rJ$p4X!vQz/!5#Q>+_^o[i>=e{xjxwԪ_Tgt8^"=vbа c\n,Q8uGwhE++?f>'cK@b9wO8+vr4"< ,M`zWqowb^su@F }vzE F3]nq6>O({r}"[!+ݓx Y)ƣ'ގ& <Έ٣Tct8ʵʌ݈;{v=?ۓu34_]Џz6 RXZo M-Y9vc+EXzU'hg7;I% z ރP'z|. [j33~8s'^e,qﻡi}GxUKFI.Hgxeb*H `lTalc3-Dd "; 2 |W/X j X*@DŽ2MpL4(/y?~lzQ^0%RH5aN8c3X y]̀Bt5C'j R(CJ j\S#='Ԅ` 18O)JR,Slhˆ!j) ֙L ΟeEyIb[\SfD."9M1B@yHhmB[ - $8?Zo\tgXe[ R3ǻ'A{ 4-~.{t4;Yoblp]B;b^@B3QLIa/=YR:NSFSx jMngMь tꛬ&IWt*8un?1sxu&H ϭoTY]=xmpڄOd,03$ ,`[<֓uO]W΁ri$ݨ{yDiKH xe9FcD ZUŪbU`ĖH$JMYm\־PbW00'q0c8|'Vg3W_)bF!( ȕq5#3\B~28CX$˴2`2,2 T}7~CϽ?0e0P)$&!jfxfp9s&$5K S7Z tߝ`@a;@jx&?w?jwIB1.!*tGC< &3)  RCca!$|8vVٕ7 㝝FOhqhڭ]RosI/W -,-@a6m;-K.L] 1gM/py~9 skQޭ45^4+.w 9SƝiDIyoWe ΋[ԩs{u΋l7^ )Iz!ir9tEڨ]B tک" {5+:bljJ|SMs$ۃꛑ?'Y,gAb4u*3,[><:Qjҧ9ӻ1F,o_F1YߞkV.3_?m}?l/fI.xm;FĻodX@l#0`Ň$Dru#JQDQd2W00'qԁ_À8l'ņU_}w&Pw󫮮h@9L$& Q 3u)~ 72{~0`#3MCOu D1(dJ@ boロ"=eJ1)1K.Ȕ4JDdq"@bbI%Oml Q V@t_J $fˆ 3lTDD 4J ?QbbL$BR%a MЧ&.M*RAM4 tVguNX=r{4!E\pV꼩e֨kG1^'׮"2lwF۝Rjb^p ƚk°ev9llg;:Nĩƭۙ?䅓zre9 Z-Dc-}ܞ6} ê$_lQN93."15/2/8, kw65sxȽFM]XxGE{b|-wHƣjJ8MYho i^w^΄1ML|?⃥'נ[&^UXQ^Bs88kFӞvNAYR:MkM-s`utҏ5yŵ ̵b`[\r WYGn˺<V ϩ_Reqz @]]Vz"cx*=ݏr^yڏ6k4Ң-_?g`X?mHMúزV[]d[$kDžzC8kLxUYH}W8HfVLw Rjk2"P$Ʋꇉ <{ (kwz#y˳^ga{6s;+H],Gyu$=e2P5iUrY,4 |8Ar %eUqzq^uU5kV*-+ q}OؕY.9k7IbQ l4+qp$<)2eD<Ȍ'9/ iJ 2˒;eE ʬ4K~G:nNSfF*BWn7 @UB }` Rfeﭩ 9hkdiy :7(~tEЈ%&)Oꯁ;U"gXdUW8>+ oLS‹+uzV~;ϒ]\*aFu3*0R^bRh$8׵Fw ":2\wfgG^܊sT%Y  ś -%nMsuߗqJ"T4J]aw50>t%o~ZgQ=S,]_ܵ(miHcLw8ʠGYp`Y^3`݊8݉j/YeC˦ -&Ma !sdhiI͊8TK\Ej@:v= Niib@6L,_BüJ%35Pm[9Mlulqt06kÚaרRP4-3$@ 4l~ 6Ψ X6C0QbHSpqd `ږn=0`F]z#j @navn [`4L#){r::i5ȇ'=m ݎ7Y-{YxqG/\sFQLj8Sbu V4yEQkߺ1~Gvz>$e.SGz5 Ӱ[΅wlJxQCkgS6\ȧ> ,w9CMM^/(e),z=7Җ07l6cBד^hQ,\l&il z.fņ`*; Bċwvύ7;-? 7A0oFh c'i{[Kџ,Ѕ̆Rq'{v>N:8;SizZy~Zv'ppIXouCzCaG3_ͫi&Uaio? mϧ=  OI_&Ʊc/H`m?vG!#={<F?г4[U/\j_>:8$^=keAJ*_zD'q.B %ᱱblOy?ݘvN.y{l/jÇfsFravJBGKoc? k>Kxe͎6E$ֽUU7cl0Z !| j&$ͼByR_/rߡ\^ygݯ}o9`RdLXQUUJ \R!pJo|_4?!{li5 )8$:80T@4|Pw T)$ØCHpB(R)9l|~CB-F"H09d`ń0xe)BeD !z6t\K^GvH#fx`eB˘$T#0E IJ h25YvO3][oMi8^f&rumoJW3w۠Ybyn*-=.BFѳ5/gg:5n٭?f+)An-뭉:?܅ao[wj}h״SѓzRTm_Do AwC~Iwcvˤan܀!GNUs}A+ei{aKSΰS_TVo2'g};NNC{dd+c͛$Cϴ"9Zm'7mcTõ7h6/f<' *|.}$-Su|5eҟX[KyXf`TfqoF|t ]-Zg[mѹh2IN}\WbUV-2Jp5?YVfarEˁDuejnE{.kqxuuؒgE4y$;HPCт:2C~"tK'xeF$9"* \7)m͉L,@A-N1mCl?OsQeZTqH$CI4IP@p' _|2Q5MB(%C.bhPYB6x#'t6NOli ضJ24Hb-ٶS{pN· U['AK$ԒP0RIis mk1+UJC@!bw5I0,ɂUn6 >X+G,}טX(σj;ζf:0>; Rpn8} 6ث!/}Lȸ#p֡_b[ס*Mȡsl-3Eq|ާe.̟ APXyrZ٣1bIa~Ψ6:n{l^`Tήɢ.þ̺&r]56bYy#8[Mo S&si[F0zCo cXwr]`11sy`w&i/噻 ^ vC~ɰ~Nf9UzVFd[$r/qζjLAamy+8f+*wsESщebyuWC;,r\-$᧒h9O(:g>j*@,sR =;=hǧzEj|>jf>hw2omgr\{?^Aܺx(n]}="O#fpoGp[|~{[~_pKMxeFEoc39!ܪ2`)$\$ک-_Ac #fs}A o%b$N I 99HE) 1 ?_K=;.8>)xΘTI¤27!V4{2 sDW?9%&('8*͕ 2 I*7%ሩL (!gt7t&b!1D`)2NDnAQc ϡ !pQ?uvTi=W9_*)OO(BS̠!T$oX%L 㵠\rTwVAL^B&뵆YzD~QcܻRUAU葉.{4TG\n=ta_>@t Ս_;U&}{x^'ob 5t"nXSF=Ʊ*@[Σ&f4hb;^v }{zѢޛ]J/qbςxkGX5/h"5ٝK(BcӺmw }p6J°OQS,Y1`1(2ɺQv50 [1Q%}gܩ\mW/X6܄>&{s";ЕFF.L[ P[؛1PqW {@1_bE/Ѻ5Df{ˣ:Uk 6 9hkxzw%|7V1NXU;:-Y"AGˁi} 5n޹"Yr6N;Z}po0QEy,ي!79a}q,)呏NyU S:[w5M7&6h%!Y{i}/ާnKpxeFEoc39iYU,lXQ %QEFUj& 6#;w`?0p`dxwg?Ɵ,PS-E%.  p~囷zeW/vzYUƓ$1Ҍ% v 5w}"|xz͹B-kVBD"\1"-*,d+#GtOmKbP5 RAPU*1ըZ@4LqSJ^\|?<O C"L#lu\C 2:GVEbQ. Xڒ ʰ?__72i6{}8?79 q41sLxSZmqBOJES2_ V`пDޮjm0IY0V$2܍b-r0s38De)mW]-]Igx\darsoƹ\mdd́xM`웺J-Ju}ԋpi?Zf8k[{;ϻ#Ų?MZ3?򩝯N*A0yxNt *=ΟhS#q^zF(ffYpx$:Sꦮ^Whڶzju#x2 0-Ax~gUT>$”E۝ m ^3_jEۻ = ^{j3tq*E1z|}NFթwwt3&튯261vhv?nGqq@uKxm͎FXFEe$("R1pcllBU`l3"R /2OM&{wy?"s gLfœI*uʳ4hf ݗ_CqwXXCƩa[Bc$3L!@tB7L M c 0riH 2 db0#|e[LAu!2@f r 0eX91S=G;pf?K)?<-+qAy0c0 3 9ew>Γ~[ K>$B9U27sp4'tSej_¨^3k@r/3{ f2@{MhN\MB~5c[U:ѼtH[YX"m/MmS/ԽQUpP#OCsV&4L=!a LۡSPMwR񒒭_[צ@>oҨE܃aˤVQ1Wj:ikeD"ikϝ\>ִ5j pjyvM)#ZptZѝwۧAxV'8qm}stU AA;$S e}*/=熎6mAZcHlݳ/!vx?=.flDAϴ ;L*?}6>OJV~ؘ^vԽxVێ:}W8[8qnGh4rl'\<̷4>m$*WrYFUqeڭK{:w'Lz*^$u.yPL # 8\`_{>8M xhj V9IဗYb9 /t w"ēȧPVOҟCk9GpX,fyLANa9iQfsjm2p T?~SRtV)om mh ;ZϛuZlh5QLW HAVo6F؝3q=wbt_&wLiuIߒN;vrhv\iFזG Uߥ\=j}5"_=Vܸ|͉5Îܫ%\˱X+ڂO[-m.YgLM![+uag7(ߗn6O:pOey w/Öm)Ju4nn|Q-*51[w:}^ԫfZ(9*O:?j‹J'tVA`s{}iva`)ؿsKw8쎚 "W#3igf icT[r3SCy:>rcbl^?s1>lxUV5HAJhQD+sPLY f cq i2)MڼC I1_?>|ۧ7o/ol?uilǷ<sih$tL4fDH8h̤G}yx@H Hvu|/,j 5g֢r4%k$<>jK_-̚k$?$ڙp{v<Ԧ\*]ʙF29P 󁹤Ep| 'Fu8ےv#jw|̓ōI jfj1 kj9l+ Pl%IJQ.Kk3$+X^aH̰i̳h0%rCWEeq.nERЍN^E57.^X7=#[2}PoG',uE l[q&88c ss+{*ֶZUM|ʕvqJи9q6}bYaÑ0 q Ek#RV4o0OF :e\pX6P ]_AP.Cz܅[6jh8Ya#X垴޲myf9x5vλdZTTZ QuQ.ۚd I˼&Hkf.x5ҙ5'?Gk.j[lӣslme̺XLgsoB镗? D$D\0(zzUiHEPÈJi>ICf 9&JSJa bf!}4K3!d!O /ߓkKIDfU(Jdpس./ #?+>j༩$ii~HTF4S,vW)V)03*:QNzy\2_Oz:gu)WI vS3$"XwzO#-']x^YV}3Uugyz^JO/sպ(Mi鵻͛4?TF_UUZHHt+aNtqj#]ݸ>L'n]@%L*Fi/I,#u z JYi3wˮ:_X# S2؜,+MWsPtܗU"8V7Cȍ^Gjrn̑!nЛ8$/v!muNUlRqz:mi^;:V\JG?UsxˎD5 #A!Œ;Ur]X87;7'vٹ\.Ilb;7 ~XDx6d,f#,}tׯSd_~C!xD (Ҽ@o_>3cQ Q \qB"1 (#|+^cv?>FvG$">*3t(!DϿT@WI%R!}C o:0 $|H P0 #:@\OTȱ䶑zO, p߭eԻsx~X. bGfKt(Od?40?b7,, CCʸk4-v;Ali(]̺-=d3TbϱKG5;õhK^qƸnZRTvztݲܘl<$>ե=e5)IE˳{{=wpi6J iɰcޮ<_$^Nyn͍בGEږPL5tkpkA=殝kKPxjEݦ:NE;˒7d KB\EajڣqqmU5z|Ot8VoV&$>s'm(j*{}*B%ڣ]3,o2Gq.;`ׄ-@+q>p>Z/Jq|qn<5R7(f%r&zKFy螃['fєB;iܦe.9i4xZKV$Zug1&dk+ ~OhgO%ig0eמ %'{ȋ]L˔'t)\[.7۟ve;V+uW3n[]YwE=|{1NzYi?AV4wrw#kt7XoBZxe̽NP4($.bgphj"kizs>DzWGx=.n_Q;hl=ca\pT+(ϩ06q:xsrq$`5  lyEzgd[HԨ@Ckg QhI{S=2IgemFÜޯuZ$l2B鵨{tv~4,UY-^w;jڹggX+dxnSAP6R .)] ٖD DnH,DˉcDZ?x <AQmmWTɴ^_UNJxVy޽p}p$:X9aВH2(drTzu}{c^_E0{$:+ɲZ$)I‘UW?0<63-h4hUB(SHULdؤ|bYeQbaz P)R(8ZMբ0q6BIr̫TG*c/盺^? uÑsYPV7$J%Nи˿.VK(=Fnj}csHF{nχ8Y+jR紅鼿8?iEz^kNƍvGC>>fWhl٠#hiO(S8x}ˎDCi*Щ*HKҹ'NUʎs'q.~Fb x<xD F_7W:DoCp!@~.>{W?~t),'GR &8aˆi q !41"FW}tp_TYz`}zUR1#\&L4C&9C$ !'& թ#ߗ~웎0! Ks!&!03 c(4fA$17JmjB~cQLnPDDӐPR]X`DMSC< a& G"'$/xTT b.%H(c@\RJX"A8i8Zj0bTl܉ci˳iUt` ?p1jjգ5Sg4/S,aK!%)^J]`5lU㹽8}*Rum5gT]yJx]Vrou-ćpcn骄Wŷ JUnC>eX˻q:NFaWpNOyK{Gl電U% Xt(NM ̠ܠޢBhpfMeSbXup(ھx{C518^]/V=Te/i͖uAd|8%G4sQ:36ƃ(:A>Ahe^+M6]@+*C`Zkܓ"e |Q;[WŒC`6!+6¤ ?;IP/F޳2-\R[6[o֯IܒGyuj78iR 52'anG: /yR*LJۥf_C)aErw[+<ߩNW[fU^ht|_A1Fi<_|/%;x};k#gaE8BIwRl1#i貺u|F+X%WC 4B&,8߿}X `eϯ.C#/0 !T+@0ckpNj7|~[ϷE}ũRZɵTEx/T7U#?6}!̃ŁaUx ^XBJഥR"hyM9Ɯ"DžJ C(A,'N#tn$) `KT_=@✄K>э^u\b-̹[I#0 ;/SFa;jUL]ain$&7Ӡfq_fj,F^TJۯ 60Wis/A,giqڋ o>u6uw{ ^+:'Y=U>&kyJ }\rIo18i7/v/Cz9LLR!ẸLF,m ͭ+G~dkjR^g?k('fHȰ+;yVQ Ko܍^:212,a4ϡfW'MIoQ&UzܩQ)ʃn5_ԃͿRStx}MDjY AzuUZvI:vv*ۉOǎl $l8+N8gF#yx~@7@׼F%?ZopQBuHA.p$uC (^5|6[fQ -gܔV3rdm,*_T!i=;ji‹Z/&%3fIQE0L-]HW'kMoGsxVJw> NNe& ϔ x|晫\Џї4 ^jeTƩOҺ^TvyS@Zvw[&7qmS[^+R|;.fHFVlh{n/6Vu,-uf$u~2* !L)5׽pl{żǦ,ѴoGr=[tgG؂lSmt:ӋypHʛyokj_jnG°#@K8Ml#3؎N]}a{ם{2oiW:گw}X1Hx}KTQј. -* y=G0ڨ t>\g4!$Oh"j ,_(`0N(`S1u(!H@|w }gitQzHXpRIbifSBbk JJJ=S!e3Rrl1dBDsr! XYFL(=#P3S7z7QĈ"R  +JG^A.h) 4q1-fEwj10!5†)cH=AVݭ&ե$]NZl;MQ6UmjF})ef4W3[l 5庋Aa 7ԒcMw>{ќꇽ`! *U]{V֒[ytuٸ'pxm=nQ`!r**{(&$(c ޯ=%'&Jx,=PJ:G|pwϝo>>Uj 2afGRFPσɜqey:[E=n]Ek|`)$7ZRt;Ѐ`M( 9'閲zX"֣,jĵO6$5)"M8`Ā.45\9)ғf,&haG;=Kan9\VSZx>V/agyv~xunAP4$HdAAaH8b'\R m,+DWy^h\$H;wgٯיj}Vie٫bycrqƝV:4;cy(D9'm &BEbքad{ON7Ɠlp(E =F8!,^'cJ90ij=D.E"8C!PJ"D@RV%%HC~vgouwZi1>* 6A2DFU+ڢ ;?79BgJh! t&F{q"$b;}Zu (q=;0 9~Lm:{SSK{?(x}NTA,I\x6&&ơxa $}/0OF_{xf XUR|=Ű}LjB|.i9$P哕+wV'7z0)6X`PD6HDH,%R-~k~3&On֟;^fFGVs@2rRRBҰݿF[\}LFl9jP8!XɔKS` KpU" !J&CbR%j%&w>2 N1ߵG8[ b3Q-+'3.vlHer(~kիr09n{Ol|˓r|z{>N׏zQYoAcG5ߝmVJT>xбFp]HBڋ"*U$g0 )6`cD3`1ƀi&e<@tϑx\;eW?H=>z7<|Wև~WojoŖsw R D#HaBY2  _?x!?%CENq!x*8X A2*cIQ *2~ OR@GHyy `aeH< C DF>*y1D)[ B$@V )D6Q"L"D L>!L{)ғ}T-cHLgȐ HƓ?~T *|THoX*P!$}?K@SZOU mn~hcbǓqoYGQIE. a|aʹUCY˭ҦSRJ8.5.1)Ku؋MuG0K^̧q?kIk^mTe,=,SQB 1l8m'd9^}ZKJ.v̙Kq&W՝gr؜]$* ꬤl 3oQKjzr0}Yw[nebv튺&JHs TE.*5}Ǫ0+{*kiORw݋~$~ǾP=+rV'9X@ ] ]zikP%E \|n ŮXpJu2aQ#C[@ždrTff?##7LE8poum碻 bXmqt~;ӧ譆FO좈pM}Nc2ab YkS_ax]czz{E/Ա1•7p5[`W8mG5,8y73fwa?o/VpxT5Gh8$C]Pq|}|;oo;Nع:)( xDC%=k 2H#,U/}ߟO_?/}:.}/=sE) -VeR fE^A~ŮV 0@"IQ4BLi!n0IH^;ŐP "2 e9b$D KN[T":}U`AoQ)1Y,BiAl3@*e"CI(r xgO#;ԾUS a`MhCVj[u#۬=۴ L#[bm/~89%cJrYIOIƬ˷h"MfYxP]ݡTF}pXOY{J3 Ã~kl}w#'tj JgڃpaAK0RIvcSqkw.xc[Iɪ,ڭke;>ʒȸhS,w'N/3V96]MXڣ1Yz {H4/æ5&j6_h~jzQȼa{$(½8#;7tzxkyrlGp[<ΖS_AM[ d G3-(J뮭e"~]ʵޛ^'R )f;phyd0Ml]5-%%q{$ҨZ 7:v`u",:BFcޤ歜\ڜVA>`(g7E{/{-]l%xp0陴c{R+ݔAfsm8bxyvgi6\5wzn2qO"ד2p ʯ#8 HMũjwD=q|T6E^Zb:½x :5q0&4h釛z3kнdf;IJ? !ňvXufH`@qW8t6(0i&f:z4X|69 ʠg:D榙ܡ5y󰠑jِPnQ/q}|e^}]tgΑDa%Gu2/{?Z,,֤1YQjhv07K~gA^<ȣ}8ǵM[=bY~wi4;aw3wZUuνݤ V]HY)Wk+csAr]!kѿ$7Q;yi՗iRTx}KD`րABЩ] َvvNp8vN"O\܀k 2,?_Tͯ?}Iv!=㿯o}˻?_}usz'?Uno aXŠ%AESf` HhCʀI5wGsm>(wV SL ƔJTXap aJ Y{jR" QfTR!P6 &X7 a*&^Z&Fs$J!1 0k 2Kc'H O:#HoZ@unI-ЇNErXWK IMlx%̱=l'#o.mj{c= sS-o!ҵ-@֧@J'AuTM%b7'h8ٰiQwQR\AkWlPX`3Ta%٬j| @OuAf.S!9**byNGOFxym]v`fz=edľnKO)]UvYqEA<nWû4\#viՓ[i[j\XI2lFx9"Yԥxt}ܟOۆz+ q5\cJ2WzwjOz:XନEͻ߻~<*ӎT9x}ˮDuF V.̱vw#%sc羢n;㓛\8(<<Bx^a$3T-Jo|_T@7}~tS~H/oO?>{WO[5a?d/+R%aD8$PcPc"XgAV &:jUq^[]vwEPD@5 )D@@"i" yЉ5V*ן~=]bQXH*:T21 ZG*EF\0*ګ߾W @!+T0ʃP!*"ΩbQVb+op߹*VC*FZ!@QQvM}`eXR Ujjo$ioQ3hd::nVk0ٮX=]hnIAk˓HheNܣɼ"D>'2i0 <&msp\\Hm[S8F!&Z1WZ=XYn-ilj,_.sR;K d7:W.q\fbt6#39͆MGƊ=#q(mtz'uq:M,ud_-SpO{){X؅OŰ$НeMP25/֤Z`'ͷ3~ZXSCX#Uދn6,frptVF^ҪKJaw)nc&='$YCy3)z q;x\*ӑ0cn܎bfupr7s"`csGaÄ-v=FZYˢyVZX:? IrΕFla6#Ux`}yyKi4yn{)]4^kkd(a:Kzv ۍlW7V h Ѫcp\itr|$.>Gsk]m ;);!M7q+q, 5x`Ɩ>GZ'M%kVsZ31jYx tLzJ wpDq+G`-Z:Z>Ŷ9jNjtd"0`gn(/PzX ]YN8KwӼΩwvxlT.Za:QY>wyt g/m*e3m:n6ľCeo+1LA؏˧vnUY"arUxM\EXlIs76}kiwXLվVHf7S͸C@jPr d@^%=n.{%E`<ѰZ"X,"$/p7cx1VoX-G*|oBXuhub&rLrlZ~[S3{CChfAC˞)>[>Y7tC\;OnY)5u_KaN@x}ODp1,,X3BB$Hm 8Nl'v$\e'nۓĎ H}.Xs Ű|}'?槿>'N47~W|q, KItl:RH@(P^m۷ͮ A0C`@S 90' a&C$nt@io'P7S,$4T3tI$X $P:dJŲ29aL SP(S% )6"-u,tMP3`" >xɗDH$%H^*_RERX#"0:aAןO[a5n&2 L[hd?ڔ5`(4cs>uZzCm1%I6$# _U/OVr^$_qV`FIT 088R#F G>FkƧ;SL⚢z".xQiIĽ(4aUQS`MC @$7J#XP4*)Ii*[9AM,-DӰ)1$ptŷ?AU8LCD4*FL } dDIS* !JgVdfSV.z<$;_#b5eJE3PniFg;|:q'oA`nu酧b]u[UY玵XnYN,6 ,O(SK{LIYwa>]|;!veơ邑([J*aqgFt5wb;o˸7G[q%Fm{@ٗ u bˡn6<*#oq򡖱d!prHnvRv޴DQqa$ -bˠ*CFmޙBoD!KBѫL$\rS L8pWp< {F22LM1+J"[ ! @/#2eY6V41& _ *h> N`bIX_,+Qǩ~ɩ7 ~ZTV,dfL+B>:(GL 3Z5Xuy ()mK*.V6˲~lz\6qD.1K=hU6":l2KjwTtr7st;8tp\5Gc YgQcWz=G<7f]g~d>z+ `R7/֗*n8?h\%3/&wRv̏Wm\u'nX#:q@OھAyfRtjp'J/EK \;Eoc^BFde27(G %r‘QVr$)~>(ᴗJҺktZ3lˎΜiMVњoVocxy%q¾x<4kQy/ ~RjTj8Fna(nly nmfޡ@֧?4g"86nTk:բ ;9խâ^HCviUjChlMX]9rz0ix\FM=4xlq[nZipft5`@'L*YsU>h:Xx1W'0H6(P\sȸ<] W̑s8lVYE6HvIdw&NL>Z p^M5H{Sb,d,8;Fo AHu^iyȶkYU8"v6')XeV4.iTPPv4[t!&wV[|ǙV.ZWCEOj$$列+AT '#ΩPie@_.'=UV7`'jt =ws)'NbsP{>/cT(x}ˮT`RO3TEP%$j{W*±sb\4f}$8y#(s5Ġ&_ZzϿ~Re˗>zW+e"7eg*VB7F_}6Z^cQ\Gr_y "\?˫|Ⱦ[s).-Gs)ę0& @u $XXƺ@b 2~oog" IN0cN!D@1$07 xCi;GgI&)$@ˆecj h\`tJ e Ƥb҆2J.˺ q0,5q=Xo"<P^)HpI$8 #!D02BE!cЋ044#:ѴP8xɧ;)fj4V0F%K@6ɜU/#IH 9l1L{u{4#KF=xUV΀uyz9PY,=4 46NP`pzdMrbs~^VvQuu;>egԸpNݥqU؞S/ Wn{)]n9]AׄQ])ܭ QY]M.$S6 QX'Zk8;{ـ%g5ܘ.Aj s'oTh䄧Pdy]QT볦eLpm귝ẽp{ߖ9}6$;OKVN'!oQ5K|Px杇U%!0K)ЇP@ 0&ܗU)B@"s ꕙ303NhUݞTC$FD >4OM2$0Td~M$?>/g/қW:i},lOy\h/;E||مi[觘{ YNA>;0 `y?\KF#twܽNL#" zdVg(%AJcf6Lj iƑ5eݼ8sy7w JSmRv}%!6V:l*gU`*;ޣf0?Z 3,zlson~޵twc=;X ޤDہ4[(2q?,=j0t;Wr M bO=ԭ3|}oٺSjSx]^o>j{t׮nu`G@ Nci)C"x9ѡLbNh-o}ii?ĽS>ýq?)N&4l^ܻE>jiRYumd.e2\SֹNp듔Y`TDqqaڰR(r._x4prȢh+Sz5a9~bt\DвXiIuGvmҝ;wIEx]͎6p]U7*`cc[j$| kv`l !yJ ]v}LW{Gt|鷿>?Qy3G:HxDQ%8'H$Lǟ~ϧr{⓯BD.BLyJjE$ta(zoibɵ@jHiFL=(bH JM M0;V#BSs2-i9ͮg@(='ڔAD'\H0hC ,HjI_|zEgZ7M6%ginxeR̖krTq=J~ˁ^tJdVV[th?6xI8"7ϛE7N7E'ٝ{ތLR`@uR$*8aV9V%Nx6;-6a9qgMw/YyFцM^y22kwYytӾ1K;'W%Mجʥf=nuNsi13#}B3'w[JS96{xJnC#PM?4- ƢUwwDK;IPXGNy'2O6H O7M_xuˎD` hXf3b%Rw\Zjq:iq;iH K:lذg,_56m?|^kݛO~Ǘ߽. *N Sb \ - R0bO~mLz_.|XW@pJ9.Z"ű0:F+|G}{x6dq8D(CF#mž39g)6T3(]T8Di>Scfb<6Zs*G*|M0!QW|>Gy.`CRjNGP@߿r4i67AgI|;ĚG j\uF1nu=j;AsEf@hRtǷ$Dz'R:sCkX7*͖2DI9,2/WMƧ${TL[xf٩oe|5Hpҝ(L69h0 ƹɤkgS.ݼÑeҫyjɛ;ƏQ#6_bOy8d5/~\pfiwMd'==8eFwZqSlH }7Yzpϵ$b -cv.*hV}CtvwaO#S[Ctiyhs1P 遞Qem^с-sRuUhw2;-w2a+{B5MZ p~iCq? =ZGmzXzLu`jP8>37e?t 5h=.mԉ{]u컞 [&CpgA/`2 |} Tud7 PʝǀQ66^ 6}i &Ȅ?*zőf9`ƄVev1C&.t]SGuwnaO(`5 yu:Rsy$cD,V9Nj&ד_z<y蓌\hDɷpOl;#/cuI9xe˪FE !/YOBimJ|eYe,ΨJU%dײlkr#@&qfzz8{u_o|_ZOŠV 1Ds(b,F1w6!`yPEk#ƒ*0sJm QA!Gc:x߾y}3L0;X@Q2sD±( ٚAsuN5¥1C %PA"r)5#&5CʁCؒfY3~+؊ei-VXie>"Q Ce×@'G/u$w&BOG:] ]1Wd,b9ڦL~Mojhs;'۱ٲi붣h7ҏlfIWY=YVvE:oXȧŢy O[N _~UDS2j se1tOr%F&)k, i=˙A%y4_\L,gE-r/|k-JJxmˎD%EX9ٰ@љ}3BNb{ĉǎcVmw8ʼnsیx$<ĂWUo~S 3@:ust 6ȄbDI>w?wx>kO4,3UyC 9p0l\9UQՓi-o_07iHHɹ)M ԑ @˜4D ȑ0Rƥce9|ycȥH@l<3+eɚџJj#kO43 di%%:C8S Q S" ɗkl܍e<=/ƔvKt 46>ҺھG٬5ضs=>DnAeN`5)q ysDe nZlͦCq4kfWpm28"E(}uɓ(+>="&0N]W[t%w/}e0e8D^;>ujiwŒ2ȵIɶd%c9fh-)Q׽nF6#v/ZHǻN&*nԙ;{"ódfjOV;zKyyyQ)iora`q $I2Vvv.ğl[H=rg-7NuZ pfYrX L 5$뱌Ȑa;Sڴ2`+.zfvRϼ͖iVKk7y E.Mk6}9+G8?feޠ\ƕ [Rɺmzu~q-EB]:'̠/O␸eYK\N TN[DxU۩LL nhJlxeˎF(eDMvQ)6ml6*mƦ}ٴIHYdw6et6Gϧ_:}|__?^~300rF,rAɵB>C?@J߿7cݖo7AL乁 r KDŽRy.aFŃo&"|](@b2MJI<Ǹ(t@D#(&hrBf"\ps@(Cw)V & C::.c #IftYW:1/]g偑d4B n #grsr )xXRc R%o^#H_CgiQPpxo8K홖=S+WrDQuh/AߖBz=l=7.Ԟ;~QXQw)\n'/ w7 #@l9Ղ[Lm\ET ׉emětL7r@mu[nhw jr^jN%]I |"bwR߅,hwlΣ0qd)Rwv|p SOGa!i@؛ N,fE$"nVv\W(gyL +zk1Nc^hfu2Cߚfü`汌=:S Vy G3?{k8OfqP-(@{*_EPnIx]͎FF((&RoBi(Hd 1`n*l1ؘM+o$o1e'LFwu|~0?Jҩن.c)mQtS\0`a?uyy)OP@fC 148"B ɡ'oģo~qnQ ʱm`J-Sx\3s(` HCݦ,sK,;m=^كʢؒ!X 3G7"t+gsa79^R?(^g 6f$T8^lue-%Ru8h6L]jj ©c)]]!mǹ\L,F/gv)v/#/-p$k(Hؠ_JQLP:W=-.d bwAo-.r:ɥ{-ݭ흠+NYkxR}O,5\d~}u^N7wD㗍z)H\%3l<%jtr%Md/̰^ɭ6f^qEJr68zѧ;OW~|~D`oN5x}VEH(VRgH7E*4<||H)l706ps?t$1HReȴ{FH / 8 DH $T* (-jaČ'Deo)ӗ/$ $`G[SäJY6¶%-/g~F:N1:Iv"ޱifݤeX^+N3#Xǭ6r$fx~P#SPJ߃d#2;{]dKUpqڡʼnטKflj1VƇbb`Z:cY{:ݚyi Yu8n3< yMe6x|mZ t'hO@4\6Uq+lNhֳkߵ.6F  jxUv!֖i/OoM!xtzoeYu NoIr)aTV]6O?9S~[{Nax}DE ,9 Үhx< E.sq;n384[~P& ✂ŷ?旿ml::췿>?|P& Q%Rp 5eP%(% 2M`V;}aU;kO:-I &`eHJ~0,_~8 YUnǽq&^TVzt AbE[S[8nU23gF'v}&Uo* *G7Mp<{/G9TU&B/è9I};8mYñJTrv =qP"i"' @% Eq 5i0 SRM3!f 3tbLLO59W?.͔SSbS D?B  @q ZA=t dby/2ZV9тcY94-6>H<2vޭ,_۹vX˸8/kmmSoZu/(l[פU.+Ļm63Fhsct5 xrAgwVλE"p;`Hoܓ؜*-ԇhu [55վ=%p2כ°Ky~PnL(D^a4ג Qbjg8=\aiW>^dGVoHp+G8W| .VzOO |ck6[?LxBLxmF+'4]rEHnC*˽BQIԜWH1X~4)8 >?_a㯟^{s.,U”HmSRN$|@6m Owb~wŻx@&b*AJ؀2$"D$&yq5!˔HJ9d:D(H5 !!)525*1FX3 ( ,nB!ЖĦ lm$0ɕF&~ll KwPai&fFd5e0"PDܦR/c}t{']QUԮ:\t,ϧ0xcSDpY0kݪt>ݦM/NĪj:Z93CS܊/E;^;CŠǬuygA7cǩx&i~b{6D:g*`nuU&D!{/r}= 4rC~,?_m|*scLQE2,j3ZiŮN[[5N^g8dRxJ`="!N|re/e^ k .TTONW~lgQ9Ù kaiCAi/UuF%~Sg߻N 沒8Ym+¹J@WKoW89ݞOF{_·(Xz3=ZF ,RkgKsnvۓ,F -\VԨpGvj(lt@ݣ9כ2qyԫ[l+ BR]ywK񳳩[n+SS8W|2&҃{I2 bOMo==ާ7C>IRxeɪFanDi RjZ$ ˣt<[UJ*[5 o-tW{ Y$YO?W׀qD1ȌQli" UjKI3fH 8OLۯ~/`1I@1I+ TRU0k4UyDUS)ן?;ᱪcI DcDhQ #b H9NB/5DDjQtĉJ`"04L* ND!,b(VyCqDw$ #1JUrcq{hDP&H?ѝ=8G9G[BH !qDqORJ?>~O~U9)@a U>˼߯9p豒h?jdN4S_hmW<3?=mGLƇq4nrF5;מIgO=Khr({ VynSqnI0mC z,qvRe):fwӡ<ݪI~k=OՆzY7ȲX,O"LZQHLPEn0|9 qˮmLfGURw~O# -C# HY@sA #hqn1tt7tXB a20@JA1S(0ǔ14HgP~ ul !  * eZ1C#\<1FkFNW&ʃ_#dl7=W/RHCm9z)`ԿYGVZw/kr%_LΥ뷮갋9n};gхoz}#;h-ִ?Dz`oeO7oL[5 FddZc/f'MZ/W0${VQW~Xl^*Up[8갗5y2idZzV*~c /0Zb:V5CiCċlZCDYWH#R(S$ݞn@\ }=]5g0OwO[-56ngm bܡ֛vuy^k;{jP(kR #r M"a1Z٢HMЦɫ=.A}gil{SP/:\=;Vp6>ⶣWCnP͖-/skurj|mwkSIsgnk+õ".ZG"!N:6);K/sÿ`<-yYMuR]xˎD`50b`! )(]U,w l쪲'۹yӯG!س@g7f;_: CPG ?ͯ7/hӷqQ>Oy71 $#d& !H@!EĆ ~gR=q z\i* f*X l2 !!2RF A?&XX"Q(¡0!Q,!D+>9 Lm_}Ql0PR@(1 "F L01b% *MBN?MɡQ "KxM)3LN91CA0T0IiggzA6uKTu\pOF%G,ox#B.yyȰʪ o@oEuW:,NrQh0/&4icCHv |\ưeK;Vf$w:Kf&Emn hB-c\b^ym*o^6vU;P.Ґ5_jSղ9o?HoEhk#yN(MjMuZo),s-Wqٛt҃ kJ8ж"+=c\zfӼ2ʵC98(ǟ)Q Sn<冊/M#ME>{1J:7ӶIA;{hst?w/c {ܕtB-|8~WxYWs]{`&ef[6ziW楿Km;9caß cxyߍ >KCڝJzIJQkx4Ù- p.roNZk.=ɉS;|l9#;rPx}ˎD53,$f9BjR.$X8v.ǹrĹ'+IF{ޜxݯ_:*w@o*ES>}R[wy//6b+1(b:"(ǂ *T0l@D[ՀX!77&i4o%t #c#H!A0tA`5 nO*4Tq7_~"!`Q(`@"UD1"4.  N=OHp]Q1jE1 hpD#jprF5< HXc$ͷ?~cBF̑ὶ+Nj=O*Wh4Lөcn@q ۯ4{`>ߋi; '~w7 dej»" /9mk"pSM*lbv3\30e{&ˣk_&Vs9't"ת<,&t˲9/;'n֍IglOWu,+;k ;6*v:o͡wLpnµ~ճB(Z6ý]ӗ;ZQޫҳemK$q6Wx0Sw@+x6wƘ٪!*rnK<1%ͽe::6e/:Pup|PV2g{Їv f5C:@yn/GkǛ|N˔h= S%QۓOCFݽ] .2kڨ'[i~Kj)Jrb!=1Z:Xbn,a)n$z%w_/^!mc̗:btl]NFQp*!͓iL2h@a>˧7GǵVܽVp75 2VXLrʼKxR\3Qb2lҍpb8:Q#kE]d7T|;T=7 Z-YtV XzwwQh?u=_<C{nn:ɢJGT_֙bA/vK6eu!JhlWA)SKU=~<98VOR<0mUzptv[uӮpvy G7]emT/7?{b# /#9791󣹘(>3Z=xojVxSea4֞lf6f+no֪+n(x5̦ Yy3;?oU4V|fe\Ar7n5WvMʯwU|MDx}KFQJ"t'"Y**JJc yfr$ 2 (Y{twtׇ?I{?{@.5b)JʅJU`CH'Dtϻn+~~޶ʓ󄩚kP%X$@pU xO/Qoeu,d1Ʊ H*:J J)ю(1TX`DϱX-!8XBtɩCBTI@ bKIj_=w?*tB91аƒ i| '$sH#O?UQ:`8E@S9V_.3:1&Zl'&z6:O9*R*y๋؝ǯš .& \L:\ԗ]ϫҜ,FM;~׆:I:}DwˣvY=0 %i'%S&wOaj/C/k~Ơ ]YWJKs=f1idhb?ȥrˁY{[]fh!׾ΡZ^tҖ˙}=>ECiN|kM>{pwU!_ڭBWp 7#;#6vgI5?Sʖd Uv6ŠLa^͝1UCi|4RJS8*mVlq`y|; ͢vAgV핼0]z76Mp|QGFNtltxMcx}ˎFU )ۑ&zEBj *EY|ڀo]UAـ`lcMB~E 3`yM̌^n'Y˗.9|x8 *ܺю#ɽ⊯Mxk_p]ZUjU^\9kM9TFZʪq  Πb-w-o˺r{WxՁN6RKQ{F~\Dot^7AۡYWѾqA܆&֡ Vlg֏y=C v:`|{zE.V9mI akQcU򺜪 '/I=z J N\yybM*;xZV/h\+Q8ΔB/<5 v9huo? lƻϼ^й9ʻ.=, ~ϿJp5/a3a-(GX^}:T>o>jKuaiwUכQEbV7l_T'9lͺMop箢˩ ٮLj qxW̺:'ou#tu EP7t_ts ;/N2ʑtdz,6$y,S{ ?bObO? fV*l`fxrڙy~1&ȜfM:wu>+ 1t5;p^YTwsgqz2 vKG}ѭ#Q_ }=AHǷ0}- c^ XHuB?l l&Ixm˪Dq PaV28IUB\;t:$}U*$}˥9 'pN\ q5 wP߿7:"0FJu&΀8 ԠqB$ܐ=`C5ʦȞy{3ȅ!) )& &?~ $ĉ4d" %ab 5!DD ƑNǶglmD_8 RL1Ha$449R`(M~c&Q(%."6&$LOS@!E@!R=EajVoXʏYfN5}4nj%xkWkT!rxngbBH=0'ώjyri d :HP9káRݜ>7=

Dn^8٠:KNdq8!PHKuf{o~ _)<52ZPK9Y,BVdwj= ьe3roO^h jb,g]\g3@uys cK{2; 85c~FRޮsijn"5/]ٮhu<{k/ZEƠZ~ǫnx;>Fr;sUk`/6;yŹ)Cێڙ½Ԥ24Ҁ>ڼc{O,:W(?64eܪ^j,/R@Ʋk[vUx5njO/\}?jKD=~;I|]KjQ->!S!@"\ J8q 2"Ě{_ou~HW'pbPP!8 aHDBUP ZM}s/>0!D fg*i08fLe 20NT<< iSPR&0P1hxC0P)0kb?LnPi75 y fwY bFo*CB]c]m;x}>f3WQGV/fy2jWjOfI2 i6vߦU{9)PCsnιuoBV_KuŠgHlAߝ=$=.F\hsC[@Bsz3R`|iaXS8z1>ߚ"3Ѷ=Y?zo$,ZTA/ؘu<7и5QI%-f3a'ZOT7Jn٣( p87EnNk[CB崍R r[x7іEN e6b^Zogǝ9{E3VB>4%4y{۝v½q{J&I=,St)žw ܬFsɾ}B! [&xffshn KvnpX_:8"ۍ$Y1:e*=xI r7m qy-ϩ.m{7a~بb4^!+z/ypOoxuɎT4R)tw$IanL$8+xPK<5HE9^B@ @^/*!Z MP $X#)i8aw2 Gjaݟ>*w!ч)"Hj]g,Nxr; >&{o\(pL""1  q 0$)H:Nq35 HLt1Or2Xp@:\1 R` (3$E WDg4Jv˕ BTg\j go3.3c cy c>#Tᘖa5ekcfEq<(+dWCel'[2ʷ35?D*i'jք(]ӊ\";í>8dž>mfl9cov|虻5xPI֍N9j bӋ%ϏVG^Rv#BJ= Z2# C^K3gK[Jx(Iqq>[&3ԶDǢnԽ4]4&D@V}8vq;`vZ\JaD &*|O~u\TD :t–^OtVU>S[biݺ(l96=\a;#u0lTc 5ĞŊ nX۬4`)U_ۣyZC㲾ə(fGv4)@\pI]CDUN3]Ao4N>9`$aa|SO^6@>\#ړ+ͤAv񣗨#PS& rh[fg4143LðdtF,- JUeVZ?R7'ʻ] }7xj?S{P=x}ˮTUD1 11=7-8'q83{o;8wO+ <C0g; Y;h`Ik~}/|OϑJ}7{ ??W3@1`1gPh0 LmTj14Hn_7mHePi<0.q"FH@ bS_GD V)D\8BRRXP MA$AB*F T"LbR RUc@7IQƌ%RGxy D4A0" bXb> FDD,e -"L)  &eK )J [=óWt}k[m9v[ô!+nSֵuzN6>:źt~Dl[0,p O0[Os^4 QWmU<:zV)0[lu/g3_Yi2me5,;9.7lc{a\@e1o7D>Gì( ]E/)L:͌L9rm`8aIeN;cVj4ݙa彁m,p2kl1ېO UL&lft杍IN^%4r)s wvʙ%r vdk+v˹ˮ94#[> ik[FS^mjH zzz֍L'8O.,WZ`RuKyp{#A5xOsgK;Hq/F΄9a7~b\kd]А4)ԛ`ڱK7y 2Ґ,we u;)զtl> qeΡ2(g)e@̶5Y]Tt.ѤjKֶwn!იVpZy[\|a*?<~PdosP-P\bڬR5.VD4:rIO뢈ެReTMK.iͼ7Z*lM`f^֪zpe,LW%J>$"]`Y~vlMkfa9ٛ1r}V w 9:h]dWdnjC0,4=V% 1)]suw.\ ׬2(ur꓆(B~I.%E1e )qPɓyV"4R H!!&J1~=y Ul4ҟ2bpq r>Up3.ݪ&>וٹU.qxϏkg\@Dj 8@B˭2|~ /q-^x1kgͣƚ$ tpz\r[:7EÍ邝bv@~nvfC>k`ZW|)m/궞 zlW6_ejumJKy]Nƽ@9hNUp`l2:68Ы, & ;bEVb;Bn&˺7ܥ772~X^kNF#+a1zx! }9R߮oHM]Uֽ7"}mE K]kvso_=.vy3jI.Ջ`BDsuPu3u45+\/VvSmo ֽ:F]V*-k~U25ieHs}b|8RemUr@{~4ٽn1tdXHkkld \XD%hn|I}_whRIQx]KFaY%p']*Փpmɖl_eRd%?~Nz l! BȨPΡ_vg%Hh@6%RN%GH c o`~;XfN6kR:mfVzfk8q@t3brtA7]a `حnR"U#~yʝ̛:>*OF(n Fp,ű/_Yf\)6]rޞyLT^g9&53euu}7yA|Jyul=)n@F7ͧh IaxeKV!:,$г Q,|mKG9oKl_ٓ@MdLxm jTWoz? gRE9A,r%‚;dR A~7ߗfB`DeYDbScI W*"_7?R"$2b|ʼc KCC@4bK?acL؂<7 eAY( `P\b9cKPL(g2Pk柿'RX(c#X].f+( -l)fJnb$C Gxm]mhT汗蛮<e\Q=4=?CM$ՓPA3M`LkuB]cZ(ֈGPQ 9N#zf˃<U et1 ևvvo$xf=nf*qΫ ; TX[)/2PI].;4hw|{%3/N'ܞi'\$3^|V ZdW:+tiBߺ)T]hHm$Ջ@wBa&"y]}zI&^iDbԆE) 2+ӳ23~2/]#=L"Z=4kU׾dq+^RǃVa][I.y(6GcugSsNm p̔uT&'8G-m`S{2Dmo0{@tCqtS6]q@ogW'X7mρmr"Nm(siF܍XI]d4?+xirIxeˎD`1#nٌqU.^ R'qv;ʮ*iOǹlZR? ;|oݫ={_w!6 V+ĩB\ CDL AJu/_}Qg}$1tc̀Ѐc0jJM%t!LA^Wo^~ $B&Oh&cH(hO F)qBA) ELJ|L >`c cm3$-8Acb@G{u]B%8$ou|!rR&4 4n5q rSʼnDqs}?_zgʪ"&. E1es `L{,^=x:GI=\ .~Pڳ1.kor٣u: r,>7=lTѠ6NH7v:_NGN+U܄d\5Z-c$J?]im͗7hIx]ˮF2QPMYeCr H1®nlllxs7t$o1egM6D} 1:J$$:)0RF8RBȲtdѷ߫ z).fC0H `"9AĈpDuL9!o~^۟Lq*Y!`zBb* J̔>0 Kk(SDP](YYpΠ.f#:IS /ͩnn" X?Uqa"NxIȤi9DX׻>9 .F7"e} jl\ {P+ݼ8(67A!mFNV=yRhÜoUs{esD\!Zm.GV 5{ɡyË(f=~wCP CJt+{uW ᰞO}k&-kt]"GE(K5vw\u8r72(7>:O[:VEIO=kH2x]ˎF`"74ٌEe"KRUDm ͎W ¦7OgJ6qͤ;G:_>_ПJ)*3 s#@ BTdj101~eΟiSʰLKʁR 3 \ GhF|@oOo|R2U3#XpY5"$i)d:EP$c@=үe{Ə8J5JI c6Px'g L3&i !4 "5q(f੮qT!u&4 e}!zT4ҳKdn8zoGσmrRQ7BNR|vYD2m| )/qWYf&Wl'i)?Joޜ2ckpnefY+u^I1<5}*] E_f гfZpݠYJ{jPh0[7 i r}unWm;/|0fZ#UwR:HBSryTJNhյU ] ũv몮WEtw^yh6}LCzҾ^4^fGk<3w{H]v͖NڭNSsP\:u$ݩ=.X"`vHO\۫沜T s%k\-6dEZ|A槁w)Z.IFdz63'TJ5t5Einڃ+l4S cyLQyoELg% O褗_.ZFPX Nzۗάx^C@u vi.ba^J,xmߪViiAzYP(E N^䘨$޹jbF&7(')} m3o-b75}_ ȜHĈXBݣPQU/z?PTi1sTcr}[a|o&, ( +31v0U*GLQ1 Ca1m?'48F*cb b @Fb@{=GJ1U!";!`9PaTDʔ&Xar?)`PiKOQb>Uyl\^g櫣RCWmg/{cbw;ojteE{NP)n<áy%ǫNʳF{oWe{WPfG3FQ[K.\ˈj~O[0E&ʧ@^c<:Of1eiͷ.L;EƠMSwsjM4Od ߬, tRU׽^D|^ u@'ݙ_:۞(HruC*v᳓& %Qmp`hGIR\]VDH/\kЈ%_5Pi8WΠvZ{8ӨW׶p,o2&Kb7[Rk[8MStQda/V;/mZ.ٜUeӁfdE%9螼cl0nbmOa^ _7%0uY7Ulgu[Qfv@5MPo wiZ"1{#PGa< ubJ3Bzҫkmh$Ԍw/oJoxmɎT` вX!jJjwX a;Cep%N׾dl@$l^^|A: Ä2DRb40\;8#Bܽ׿7y},fܑ -, +JB J4Dq"0 V?҄$ "% @ͥ Tq,PN5O x# $ PS"AkSFhJƐs$)J`c[ H>#D+!&i c$U펿AIfi:GB*s_}7}vp͖ͧ&z2yT?y}"?K@;kz]:/<' [{m2}ٱ+Ynbuxn ?K >ȗy-G[wpr`|q#\\nuX5q,#`Meyʔ#SCpr[xbY#,̲Wy{.ĉbҩni[[ESNU3?׃ȊÅҵ"sHsC@'c>W70oԽzRlԿ=E3f nxטr+ҡ˞hK3~;aʬx?ѭͭ UiO`FÛ.sW%M鬸~vzt^g#|BԚ/ٵ!^7CǦ Γ4\q:O~ 7r߫qXp^I]in|& MoʝL׊8C]ͤkLB捍g̏5*G{^M&u۟9r4}r։Y66)lűkm7?s%xmnA DžPJH^8 όg۰-IFizٙ~~J/}< >RͅK%|wvco m1%cZz0F\.-2"΋CAӻt:!aRdИed9j`eey z$U')H(Pi26X :jv&hqwQ@2kjl-EgJ",VWo`)$`jtP+"^I۹8ѡ((Z@:&?제v/TE9|z:\Tnnpw.Y8ڛ;qdZβjZ4#3~[ (>(Tbg=NPx}пFp])TNQMEBZfa6`0^c N50 ưk㿘fbyHiR)+~߻ݛo!HEwoxҗd*LT #:S21yGv_G/:4#d`@Cji \׹z1w^^% Aj2\7  HS,O6 srPƲTc 4UBts2U#pH)8>⟷3ATTF 3mNXh8*SsGZ e*Tuׅ{g;c[1mzgf %;l]LNx;2id˦3Ǒܘq{>&{fliRp(`tv./g]?n5 I㶅)HȝGeKn@}X-7HWea.KGn4Y&VZT8(@q2 Zn"-@|݇0OִPm v.tw>T(sS%܉4pΝ< T^]Εp浈׬Sl m1B]TF.I \':Ʀw~*eXMmcFn$S)L/M7Lq{u2(Mo*EP XexUf[Ig)cQ<+o\WuXY dON,ǁ ߈IRk`3O'a3+2)vTq,n@M<fM}=qx'(5]Fo+o~Sx'=x}jQ`Zր A(~9sfΜPbB Vz z^ " o+ޑlc.-~ZXJǓ"Xtf3h'b f$dFAtcpni3"rMΥ0k8S[j.%?*vvA E ClVWUjVUP55T/EJfi::AJo8:j:PR-ڶI\H-tJrdw0s-Tr&^` 2fePHA\̟孝W^~sP]diG#hܳo$^gANd''vLtÿ*%#x}QjA`|[Qw޹3#b Zs'$iU(Y p ݔ> >99_޶:gѻ1A`iX fJA!C>yi4/pKP5BPS,CE ibcbc.njB.TΪs,j 3(3&zEb@1|Ab6Sn[ N b13IVR#'Də4˴?'=}XM ET 8]k!DuhPGC1^{4yi=,?cWBdxXhi3OW mSfyr>?j>7~y`-mxKkSQqLhATA̜"JJB5]y5ѴHw.WY\R^ ^]up``~s]uryYzw"S˟xiyvT~t9,LX~UI1օFυ]W۝|n=;bJiEqJbA$!P*ٕOS>ˋ׍V*MAb@%J?٫ɖxcs %<!*I&1:"Rb|r*r8DGGe@V1W-y)EPZDr T_QJR$M6_X $C NrkR `*K!u 4FHI8\yZNvnb1`ԝ$g4A{<:c;ؠ?X^w⑞o{p嗕odyWFx=D{Z-VB ϸp$v7hfn*0HQ;k*9hZ߶ov']c66,\WpvYCH`oŃE{BmzNϛ+=< i4\OPS\C"h~jY6B͇dus#X ߿qX\W.6^F/tv4{׫ 8JwV&$`a&lń4h5xR}&<=4TMPYf6zAW9HDwRʳJ xkeR{M9TdmCp\ׂQD' -I{ZbetIi}>L ^XZ.*fYACʧzO(ëBdB{ƑGAd`% xg:F>hFZٽ.ws7'owÖ9mN-WӗΤg9[ǽV7V\\ MVxmKTpDJā:Q8c=ݯd_IIڴM~MD8_A9?S?`W~}O>z qSo뇟}.|^EY1^x) rlSb jDh[X\: 'Ȇf{P+~x݌*W 8I 'r,֜-@|៘P jH ŨĐH[0#Ap$$T!/yG”" 3smB :tB Kac}"A9οGYhOWTxF\{asލ5Zm& "Et9pϟtGc<׷f/BJr^VM5b%Hqw.e2na|=>L\&U74n+1Ƕ\D-&Is톗h#>_:xkٖӸs, w:y+ m~μ]*nAgmi>\ny~Qւfˋ*7\@9NSxdʧBY %@$`f#(OHEIv>tsdžӢ+Z$Ok',#ka#7<ܱ' J͒prwUy? F$T+|s*.WVS&;nA~(.t NO*$X[5]{f 谳&w:1*Fg纍!% mVڞfhBzVkzK|f}+&,xrCy팑86sz d@Ko?+aJ1W]8ۀ>tpz|"v[ekx[޺.{ŭֻw"z]; q-fܘQtqj|X-ڌgxo0|oށo&AxujSQ,Bܸq)&s̙spb-Bg.% }7JGp|2a~c.^6rh`ǯ7rA(@z ~}ddp.*I((lƤ\"c w`]Umo=xYd]2h,t`H9Du%X80)lC7=?^i7c 4H%[4{pDJ #XtPLq/d¢Hօd8wOFN2$,`s"P* `Oykz>MG{5vvΎ< ͨxv[o^ "4I=7^V9^h;9yJAZ޽^,Ooxu˪+EA qNuuuUНt;I_DҕK_IL+ _G8|@0ǁn3Zoͷ?iC~~>D">TmawD\ Kƕ0%8WBXpENcA;Ht|g!ܮ__;]Iu, L2!ҡɰ!(G}ÛQ$ &&@ӀA`dAmRʂ":&LQB n4潦7+*[I-qb:VdH"LN0:J,`Tʎ[q:$:4", e$$LGXaaqW63@PҐVD Q4g>syן6wm%^ȴq275ଗ90 ҈c; U^g sȮYvܪ HFj\9=Iy >EJu\vMc ZwU T{-ίEN6zr4x5+cA7KjY2E:crD$Ѻyx/ޘ p:_NAaA̯7:Lv`c$\6'(e?\bGYZojrJ  8X^ bۜYx%Z[ނ~Ȩ+J$vɩ >OJ5Cm I`V ou6ML`5b<ƉٶQXH'b4}W {W*xɎdմ`F Ԩ%l'`'Nq%egpRN6 A?[H-@[t|~/R*_@H |@ `XGo~?/?}t}8^NV)|%ݘ$SL8!'@:aFtAnnjH{fj_:ݷtBDDSbrMMUUbUú(F*z&Oj/މG_v3Q`pAjȀAJ3Nt33* š"oq3 H 4Ǡ^Zj  BP k^7O<-Vd~v!4Hi B z(1W\ljLsN'u}9c#ќ@?n& YZV&k?{)d"{!jt؄p){n`dZaΰ1h3)G=|eT6#yswQ}3~泯+3xnQR,! (,sfm@)6 &Q칬71J!@~ 詑pv4_}qcE|z.d 3 TaVΎ^ݸ 8N$IyP ' "imMO*kIV[mPJNiY[)*єXP`2k{ #G%dmb/-"RMV*(4 ,9FAT^vP+Zk)$JP99 ke031frm^& uJQ<}jsJG,GgJ_C.[6 0FL!b ]nB'u| Ýj̈Ӄ񛐋gfڤדj8%h׼5daܛ%Tǣfݗ~N|Xlf0aW c'~>߭m6ֻ'sOxu]F`%l`D)[9[dl4Q{[$[#ݶ1c/k1evan7G6{P΃>?sӑy*t5of|yj͞2]Uwmp`x8uKkT{\]4,(ޥ[^Ydbf՜^MNQ:v 7&Q:i% +l,I#tCvp u)O&X,!b\dG5ug/~9:pѝ*%ڎEOjڻf,~ljU l,:PIL>29<5ŝ]Jy`  ̼jޠ<#M'^uVg=QV^]&kiTMdeאVy+&m\u5gHrmhl|kfqe#)c߬SmژV6yNvu|8ƩK9LxMˎFEՋ<)hHdX P4 60ػc6 #F6DrW׏_~zTgB MRQ&QP!$#KrP=~s'HN@d$Q*bSP>=w" @ L$*R2K$Mc"PY!( rB-軸ۊVKj{N]\ywQ3Ju߮T-eU>׭9mSPN[TԹ[e-Gt{ت;HzAs@lj^VSi*o_/;2YױwqHŠ%Ĝ,:y]5#H +sun=zj=Үp&P9<ǤrL( *j`MI5w~qpvWp Vp2^e1kv.Hda/-`'V.W- >ZE*^TM^]nAusXG3ZKh9T{DA-=t;V|ۮ׍e%qak u'fDɷQ{r~5!8XZv6N4Lk&T&~ "Aeo}ɳCvb9Hf(l:QxeIVEIGj)H>(`c͌1ր="l!R6SK&"kzuѽ_?//?4p9b213"KdlLg׏/IKP@ YnhI"&x$@ea*% 鏯/MRplƿӀ:E0eg7_ct9gNYnܩ0~֖/7NN7lJD7ƤvM ҞZ O@C5g'ʽtXi%y.P.}{\\bx}!0)T06&aeSU41.~/̴dA5^a['nQPry%1UU3(nǥ d氆!ڷ BZkֻ֦FXble!ٹ͹M%;X+);Ԫn;\̮Hlp[-$'& ]Bg NekS'EC)Ml%deN\E" ciRx\@βyo:#Z`/baAfKk2z{K,TRp[Ir⃒WΟdgt)duU CtN%D51JC( s!aȰٳq#J3Οs*$TDND"⺆4 8EH"C }ʧR~ʼn()2"< $%&1!:CaG!dcLgPDGOEvZv% Žau̍awfC^|jв/춁=.|%A2/(<pU=G#`涴? uZoZEyx:^/bjf4j|b {yѥcpfܵ8=zj.#v1RZϡ%ԭCR$A2QN\-5-vx;P$Gs}l/Tgc'qkŚ8w9_BE6N~wMf?`m6m]ZUu`}Y1&COMՏE9>3r}1eÌy6ư 2Qa9X0G8 x~Ia/*-Z+bѠK-1xjQIADpӅBV.Dι̹=1jΜKLIZm֊+(yMߠӸʺhq5o|{Za7/6t24ΟKʽڗ󋵟@ dZ$)+k)qarv;;Wk (p0#Ch"&10/5@'UVIqItydBx $zEFE^1.M y"W ޞa(TN h`V \ ")jcPTH 3,LS\֘bZc6>/Jq䍥 Uw .ēvRʣ־TpK֟|mnȋ~#fl[x,;3j~Ǽ$ʸwNhw|\U;l˖Mc1>]q:i1X1C{~{^ߪ.vUw? dx];NA6v6TD^;3&fwCB!bP V44^ACx#5_}o<@w?Kh)r0aEX2F0BN/@~uxS/r"@lCDhg Aq yO2ahOA6۷: `H~Tho)]Jm7_ J6y*K$Vhn|lL׍9WLG4Yq~Mm-y7@M0nth<7wR+!,X-sTXfrxM;JQiL#&d78$'v5&&h,EX Uc8|pv_+z|nVHHcF$6I&ǚ0 1r(Kp=y)rJIfpN51 T܃bͪVj-6ly8c`,q(N{xaPjrx(Tv0(N-b%%w S_W,੶:J[nҖmgG]$EVw~/ZIWχq&\*Bx}ϱnS1`FP:!$:\>p^ !m@6NӒ4D, (OL"ڡ=?w~u  S81߃ʖ?gnlV\xuܐq1A K A"]r`P(UMq{3).pN$|%  %*n #I"HZ.۷6y\TjkL (їZ憢bn-E(2`7Ε m=<1rQ+WQI)K#B:&b DML!Fe!J'"2IEJxkzg\j-6]s%Y7odYE~^YcpǤm}hNNL2z4y-?*3á~"JxgK妣VlZ{?n7zoy^]ŵ[xe.QB]4ll$~*Crm]2C2$oYv$f򵲧ab)@i0q q^47Gj.H*hs#XD^Sj$(w^.!fD;̢qh(w/0*ՂJ %Mzi*AKM_~(_'p;Y8rz5a~,Y饓zD&L6I>țV%6W6N xmIV`EQe2!H%*|{;RLk10܀i&o j YA-(+, LJ;tǧ?~KH*_|J Cj$C(B1ŔG:G[PÏ%w}qJk~z+-@DŒEB!R51-@?]Oo~ )BX0TI !'?D 낄T ?ǭ_麔Dp#@cU1As&4GR? HBDՐ6cN$dRz_},FxmKkSApڦ1A]X huޏ4>'Ι{fn.MMZuRP|?_¥ [[tQh3Ŝ|>~ǿ\6`Xw1f *O=ϑ}*c+2!I:6Vxv7$av4[N?/vû{cB1oGZPZpZ _ffeZFŞ*$C1h#` d;dZTL$BH?iyoI~8ʃdaA q 9IF)MV}4uzNrBZK6efB"}h%F1H"0x?>'% ,Vr7s7Lyj9܃g8,2'-W\{)>ː+jIł"=3DGQnfn?Nw^/m潕nUG/]*yԲ="ҭ\w_Rfvۘ{Ozh*>liw⵹Rn^~xVk:ί$5֠G_ByJׯn3gjXP&Y+{7 IկtCqngā3I+qjCMvǸx {$(gE$>(fq %?(pEF6()ʼ 'garI*+U"C%+J an۪b<,L3S+CD/|_I% PS.="ْ(J-P)s,X.?E1З4*_Mn%\iHx?Eq qӋ%j +7;z<(#MFXe=$yirGN#1Ҥ: f\|]db ~zևYq@ tL(|xUexg,ϱTɃ|RfkwFaPH~rÄTv Y~{PGJp r=[!K,'gCFiN?HoW(~Y$p/W5)})HnT.}ʁSCP&U+aI}&U=" )rm[۰4+Fѯۆ[Oo;ȿ[FB^\m1aMs!55`TEnTUj0(BCGG9_.p.A13!CT4!`X t=4sX]jC)24g1@V `0ӑ 4C#VBRidAC "+誱aZ.5Tb T®03Ljjz!UjRl3\8UBӰn`hz: r=wDbQSiLӡtF 痈=_L?>BoNR;B0钆4iLzbi52jm4mq64#57 SqZ/wJSY:svvduK Ou:/qoVKﶣTY[ix&bcN/s?O;if'5 gR]%Z%cmWzqsm w-{4{c> \OȤ|9]F˩yo<}]Ҷq=ʂ}E+6|{s&gqbٗ}4qF Ћ1}f孡G8bQŢe8?JVZx:5xfEVk.765;&FրoGeC;pY֩50{%I+ջ[e75YOpyb 8}=׼}߆'sG='<:xSihok4Uhj}ȸYNi֜*@0aN04GD벮jߐ^.W0Cwp ]qc(hF~a{plgygU7 %"4 Vug)K:lKXsPkjŸuo g)4xUY8}W8l4Ⱦ͒%ۯoTU>MFPls ;Ttz8,Vs$OY\- 4I,YiS,VIXeDÄ@~> VN䴬$'E&WMV꟤Tn&$Lm^l4Wo5?QX|;i%,K0Bʦ vFLj'x)s'q7Qs_)<~\ʶTiTVb)ܲ@"U朦$^W"I.+" j(t[_/$pvC/@YEzjʺl܀$-C&+7Xޢ,ï&%0@YK xL_bBo45p_VEB3 | $qyN%~4چ6[ 4;(x)H{ H )k>Xh#%ZVYzv i2hoRR^Iד5"v~Ls_ *w.{9,q}X8%~|¸w]xWВRBҸgQy/cu$1zIW[ۢ ipqDź AI{%+DQt"E1{irIr? "&5USF\.7tMg @&2tjJ\}dzޅ)f±Bb"XW4Hi`ơC 12["6jPN!!r! kGNu ZTLN[aċb=dB0庋KVQ&XwANTUHHG.ad:9'bA ZR%Զ:[={>\Ye {cFg7:'xV}!:8Nm(2V8ӝ\G{wphtm6e O|$3s踀Gj5OZ6'ی`T͌lDkIҍ1񣵰Fe4ϴjz3a{Si1̆-o㬱UF/gIfzQ'k"ϛ{>كS1Zn$q|oHFG*{^l1u00y(8O z]EOԉ \::|P{)JL#\Vۚ7ZQ7FLа[dG *7 4xќФ-#iM)8exjBrZ$(8`CV]39 _gE 9='XZl:oWQa d/6\7ץwr}-/m\m~Ovo=D}?;w9Is-a3|nZh$OQ:4&ͩ7o(3 ) ) %xkns τ`4?7VƢ3m4WMOxK,HSpIKI/JQ*Jr(JMH,Kϵ LUSMvNSMNYz)v\Tx\[sȕ~]zTEs&(L)$eGoɦh@Υ/n*Ɍ K,id? >>]ݏ-7O~Jسsg?cuݕ˺?-bU%E/ zv/i^KoYiMWfEQU+ڟ>~郵OӁWW zu&*Ua&.S_鼮Żs+[e.\]zrpb/ibӊEe,+ܲo c}hf;XB,CA$ԛ.k6lO| \WUL*|$w;[nL6m]Z6ij/ΧgԲEu;}ˤ;Ks_dٿ"y;+̰c,>i׵u7K5pңGQV,i;`tlK>qgTf Gَ\u|aU0lOPW,mo__K_H].'S^l2C(-}J都vC,x\D${~/Eoy]De rJLݜS]$ґE^CtiH.gSE1N*ɣN$-yV*0i%_Jatfi""QsDcI#X+R_-ߒ6KQr^mDYw>î:5KHA*pȯR`YվXdkT-R/<5*P ʀB>҄!vǴz(VL+$Vv4/ ?عI)J20s/0sxC^| #!>x=zyH%tb>ou+Dgk gX.DW7G!4/}IQhK:1Zf>e?7Vq`M#BoΨ]=20(tZyl оXZz!lpӅv挎N!e4 ۺ#rK]T)=ɲBkp,|+{"]K,EFg"Bo"'m"͗k)[ّ" A7lm-aU}u R3+K|, E"  Tzp<~&7% mT`5& vkݗm[X?!l8<~ߌf>LSތnF@gt *:1oEM=!C7 b6KT_I)Z.2 .>)BX?"ÀËQ;zv\0fi큸g<f^9P38g][ VW톳yαbSuPۢd5`03@Cȿ*mb|Od:y!3 ^-}i&]ǹ 'cyɕeKK6o;`(Wʕ)l$!v:\eTVW>eG* y˕)@q˞"6? 7PlOL֋n48"E3asA%sVE9;.}Um n-OlrY8bIXVS2|cxcpM9B65n޵אh.j9ˡeKM0FP&Lkiyt,I7 ~snK&Ag>D,?wzŸv).ڂW#X/ Fè˲d{LEx/`;!.[c8$(qHo4A/U#8 9D]`{)*pMNIfk'HwZxaQ:ɟ:i=KT{/rPR.Ab;e`}gW_)b%&ڣ:ת}m lJ{[u|`'H*]b$5I}'Ž5FH LWRn! `9oTף7t.@fB!OV^r`珏i)a/j\r`D(1PKGxM:@̬ޥ)9qhƸ\)o(ImJQaG TQeT? QNE* y兤j# #d;H;H"B뫢Db>ݟ` "mNSr4P} S )4j8E]!Dv$iG(3ڔ4 ? [+4q+́pzO&!=`QQ;HPbMw;|zx P+6IBPjt]B,i!wϾ&Y* ޹k璒5mZ®\TN,)@c`!Pse*X_{ELa_Q?90e'3XҮ4'rVƧ$Nl0 Wϒ hV+.DS"m;(w2=/Zxy @Mr)c_֑oOc.EIS4T+E b")Iƨ%h*imK\N4wAfR Z c7FONJ+Jj 3")dy-a0Ahn 5UjV,fZTloar!-16>&JoR ]ՙx,M<2]HlTr[`>dhN;fYũB)m\-8U~!7&!++INi%,yk(G ԛ1+ޟkdB;p\4Z#'ZqTq cFƞpܰoßGҍS=ov\C {O)rLh$# ;v; #RD\Uڢ;$\^CknqMגtBEP2[Ω@m)EWߎVعm:^p-O@JJRqᥕgPƞKyla=i!a#+ιοЦ+ ?F$H­qF`&"f=IMl?i&4VF.t>kqOS;P/n fY$ Đŕ7q&s8K.Gi?8DA1O؞'pLQgdFԖi=Dᄰ ނp-%‚F4l i$ CȞ $eWAs8ǯRGՔþ`sP¿]FHZa(< LqQg >X;q. iN injy]|hFC8 ]>MJ16^S_5)>y [ڿ< |Hyx]Iߨ_rXrK]$<ȥq\"%RiՏ"X",yG_)4ZgLI3/nP#8u2&YM<G*T7M{h%QW?CsmNNyG>á4;%]ik;[q.>#D9>r)uR׷kw I/Έ#nғ̤~ڹ 圜Ai![RH̥9H$F SijCXC+CQۏby0e>OœE'Iҽܽ#W፞tbɜOloJ{ib"§ߦ%2'/zqI `bx8% Jis@y*q56M~1כ+Аs5g޻hN#9o*^q3m<*vu TQR1=RsD64Dc"k" ǹ9v'CF~fP#`p0³p)Tj4n|0:COͤ6QGnH~oSzW8##ASdij^Ӡ r,*ly"غנv rjm 7|:fR)nlFHɋl^u?دd0=۫i:}<| >4Lphn`iأ&Cz#E3c6py4ճ<>~h_!?3n86DLg`4_'h dnfoq0S>n:L:=<ish|ӳq2bGG rE 7 F#,I÷K|@8~`OLJ7$B'`jT4 ]<_A$m>?AHѹ#,N'==σg~VvW+vHWglp3:L޳ϡz8{ OtAFzGF6H6:]{OH/lXd61y5'14~ L`l15&7Xv0V~$Zs Aɦ=;RwzzcGq5k/#<-LG*rd7P?~?+w2&5lT*3`G' ȸD`͊-v2ߦSz,_ r)վ?iM)&C@̹s J+Ӎ ;4)nFWAfq(q$[UZh (eHS!hkq&}c'c`sYTn «i +LkyH1 B g 3\Vv[pģ8<)CH:'&"X#XYD iuoT&~ L>_e]K Dln7vNYo{9L&(nپi@H!w"m3w/sVakTtp=AB;9/*na@Hiwc=1<֩u;Hљ9MX#6f+Kg߃R1t3 |ܵ$h^,rJ."K3)~vf6:3#ՒY6cYM<H˽δ+Lէ0U}P?۳i2ik} ^#\M@c|Ɋ:a|]} .uH{>)uxŻLw[~kUpsJ6D{йݸ)T u&)ֳ;)@|56{rO:ns_/fy>n$+npH֯7r4L SҵY{Y%ter-'4J9x!5+ŮXr |,$#B-l"S HQa^nz*4 /+qc7WLohlS+_{[f7r=K;|y}iqmJ-s+Lb k/e5TBv}a1&$P قҪaR!:$mDpA:$Ovi*T;Hi޽r-wsvߥ yNIx ʛzS}"]:P@*Hr!~GD@ Z5 (qXtTx2!ǹaHJCG\XȞxQɒ+.M|$mW4)Gq%sWmŕ%bCiJ"uVX4 2WN%)eqCxU923UFR•uBl;e:ON:+tT,5C2]}I$'xt"uZM]9iHשJ$KJ[a3?N1ok^G|ޕq|E+ʜ @d3 *ӧxg3^G^4A/CTVi&V-ؒƔr/dY @t Ɛl Dt6lAG@d)x9s[ %D\~zK厉"SnP/ g $ŊL쫞6b_uFA#AXhxFLkKhHY}x%e{J'`Ɩp{RƯF& 9ݹK*qӉ5ْƈaNYJBWʮ?YgNй,j!Fj;CЦ,B~,)Լ]CU5{Cح"Бxéf{B?rxcI|xk085J:0P{$'^&]N2 !\5ebzhK fg@erEb 4_d[mQZD*ԶGXף1(T3#H= G SD‰g 4c,a{__1y%Ax3JM#N$2XYy*` `^V&`<),nQ~&F1a֏h}gN^KMU!b UZv _(L4Z *_t K;5PuۦH,("Y习`#fY(`8KokZ4MiJKGauF2|$Ja]t5Xq(<' _U&)=JÓFy@m2z'섟a{P?I}EZ.-<CID XP<$ZˬH:@LHg]v]۰o]i L^ :L吱A1zMiNJ8BěCh)(;=ae1dI#6x&0PPg?9{R71]R̊d)QJ˺`aEUac&0;M#:ם+vkyvtTlؓC -@;HT t:a^W{#3|K6u7_lwQF^Yo~ 8w6cjZa5}- F[<D_*{?Dٵ$7$Md&eIDOL X2E4ePhJABV}%K0T(( N=9 s 09˦R]CVR$ıGh(CY1s*b; wߔLDxafG7rr?٫)^Nf~\M.Fǡ`I/#`uFD 6 h ANj%o U =cdnɆL3WKF/ܩd 'u󓳡'ϬrY:XO(2>%'A..HR£UkHeR'2cY/,Hr؍+NB8s*xA+""/w>dL[P TDud ҁ$@ۃ(甄`tWtvdΏ(IFuȔdVrrMHɲN &#`*H}?:6!`5.o${h+T\8ٝ_iaHNzcOh]#QaÞ2(r0X( QZsV϶ jsOSRyYCB3@=dlȁghit1i{Sma2> ;?%7 noWx'U{5[ 5 m.*2ȤŮOvpR\RkQTYdIӤogv0>$TA3 f?AUɼ fک{LLX_3e;&H%5m2b}9N4uD3N br/ZbCdh]InD\YB#D4uұ8JzĥPo ) @n[TQHB$,P"Nl`FiXN^{:ąQI9c 57Z7< S3LN 0@݊+ Q:i6Eznx9#t#AE"q\#m c d.Ҕ\)ݖC@Uvk21p4:P4=aѨv "A W^U>oԭ{2BkThhR_LA+Z;5Itn&I<XҝYbλJ 'W5Pdo \K('yo:Dx`ֽAfPa2]97Ni3Re"c1;*!ãc@~ω},f+g2'8-@uKG/SȊzl!.Y ]v#$rلDICsMۺyc&Iwd&I |bx r^xl)?'-jcY{)QF ͵mL( C9`) yyc*72]2f>wYFa8yj%IS7UۆRlRpDi`\rK'7YR{q;0痣'6dJӭv fa3wKBl9Üʞ39-G;ǂv1/Rca^_ ^h|2ޙz~@b" TGYm*mst 1k{QWCY"/z=QM[:h{&VǍ.p r8OTσqHI /2 zCȊVBe|_, 1f &%g SiL{H_ג^L4+{I7]?q~)dg+(Gv&?6~7m* xFcsiѦ 6wUET[p*}(b@a ix_;%N). C%=}.@U T60@}Vj2HSGo.U{XI*T 0޾OyV_ȕ44#-<620RQ^\{'DDNJM⎆&4r݋[ Wmv͡XLg,*dw\].M/ OY6X9VA(<{9()yl =Qğ|_PDܐBW?г,:r-IҥBPj_K)=$HNL6XR曏#b% jp3k3$u.EHG>m^N6XktKtGYapR凵z5߿F:W#w$8_TTL <Ϥ^{䄒望>Ԙ=6'"6{8Ȇ/ РHToOl) g5ﴺaG.7=FmһԝFQ+}-]\cX3|שLG(aĠ^Qs(璓)#mlo)`9'RϞ[aLi9Y-}䭽UJi(j~,RW}IsƕEyE_]8NbRn pRrn{9mHC'xO;)(x/ shr$x|T|>zo f0Z:i9{k=^xAJb{_t!ޡ6t{BtNS|I*4 >#'ھگ/؎TG>-%8ozL5`?-_. L_~e W6n\WyCNcQA mDŽ[y 4%LJ]U&R8qeW(UԒC3 _mTOUr\\9?R0_\_۪$iYՆF^"0iBD{ }ŀԷqDRɵb%Dg{/.c3~>e ^uې/.|.)c@>I ndN䥭Z۠[rI&}UC@*&2ݿ«k?u'y ,IV^jW&a 'hH(&DObCȖWe(rձaN,4!@>ʎУ9ύː[E1g#~+.odIwo%Mܕ2Կ>t~#-t4:lnKe9p;wGPCC [awTL.uF 3wKOHSm FX]%[.d /lTR"^o[WhQPEuòȅ iՆE}獶@5FJ5wJ 7C2nIjM,BJJzҶ9=c swijVyflzJ;n?( %%43H4jUltN*rƠ{*钐]aY^;$vw]$5 1a+ O;ʝ:%b9n)@6# RR:M8)Hk+Z҇럆{ыg{Ly&J BCI&f XhO)@2 /RڃLˠ tz7ofIo6#W|r~mL$:Ni[f xWUTEחŌ@Nmp'i:o l@U/!FJY=?/{nxHM鲢R 桾"p z]#`~p)kM= %r۠}P)O(z X$|g+P >!x+?eY̑aobjxB_Qj/[Z\\X gȃG}"t(I!G u*ᓵX pRG a6zv:~^Mc{{e/ޏ1yhu~|so{';GoiЌy1ߏo-f8!rf#؏χ'8wvjC{7O3{7mrhFT؏r`hϻ) "xL\\?\ oi{6Fo3FA a<%܏N'$ ̺P~p=l8H-@QKs|\9] e)`^ti$-3{06=3ތ/^|5O\0djuވi#x+4#9FHLs8/Dbtk?>ɓ,-lJ[-~d!#}"!ݍ/&=5g.nIS$vDlj rd*Y2BkZ?{};caݏ,SL~;f:!~:..Z/)F<^}hr028H+ 1%Z{ ۫{҃ـeN⽞&=1 ]6a͓uHf 3#5~u[unWUγl16f+yNHZ?[ο/ov7%A(/?#`A 5E/ir G'๊W^;ֆa~^J@p_<$HJV[?TP iz.zL@{OS[`1T<>]+uh)q$n8tWpn7OtkZb+[S2dQƒ$+K@#^dyȏ=E˯OPWYW; gGބKeQh?#$+xǪc_soE`%v}s".jLr|ryLVyp#ƛЙ8WÓzh „ o W_*Oo"諔/}<N-$BbVVn7 _R^9-&OZDlq<H= <,Ez<ÉrBw$ 7  V~:2Lcl]tg.B8+vo$:p C"\Kofa0u9&X80^w0;sz&"'Pḷ0v{4W^bտDIЇ(L2=LXϋpǞ \l EZcörv+t!Ix K(9( I`$HNiϓ[ I\57 [~.W0-OH}4 NzzCHG-NW@n5qaljA 8mpx L$?п?F2< DٻFכ/XƬz$k^3dN .[/"@ȿ6]u(#8D򔺰S k8$1P#زSgx`s/N""cCou޼t"[e[IsS@Cwcx:C87]'Fs _%Dlb4F?NXn7ԉ86Q_@;0Z!:N/R2i3RV=(e)@C4dC!`!?/& |K6^`q/h*aPƺ/%m\<3χP ^ !o^Ǖ +zQOk9.^ti _~kzG7 ( &/'ېR.'2`: ^lX]ͰóG%ұM"񑁌pL`<;3-atjtaW8Q䬅} D6!:<"K0$`o_޾5ĕ6\SeM`Ѕ"]Pa)9>i.tK7V詫8rS?4~Mý l.(}r`mܓNf I |lj1ŷ8'xuwz6XduhtIG]}z.(T¾&* N6'N|0~wߌ_}x-FBak,(z-暏~TRl!c( n%WnJW)æSa kx -[J |T adk-#fxT͒ΣKǑ8@I s<)E;`̮۾޺dw+X2(P芓prߘ08oIx n߀j:={Zw3ܲ6j졄q"8.߿ptVҁ;Xd2M&zB): @PTᏡ?I]<bt!.]RFào5i}z_i<㡠ɜ9S> q]O8wEo6%+{%M3]B*T%(\tk\5&.x4~jdy\ c9:_p>BS-ڨ{'5"9Vw$}`Yv X*}u4gsw5K$5anwڞ\2'JW"U2ke+qr]veN^U֜ՕdaR6VLL&kfw趲կIK9 frᆩstzrTZתVax)t׆<_/ݟdv&~VuAɉZ)jy(*>;kS,YHx UzȩB3:S$]?vYvab.W4FaIw>r5:lm~6 8p+iRˋ+ oRk`da3uYi{t!N6/8VFrV0Z (B֡YP[sj"Z)Oc+s^5R 6:j:Qƃ)G _Z+6_i"'˼E".^ 4{Ap}i|g8C9~m?g ċ$lB[H\9a*SkB6)ɇUHisQs/{c?CgF3{+[k')2ygI޺* 2_v6/a^y@T8S%zĠ.*ڨ'A~oөQ!#{M@(R| Oޑ0'*,lR%{>"xM/t-w1xL_glx]'sGZ Eg;`הntV]%}l/ /*Ƚ5 g9Z{'dd?*{r< ~3G:nZ=3/v!jx8F}" 1RVϟ\s:n|N(kUl?Xۻ>}Jt ɘY sg'|SE$݅h2j8>/qmRGq/.Bz{|y6طN㚲c^6~3}EF{d!-fN G<ԓޔiu[[ه6#[ٱmr%NGGc&76ҕ-T_3*uIPSw+cs]f$8{GB$o%v xWt #O0dHywJ$:!;k_/AN@B "!"fUx־t&(?-ArxkOO(t^_/no"ko49sFŧ0-g]j#(֣1*]MXg[rK`G=a> GK[a0_>B2˽?H{Sb\WNw c\E[kTTT%w0|tw5kgue|3b'scIvh!O[( |$ҶП{6v5WI<)0Zq%e}uGmzvwAwn }&:reM^k(Eu9PIthmN5~gX@*P" l{q~,JzU`.(e: "4R VsgJ+||1O$C%g-̢z!:n.qSTZԞ&eMp`UqYmd:Czzs$gOTol5BCAV@ȏ,!s A^6 4{.ɭ'U6YkqG&\2} -SĨ0mNw3Þi{2gsC\\pƇ6ΨLR,o :I*HHYMž6Xak?(W&u*t(ә}=nbxnK}5$WEa02H/yطv~9. +שV=z~"J\\$L\7ZK0 1d=h{*azD@Q%"T(گq=T _lm`IlXڈJCʚU߃xM+W,v'1Pvԫ!Z@?3tӞe>s4_j*kcڮF¨.IӛH8um Hjِ2$tSr<v5R\zIB6TPxdR, ;X5[7WDcԏez!ŒN-md`ݘqe=0ɓֹ@S[ҁ)A3TU< oܬ/aߨJ.jofUs)}CO< NO\B"۠J㼰B²%up`O t5!]—UѿkqL ՟zD-˘U~f7`#e^s q2ZҚ.}Xv=q0q#xx@SR;U!@y\y/%^Y N rͽ;ѯTpn>8 &{ץx^ֹșu2'v ԗ-XmFG@aw8ÀuNƭ&bT- ua d ˄C労 Wt-tR X6) H$2*/b[{vC}1:9>?9/į,_wS$t UrAa<#Uk@%Uh1` }Lc|A~4C"~^̳ o=*?nW*O=H難v%c9 GlSqt`kCӅeZT`739:>:;9hES34 U <Bh c$5hB\Lr|\ȢT>MaN3tbj@bh'2:vStBD/Mbq 8ݣ~K;0jFj&p dAn`~^PKW_=w30`ʓp=#k"|$zH*n8G{\-j.h>jРXm?k "e`YO|"a@sGnǚ~[Q/Ef,4R$bz·J X+Ү "Ԫ|z㰮BOTm2ér}5J7f+ٳ6iV]I7_nZ Mǧ'#ńVxHy@=~I[o^Sťo^%1Zm@49=@;t=*&(Hۛ d@"Q M^B_Tw\cDL0OV,̘"ǾˀGa)ۉsAiSNqfVޖ~H [7% 'y縗D#剚;; y.~D$\: */TW [{e{NMfP){qRײ4a 6xBj hSX F#6IG[DnwL@rDǏr3qm+q3*3TaOΪy V$é$xoC5ASk.'a= 8&jXu ;sg3Rjhlfs2tOșgNk_8ȂW1""EHXx!+";H;b)Qؿ@Q̞GF!n<Pje: htg^9T,P,/]WE{ 9>\u=BЛϿa NO,Ơ?IF0a$8uj8Nu,a#Fk[s\Ǥ ʃ,y` ^_3g1 ]քꉊ:L2&c"҉oi{Ȟض8]>*UfF *VԺVyG7tzLO} ̀nTܦ]H5ӌR5NRF2Rr51)i8\uA,эu`Dv6a%-+.)Go@tU- }$}+&fOͤDJj2â&ȲsР $MivtbT-7[0r9E]sx"0 e3?@{5f*YO+8oUR?DcJf;gz1g Sz~0p[XAE]lܜC(ZQEYDG"j†S!bp|qtz1Bq\)/VVj/Vὅow#'xy5'8)^//7"їOT:DޜұX=P(@yDiPN}nrW}/`+gj$C)7LI $ࡠkLMP3B&8{B9g/R:1ePgRH!Ü ߙ9 t̟\ҜY_9SgZ{'U`0 .pK4Z K/F)*h4畠Ǫސ)fM|2m,/>*!EYJqv*mզt*f x;qB x{*eq5"W xRzIJP3!E)> 8w Hf꤁~zdSwf}7 Sγol ΟGşś׿_}wW=K]{HLuƒe LoCtt raN:*.˟EOOCfsg]B=%@tA0A~A1VUTUJ?Yc 6TXTKE _6Uhht4"0E ݣܾD1{9\idNQGhr=|wxӂ+bՕHv,:5?8,jOPKN@r6L&)Q$)?99v8H7.)w dX0 Q>3R1/ aS H1oj6!5Bfv9ګs|_QYpaeb(t0+#ZxBժyk/1I@؏4P:2 @6<:{#XP.11Љb\=k̕g'/7h+#G!=n/Tuƻ>T"| p"6Er wAW_D5uVu:gGҨi_mt||1AΪR&(޲u2 "#\T UE,>xcZB"ŜcLT[se&bňfkc+7X*阶+ XT%ur6ծ ->vYoY)ގCB@TG.\Q&~Ne.J?ۚ р|tPO6 ;סij+YRVf?dVLz~#j4!%ۙ&Hm" PN,D H/!8Ӣ]XU!Fƨތ:NrƃWԺse<&B@{mh>oBft1Ƈ=$ݕOniQ6d_I@/-Oc+5cM+h^F/nd;GkW6}ـ>Lj¦fR2uOwZx`ݴC㙟7iE[%qbb*\~]ZpKڑH@moԖdpHL͸pD򁻆r\V%p*YIʏ & ~KiMϘ#ByZLK vdl~V`dXPw u|.F<.U ƤǮg6$L)Ga#=r{A^Q˞*r1hQ)):;{f!?J[vhS,S/K꫎PYCjAIIRXL"[ʀ/„\qj$%F'o{ m v+LPAo&# 'ͱ\VC2CK"dJ*ĝiuז 젋?+ r|ζr z<<+j-\50{y9mziw@ن\oET(g ߣwx;Ȗu&Qx+"勤}4[D1VW7BɡY䠧YvHF g lGĞ.e$̤:&>T3CrᅐR\x#ye*!.U]j/s~45l: '\-V2jnN }g !e8wA~&#ɃҺkgI&S1j$]{K&ȫF Q/+PK}F&vG_,0;=- J]`J yl^_XEZTA mkCvDXi<~<5] O^Pef@|i24wŽ-0zMDLGIښbl6n$6GgGֶ?89=?vor%%/0-бWv?qO,18n86l/3JMx'1).1#ҝ~d{/x2ڱul2$3s2*a}^b%#ӗ04w1SB/tQEL _fwneBm E5ŭă{ڹB|e4A_thL~:A[@1t1/I:bFhy錤Xsڮ"v2:imq-dچs T!b#rL1b*IC1}k/9KΠ LL*ʼ [{4ϋ HHe#2$!%SԤwuw4ʴ0WI_<&7IJl`Oa4`5Fa Hg\8>+5jENb(5CH8q/ω{\El~ z HϹ3[Ы04D&w/WqX &Ӈ_N]'7(!hNJqhc S.ZЧsJ wPI1Ulgu1"v?U)Y%eⳉXCv TUpF/A Jf E<5͑RU;#XV򍼔>'>lBm>DˢR4ۯAŴqs8FH孕Rzm]ϣ8T(S`Nv g 0e]y*w/x >H9{%ҍ2\sz/qRA,;2#b`U0.% klPX^Gٕ]<|娏WFC{ q|[:(}LobG@o**&R;qCMQKG@qj'^``W0 G' >L=-ƪm󜲸#DI$![biI}2S<:>Q܈>wQ \lη^;zRt-ʝY/RW!k wuQ^{,-r^` Rv $ 79*54k}Hk fX #7([޺DiF~%m QUW0봨!wnr-%-%>Dc-W(F+jrѬ٢f4›/pJ7>+Z,0>ʽʷF; a:a6cϐNGr%ݘ,y@mfޗQQfd]4:f_.Ci9+BPW8fe3פ֦//&Sos"W%ua{שgH(gr{lmnţ` XjOc n[AwhI/)Z$O(ggY:_̀)[IM})Q xIo1rM(n&fb*aw$Λ:cbրtajEh# a }6ާ˷hpטu T qXdoS]T*4oM@WQZ} !lp8_S_ Ep?|4k:=d^ooJViy. c6ٲhtzĎ) B)Oi&r9p0$Iutr'C켗0ĔwU濚pV/3> &Jy8'D:!Q8ymcT(/&,X{`sw`f]2ڭ#ɹY8 >]͛W*ج,ht4:q>WϋH F r.҂:AV$,X\ aI$Y]<{~dSdxޛν?Ys SbD\?] mC9 7H/Ÿ`ZB!׽ߖL)YpP uHMÎ|/iǿ}7 oܶ*p1kgSJ c9NF膎K w uR?,pH ts1~,K:, ]-PfG䄼a=X }_)&QOd nZz';j dWR3^%tTArW;`?]hd$oXsvIןN>9^,uL<+` [' 3Ftl+_T[. ?í6P *KY"u"̫J.8ח@x^3iPVKQͦBQ_j 6JUăQ6'3:y><X) pAE.pԧÄHP!=*[?<`T`^bra;0vԀ;B/?l.YLnmT{S8!8~t(zH߰*. GVG}|G'gkӦXyC䐡?(eõY2 M sҶ9>2.to$Ed9|w&E:)l; J NGmAeSU!7V*ҿRgSƚcu ;T !=*!-_v>p7&K6W !nћ|*<$3EȌv *V!#V:Q1/PQPg4Ѷ5_bG8a9E4yu~r8pt.&>e?/rrr;y=j+Wp G|m~1C-*#4@Gp KeKTAwm:ub`h*E01B .GB5zs(T,OKO<[4`wvhFW823A@5) tVf2 H8N@ h%?m/‰CB)$ 8Ӄ9r݌YAJh_-1ڂ 3I18Ui lz#u]kk 1Ihط-#O+ ڇusΗ0K75V"k0NȲn 'a@+'CJN8Lɼ2/V؇f*pHiё>F*A rTYCENψy?w8Nʾِ3Ez@~*s(Ќ-f ڹI NMbA‡pJJCpZhod*T Ulf0P5=k|+!NgToǖͷ=}P4#!MXí g8iZ&`׀Nx~?`^?1I*C h% /4pTVJ+hT j,F݈oۢZr洬*R;IbBZSXJjLV)| =J<Wac=tHL jSu+zEn2\ZT-+ȓב5"Fŗ Axo)[U2SRB z9#.0^+(fQϟAG̈́H8KJƐjuB'g҄@IWD彜h *rDJbi˛׏_[ Q:%<Q1`DζuK! n6]^kق =O-trGw7].כ S!\9 l''@!%l(n[4߿^Iևfk6ϋu/U'ȲF8ZX)>Rv,0` ID[o]<Da)|' l+*ƺUyYb4 I;E[[PG _f9AST=u(Y o̔F`fz{XD•ʒ-xɚooԪUr24N]$DNb=< Oʮ){L:o;R`QV@&/&.XhAFOp/;FUð9_[HkΔ$j`%TEQ eXT5VhfYUZOMaN\@)iQY\bEH<w=B[$!95WtU|W㫛:wxB,` <1c8'+56klw !o%[.fS 3z<†lҍGz Jbk7)M݈l;x^)sփ浩s5٪̕ʥtVirYgȎyJkN ;nȹm5bI%ڰ("'<@WMHԛƛagN6±B88L4QSUXk~ҍ0Jkj  Ů{ D Aք@MX~[I[ʱ6thՔd+(H4hxrb<{bo~X ]r9Ww:\Aɸ]I0VKLoq. ^zl C+{\V=Fh,)L!MG]bJ)ۼ 2;~wpOqIԀ<`e5O< Hrm#] Ics !JM(L0j))PSc)f) m=ɮ qKNoxrG4 |U:zb&:ifI}iFT /1|y|'pL!;hc˩'~f!b:<&+G/9D%9ǔQa $gV؜w/Gtفx06 #\teNPi?ô :~YS=go;AO uO/^$K9B.KE~<@Wё1#|2] ltf3 Ϻ! L1^Sod`W(ㄞmq/BpO+ $ |ЯLeoɕZ`-4ZM0uwMU U 8/B=nRm 4FIC!#>ʉ.C쩂wnwiN dKhI3hy2& Me9Kk94 1G>m[}>bYWN', ~ޤ]M^o:Jc)hnF2#,aaCd #m~߉ \("*M Ң٦&7Š$UȅKH62!0~lG':gF,Y?~6$)qxK|D?a* V@[ae ׮x_в|oC}@BNZ4aUnfȂ^߆K8?rw|( PNK)Nf;ҹ~.SLy:c6&o)gz㕊$X5@oWѿ0 >PQ}l}SUgTIfh7~=ڥûUaJ R))=WB S;^2z \yp FQ` tFpMJZk ƾ!Eڌ$|Sy]RѪo/>ڳܭa7r땆ς ~H p+1t`}9B>2q4j]MXAqogB7E9Bce'('ϓ[zT=5Ld0IG@8y@ ^,3 YD~3~}1] J#F,v!35aSfJ(Sf YB̊ء\{dqV~ñtrTҧ]" A,s}"&~A'~]NXG24\ 7o+( tU|g"}S4*Jʕ/ OI?ќ7i$JdŌh4HqN4w/SkOiSΊp*ɕLM8{<OL<|2?lKYƺgt8{0V*$qErV$VK`CοBAZGU R7QS J3%p;3BX$d<0Pc1M;;%ƗNL"U);sרP 4Y$%82gxq)Z1Ę 9(Ҿmn FkaB8\=ƈ^ٳ8FNjIWoԈ5]uu$vkj#i]vdz!o(;qw=tJTMUFcW8k:' Je62h:VaE8[GՅ;i e_#^҂2c r5jIfl'x7l U\vly {5›85!}A0r kTbHx]9XC󪮶}1LE ZA ~?kj>I6wwxm6dU ՚@׍^*/@l+Tr?˲\-.co^@h= [~m[:ӈkPdێ]_I:\"6e{/s$pѕ{GA3$D7ϒleZQt{Hz4"L:CFoZ@J\-z+VI{I^fҕ7 .E?VZK_˵Y8?wz=xM5:OL_Ov~#]bW%6䝗h룩-CbKMA Lhcѩ+֜r@X/X uӳM1hR ?H`dw.\? |kZR'&2NNl\t娈VNvNȘz,,> #tqx*/~i"w2_gp&rpiOCۭ=+Eײ=:FlBlrd.#IU%u%q!%щ[+@ˡ]a),\aHyjƙ>}syV;AJ' AywCvڝBɢ}'3v4&Kɟs¿^8s.\8*Jr ;d<ۺ=LrAN#BB_ MŶO,dH|?)Uk&b-ur%cUv,9İ%h\GѺmdv\qQ aL[7ǰk1uk t8C_&"D%\cHVv08M4-mBZq%RWD?)z_i~*2ܑti! Kq律(#e5nY9a k7pRbx:uӑ_9g /BW)h| Jv\WM96 g r}p>:;;x >0wwht@TۯFh<@*c3cD7) !t 9wp,fIgeG /#%#Ǔ׵:oXR^uSQxZ:W'Kҽ4Z+ (LS`Qb0YcLQeb3uZVl*XԷ 詂䁒 qRNm$ΗYb6=pp04" v hK /%» 6 K n,NPC'1]^gCATmb~6^Hu`7-64an9)?OOa?9iRf(rk/j}G[e^޹xE`ߩp,ex72_XfE+8BzPRW(7w P^<>"6+ƍqnH@J-b-J²foBMŶ_2h;d DISYB kHꌐ4Pydzې 3iHY\$㇛4dEu(4͍4&c,*1]g*",cA?CMz !,&)T($o<-.!ΊU\Nxu%|+=0I! ep0vA/(y#Ip gnXnW7ǯ~z{7RIEU]T祢(+ ^-8[a~B9ӈ"Zq@KfT:9B=zXk$y:&ASdz/gRKi²}*iefGΠwޔ;1 4XDi@:O|JȔ6~wnv{޼ |({RehU"hۡЪ+əC{ }ߵmKOC*OtD=In%!!'\P7YNID/m::C?[:vg"e x=0ՓmSEﲼ28=90Z[TWx'Ep5,ʖoG(V3<72QGSd mRҘyRfNָW(6H|}cخKD_ pw0ZЖ;`=x"ǩĝ'ȚdI!"(t.+0HBXʢ$2Tb5ȐViVЬ^Bc $8 )W%kж_Ƚ.zߛʠ+;Wux ]=sX8Vkd?ʃEn b4;l҉!N !["ʉ&@JDF8 jbwMr5~jJg5!r9} O۞^!~SQT9i%SVWUn,Ufv]֬D>UTej=(PڝT4dDM3WTES89$aRm(0)>>A9ʠp&9ꨡJjƣVmX`Z 9B7(;]֗P@-N݁8)\ a;8 (t±savl٧L%$L*[GgDž|N\SIeFFaϣٌ7Oޑ0ɚ- SkUJ?U %B<)Ζ bCog ΡG6?lᔖbH\ 6\R8!K` īE⣌`4tk>L'LloxԀ>l"-~Oh : ~9ꏆ > [hLԕ?GO9Ǩ u7>Z"9>eOv/9 lW%񆆇5]Te/VYӼ ͍fvɗy&^>y@dZlM647ƙ_$oq/.⊫((:W]ji89 a 1i#ӞK~U+`SoYNBVծ7JXg]{6k'~)Z ^vu6unvMf[X+jJUomt[el]C':5z"\7DrjT—uV$6K6>Oon{ 轓^YjsV%[A(1άk12tO/ pzI}(õxOz[2(%mzӂ-8 ǵ_3!X ,;8{:lKbe4϶0hm&#ҳY%PЎaͯ|6v} ]\Cd QӇ7.hGer)ÕD"8] -͉^CtSsJgp;ZG9$d\^r-JF*o<~+mE~ o>Fፓ[ޓ,wyƮ5EAtx([)x#2Q~X8:CG~dDP]*TJ%/7cv|_^}0~7WVW!-7p?+8(wWW7|qj˗oW(s?Ys`*Qۆgg2-~{!:[Mrt6S:SIHm@N3E54z-Iu±?D][&wp^8޲Ifj_<,Mzlu|x\fCu#/S t9yCyE%l Mp𓉭?b?#郿p0lEQc= EYaRɋW{4T1 6&(KVKGMb$.% .!+>EҳЧx<V>yԅ1INkOPy6xcqw'=gj%}XcޒY?m"4>/ĄR, 3 7Dv-Z4, d.\iԞ=~ `lDO'ybС'CЕD59tJZm|ړ0@p? pSiYGr?;Ep#@ E3Ń|h QK057Qob[[ 5tV^%9\JOx)BұGfBL^%RcK"⣻:4â 1@*99 P㔢dK'm^)_<4i^gFf}P}l1 %tpOVD0􏀻9hct$wDw< m<ipr|4Riw0$yJ.}>~W0m48@qyE|viOi{ 4EZ55xL@fu?m2Bt$}qmWscoS~Ѱ/7^rݶz2I2%E\_{;,c}X|fi>JcƯ1KQ$LHwΣZki֕\aݢp*4*BG) `WOA,Cɳx2߈cKdaޝv:yZI="ʹ#mԳo qʜ*+dH?='|PuΛAڏ2&}{hW#+\`Sٷ0APh.J~h8=5a;fНcgmc~C Y$Nct]X+O,wb 5ڇ;lhuDo; ^[hu>f+ngѥI?(U}9<Ө:~X>mxƗeomɧ[K>b~,[{*Ah:QMqi26_KBʕ෕K"{[Y |m#Mj5XnίyU9Y<3 ^3}2Z|7}0(K^F5ߕB5_-N'[V wtķqw_]młgkZi5f7'vzrvzRT?|8Nf2Fw7)YYΗc>&&|н7O#_/f3+KV)˥LMbu&XgCgN^WNa[,\Aƥ< 6U *.c!xѦ7Mrm C]8~"k˕4hdlx#h9Vh.Tz7Ǿ1%|F҉ ^~DŽO0M*C/$;Ճ4 » ׇp~-*'s._HC'jVexwFNVwCRkRxY67mM Qᄁ 19I% qAhReڂ܂qP4h!! 9v t$Mº kNm$G͹=xQA숾u=/A?;bܕ|!21R<$FN**LEr adCߐ3|ʽQave#m)ߠՅX'g%渿D,o\wDZȔ\|An t+3\nWn|v z^ <Hv=P_υCv3{lY} ^ SqOJ!t!2ط BqBH?2 u&?wOٔ1ayGK¼8eX}A&-cSu7>Eܾۑ~ I.$dzUh{$ݢ|tŅ}]؆D6;m975V6m$tctLD4߾~nH̚$Sk?p&(~6~6F>5R!RFReAX⧢ظllf"̤K|r6-;*ӹq ׎< IPk}3{#:B9f$P3Smٮhon5Iw>by:>#BIBDr᥂-IIu\SD/I`P* ?!rYԲk987iqQW\}rM\A憭k*#ϠU֌W:X#k#(s=Ҕmf7EJ,RFXOd]hQFɒjJHfv8 #j{vyIm б7Dߴ1!N>5XCYp"GUCA҃D վ_;ψrDwG#d=>w>F~Lv::KpaQnpYѳ &}Pe/[R;[ny\^n#9xshw-ҭ>mC;Q`Bt&iQNvSPЍnI [MO thМae xeQ(JS)'UP/^} ouYzK^ͬXwC)d܆y,S^bt/f7Wsl7wMA1/lVfmWa&u@s~Q| /OS83"V D4/EV` 9l]8QVŸ5e , [X#`^ti½4\̓{-;mejfWE/eV6oQsbUo"R1^J .ePSqQ["n(CRO E/ E Q%CDnē9g\A+T_2~'ܨfP$u8hxP2$} er>Rx%OV뮦4x5NP%8R`nFA8!H)cME)FSwVGq"jOq; XTXde ȱ#HsR |pw/PnsEh $AiǭUm;[ *ԼןdI6t=uxtOףQO(v9;ʤ]7vTnutڇN"F0tn}۳=q_+i2%ĭ' sC r:@+>B@ >BH{Y/{}1آpG=*)|j)Ħa웶>YBcK r2V75\!8"2DŽjWю/߾(O)K{<m%ɂV]3Un+6Jo~i=jn'QړN`4 כiGʶ։ϓwTPJ#/ݦU2zť.I>oEti^x7+O—.azdQ_H2⇡ybT'f/ublty y;mcj^~z7Wo|Z:n&- xUj1 нB?tUL@胬e[XHgkk(U<ɔ,*75ZZ3.)9;XpG>rt۾>K$/t~f2<֨־!8~QwO2|m.Qƣ Dz}á_~BƧΫ1?+xx]NM01maκ?.520CTa#܏771~* L<10S䪬̴Ӝ qcJ겳0xܽKo$[6PeG|H/h B"2#23*##AV˞=6,CnX\,]ȾOz;"v$Ny`W]'^o}g?+[$ w~VV˹}7i8<=gaֆ V:S .v@Ngs۶4#g7?l/n_c7q97|SgIlrb< ].D > ^Uٙ$ALyr_N~Kٍs)N;sO~8Ig[[w1'`+3M⥓t''$><[n+X%(^-WQ myHZlV^.tD3^Ãxi/H ~Mk ,'Ox*f95Ov7;Mpj.(y/δ9&)d27,{h΂?EQV -*ʒo3+|~{YHwMBjjߊ,xi8+lQhu\JE?CbH“>}^8ptnLl/-3w.s\ @iSx+~oL$aDv8F`^QfnOďx7p\+C~ a_I-zi7gt Ny %=mFmoPT[")@0QK=4N4+͕8Jѝ'7!l.?ID%Ţnwb#)VhXb _}bKug:DqF C@yJ-Ji3 **Tû -j(٬yL>}$?2[ܓ*&,]엔Ii"#A bNf-`F~Ykğax0pCp;}%eQK|T]VkZT/-\i7TaYO^aĄrLM!6KLOۧc{MӤa'tc)zF/vm4ibδ*e74Nj11SY p].v_Bu‰ nH ?,-w+^1*a$/,%_9Z+ei,@F"12Q' V ^ /kqK.┽L+sp <37U;-5 0}ļ6tA,Z,[$Sz_Tb-eQ~ErsbJFq?/|HgEDQF~E3lnh ]G_DE6HZуrdZ.J~ŹQ.*M}Г藎fmDpf01W[EqOtpCLW0P5hSof-FGJHi4#Jq7`7~괩ιA {|ď1M g Ɵ_<%U۔q/7#="`*]Qf7Qu* oNdۨTn:8Tnh3Af2sd膹o# "c4!&V J$WIrNx:FYcr0wՙ$1\)MplRێb 0mk FgqّVwS q'%]yf~EfRa@10rLS L%3߉oqq&-RɃjJoCl,94RwG9e௴XG?5#d7]GRA2 npNe\[K!tMB!L,6ʟ4{Kq!~@{WTh*N V B,/aJjj`S Е6gPg\ZxcߴkX$YUl[ņaU+C%l,B軋V$=5˸!U@>hXhm82zyQDPdq! Ȕ0L*n⃧&$4+Z;45DŽ8jPGR#$y9U sTGܨjίB } Wxn^5'3Lv>q(.ލ[+^h( ̵r aLT*:q̞)D&{ ?9/$v,u_BeWt 7[HR`4i H|7*PKj:&$۬|u$e]+SwgksNJ48ީ`w_F LLIΪ/o_ }9sR/iepaf. 0h*@旪䴦ڋNA5D +RZaH=ZQ]txSG(rS OB nqdPs}M i*$Ü ¬觓8rB`䡋»N\|!iB$OFå ajx{X!/d$ "=I{g'Xb3V}^ųty/*O 3u XӹOת%ڷ~$.6bc m3z+a{?ї ց$`1 ,)"Fk9Y}GC^~(Etjt|r#~ƉIQz<v`܈z`]T ۗ.jhʥ,q?aP 濽q8yg3',#CPs3_O?m}AV<.ۢI85t2y2ݾpvG=5gg Aor}_&һWlOK Eph|!~a<9Znx7ܝ's+8nDw߬gP p'oͷ7ozs{ Z9>h,ots$VwnX, xz9uރ+hov5~"&NbgxSϖ-9ƉncS-EtţzM-mW.(?cX)` y1 %R$ XX|ycxuRi+.A8x&)nǨ!_EnA~ VɈ.KYpxry1_$Á% ^T! !0C3Wky3LO (p>/PF`e 5jWr^ҳ%U PxF1$ [E0vO"M9Pni{#{8cJ8,E< M@')Z3FT*;j%wI7ijS ,dI9)<Ts ~SFvrC.t56f?4|Sg ֘O{!(Sͅ* l;@Kv1RpI m)m{PYk]Q?*H9̢z6EYK䗬A) 0ֶU,q֯o\r;ۏ>/n/'W'_]^y$qgPm)ݳX+s\Ob;8wq_k􆋵4P9Hљ ^ .CNF~/"/H2oX_G= ajbAY!/B?b@%<B~Dr.`JTqjR9-"+JVhZvYQtP*>T鿍,3.9ܺ%tež+h$iH ?/H vIzߔ:%K>Rørc_F;-Mn1b~1Wz'Ɲy2.N8}v6؝1nEEl4]/1hJJI\@չB)ТJHr5W7{ IXPytuv6Bp:4A/1UT&5 gg߆h Snd58vX(Aܷw:wX)cq"Tj_(%9(E Y{F*j6];\w[uE[7 .H5(nƺwmayNÝu.\kۢbT"*Ww4?Hd`N~й<̝.k#U7m|(ú^6[ R3ԌOo$wpj8թ(#b1QRF$P~倱_?#dR s]J"s6RFɸ}Q2)-n+'vWkMdMUjUć M!%caBbA=ψZ)ycc@- mعXQj/$᛬Fx*{,-KcE'BX &5˜""9SJ-A03\鎓xLP0g&iM::F Y/ՉȴBhmtasyNVDh_>%: kOJFMnLA XЇtI ғk,OI@{ﰽ9 l0lV䟗되t 1I}UU*e'بJX*4R9ғF9W, vzH&yO%MR>6~L=Hl4_`rE !uJX2r=b4Tt H5&A9!s?ci=y~sdEϚAIPX墌s *mlJ"U:!Yr*=踚cDx-\jEm6*TeD!r*Y"UT3{Xe:Tn:M5JMCbj"_Kzv<SWۤYBTVc?.cp U m:;h[<泦2uͯ@y,=5Y2`Ikay׾^_j.8*/쐬Jѷ  gFt=S/ΊoHKQlږ{-Bê0߲/ 7'h&p#Ks:vsu ;1PܬND,3 .pFMO74D^ɤ?~OMDP# $􁖰r>\J0d9yD|O nhL Yj[%MJLfbT1ؑlؗpL qcu4iZ**Qǚ4rHţ>;W~:3sKRJ<⿋@SΗF_5RL fAɰs  U1pv$r~HQ0MA+Q/%F(M]FOE+˜\!Ԛ.(fJ %_KF .x86RKLx**aݠ?2Uz]BBs_ymПǓ\ A8'%IfRTyr=׎eFFjZ*vCkC'A,lB2]:P}/%xRZF:BZ)S?|$ /c)~3HDhusMМQ޲~V?, ~KL9Z g^mMu#A&zlY`B4+AJn B>G&wXM'Tmv;AuTz"G֬6 5'#_|j S?܂Y0_' [#DZyܤ;q>ϖuuvNP] GN_ϐ;p2ďG& \+PEaCޥ%HՑ`Aap8'sqjFV7nJƄK4h Jôcߡa꾨CQmEre}ê6~M̝dx%/ Dԇ,}jpM7{.Ɔ8oBBt,86෿r2؆B9@e^!88?qws0- `Q:$~| x98C8wD <]nQEgZ(`GL@%q0gI 9&p*$(yxpZh|v>0tk{v4,F~a[`oߜܾu܅SF/:RiA @]/@ϩb9[ӡor1hͨڦ)a҄G;ebE+֑ey籥3(k#,s;84[dq eE3L%jゟin0U0C:<'v T:stPU AK{[@=3 wt̴_)]s zɣ.:[)5okEާƹTFM]Z3}+?-e3f-$;݋2͖!;vO1+=D=Z q_|?lC,7He._]4>x\G` )R!}"/GO.۷'9釫!i\v5;ꄂAX3VNy{9MSZulݮĀ^qwcd9[!,szO#m.c"u)i5h%GZ{t%"sA3~q;{CPAR}$16ձw؟$ċ')_8Kyc'_v14)\hxu{#sȖRI$aO1QعM:)_՗c^3K}M]3Q,ލuVKzo ܢn ۩EUgD9]04->hS2lJV%MIM}|"Al &sʩ {IԚB8T#t"y&`*:gÉy}VNSvؓ }`TirlnjAEcL'C(@S}Nc19f_.cF^̶/Q[b]0f ( [?.ΌmjK&xXlkY"=^N45E =6)`#vO`_O'[H鱖C\WEtH?,uIɨiA4p5{tX&87ͼzh( 9qmԾra4M1&qdM2 O$#bPM n|l]dUlMe@5+u$I*&X6ElEF Pj4}c6P@)?Ni=VսD݀lK>Jpcf =+~w.}7/OD1hEPH*ReŹN!vՃ2,|l̜3R1GN$Q X[ +$ջ.17lԵT5izkX#}b^9QP?/?@#2SfRk3mn^,<I񫲨jU}̳)cmdnYf-sR 5*y1QHnVqotI*(GŹHB];cK#위 P!ܨ ^TeBPߢgΝJ#}7thB}hvٓa\ NE3QE)YūZ9IFKK+l ka46zhBp|SqI9v_]U$"d)cESR} NuT0 )|DS9 ;LzB9F]d[ P](R?ubo76Y8YFs +߆Y/|HL43)`L_kPRtӔpxQc\$ [n ?7X[%[wk2^7^LsҐ,8{U78s#;Z uLj h#ڬܯyc4k J64 [Kfhݥ,%}s \ ySm0wif?tBvn2f,պ)8f +?)OK\g 3H&Ejڤ?>:>U.ʝ̗wX) \ .<,C7`&s3}flcGB$?k= .<|x1zfDR, |O9ͻ[l/8-0.iA}`q|:jO=>rgHߥ)hoWBѹ  7ԿFEls2C]t;ǽ2`]%i/ OeQ{myf Wm3[M#F j¡o{@C])l:tǑFX{i 5?Ýi@W^j3|9`9fQ訹ngBL\ Q6/H=u ^*\-qDkM1_ą`8rW!7s9~{9:{sruK ݠ@P;857'<{!D' Om.\sӮn3WKKD4ǽad1=N@W=fI(Ϲ6 s^kK~H^!1uヒ[zc}v1Ğudݕ_w1l?x̬)ôyv<6.8.MYs|ͲTmSR鷑mT4UҒd$Dya(xm%{i+i]e5YYüTN!xQ%lS_S.=| ؁-M`8֯JqmP@4a[ťzxfZ]PSuG`z#Ow#/#}L}?>> c|0Sq"=DnwynoФ 62c猫x thc-+fNy <鄌?0Ѭh}Ҩh60y yt,'[N`nTqqkoܜ "ICSꫭ7Bb4YvF0Yǩcl{jO2֝!̛KbeX]jwT|qC[b#V I-.V hUBj_"P F2LdOLh]lm܂#؅up }5ůYt?~OB8Z ?WLMGxP=9߰ s^kǯ=<diTu؉7~mb5[jm^Ni!S}|5ZŵI[A|ȱI-5 XRjM1ʾV"{Q`paQ@K ` }{ݖ@ӏ%'e\B&`!ұ (r5u!jfi4HbaKC4ԞU=sz̫wYjOdg#&XZq$a7Ꙓ"buq]_m0$F/NC Y9vPUb)| _<ᨢͦW&)R3 S%Ø[6A3d UW Mo#sIRKC7 %U$R.v)¬[xUvDn@{̓+ MI4Nqc@xhx(,ȥC"AAeqDWfS;C,mRjaBSE|bwCZa.jl5b-"*i1.0|7 aB$|O! 4$-44o'7dG$iBF|/e -}8-.*R岺Bo KxD%f S/3`{ԴSbMɵeCO*qVbKdٖl<L{ s*e=x}&X\\HK̻k9P%OW[Fq\,+Fj&)ҜYgMC85܅)id`|K--4_X nIY@<ݿ\<~{Nq~GBKDHƘ.N'gHG}ؘ*fP/(,r7Ŭ#Vm1Iv{F:K›R+I,e`^53!'pqr Bx>7q~ 1=fִFtͽ ~ ~aMS2F@ȬymO+!^m߇U +Wth []]bH 5oP[׫ KaHpEB&܅ΆzV*vqv1W-)p|\.)$c@\h4(%U.1:gS)09T (b} VZ? '8"gT[F&_̌n.Q Eޘwԑb[q~+&GV;)rePǮ=к#41AkxͫG7+R ϾP:qďnҨ46A⬭Tũ62E[wl!NZ\̡7\ Q떁lR?paPLk4&jzfL`F9FbA3>>4Q׌& L& uKpMlzut GWDy)FnnkEW/eZ%f}^4:'Q =3S} 5JJdU(#gALl;*vlM@=?]Պ24 Z*˗]HmZ?K ռCs\JY8fT 7Y V7*DqeΉC"IAPW+Uˀ h /?(YHI'9"Cm3)YibMNU^1~o'۪2}jRoOq(烎GDI摰J }0Pw.Wń21yƅ}ObOnaitD\|Qpm+@c7f q~ }E=G_6LGm>]L84YEo1"op >͓3P*OZ=s#7 e}NZ9c "+0=XANN҆WX05I#$S:gH3jQb!fE!ۼIX>\_^<'B g<[OArxqr==9}߃#mKIux.O[uA>kt9iF &vA鶴\O<%WO\ wc,Z;bw&]e}ۑ*zGeIo_c)<bo(uCGW:Q+;2H?) Я }JZ6( iLċ^MyEjne2؞Lv6qV7'WnJn[a= WmmPnW s@q4huT5b[H (ǘ;!m P] 8sp6i4MHyT S.Y{hشE1T&ԓRZ8].~DiwfH@^<"7syQB[\dܜ|5QJΑܷ}mm#)@"}#%F?#U(]Ttޔ-iNrmmzB]?5BuF7&*73.Y|܅ 46s)\ك} "Ðf8E}[>ŏ}7fU/6ƿs}4( %fοE~ =rX7ؔw151)A'V 1A;zȚ|^o^e2[op?bԍQP"bFR)=Jږ!7D0yc{ZIUVt7]))N/]/q|ptLrM_~d%Jpy<汛0ɞm^a\7쁼#|O0f~ tܹ"]A(Rq MtbtF FJzM?\Z?{t#Dm}VQs`uTb(Gۈk}iGl4,=QcVk8M|ydM9#-3*xd݊5J]Wm![I"Al+l Tx$@(T_ Er>Pd *="98~,qjn~bےSIXuq+Nr|U|w:,h[p EQ0t T+h\UOဃ<, EAiaQ 'RI*֕4{-HŹ}g Ѝ)c5$r$St 1 ֪Gt HK&D[C+bI3t(ۆJҵVşmPuc= uq_m{QeR6df)BعfB; og 1ERe%|x>H-@M[bd0Ŗq:t}E64y?0 ̅st#I)-4欭IOE5qUyR+ؖR$Կ1; -&Zt!e 7ߨ/hr4.v~DjSyH*( ~?殮~v(;>)Aky8-NFiiCo7 Eʣ|"ۜ@Z('jo(wTyPwz1&wP;m<"mLy )8|Πװ ~?`pKNwIFiAr߂{8;I}8L/ϰOxmjt1%c1ZMZ3Ą7CFe@6٩CWUE!89;Qs(($^sj.$\wIN Pzeݔdr/hEMHtEn w#6İaf'6prRsBa1kOeqdxKo>-?nvXxI2tDYBЬ{3}L_=YA҄A`˜6 wdBc9-d?‹U6fp'Yh|FPRR`(&ip{u㳞ज़6 @Q3ٺds; JRtOUf0tȏYZrTmR)f)F|鯎<ʂ^},aX!Qo/6/j{e[Hvi.B\EcL,ČT."-6 ѠkL6),aO˗eѧg!Z\6=YCLJʞb&o: &Yfjco0&OJ-A*Sp(6L=[po7`‘)#*'je4godoXE-gKK^+3c+Z->,aa8,!w rbVҵ{TXc!X/Fl x Ȧ yc9!{&stj06JruDsfhe7y,d>6QנS|G!A3k:X{Ka@wV5~/ 4Ѐ6Ȓi=;܆g{:E 8|'O<`QvG~3_ۦQj6/A"˟7ZAIsHևpe`滺{'ܩ4gԞ~Gs~]x5YA,r'p3y6<A^>4 Am# m99tv\>= xM:8͹ҍݫpp<)Д.ۯ(/7$% sC:kyZUqkcGKyTd*)5:0@xW h*(.@ }s<J_%vzǑ3U󨫳WD4 U7)5CLk[)K3K`rF'e;?WMΡԑ__]eIkvh[~u9C袆̝I&kI JݞZXYD$7X\P;W`]_n`XZF1:|n&CZ0РѽP u-$^8['dl*0>] GrlSҪ=\K+ϰF+ 5l.*̒K>Y SZLQtpxt0AHvOP 8at$Ƞk~\5Z#i> 1B)]'Qǽ;)ND4HaK q"ݣ~@@pC63&C2e:~nl;_ƒu;:0KO}nʅ7gI Rn^F-GL)0pܹak֥oౘwX3+.r] I[!i9~fts:~CpbHh-rS$[ZOF!1 yJn4gʱmhE@U^OD7RGt?&mSԷ'Զr]{R[=v 7|3d6#<#,܃1rz><̦FRo ..oN9k;αɭqSbU.I Ed*<$GzgٔjKΏg᝻)]:ŀuHr3xȱBr/ᝤJZ,NcYCl(5hLb>]9?[_-śOB$NT f}"{řYB nVSQ&Һ86QԐ7:gˏaG]8px zlN9}^rG݇()HQ`1x!>m/tL?iy?@F5>wNJM޸̦ xYaV%T/%4)U!,i S$S‘rx*QGk<.f&kp=ltWi0D#ډikizޯixu{cd$ɗT%+R1yWeEx4g!v>hhY"Ϝ7wbcF>'LCw{8aC =0+%",^2`JbW3Pvwf~0%݅;8 XHPrpXmc+ZL7z 10^PS`  )^!ad.w !"3RR3kţI\ϖǂ'0.mKx$M #kx94+x"wpf]#6ru2&{<gPRKF1JLX}` I)G&k2IАkU,GunU!,*Ä 릫^ftsruwq?y{ޠ怽͆JGNK6KaE!6(i1j\Kadij~/~䑳C,s[1FS{wl_a9h.`j6w9sڤn>LJsz<!0dOJLPua >5/>?OT0|@M$CL[<WDlVjfug3Js>%q 2Ͻx S ·8N_l@5ֽR]3@Ǣ6j-V~sxK9 V?!o^?bqn$2O}t[^QvB%׳Co}v; 3Pf^C  f4iL؀f6Rc( nc^HAD{}+FG 4_t'kVS^1&e X*IEĤ Bjo2-߇e'Cr#W SߗMՃ7rFvDLh<3*o$LCKR;INoݞԢ${t,h@9V0/U1j i> ?.(WNUdؖH3(Ma#S^s2 }AUgAq?n鳎7CXVaCܫ󳖺Y:Ksg#>l]1ޣ1*4_i|6@uÞ 61G*$fO :ydP"RſG8mĒ) ZV~L ~V,$b$XpjSyPsil^8[塕4wQAH7ŦX;?DOּٽI%åIY! ۽Ap!1]1Η{4ٕ5VS re ȑN XoR2ږ8:`Bs?S`M<upݷ4 >OWW/&wt<тшV[5={}N K&$@̆rAJZ. c' %tZ p\%㓮ZО#k3BVɃ }֩&yit a W  agAu1nTMBVęD3+ 8l(!~ؐddh LS5 Ajl][sT~f LڎCjCMmҩZ<-_EF߳#)LyEtt.{vxW(M/Yە Zl6I1SQ[9%},xFKhܗ|@BDʪn=)C0kba.Z` 3V2ϋn< Al) ydSI kP WҺ)$ƫ1-d^[eAaغ(7e63q&vt4W `^*_;*?E!&,&3Hy3+l9(qŬ?xH^i!ڟ 7nL :wx[2-;$ԗdϘi-Lz6eTv"ȱQ@i'DhZj5OrmCL ԥtuzZGnvJIrgүɆqyK3Eh2uynJD'W,MlRFDL \kY uvv7mPv< .q|r}rn4UO/h!,$9RuOvz)zF 7g$;?Pؘ>ۼZSh,;1ovDڀv۷5C veb=K_r *AY'Q0F!!+1U% Zxt /.n*8wˠ0J-Q2p4SZ Yr&Ziְ.--dOZR(vFC; ]XYv@=Ziߚb<|ȏd<*Ry0]=q KO+%ltdpڡ|!mp`=to)\EsRYO64,j$*lhxINI{%A,<|Ibw`OnGsiwY<d\\/ 8D$ rgl:p%]_. WAB\:W~s1u?=Źi\E4s/zg=(9Ϲ1d=o.H1Za\! .P>dG R twƼ ހcڀs㔶BMh0Q7(JTw=f1 adnlm: ,C$.UZQtlɐRBs`vP\YeGqCShߠU:~z"'d %K(~Kl9HC3͝q6J盜Mq_n> y)4]^ΉGU-Km:KG4b""}Qפl[ 9 (rC`9Pj"#)}onS[a-п"z8 "C3)Cc1P*4milPsmk;xzSĘEo<||ٸ \W(a#1Eё[XCBrpI8xsyr,9}TĝIN<"7{v0<A:>E{Gn,/;keb7N0@QLc.yDDr&Sd|clYxc\gv;>C |ȘY\f`3.-N ^ga;60< X:.t eY4*}IEcQESQFb?gϥR 0T;L;*3,t>y,QbspsK&Y8B$ h ZOf.qY$MI_;Cb(GٜRL_1E߼qghtmΘl4H@$%Ot77-I*L5,>J.c~|[ۇM?uuM w}7jp;}GLɜ#^x5Օ0Ør}ub90n ^a&qur'vXf$<IB*ɒFG9/ȏ8/~'FZlY-F}=!ւ1}F?ESټ(>FZ[.zO"&I+6TQMS%{!!XngRmŢ#F{"QIxrvC|k$PP [=^.@Xt`J" p$Տ@a,}RC8_hσH?~^IL Rʅ4ɬkTZaX_Lqڥl ,|6bGI/;_8Lz oztWg)fQHuTCEo7ŋ 簫J!~ͣ9/L^Li؎.f|t.;i.wd+ wd H/0Jq|?z6BiK; ͦ"޴p^ͩz%AYϟTWYxWn8}bV0+}i"&N`;M PYJ@R X\3TcA]i*q|dz1 U6H5ê`xbsnHzh8ΨbA3weFAcnK!d'ے[-WL}_='fmĵ~#ᚅ4^)N=%V.?C|[Sj~~4n̼rs '!z y듳_VɴA ȵRzJH(ϽᙒC=g)H%Um !ua4Vr,V&Dj$֧ G"ͮ|A˦Z+qj.L;fJ"$)աi|o:Fz\en80:Άë]1~=5UlEulF芆A1МT)"hKCfQ/P7(j2$0sLy҉<- rBFI,g_Ғi"Mn嵵a6K}ۀ^Se'P<p 4)^4C`qG)u-\`Y~W39]3J Mu|r/L vs)Ɣ`O+&xz=-$=PUٵJv5Z||@x}S]o0}ŋ:-EELLD:Ms:vk st%c6u9å2CW#X R9 4 CeWBC%V+<$x=>ƬZV 8Ǝ[jҚ\B',--׋ S Jo{2]V+|X:x~'d2)rR*cCDerE0'7g+6=00&$oD/n$O`L80$6J/ϋY8[^iMw/t^N`*S 1>\F wo^u9욐 pمgO(Q|38 J<6GR[ImJe(NZ-ǭW?0mdux%IH!tGm6K瓄 %t:6i`돘_>خw+= Uv\7zCm D--yu]u~j?.տHqV{"p_Ȇ}\C W'r 1_ϥtN޷0xֿqDW'r`2UFvC)i{RA>y\bq`G==޹ԆEuMPZ~+G8jTu%;]WGYǬVc%N{dr&R\bNGjHUxW֕e% O9%:+7[SN sSfm04s`6fi?{)Ҕ"[.T7?ڹuY>2 '=l&Wt/jO?)tа]sXDAsl% (]˹,(ZKqj:/A@ʊu3 `+m4b|Ơ7m}鑈I!}IB} &"u{ъ/Zž{қ,JRtHi Nq-rg>P\Yu$AHL9#{wMo6.Տ1>l֢`{u@'۬./Db;_?jpֳmvZ@!EVM4[[Õs=\l m:C+fħs|j#, '$-Pbi ff.M?m@ i+ +4℉gvGͻGVƼ:X`:-~R+M6 Vp6 ߣ-:<Ҁ!08nOk3͛f+`z,} /L bOd&+'F:@j׫5ұNTڊZ<\%g&!厛hb>:T*)9'U+̚T*%flUy>R`@K6$(7!RL!Qua(m79[ o` _6r=0{`YXVGk.!JƇQ/Mjco բH"RuAy)!Bk $9j2'KcLٷ|z584܅LQΪhz-iz> TDz o>hrkZ+[H\\9$A7asZHvI?qHH%y,R"m ";!(LSZYuyBL;laEzeY/g-歙_,|:]  h}XfN1:;qڎ7guulJr WX/@=PGLK12[yT\fVodi`cZh6tb/QJCv[3lK<]8VtCtӾ6\^&zsC7W>edq8냚ëο2բlNj=w(>ȉJx󲝀ՐAw9c5pVTzYy6jo/؀6~ /Z~6-oCQ*#wϞ"%jaZ`zA~TpkL 'IOҺ$Lx222<\/N..q[e=/E. x=1ap?xX%Z^6e2&$.h#Z([m>Y߂!~KӒkӶs9|eiݛ+z$ԉ6-ug,"D7ؕji)Bp[.3S/#l/_JQʎ|RGɵ W/UzMRśȟYu5mNMIT!d7M ֍n$q~,)L0\[? OHQ`y?'[܂jDiDMdZ&@zo4Znd\z$xY xC`R}ӧ`c!VP2M+ A=m2 O[7o8:uid>߶E3#I|˚&s,Xܐd&Ō <]MJ#]z}RnE܀_Qn΢&>i [VDRPۉM!5yd FV@9 6F"ڐ־oNx~|G}J \\bj.G3UrkMç;gf۳1ıE:J,aavλ|yO4W`$RY:]SQfY9Pߙ~`ҥgϿ`>+cr'"FD,V@,1WtfRk}0:h8:XbV ━q3VxT&Efձ/ ^?5 HDG>^ l-6l%B TўmHf߆6qeOv6HF|VWH=PlRߵWN(wi`Q?+7 c"OP7N[)&7=8SMf̍(LJ ,نl Zk~J7 xܶB!Sy@xG1ʅ/Z UsX(? 0XSS,.X48y󱋀uʲ#t R$f'zⰱ ɘ['LJE6CNRF-Nm(H #$ѐDA "Dw9ecAd"1ֲ*Fb$Ħ{`"r>=0+t^\3zkI71C,r=pK?LdSCGIy_O2נ3P2}%ɫ L>/Ł- 9MВAƉGrK[U _Є`~(6=Mu- mijMU?MaꚎbS1m wfqT`eH@~OJ-pObIpU@/Z^K,eMkk{Vћ_ױku>1(=udq`7$|pKӣ"0fa?lfƁ9,k) g,[oVKϘodɺM@Lʹzn~a~Iܵ55LFR+ ¥) Ry, ABxwiZ.n ]w9}匮 ZeUJ0֊ZN]ȓ]/"s @ljnD2njZْ XoI*\V%,T\~/kw,cp;X {x&]v}}]zCޑUDzxc.nͧx7zOPt Ctxk]vqGxg?7Ox_G x \-fwn*c_/xk]tㆽfwn*cWMOxk]t.]B')x:*LvT6,"iqE~*x?qC7OwϺ9K %ex{:y.DOx_PUL'7pGn0 4/xk˸r&㆝l߳Ili/+0 Sxk˸d&㆝l߳IlI].Oss_V! BxVQo@~.bx\^ќILMlōvm51o@W-mSLܝog]q]3 Z𘗨Zm.t3jiIbʲ\X0zDn$*8-&晴hGk_gvDE.xDS?#u*/,:*iu Q-MYF 䑧L7>]SVT,{6/<*Pf8 FAڰ+պOngDm1wqx(m`SvL}ݯtm?Rf;hsT>M*xK+%Eg?єǀL:,=x/kB`rFjnb|f^|ZfNjF2EXY U tnx/t}B첛D6[qH32ra\o#x;¾ir4ӂrK*0xZn6ߧ' Yv5N͚,(ڡA%BI>r}|"npas>sxHUЈIyqtZ")-GoQ7xzP&1R?B}D4= \&IK@RLr^J"hlHI)HIT&e)*pN&fnjj7ڲZlYc?D2}Ye(Hq8_)tqr޼}PELEsLs&%|wT¸ pԱ9'{:49#HeԠv>o5 [ 1 Y h>DCj5,+= \jwxZ ޟXz$,IjlQuyhFLo4gH%hb'n-="*,9# ^R͡ xK7˲sxv@iȕwy(|6?~N\6JPƓ1Č01` jU*jΩU24 XUbPH*!8#\A!zuօZ\`ٔ߻Y\V wښ:m׵5USwP}E$"Wqrx`>~!Q7DxЁҁ1MYn Gs4dƇ:(t42x8K= kX:NTf#*eiE!A70\"2"=]eg˱ɮi* jYk 'ڙHzĈ +3Y\s-'ಝk_$ydk`{ ]]4sn@>-@*4fCKj-X`Uw ##XNvvj*8m'qDyk2K_7UC?V%|J94bO؆!= 4 Cm)J, 6zQ=!?qj̟LIԔ~b!1& O^b~w`wdNOfW{!qVܽ2Bc` ,RPgP ^ Թ l/2_>6b:j3"BdYG~3bԶ P*48Z*lcrG^ާ/OϞV5 XeGA T86pc/( [^X. `ɕY] Fk=RA@u"vs` lzG3h"1Xs[%PզvYnOu.rkn{޻=ݞn{;2q;ʕ7iz2AJ؏"j wk?Wp.Sh i'IGTiJB~JwRrrV a-6-H6:4z7 Er{!/5\(n{Q/ 5 }] r?,/&xWKomAJ 棸D),H ,EJ,XRܜp{CP ȹC@rŇ\ˇ ,vsX`z_n~fd{Lby+8+VU0c_ܺ[Wm4{C YWP-8-ٺ]uˡ(k%|7?:\Wert xwShrO޸eyb\?T7vgzʩRp?y%e+-h#Ụ\veq S,֙9t++x{)Q? dcܝ3fw$W!y?iQS'h#ڕy]p3=yr={}|tyTȄrdyǸvauWXW_3YUvyLqBEt' -Ҳ7fS ׮) i܊Z1BJWVlE,f̲3zH.kV~ahaAS&T9G,bHԅ˾f#7"xXPN}L)0hM/O>ڸ!t5@gBЃ{JUPm IT-vfĸHEB@0I3TG,AnA90R42+9AMsʺk`[{)kRh%s YBP0f*(spѾ\vԾ YcEFB]!g֭t <ࢫS i`3IE%{$QON..Yǵ Q163'[(q_^3%47 CEґԠ\2~앷d Tޓ%l- Bbm uc>?n [uYJ1EmdC<~awXxġD1a aB< N K̖WDkx߄Eu u%z%CjTY7FypHe^wXA>^'Q8-;K5V;`I-h`]i]֨W0LPc2qrl&QU+ >thm*<&αAc V`vLUEWGDٙ9l$P v5e}=V' Yٷ]GNҦ1%-% [Xqk* 66T&<˒D E+eJ„D8c@xK=@)<TG(!4`#b|p俊6 \<_d 4r8F8$iҐp\UHUrTɺBLpT;E15̋7/cۊ,RxݐUni}}q[gFG?pCftrhxN wFob|uy`l8OV 6odؗ5v2VU$j8?,,!C^4-Rړy3O܍ҹ9\I?66$+t$^!H,f& >hROJIH(~-0qujEnȣW q!yѩHOQd$Axh17|M_Nٱ68q2mvPBܡEP= {.+FIHkk9ױ6I?`BYOB- /-ERSRR`z t߿3~<"M$鏵'/:&R PCx9JdY0ra*o0[rBls@`# ʰL,5BrsIe@_A}m ]^(NL: ?  VTʋLMX*xooSE:bR;S97R5:dY+QwQ nQ 2Í%\Fn9A_UQ YNx,c0o!D e˃5g?n?/&`}wVJB8_f81ƉY, &9]bE\^$/OB&S<3۪Qx x svR=nӍj Z#r<4lN/[s_+2Poۻ*Tbj5٪L}YHVFkzj?Z׳f֫ZlݡU[28^HK&~ 4K?ZWzG9rj퐝| Qܷ@xXkrggGxWr7?aƆ"cC5&$Pe(n͌VӭYOd]YxE WR{fpXt9GW:[Ymu'kn0S焝%sf?7Wjޟ:a;Y%,b_D{M}ClvH+&K7wx"hwpϩK}7qX/;٧7;4 K,D k0tNκ")* 'n&eny7} (ϖHK 9#p%+ /Wͪ;&4$"N<]lfܚ=a9E/a*=l3C?W12- A:PiJ?K=.v<"O4`8鐝ܯGQװEdLd\aqN4aeKͪ>6YQy.A5(yluMlƲ`Th)m hTeae͗OXk'/LL6Ply6r&1T@ ]ܨ33&hhR7K- 0Ø >P?ӄnWZ[KB΂+*'zlك@5Y: XԄ eYz\] F8nQWS=|6-bӇWb;*QkަTZ<` (UKڠGC9sU5Ha8I`͊)LHY? ӿm߯(}k UR_iޡxdyVKGL}ȭ3xWOs/cG?Ji=$FID† Xvyo; 5=C)!UJ\7H{ qëڙ^ދ%3k9U\ɿ7p342~QdL鐩7w!T7Άtハ, Ze\|mW=yo%!G뢱`^ᅿ\ؽBG޸biB\9^ۡ/wţ])8y70Oߩ 7w%% yʶ,5n7Q́:46אsz`;4tD4D@rpS*7~4 7_7ёôlɴ̸>ksaj%AEH|bd E1+]Zg$@*UxY"ar >jZJRB;5|6ӏ)8{}"Ӳ *{\2_MO.U) JwC[Pmi],.Bƙ 1mQm vnR껥m@[/ci|4zl -XEٞ[@W_OLNyKdGO6Jܔ ٫,RwzYQе 3iSYbNGLz"e{d*djvnX3yEO1gj|u .X ŦI~P\MH0{*K"ip c-aU>8a8V;ܓ ӱe;"!v!v\u+Y>_oK|6\:ؗ[׽X8vw`Uy.ݠAe->PGUN{!"=EYa91+!Zԙ0|WѠcY\^xn |ITg1Z_U:a\vX5JRfKZ\C>sy2 TC? 3F&h=m˵ŷ*Z!AX3 >8vjiƊa]"WĭdϮV7XmL:cMLGU GDZn{gFpe_U8)`a!x{t7hJ!tۄVv x}uNĒԒ%M9`1N~8NCx}u„X& 0gVnz8* kx}u„x'4/L+I,w|Ex}u„}좓Iede&'douq;U>LB`xSn@V+A*2*Dw "yxU{!hy^g$ܸڎcOٙ~fύamK1b~ܮ:`nr_B*leK' y "DZ2<$\W$F&)(+ tܧk{BBDu´413ͰD0Ĉ agv*&)Hٛ~УNm25pËyس9"1WcI\pYU{E!E~F^m-T20B_dbɾ*LxDWbcſ=GC;fzMPer PlbfX^?wKdi4%_~2zn;n6h[P85-\onxrNl?b3'A`M$״*  YM5\H>;jn, mKjӒ )̐ gPX=(Sl50_aZ&sf,Ϊ!#?RJA}m-g;Tp4x"cDĢ,'ppM453S2S&;R!/17V)5/1)'5E79?//5$3?o)&K-< xBIF b,!@4Ԓlļ"4RF*敤(gd(d+zhVd-/E!1/E$WF?%8yvF1%afxn:yQ@j-B#*T>XwG^{c;^'9c;i!)EZ]ό?=NFjQjnUq|V^(eN:7uzb0E~jѷxY%`rNZ6"-RRH+6ZĤ=5^",zkH֎Jy (>t6D( 68`}+y $F;).SN\J312W.Zn[_m0f& Έ41;I?dd?HEc'`TǽҶ"IIy_JqܟBU BiͪGřNTD*a?݁Ϋ%]clLs'|rT%^9WPOY\"`A6[) TfVXNseޠsKr[2/HgYK5jF,C1,NaOu5+Yb4y֫kt͢>Eޞ{H&JHp[&эYDggEjI34T[ ͈9h5 4QKÅU>X@Φ&°6IgDK؃}݁IG{kQD#hƖP6n< :C*Pt b$JlJ4c]C{ v8o,;~YByJ$SOtao]ݮms>䁙iun[Ζ}C vAkˑ#: +1CH_>-nivBH^<ӡԇ3-S myͨ!IxN< FkD ,Ao>akX%F$cqT zX m~{\ۂjq/n)!cv9MDBiD8Aa#*Z6CKGsb zhuM2`%rfL橘 +f$y^]S;z*L&-]rhj#Y;6 ie>QOS 2My"(xz;nE@d9X=O3a k]>¡0M+iIHNddӆ%W:hPPp#}|ٝC1rњ*]T! Hn]j$|w )4}Sx!Ll ׆E5Ek5YJ*-8mO hdaWxi:.?r6dvxUn0+$")`;" ^E}+hSJRqt)ڟ˗tWN ;;;CzrrW*Iѧ8"3å^Mst2ۛ%SQ/ܔL~zu1_,?Ͼ|;8Hi2ɘ6ZfL%Ip1g4:T%win#/Q h:B=4i&ČkѐfF\V>Ό媶ClK%"M ׃gYҦKƞ 7Cjȡ˒fv "ʍўܠ$*慠E[G`HHn[-Q jU" `RB NR1K޴iҵz&G̓6qPM8DSPQzC|#.p&K27¡b:+p&<"()#EG4̣,ZGz;ߖm0$.A)i)­ݢ~ й1\ijFsJw-vl4XQ){)pKW)ִ:l+쇰'Mqn#þ4*55= fCCƮ#:k#4Kڛ*)Ϙ; {TV c@~#WaEOeqQ\s`E[C2ią48ޞ /Cx=g6\_JYՠsZ]xƙ|w}y"lcjÓ݃Vx-.#~6ӧJ+xWm6ίu7 \ТcO&c۹BoTjd/w[j+Vxf<<3J)['>Hufr+.+J:x{祟f~9}lzd~0LdB-3FKJ\+Z5.Y #/F)ӵwKi睮Qȓ񊴨`T[i,|GW5ekr^Fio䚪vu&oqL cɗQ~t_s&Ų&"MMn8$w3JE)u7ϥNY^} ;3i$ژj&݋^CвM[~:parja!_݂ vxf%GB8+Ye o%8'T w?Q#W$m.u:I^hX4Z.Y]wG#Z3iܤ)Y~ GtY+:xdFnz;K ^gpCΐI˙ My9GC7V1A1B2Lbru!8!-fETbeRN{2oodw$t [ l+:0T˦ 0t,c5B_ HU^bLB_-#/ԝfa'hYL㚐:yTU]47ެcH/3c&q`|:z@N8"()<$S/і7{!E'2 }f~lyvOeοDD-sy|_h]k+F*\Ԅ挣{A Dݗڶ/ЊqB}-z˸vś]uKBw&&y>)IeF~6I/3M@ed&=`wהTTtL*pYPF@7ħ`O"ݦp.0 A/dx_.Z^s5|24[\t}pGbk%<7Aq˽ g1'+|8Ţ)v'x&X C?ZcIμ5zx;5oc]0 S"]f'K(&W<802n|8R7"*H}q(p4oMXy6)S"麨U$2I6}}tWh[>6ԛ\4v4b8'PCx6+NϤiov `v7+:.K35]p6~f {Q8e6^m.#-⡑70 bɱ^WCQ[]^&佽-[݃o|ҿQOwJG*&\ZsRÒ2ޓ2O|Ld֩( Qʄ X CZ nH'+PܺNcXCorx{yQ+:(]/=/?7ur>D N٘D&2KN~4Ed%|K/F4ނ薳5lfamFi`xWn6}b}inoї(J,ai x$(ECE?/Hr;leΙ3g.$# J* 4*}d~ U~\ rP&qY*YInag&*U]m@אٵ)r׬mLPԪ\W`iŨh0>:mNUQ)H*4JekFK RkS܂ho?%r5y)ǤnR(lϟPx^ - tS[!%&l+" $ᜄʠU=J7Ff̬Lzm]@7x ]!c Qa9PmIjZ%r 3Su%{lt" Vɓ†J?Rkfn6iy+-%sqjP6CCPWcu+N%{1e[}Tu1#pe2yd /)-v~.ף'ĩ^B?VYWq$ģlH. wb1e£ (⦷] 뤬Ӥ̸Z$'i{"(,9qxRlNNXuƧa3uK3``0,K'Ym$HK30l c3:kqюd.0yՎ:P;iHǩx=dH7X$⓻Em(x[J 48Jg;vv[aM煰CgT_MeEn!*]v_NL/Ϯ#3.cd+pu.>6J2]# GLe^9Z} M,2]uL*ckOXa9 k"ϟ^dq{ֲۗlvSoix|iB_bnBNfv9E ^QbQBZ~Bbrrjqqf^BqjI . J-,,J-RH53PHO5ɨ.SYR S7~) xj0 z vM6v  [ dl2vK?1tmuҷwĭ(X?9\CO{K+1uDI~ TnUR(r1,[sF-7W-S*C )"+c-,+/jt<_'b̍P=pB3Y^naCL,X8uE!(j? >TxmM 0}N  Z XADb;4 ?t7>|) gDZZ.Ru )&$W xA-RW}Gfr\Zi>K3o.9U{`Gul o[@F=ˤ%CW5x}rXv軿bؚi\y,X#Ӟtu@bM"~S~ HUy9$e]@@jmXƪXurY*0$Omky]7ݵc95U˸({G⏥+#l&o2T#!~-$"7b,SL,K\ 5d'MT\ȬSR L#5QE=?"EŝʗA1E2 Rӳ"+# xw"E1+#$"J?͒kʐNx%|z#[WEy9])S4x.:ӎӵk퇑c`:r%^&@ɒ(,e1OBqrTtXN:Md)<(d䓹\ypw 1XL|EdP(f|О zڦ\qfWEf 1rl;;5/A}}!1lƎ?rbW ,/-lA޹E7[7Mnd֝1eU10_? ʨtEL<#k-;*R=`㷈,[:W=_^~]wl@I1A=w&l@dQGu)@} +D • 4ՕwʂD˂ 蘛9 u" )8%TaGONJNC@t1ۚmPhN%%Qf#H"HS=ց9jh,A Ot$ :>HF `71 ҟ^ B:ug:0ҁ*$Ua?jx@cIvŋ9 +!ҳ ###k/8*G)WKPg//˗o޿\.I X}߶z=GqLh*rńv ހx{o쑺Ϭ6/`7}63l:jiN!wu#puÑtBT6'"80=rG&OMVy#E;ڎ.h]r e { hg2"^aJCЭN,ewƶ#rY^8Ąh&'Ij5CUEx*3 !f͙p$Y8"W_jLxM (4K4w=j:Y+!Fcoh1Y50v[qH.Г$_n+[ yI4݈yBI cfs?Ѣͣ W1`bgԠQӹM7p=? mov(2OH>"9}L48 "=V0nFv,Cxdž7Z &:+W Jj jvo%*t!Teo(Š]%A]q&۾tԕ$:^ MOL`j&">.cv3|Ǎ*p/IcM1ZGtNV!=VnJ՞FϝOΧ\v**A@?몠CdI (2 1˛U*ɂy <((cNݣ ڀZS"4ީ)5töfr#fݘ*nR \ 9"(*&|Em$7Vg*T3xCf jC9BR.8!2pd#gMuQ𕢶|s UaM\JSWK8kah:iE^$Bŀ,71=֞^fnޔؗ|:G ݟ|=h -Bz;r8 VA6}ߘ6.vGԦvy^{ʥ`KA5 !:@N2(?0&p`d\cdE&1fO(Öw~9P\Z\N )ZL |[Wxc\劫7NpYmO{_;*X,6:7[9X^%70&#qF>{}u廏W:Z5Y"ՀFO R9 hsl1NDkKQwr{!T6ǕףB5XMv ^BLW{ttK]c(T "}Aߦ1XA‹ 139HVkn#cٓV.EQOT j "Y65ǫOzMm}X?:kvB{'iY} f=RۥeX3Ӊ΋2O,scgK-CUpU7 *Ob^lISpa'~y3{d9r*vĈ߾q4u}ZG>J03 qLbz / JOږyG)ŎI9Cuz*1}bF [; .8] AoN]R;-o0A*JC8A`Z׳}zvޑ692 0Ph݇Fᄓ3:ge\{iS )$PSɐvo쟚'֓jbĊ@A;|r2H!-s=0wU71x#N-h`4W2 ݡM2P24q2 [;L1eYL5+a_5q6T=rm,o؏)XmA \5b+0ff H7ӋKAI%ʿM#}5֜ATNr,wn7XʿIis6%ěN팓bK[݀F^^Es6WSEj` z޺˳}`Sk[r!)S]II )NfbGn,jG9؂ @P)԰A.ČHm*T-V̋Β-u]ƬO4?8ܸQJ4&nDXY,c:8#FOr]iDK`űxNx.*=R!&'eeםWmȎ;mA h^2:y &3)A?.;XT[hM6Ծp3pB’y0=ryR*&w&kMczU,K-ę >tgntw9N}6+Us%sA+rK`Z7vײ)}2p@w'M|هwaA^?>xh2;K(u)y )7 Yz(X$aX\˦7BpG=)ە74%hJiվ2ٯ*u _uKYiN/5r\70m*>=J Xe! W$>I42Z'.qgsBm]^iva%S*@D˜-yRFT(D 3(f2ӲйI୉dS2C9OHsԓ(2Xw|vb]]wZ`%Tqi\QskyUAᚕ 5jIDkיmI+)1/U!SoгoIgD}|vZmI$o|/ 9B/΁UB/0ɋҒ>?]:?yweF; j_K_K imk5f Zw xFI6%.#Y-KnL w^9`1@^pQ3 &*N;Ҹ@I^I,+u@~DJ> VA- $(S(ȗR'0Wk-ultd srVŠV8JA084c#JGr \ITi2 !߶-Ơ̄Hѳg|@9^ /nd^w`<ϒ`M3:\W WOGҸ (ndQl$aFlV"4~9Jv`: h tMVa *J=(b F7!Fk)I|}kIr@5>LHV<wFo4gTnW]Ѹ3O AԭDW>-4jAC9'tW:=\w?Oi @᷆ՎwR8/۹'ӵL<ܗ?gYC sl_#*sLÄqƓLz  M& ^3ayK_c 5Xjߎ .'(Z5A[-'s.kDŽ8J& x]6 ))/'tt :b0uDc^=C5S 17Zm?LR_vuf2f,Thܠ쥞ΑI;2Q]p9D•9id?Z ~TK] [_&P UmqjiAKG" ?L\m*.ut74S0a4؅. "ňcwE=3d675Ђ{}sjO4 <k8)GyxyBz hǁ/ސ]FU!G37Pusu [); ݧ!7S[\knIdo|ٙ2\[SULQOQPvvpL 1h҄NDg =r $6` 'yUʚ%Mz4 1YM"Yc:[P &na/WJN;v >{]榘L` ͻ>;l4@Q%L7go_~|s>`b_&uyR] -YQL5GЛJ{>2e@Xͨin&fEIwa>:QE$(М5@t fDBҨb:gMV [j=`:0E0;a+`j#gjzzx \^M툇r} 78w18C}H]88f|M3cxҳ=B`:w1Q^/__;m,k4|V??NH=bv(/a4(3B@R4(Xz`1=2L SQ9MeMWrVvhJC ت}8GܧN+vE,w +^B'Ru-$[_(YF}HMc|wnzj|b{0g7a֝%ڛلʻq`#h;M#R!*q#-܌_#ɩ&>s+S ٫xc,s"Й)BFr[O R?!"Eh'7#4  w2].i5  p'2{y‚ɁݭP If&L{#w$dOY8y _g256pb%C]u|tTA0\bghcާJ#y+Έ7 n#ATDOVo֍44N7tnO$Â>\x ĴȻ{I[ZlRdJm_kY@Bp_JM#<^զץC"L\~ϯ߿I|矿gƻt匔e*ĭe"nSfF39tR }euGr\}Up{=b%^݊a5PYkj,Ogz+ mmw:ɚa:8v86'՛^[bN~W\|n'_w16 \{ޡR8R^>[O\lsk7^kJŶ7u;8ƕfWq. i@O[0 .p͚tƲZkDm*57|I](SBrZ,J .$UuJ_BD h@FrBxZ;r:OŐsǦ\BD:d֏FF;?g~KN"ˉ |Ҭp~iS zaSѰN{`[bXȾbm- 1g^L]$5Ki] >N*)ϴw)L1e% C;Z?ÉzAyky|K7"ʑp-Tя)Gt?bprlx{pqq :d$)6m0x{pq },ImGx{pq! ,FExrɍF Iy/xd&%gT'drq)**$'f+z9PQa3$#C  +#c+#ɅB1#m!x|q J9X(n9x|qFIJpN0Cm7*[1 ?Lr=7<|M<zh("twxm;ܓiNqMMUL*J,ʜ\/'雟``_`d`h`hjeb`ejy3_'8mIxg-axEJQq%Zj坙XSD-Ǚ]+:F+_!k=C!zq07?-tn鹙6*%LD1?\6wf#u))xDD"'xy!%c1B(gNuqHԬR&dce Hd}ȋbJ 1A^WA Y6ZbSBmZA:d*BL*\DbU2L3%p#yX kvĪݣw r[O:".R]fFКkSύ17ϭ_Eqmsx ZX(jTx14M7mix1kȅ<) mx1q X^):x1qsy,cXA8x1qs,'7 NΑǮ8y7Gd}V#K#CSC+CK+S͆qmx1qa7*]*k2xĸq6-'ORjHxĸ*s*sxk(\3wikQxk(2Aks?GCTifxk(෹@P@;i(x:vk=Gi;xuo%[?kx۟z%iE"ek*x۟&C"k@x۟6jVg]"tkVx۟,bl"tklx۟4pfj >yiBx{5ks*k|A?xn@UEUE(PZ B];·[~K *~ǍNVצ)ހ 8rAkM>5kV%^,n laRI/LnXMC&"f4Mtik\OI'Ã{<6CZ p-91rfa橅QQ8JD<upqcv>R$yU"vOA8U;=A=/P5lJvAO:,+ +jH HH:4?Gp^QV ^z^wdGK԰[#H6>QHZnteSaep?ijijbT.yDfh?LP౐ , 0?hU-jCԧ =t8]tCH ^84NjijV+ 29yװ`#錌@-@n8uTƔBIn y"h2#j.fd;ndZ>F^'~m6lԄed T J^zn\0PG"2>rn҉kk }G]Q3/jf]٧bŐQz2t~6 ޚj0ͨVȵllχs:y;sxAJ@`]n7>@gRAid ;SfA;x1t }ym7VʛǽIKidQKzճ$g1ɣtTbaIXt>@6Uz4oYWjɴϋldxQTZYGu0 =v(Ba- fG=U/OeZ`d9D8d_>c}!aW}Mmigx[gV35Ah{x[c <kx[iG\.!m$x[0YOs;}y#mf'aDkVxk۬2AkwN!9 iSx['ǿy[;wVkx=AwMCk1xphy s ixkj9ThBx``XM SmUx``f.v6 !zg+xk0j[$ h)xm[i kQxŸg 6m!x2 :3+m:xq, J9%?m2x\ J/Mm]x ڛK3"ux3 eXD71IWm x; 0m7x;# 9\ 0kNx;Xb'Dmcx;Y x2[x# J 3O6d'$_Z]_kkh1DiciďZ 61{mAxu J]56mx~U }We1E1x-PN@ @J DBM<=E9y^`-Ғ<9jg*o`aNofW_x2]|/igCVtPB9jxnGgYc.Fx-᱖ v?i$.9XYc+a;s3?`=Oa(S2ε&|G@#+-ړعn՜հSGt+=T|l<^e*JB@Bo lSH?"AWm' <@jq[aFZ ED 31]bz|JfMwx~eIL̆zFX63Mdd2ԛ*?Bt *x~eILƚ ŹrHlfZ jQx~eML3"$k5xj_!~mxs _2 g2Kklxq=2&*zjUxMU"Vnjxq=Iۘ7"mx[}- ?0Z1g2x~DxXo6~_>kXV4BWlY:MZ@Ię"Uu߾#%;M5YU͐l0Qi\H]0)2T bR^d ^& *Cr+Eϩ^٢kJE\v?pŸͳ2^紥*\GhyMyK:z=xxP?Z* "Bs.xh2K\)yka6źPNyzY^V ~ONov8=Ӱ*<~+e."NƗAiuvrRȒƜXQ-)cAɗ`#zIPtb/~+UKe6TGI&*jfЬh׌|ҵ1W>~aIr$'s4ty:T7W hӌ[cՓEx@@oalh9)Iؒz4 \}.%Kzc&kt8vphQMVGBWxH0k@@c5Jr\Pa$InN6i<^UlPP Mnzp'{ij8.u%NBk.QaM^2w 8C?9rz~z{DlUQ3-纼M 5p~x-$P.`0)zrFmȅ{wVV5+jJ`hW-p!NΒ"Z#@dX7 ;P bUBKݞvWYHYb;nr !N6ҚcIܜqw25%#hI7ڛ@P  XVʍELj܋WF(u7jZ"E:k XJK.RZN\oLgL $0SzYwM0axVµt]wߡ U>{.zZ=y01W?__U|Wq-o<|?Mƥ %K^{:GshL=c'J't~LAvwXDڝ7>^}Jǣp]yK[N ՏLn c=\ām.8A[_,32DaxNז:'_PhRY?GQO&wq=Aq w_\mpБr&6 {&{77 ydP[$?wixk>8_z^~nnAvnI~~{6 'o /xA''q\ o-common (>= 3.16/17.10.20170922? SlOx;>W}v/8q&fx;~Wm;f S{6x;~Wy;f &{8's)m|8I S+x;~Oy;f &{8&rlqm2fI{ ^x*'##AƳg "B>,gllx^yfs0Oxf҂bɁL13oafC /lTxMiG<\$: jx|[i]&Vs=#=&Mdؼ#kN~zf歬6yطCgcQ%YRXå8:e M L M lC]ҤҼR_96qbln2y m?yk9. lVx{t\i>ͷ;y(+xRiC)^vFfc=͆\ZW"{lLxtXiC)^s$.cxԧAms8^s8>Ux[\i]&fCSɊ,b3]earL&_dc24]l=+ @l4x[Pie7Y#gxSS0IpC&XxCixSza Lbױ\cMqyv9Nc=CM%8R l8x{]f ,65Nx{IqR2윛p8jx{xIq/& NϜ2_|Ɠ" a x{[z ,6U좛o`V;;x{Wz ,6U͜l8?x+JjCB 9@:x+}_jCBg,,FzF&8b78) xVn6}W[wQt7W,q [)idqCI9Q?(/tH9lbgS/m:<3gfy ,eK;f Ř350frpƒ5i¤s?WL614a” l;Qwz 7  kTfG =OjUzG7cY-M ӜK0χr ZJ/i1Yٸ=AI9?gI ] 3*s<򲄄AYV@g0߾].CلM!XURDҷ率[ ov9"[m u'En^ES b?(SdcXR pMȴPf'u "w)>3x˜*ǣڗ*Cƺ)' c62E)J:TmX|$u"-*B}3^A3iYSKs }댔e\W4z]]4w{z,r!2`d4$h=mP)VNSa r?~7/=/-{z{BsCԃ >|4pСM0쳁a.8q3U }m;ƅ>D)vqgްN5۴nf0L1c5'5 +l \Xmrà==' ǭ)K$+]@eE*JJP(gVshy:G>W44*$݀A_^$g-Mž;_9w T1S+TӋf ٍ36)ʓ{Kd\il+ ̺5jĎ78g&"uqkT~s mHr n'y#SQi Ireq4ԁP,c7YP{Owtl6xZ6:LƃpM=s95E. U@{UAu$߈b!ia?^_o/HQ xpQA; ;M*2:7Sw-: Eܦջqc"h`rX4@EOzarހ.!'ƽ7Z6]Fm ^AǙ \* kPpVnDR՟"7yamSFe55B#y㒉5t6%Bx@:3q>J>{ǀc$u7BLpdHii7@ݬCUv">e 9莳n"Qv*M[{[{"4B<d:JO3aTNe$hw+{PehK$ghM(?VT8 5C,o),ԒI %ز4I/> t~zqЮKSB5b\a|7oQm4B ?WL-*6{޵WK'vn#\E8(MP0' t^i4Ւ=M:I콥 m#k@#QJNֻ3Z*|{Nεwq]Hk LVIT#>NČ'>ŮT\$Pp_A*2)}EDtp>ǟ1ey>bwrG!q[u+8kXRO\pp||9m: k=J&qidX/B&S!.qzlr~5-秳ɏ(e0ϞF׋`|.=M e9ME.L SɤahD.'s%T|~uR0viAJHeVI_D yJ5+HR4ăp'C|i^.ms`*rtnN;,'e @J`H ^@ aƥbRql,pdԤ1JT!ROIq#b[byq5]LGHk?vW ,l:fB盿-!i'guL=:d ‹.u@hFyҰnM^mJ P ُhR"gbCUx2u4T6QPDz~+ sZs&4Kް H "x=3$$??xbP{nx^njQQ~mf^r~nAbIfRNnA~f^IjnIeAj1܂]ƃ," vx;ϳkC{f^qIbN@͇{r"#x[s##n^nbrd+dlFx[5kL+4x337xSێ0 }nj:2}Cyc ["JRŮ:M,89>=>0xZzIwuK7GO#۞<7؂6fo]U6y |DDc;oM R7O[wO)Tӌ ^>K D;z@14gc|q0q2-?m O+p#UC:x m_&_H@LR?3S~NvXP P9˹4Us-'9O*T%uG ~AWZ޵PhOO[AtIsIsp)Z*u?"m1xmtv1-$x+-.K)MI*s2 ӓ2ӑĀdi^fInqjIIf^znJbjn~^q>SxKIML/-./H,JOL/NHM,n "xK0 J!*X`v}i' ]=F ]U_3("uAO6s Ln]ā {*X_P a h0xƴq>F.x}10 wB@gc~?k"%5+"Mz$k[r%֌U2pÍPQɚL;t*I6Q,uWie艏q<,zEHv :H? |a5w0 ?}hn x4im̒ʉL)e"x4!Y˻xA0=L5+X3C;ԉMin qkKGw#OT*ԲUg)#.K"~B"Nal7W|̐SW镄:aoS䂇zvԒ`9ZO4߷Ժx+N.,()--NL/J, 3x1O0w#aa&K7D$18%#RT - dYg{w:T$$~{yj`K?&unTk"Av:~ N[?N&(D92Aʢ|*VdG|oJ.$K3r:4Nuk3~ .UtmxvI-./Pp+) ,Hu,(LN,KM ,TN-)K/VpILJV&d&闂C覀`LIIͳ-)*MR0NxmP]K0|ϯYBr׃mڠݔ|hyd2\muaȢ%lX/{͍C^RgX2X\w[;2H\ lP6ݕzDTCjlDm4l:Z8r.~~䛾; GKr}_<=C3fGTrow7jX즹7\1wY'e=^ /2 sxb4h $ĔCAOa' Fut7yҞx[qB_pɌN ;x[qB_pmiRi^IɌNt ex[|i>h%```O?%[ҤҼR%XjkԊkabx%˽ ݧC z1mF8\l6j숞<NJE{0y4+|zHeśR; W xm10 wyA2!RH*A{ҲnFȴ*6"hxU˒0+( &T^} b,D#]J|X_(=3SE'rJTUXZۤu]wb҂͗%Kl"2/.R.(`Idx WsA!Ȫ鍦`̅h*ZnW]| tR3j u(2}BmHj[܃%c VohXK kr?8OSwZYi^yM ܭ bfj#Vh/f Yt|oE,K wUCJndkE jh@/'xX[6~_ajҊdV:0͢%$e[j:\" 3`H7Oɹ|qi;ao;]7s}D kn5.{%Eԝh|کd8 j㭾b\5 Y;v@#2>?G_dG?:oy4>apYnAgNq4a7 ?b;$kV}0u>WwV7&h\Yz86*? nT?% vϳrz>& l5 Yl֠ݨ' $Yo %iGG6O[.כb.4Kr\vU4|G*.:%JATJ^+N=Ǻխ,=eGOqÔNInoJd$"Z]n@8Ƶ5gCmc]8IL풺EMZzqMɒ,G1%ק:QY:I9AQW5(zI뎤7'ADчv[vFs2^UA%w56mo <DZQ {S2v_OުOԚz! !mѯoK$U[x$H^Pxq7k[6(&_v L_zM QB:޼y0@ e`^Bg1D"RC637~S$P,-I.O~aMM9}gAgK8?t #WEZ㹱;I>2n1nx-Mf IsS ݪom۞+K}²vlņѦ'wUpu7xrmwx+d9HLK_Q)˷[+>yVYR=&m.),tZj=ȉK~_w|޹c0RdI쩥e"S֩6btm ]x폶%ϗBk$ )9=HrA%0OY=0 5aB FPsF&E$sr10\0XK. 321)hw{b2hy 7¤jm bN0=Tg",gb) ' ˅&l(,U,m,:A,lmP3ĜKĤTgL&^iuӊ6%eM6fZHY%z,VHuzLPs%cAe%C\g3ۼKe0"ʪvԩ#0b9.X]),g$ÒF9E zTn* !M ]Nk'pe0#h;S|o 'W!F㿁_<Nawq9\{jޅ"n8>K4ϝޅ{tg^$. NNWdb#D=,@O}@(W|3ot0` \ y5v hLtx=9k ( V]$}44&>:_{[VxS,-PP[@-zuD##ܔh*S9ZpָXKb-BO?NĢ4dL̎b<ħ5m{%3=-vE96}G$E텎Wru(bOۍ$-MceNP;!=1nNsebm5n$ْ:+/p#tܲ  -*"o-LX;Z ng2zRa/Z"vsWj] OviiE(qT lϤ T킪 x Z*%u5:g~=182 ao dq{8܁%Ame+i<#o4gy럪^{H9. S6x֨x`^hEU O߭CeZV;Em=9k77n}j85|qg61ݩSx%HzC\%lyś͹W1M?YS{T|$eajZs)Az|ZQj\,ZZRZj@"x[msHl~Ŭ*1;`$u@: .ɥJHR' nuόdgv4th߾7>ICQȄZDsGo p<8OOdnH:YoILWNBR?o+b Ґ8)SI,m!\:kЦp*8uDQ5q vG moS"sP{l.<| .kP:x_Lk'rPbBc[ 1`[']#቞%mp`{fll]L ɗz=Z#9~cSfv Ae 6mu1D[J+T8ԃ!1$}2!d3C,22ULǃO)h~v~X'_vFb;tG?QNS2 v}3Ь.=m|xFڵ6٘hZxv?iCm@y0.Nf;!7JytԿf'DC+72[0d2%LӰϡaW^10LW|c3rL{9#TrB7GvO4C21J@%S} S6|d<DX'a>8?|ttJU&iXYP_8@CG?> aa7yET=뭒3.UH]+׍ tcNMjD)D`YeP9 i}+$G17[ur\(0:UQlrۿut~R`0ktL['מ넞KqG'ak1k- G\F[z7R)sC$SμNuҮ^%JF,ƟyqZ'gϨ(Pᜫz_T"~s.Y{𔵨miɚDWJM5r baWYi**ko% GyW9H9f>cp§`Z.cʪgz ˢKcKVYȼ}@Wz~SK}8 Oα2 y OdFGDr\f+ ivmƅF ?eLdMn[Z2bIzucB9it ,29[䝌_Y'; 63N!YŞw<' w䚥j spr7%/ֆC=ESsb)2!:R̛ j8œ+]%O[,E2Ôjjdbο)yK ŋ28|>֞?{ \QHB|OrUw[DeYh{zkLP<tY /\9 JVkNHbHjk( X{ꇄnC`GO"\eP|FPL>L쀅7f1//y;wCf]Ūklh5}~ 0u!V5D_(ډ(:| sH?qRV’c)E ek(aW?P*"dEe!''ی`+P/u}V44u'fb7 B훈QߦPNQ?DzhaOhf˰?ױ㑎_IԌTqk`0vm~ ޷L^_M(%G͵ǎ8M^U~"ce_@# 5'^UaMS eY eA9b=}"BEl(x<7Էo)B%Vұ<(2$V"ݧUA"Z"U}̇"슭;d[:|aƆzU:0Nx20%z}9/<?,,imsWJv):u0^':*;L3;BYFbpFًma&׺R5>-_FܳPs!I<8Jτ[,[FD%/BH22+طe.]SL|X%gE(vJrŇ;eϬ%ju??s^ctg f4& G+Sx0-X;w`NQ#J\_7QSzȋܘO 5K7V.K6VE:tJOl^P265n7,r^2ȜaӁT覀ę3ctO!U%8t>(H.z#] w|M}@X \LYV@UWiISӰ"mDUl,Z]W:S'XFa1xW[o8~t OdzX'N DYHz,N&ύ~ϟy|'kYߦ\ch?%mhљ%k|2D&Ĥ32}c21/b#%BAtFMi ݐPğRrdoarr}8|p8 ŒܗGGLhFBm%SX;ΙeUBfK1"Ȏ)=ϲRjC"k"|@=BӲ^~1©楐 _x #fI o6xX|/qbJ`َUx^da +nʟGk_/K2&ڿ~aygk]9]'K4f&>#­f41=b|%C!NHIuv&Zc9W0OEq$CUC 9CVĨOp,R9WRq7&^bHV%"BB_^ŀ 8do >ğ`v`Rhfst@"Ȑ;)OEd\B_E.@7 hǠHOiOh: `Q'xU !Ң.|g &tY`#'\<b,peq #eUie z~n|q Ѧ o*1!y_FSCS,~͂u^qo*nkeCO.l/%aK$jP98dAþnXp`M su"n=D(r /&?{\f >>5 $H>,i#:9 ٙ 3qLHL_(uʅ 듹b4P4<ѓLwU&FS Ŵ9! cuJ4EFPVЧ}ȼ |>KMjuT(Y7HǷ'݀^-6 Mcom/ڧW =${hZCSڰ唚6Rּ*_a ^r!6&2ɪdf)^BP:s E+:+J#!v3cI3؟#"~RNb#$YUXkd5sI< ocItm~]dT$[==֒4cEw=o&Wq"\R"C^AȊQg[hg#}-P:Ն]ÃEMoDv%xH.(ph|b^N2}V]hkSٳ}b䬅E*KX% s:@:1?nyg9x{Nn? ưFxa@?7x'+r)Ѫ$dLҘUYOk$gw&{ׂ1U=`?V@65CoN)6@gWeir#xh=j,n>?ze^ ]q~yR195 츹cjH]V懶T i% Z؀F 48r@S!2YMq4أ,g@oڝg'9 YF²$98PAnu5ݲ#jaؿ,x'vb${<ȺFF*wu!8QHΖx8ˀm8J{zAͶLf_Z4a:\I.FQ:& FO1B8IcOɰ$dgiK<Ƃ_b TbO䞵 M<j'|$߃mŪʯm#jNz%5>ό,?m.}{{aם *An޻qu&1]p5)h~5:)}z4/M9䋛rDkmUv*WkFp'-6~vktxuAn0ET>o$" ]8]1Q(BmoQ U;khnM#Lj_nB_M3X3al Mj=^3M%$2u4k\d3&XR"Z|Xy&"')ygh[XM+P療;FYVٕK&m= GhK'dCPx͎vq/\k ʤ|L܂;K֖ zxuAN0ElOa VDe=Jk(TEG(iEn/} WxukXjxb) 1m27l,IH䂗ԧ+iX^!zI"bXxJ=>$O͉Eև=a];o b C9Ws3w=V},gM4GH릪d5+"ɪOix{q}|,e)\G`x;ks㸑+zZJg7qFydGo3J(C : $H䝤r F7eoa<^<7޽. FxڎNtg3ZM: t?fj4O}H*c×DRQ>1tV:.A!8FmWxj 0C`3 EZjC,ܐK/qny,H@s|z:^>?GOp@lq]d#oKB#df VM ~>Bj|쯀E&BxwAҿj[-D ĉJ:I\C;"`K1gl;;5K+_j y`~Zsŧ920C.N #] o pN6OKC zO;ؘc ykB!tJn،\}0dGo4u6<{b~(< X1Ġ1MgV"mI)+`l}Lp'I22!=h_G8>q2^q{!%K.ap{[RRCdⳣ*jEG {1=!P/ ~p%ޓ׽qDg[5`aC?VC Ab Q>bG*.`+#a|oI,Tn5 Hʎ~4EYi|',FFqzTs[9!E֖ 쵏eiF&IlלLQsI9R+T1HMDsp:!K  v}ܑ[X 0K׬/1ogW!%:``$-,0@jW;{q%6Wj=]ILm6"ƪ@v -M!9fң|)2`pq/vXz7PE+ tMI/K3'WWDw tAJnAF])[" zi-L£ cglw:D=/䝽WIfشˀ/z *f"8\zN}c2V{^}r. H>H ZBӇ7B"ѽ\IR@HWR,XI}Hk2`bxAYo,V?&w}H'Lu?Z:$H5?[=;P;QPIx%.'F/ݙDqE3- ,PoFCŬ庅gK cM[Hq !A%R-b<۠nI#2@nCfoyb6M&4 cjg2 12T)ՑZEpXn}g`] 2`J`bx%R'rqU[b .+fv;Vʚ-dJI l'j(s#i06I_#qD`z ^^i1րK}Z"O~\#z@~7}ĉĚ_W BCXή e92%Ihb1Ǡߤ{f>BüSY.}jNJ$?X;4K_8OW1\@;祘"#b.jG!}J[Rr229 CTRMޮ.L/ jݣ}c^.R.os+n<]}id*ظ]- "]&3W*"k*yJ+]w BT't}ՓK6MB, Ү?Y,ԚN@zLnd5cJ-؉3V|ջϮ \!Kӄ52Te|i4?FiZ43Ek9v-JJguB= T;m:єVwGlt,}[Jjc??^ @/ku~W#i5ꧪR C[pG؃QCy_mԅEN F <'>܋ENf$Ge O^V54,VkS$ TrkXhηgpV~,TA(çw km~(;;ST{F(1s~N EO\jƷdI*2#8hM.1)L:vD#H9s5.K~) خK;oԒOY. ^ą@mNWvP AS&-XqTyps*-=к= +k%l߼shbbDT4H$VIM1Z;VP)zj\79OCENZ{]V.S׋RYgŗp; NxqKtXm "$x̸b KPJjZf^kkw@|hk|_pkc'rf^rNiJMNfRz^~nnJjqvI~>WWRa5ٖEaK 2$6?gbb+.)*M.PGtv6F.րϔ_87rv3n>-K <#|]r+RS3KsR KSKSJ2SJ JJ2sT]b Z yy%y e9I9zzz& 3Zo^+"ȡS8yܛOv};QG|0`LV,hffw3VYpNx[Z| ,rXJD3sJSRҋSt t3S7c9T2"4 wxV[6~ϯ8Ҿ"0Z5dP!$tSd 6 8ܶ\ZHwKܵn0}n4=3ʵ^T("Ո4Xn%nDfC R* |(HFmTSb.1I{+H I3d4 ([Ãk+T.A4 "&~0rQx5+Y R(tmVTA3U%8.t6ahmYmӆ~b(KR!Z6< tC۵?a9,˱ sH?zN"7 rd&C'p|Z8DR‡yfES)>Z~\(0x.UpBBxfNNfbW~osb^Mnr2v(KM)RRp/,L(QpT0204PJMQH,QKؖP`QRR`_^^W_WZo4 3RR݃]ܼ=}|&W3KAKݔ x_G?Gw H/N/J|2LG) Bļ"MM.ey H־aĩsr8̊6V;5ThzC͜fW%64yƔP ` (F#Bu-NE 4=@N9'TBSEd=.-T{͛@&x./:!Q\!<3''31W+?O791/O&79H;deꥦnl}$46S؄9'dǒNs!OO-/,HU(LѴ—p;yy 5/=i]);|+.I,*o?T@N9'TOR Z\] yx!8MhC63shPfIM Œustw RҢ_`:YMQu(8&%ijr)e*b%9'Mg0VV;5Tp*MgVƫ0$NGMbSCq_@QfYbI*HuJ kZ$\٠Lvm6hk*S]f 3GL.PO Z\(N5ax!8EtC63ckdfIdn))٩œ0+!fqtԭ^ 㛘Zɥ[" qI,.F330VV;=LjIg&IaVB,Ŧ̲ĒTTlj\:98,?3E[Z *IL-EY|AQjqqj!nJy% E# r2K2t&+rk)`U4[i |h)&]v;\vEt*h)TmR1yaw!Ҽ~ rr89C]oX/j8 M\qK`o> %Ux&4YxC63{BfIdf7-75H4ҋSӋKR&`VB֭舩[G8 71/1=HSK9%5-3/U=%ɔi,MEjV;=LMhx#SjMP KDKMI óEe%hJ"ؤ\f\H!ήaZ m`wD]P99'WrXEEC L{(hsw'Lx&UxBs~AeQfzFBPfrFbQGizFjMg%nl{39YD1{:9)FzqJ|r~o̪ r,. u܋Ss|S45SR2R܃]❁z8`3"L>VGEdy4#<QRrE!2AAA/υ">+,M,VZURY N4fp (dQ'@K6/qI,.J+Y u4=}\]j:CN6dr*:{ Q8=qMIUu. 󿲫(N;a"N-}.OFx&CpC63hBfI(k)ũ0+A+8(Qp/NMKLO-RNIMKUpvhb+C7,rPXTPT 5ZBK8-fSAvu@QfYbI*BA6[$+uMz ekB&]S -h!Bo#TwvErmPU0(P<)%x&tAxBs~AeQfzFBPjGbg^'LA~!!~ %Qt~A 0^_WX7 ,.X Qp/NGMKLO-RNIMKUpvG6h2M~"V;,l FZ&dXr62KRgEr#OI_ص##]S 2-hvGQhC_Ł*PK{(hs29x&4MhC63kDf)(] ustw RļߙYLP(D&%ijr)e*C4NeqkyL XjW%DEVGj)ˢ8=(,$"-:&ebsLuX!!Ʈ%b4 YvJ#T'{(hs)Ex,TxC6adkcKkPrJjZf^B|{K<әjSDCʤĢ,<(8y`5DG8(S њ⛘Z wdsNbq1Zڣ: ?6PxUr<6eM,n (,K,IEW-/.·cwCD!v-U,)haDH%[8'CU'BON#i)NAK 0 >$Hx,|A`BOj^^bQB@~jIIjQf^MD̡.Z)cBfY`P?x_G?Gwנx..̼ҔT$ ɋeP)FzqJ|bX&(Qp/N /KMKLO-RNIMKUpvHYAC#[S,ňJ` 'jY r@r =- $\fS@vB@QfYbI*Dr3HAbQj^5[` 1vy& م;$[sqT* [,?3ES=/9/8 Z` \P|^jD5WzR~~NjbPj]!jZT4Q+D51Odr0Z+hs~x{*AhC6gcKkPrJjZf^B|{K$[dmVe-X! V aϼYl (,K,Iyfx+@E^av' q+)`^n-38 csw-*/lLJN4' Z\aMqx{*|IhC6fӘ&dâ5ٚs2?wjeR~bQob^bzj&rJjZf^{#,n ULa꒞Ǫ=y䣬@Z~!\j61)42KL~̖8ك]yr>/P1!R8ĥѴ(h)@@:P'rJLZT_4ـSr 'HryN1~J5x*KxBƣX]'b0N0˃A~A 0^__:YE8I E{qJHZq"hR'*Qgjaf7VE<19?wT,Qp@UXlpMKLO-rI,.Ԅdg0 ٬vP97YP#N,aSA3(,$[*6Z@5W-Be++u](5u+h)@@zqJe$Nq8ꑳn 3YTQ?97MJ|<6Ki2HpW5W)$SUb%Q/xJ,ohs28 xM4]]Ur8TJf&.!YxK@RC',P\1C'㍝DExoPǣF} ,MO)Ov 3&Rl͵Fr۴2 &}7M+|siO~>}wj{."O`>h1Kȱ:5ʠCBVU`xXށsUUjS4<9`}!QۭKcGo4/DdU,Qd5#Fyd^[tTKRj!y5t/0wf(pd##ĵ- ~.=935(,99,Z_ZU/^|G[B̩PFJӨQ%"T7\RޘMt幾`5b"ɍN T8ؗ/6-.Ϭ,ӹiLt2=vȞO".z3^ )UX a[$0XVЋp8UN.(_rN(\ j1X(asqDLP$_G市-+ Nz<8pp"GH*8M0;hץ XG e:60&nǯɴq'% a3q/%wڟk a6c`[k\!Ha33x=*#85;5 3/},Qp/N@ꛘZɥb_[U̚* XQ߱J HYG@Xٕ/(,$Cy,T+xmfhXQZ`S;dřz۞28Ne1W2K3eMl  ustw R҂Ē,0 ,NhZt܋SB*}S45SR2R܃]zk)hhdkEC"\q59Ua 0[ViS!*cNbsc2 <2ˀ\$51ƒEy%\0A^`a2C'$[sb3D= U%% IMxwPxgFt#K-`͕վĢ ,BU̵(( fд$&pE@><{'x-PxC3{Kafy8ٝ pga/NO44YPI Ya|kH{pk{q#H[4\|V'YzCd+Pg0bʨfEV3CV6GRfar׳qֳO&$7YƵ`E2G= uCvatDxJ) FY~f5T[pjIIf^zob^bzjLc|1T&>"Z7fn%E% @8؅'ȭ 7g: 6䠁 Z\tPx-IxC.3c\fe 99H>`V`Ģdx6q Ǣ$JO> ^*V+=ٟUȪaUt$j6 k={^~n*7(Dt&;?eQ SpC= uCv8@nR@Mk..9. Ԓ̼ļԢr^\rb*+.I,*Q@P8&`KdƊ2XTJLNVv sustw PXBmƵxWmoFίA;M$7)j+kf+뤴 K.<3/^jШ5`$:-Pdx`Z_Zx@jbX%IaP5l%V N4S"b#E̚+FH5PR [O8HDILJH@.,j\K\' B/O9$iCSP x^IV4=an9@O 0QLPLgX:A4s bHw 1Q{3 PthcXRHq]C1|& ;ܞcj%p 71CdKH_#'ti ;Л̠ t t2^̩E5W$MPƀ*$ 8`{Fy:yĂG&L4 a(QNvg_ݯR4&>sjoF"QxԆuX:JG8 (\,\]#.ִL'1=-Wo+Ѐ5 [$IFRyʷ_yE ŕgP_G; c0(};+kZ̖ma_i6DZV(ck: g4r Ne}c7w=n2BL <.Oo4vZ,,.1%r׋ %-§yf_ -{B|ڻ\GҤP6޼뺃qn'y]8Cn: [[xTcStCC)x1Va9$*%N1Z Rɡλ{W5(Ikz)bk3qfpKQEm4b;XAq~'Xcċ<Ej s} Qnyݱs ou(KvF*O:9sjE^ s F,Eg#UJhQú?YMq0c'2s3ӑhcF% {a7T_*6D+:w=g/Që h4ݝ򮄟K%d]Ewb0'L$Q9פ}on:6/^g gg2ֲSRf*m[NJ+y@}ts {<[EAɢ=1se+ZjֱxUQo8~ϯi_Z]9)"A+"LJ|}3cvdžL>h7<#.R&e{Ole 5y :W - Wad)aݢ+XU2oV!ް 5$L@)WZ#p L³![M$+j@ff`+V¤^]ŽJa`x嗷Ix4L,frˢ{("T &f. A,z{."!n_Q"&W;pn%BZVF2 X,3As:m6tf0F }p)<liPcx :n_Bu(+ۀ{C|WA/{'[GPn s,ǷRqJAT ye8m,]Zt )HJō gHxk✐h1a@kk{G|E,<6$f:@<&<؁Zt{ }. %FGhL霚5/Kߐ(Mc0b6s7;7z4#;E4~{4b@Sb'ܯ=qMv2۰T7b(K潮񣫡᤿Xjhڟ0^Y@й:fغ﷩rڮ!h(tY Ol;١p__Cr8Fz3 |ex{: McnY9uf7NRᒯ糛vz+jQcrBͮf%%ffG;O)l:=Jd)pPI:xKZr4H Ϥvřp!]4߈)W\eK= ϑd'eKvfHrD<qIzR H{y4zEA}Sl+@ a|v]ֶ1{?R!*K} *_Ҟ%(r{O) @Qv0PUIdlfƊ)7@cBuɺOLz-kWZ*4i.'p*dhe++L”PLkÏx"\ϥԽ9Xn5fSTo +bsa7 Vv, rs qKFBggW mi*a#'\NUȘ֖lo/XNYBcM"ewryLbߢhDKhuē(իjHY?}OZ%)Om]N8'U_()./ej)S|Bl :%rRh(MO&+,G=P,G#$JeTNc.:̚M=deRnX͓H$٧`1F y:R6xI$#p}\D# "(:R&qW]J*%S+G(ղTMӪ%іh V`^$ H%ȱ]D%|{nGL_=ee[A<ۤ L_u7UA++OCʭZ*+0ŗxNRF|<qln8:鲒^nW_ҵcNi\^ ZL35cҨ6+`mR.azNc8JmveX):BZ1# vai_x[>q҅ˡ~34%Gl_>V yt3b4B ̧֧ԯN2M!2IhU0*(%ϨL[`T&jVtGڠ?!1HӕT}Ơ9鑽DYﲎ1^(DULm{pنËT^/GmX!2bJs hu0$U}q©7S .k D[j>r\-֎iyMqnOr\E>g}gB՗!KmiWkrtǣTG+s2KnvƩC6By!"+b؋IRFh7d gbo+cϳHL?lkXҳ6dS[KƺyZ>1QʃWef0Qk;Eӗuzkm3b&#RJ$+5VpJ}~9mOlPt?˗ a)u*am,~|l(+g\Q,-ӍO[^?Vyxe$&vQi?U24D\}$Dq}S (j$,|I"f]S&%|.ȗet|@)2]${b T&%X$L[qڧ((\=HRS`5kjlXgJ8d=o*-ϯ]Q}OO*)4[?fQ54;IĶFZ]PPKmh|P-2yF$DW OJ?"SxOVY&fS<N2T]0sH:2PGk,?m?<ijaE$M& >f߱"/XWqS T0%x&WG mQ)jE*]JVx;ʸnɧ9'gqm6j6R^x˱3kn~iq3B BzqJϼ%6`/L+I,ϛb (#)3x;1cBi)%œX B!lx&xxx;̱c+f_ A,x& 5x[o8)@ЫV;;VJ34ECQ\Nwlqi.6VDΊ%: x\whPu gyN*wD*diX%eNn?x u<)XH1k*ATB]X␃Ą)-YTh!ɕ@ZX6+H!hs"-_\(E,FBrmFTFʢcV< ^C2Dn>*`4Fr ba5IP eBI/ٙXPD!)s i [M}͞L%c %nPl).r&ԛ8ľ3}% >7.I\-I3=W*|KR9_XKrJW+[GRejä3Mnϯ\oCz~vgRõLMJ'mccɖtbmQWسc}!}Z!LA7 -,KNX]S69_NŽT]OikMp :33cށs\ eшW,2#<#c}ބaZr?ȑ.S5oUwP~z馋QχK$||Q#4b풞 OPŒ7޳S𰠻T|bU7txG่ l- ^/{է-UgwKuk.J )>x# !sf~.cI6?~xZ[oH~^~)Ѯ0ܪ1Mشeklde= 66CkUŗ\ozI@jӧGjjfM|5AZ-0SݣFә<°%Ǩ@䬞\:_0I\_6W0ˁ>f!>Pˢ96 Imx4 ?% Rԃ]l3{]҂'.1\:@3Ξ8L؂#gn:Tc3qHkK1^={2 i^*A'Y7x͋0QDnYrBg3д`ؗ5EVhޤhwV9&m6,$fniә~";]\?`/+F}۲SB|~%6vDC`Ԟ{iiEj̠P=! Jw(8QTZмQ~ )>@]JhROT?yBHUUB e5*r֑H`lf,omY$2﹞)3 V6kUv")nsVe>*%AR5=q_ F3YmEf*5I\H+TdIC^{'8yo&62Tw~8utvAYlgQI[Q*V9 ʼn{ën.c݀Ehͱ 8]((j#gy6>V1H!F6B?f>u$*u[7u ~tN K^ !Hbb;X^{րr<[:J-ͣb@?lOz&=U,R&#oJLWh2%mw k{ۮU)n Xp9 r'`I0i=kXQDύpMt`92)uq]xdh^2Bt4U&̙eGF7 9.Rj'I&1[M&7m8zr g`ǣMP7#z x.γtsFgLB#[Lz=bp`W,+T#'wiw@4`{fv$Do HWay$? mB$c8њoHHJxNm(RLh^' y$ŏo-FRu$ #}XO3toM<CW/jUQǸާcU،% fˍ/w >k ܼ];V BTtSr%j@ e'FZp[ u:h.FRKj+?d cPцHBΪ~h/`(ZF &erEP j7Pͼ@)!#n-LUlfy-lU{3LޔY!س Q7MmƄn:cJA*'6V%uKBxQkP)u+M':]e{k[B.Ys^܄ܛ@/L` >_P|П?ney psf|ub/=A;o2t@|>|?+!@9qAI@uJO3_3*T ǰS+a~Qe Pl!eo5[<@=u #\/v09 >09.^Zm(Jh'Vi$ՄbH֛^>eb9hLF.o4]yZ ~VB^P@<[/C1/t94º+54=k^Q~#˺O$JDY2;u'..W bq"rd kxsS^W.:7V O]y7JnS ⩪R׫yZK}(%hx3cƁ} ØM*yC,o>WS:V(G_7yxJ@*YYЕ(IBu,JZI !&c[3V y |.q;"Mq630s%>hiYF6A(n6aש\M)jY `A., !w{ ~$YB70f&5$ XE/?"xt%_9PtLQױ aREVT1BGl$Fi6 B<ؔ!uGWq$ް$XνM/D7oR!x}vFST8cR!)ɱX%ZaGېTbOwHIH n326O2w @$|=ukhEH$u{H'֜HZC7Gpha`ՋcquMq?Vh`OӚO*OV o ]?)u9taCϜӽ/O:fCDJuc;FFM'?u_ 8U:a$@/ljn$w.GϞXK"%?cC `o1TIz s+M P^Z# ;w(}B tmLd.'٬ *a|{ ڣo?YuTj˯=xzv $nF.XQBm>9x{,] eo=lO A:]i_$Z}%}G80pG1̝7pq.=&@'D߾~oD`Xs;,8c =bFU~/qҶ[ nCt%oJ|It=/HK.ozWIj^"%_FS|?w ,8-q|Ag1ӱƻW#LaK  @{lCY8衡XWc~ 0%p3 vkt-V ShH`$Z  -ĉ\`pBB*!-8 &;л(+ !:;k³(BrIw4U4  IHTЈB~\\"!# "H2y#U0@JB=B1 ƴ4>j;Rb`A|/)$wt L *sg*nb5G,A;zi:͖rF>JfrС>L ݁Y{*d 1zb\i4:.(ͰbmP"e*}N0܁iH@ƎψPzr1 W4yB7 y01 PQL,B?Ҁ^ɪ ˈCr>qbŌ)V#cNfn+j$h9%.`qP2V8x!G=J3`۸H|Dl瘈alMڝXqQq g(C! J tࣹ uhOП0W H#3>VD;< !x滏//_BWMEy$&q[īW/[^y)`;(xRaV$A/<5=kن1P8_1ʑPkNp*@ z,`fTX/yid<$C Hl ̌<0}\ڈDz) sH3!|e\PAftA>p#(ԓ>^#di%Hȕc\58D2x:Qn#J& `u8@`BF G@! Ml?EĚ*KU`,( Pģ' WV0.'؈/9y-@=ļH pdCtq=Fq94YbWsDC8Bq#aH=E݁I!2#jtT]VڷB 8*h0Іi9a&0eHt/1+Ú.?fHT85Ζ9]b}Dn|m^G0V XSH d"L]s%s$+tsxu+B1F0†҅FFsV)󈐀p1Kp+ F`<,(PD >*>(@tUR)5R}"@9䁐Iea;6L{q0TÁid9DwM ג^D 2|4rKܜ {T^渕epSPEM &. v]XHn x?!\YP`en0h; jЂcV&M%H i2ܢvIgSe MI v-pƼItR#JC zߢ|-g8 )@F#:=eI0EsP> "eHM@na d99;sڀszfХ Z,OD8]DޮR(b!CWxDԧE4JXȑ8MG54Yq&*}̥2KZT#cgsPdوݭZ;`Q aD')4y[op'gV/oG꫆!Sfx_ɺ&gwgԋιUOTȧ9,޿~{ ߭^2_Ln7 ">qF*n=#Om?[P9'QTCj́NEEF-6c3:K F 6s5 6LL)_@8|?dYPX-g:lI8bPpPr5|OұrZq;pi?_x>|>C,!Ѕ~V$#hb ?fq 2K[|l8$PBSJ}M*d.Ai"Te$<(-TlD0Z*=ϝ0rI,x.#n.O%kdlgt4rT ןO 5Ew/ cT>5Sv'[K{qQ*xQ[eDUpY Ęf+g (4c"^ϷTZ}8ԑ), |b>o-˛ ɰE~bǭsUO.Gc̫Bm܂sWP и|򣅓%8>v.>qGI]FA /.`ԚzPz^Nt.PUґvϸuz}&Ҟg3;Uk= oЁqI\c ]zT_tw"\&ٵZF,v%Sg>oc5_A*$&1+On^~(A)2tT*6_Ifn&JQI̤:T` ]Dz9ŬD[f@~%kp :bAYn;oFYԎFPWeؒkQC͑}/u.l2mU)a>WX52p8TʪjhT(Úh)<< UzTth~xZ\%-CKK*dBV?ARO+ml{xurn yP߈pެ7tP`mGXff=yi2W}ۙ>̌ +u9-NyX:nM.ZJ19 :L!q2sX՟"h NMnK<-'_G.z]tA>V|c89оX÷8,,+f N9>N4}TwL*'Ա«z2[xS-kDU\.(8BRXQD":lcGNş<=\>6SƃRퟘO{0Wt|YmKe~cWr<$kYE}&/5${9Jž g#[C1Y{xQ2Y| &em(oRAWcNm 0#H]5!V/rR.EUB\?[rN#xS>>LtR i2@>OU IuiL˓MSQlśqC5U ي2zz_MM"ޗ[b&27X Yd{?9ѬfztU^,Ú0OQH};w~]0rzJ7Z VWgUt6J+\.z|G_ Ϩ᣸ii“ҁb\IS-t-=bK"8Ÿ{w.1l& X\kBa {2T 4/u~XX"xppQԉ6ITp,n=rVbRQ>S mfZ8Be!&:p% /5&ii [<1ʤW6$= !#} MBGQ^wnl?%Z[_COtO p+^?vƮ?e& 2 hՂS{QSU~jyrkk&# dKZ;V R|X1%!)&ip7ʗ=GOIyz3nhnD(j5Am~[vU>ӧ: cEts_٥vB|rh팟A Վҋ a;ŝj 6zouf1kU*)zapH!Az^G$MUA?w/Ϛ&^c4e@zjQM~xh| ga,S0GK?و3fPey}-99&9^ foS/SHgYqR9;m^+lrgejΏ ِ*c{Dq+]Y/߂ԗ)ʄ5ը.VjT~m3 O718G޶,W<_RZYiY.s`7mo7ͧE}QicpG."GZ J҆m@x;ߔlxyx&^Fnæ=~bLw`8a2+p|2InVYJ74C*ڍy_c2 nnl5˘[r@xk&ܽBgW4dYuu Ó5Okmy§|NQ @1T?-=|>Blx?9=H5]r{-qej&k/YoXs]/Oz1R5VtvW7YwzRa1B}'[av/3=wZδQ@ 0/maRB*rzZ5Z @UO4͑c4|m}љIISJcf9Yb/=[XYVV[7/d^:K]]}'exjĤ7Oes'ّ>_䊡>-e@m#9+!>^,B]lncfOk!]fayԽb1=g$wxB,';--e|`/{VɃ;5>@ןeV`&Nhjz~pD{d*1ؑN|:&c2i2= +uRq};7-=}jzJȮ3pQN{61.COt`%^nQz=y74oX1r^I@׸fe[?3w.:w6*]RNwf6K.'k[d[axj*w[v_G?_2QV\\ɖ\x[>Y,9`ܒE )못Q6gԨxTSs/n/,41lsnLlUlr{HwuU@~ú&U>ngK6Rt NubPm(*-7ñЇ|o.κcp'UnE͎Hfb K~*+oE[-^0v]Z:gc¶` dF0/Z4U67V/&w7J<*p*?s3Ռ^ OR#*WXȨ̧WÝ,^ZKqQaGʃ·ލ{Z c{UchfpCsۖ8EuhmkZwmU\|z*nۈw'#yN+][geƕJm,/ݛѭ>^#N8RoWg#mAF^Nl*U;0}z/F"f2O Q@˼4+qh1'P^jUr[N\{·y khg.Subj'ˌI[Qo kf?7D^GsBl5i.r*{òMǯMJg$e`뼽{:~{uh1.@uo4I?PZy:F>@Ҫ~ֺa9W2=y_iyea/Rk힜Xi< 5]RykwȏYn϶WYx1:tN#ۣw[cqi"_lco`ޛJ΅S;m6":ҪcMtuӴ| ƨW1R%´ϲ ^&d6#穉+K,Nɕ|L}X_F69j桷'D2IZFkM![FpSٿ<݌gBf**~&~،QN.so &[,(xןCcRIB) ts27dMtbΜQ//6ҍ{ST|-/se-Qʟ|g>{W37|B01'^bcBu5#tcYʁbaU-C-ЊVDj5t˘ncc {vBӃoaHY|SmR ]5|EXb )DÁgN5lgG5ecM'Ә iC Ȭi y?Z[0;?[6IT ^m n0 #`oR ڙh$!O0Zr]o* 8¼jͩG&*kezB5N/bV}LEe /I7qpC{{K/)~Q؅g6~9720v[b[+)vj;PQcP኶(` ^LZGXv]*Zy"m(t.fioeb-&9&B[Ͳoܹ~B jk(D+}ζUiOO-Z V{' AU%h'>D4F}?? O]%C+jhiJswPvHT"YE Q?U&9gCYAgͶMxFdl/AQx} j7ؕPh5\ G5kQ-TនNJú[*8ťjn$%5 Cl2Tu%Qt,Vq):mE*nKL =$hkWK8f d k{ eHKh%;`|zQ^+YxQ;KPFZ Zkq8F$n.8XTtq1I57]| "Zh5Iր s9.:x2ֹj~@[_ff>HE,#pJMqFhX B~ ={}ĖZf{Y7P㽫y~,fUg_hN`T*)iz?X"k rb,-*VYxm992 J@_@Ao9VZnrx{ 2/7n xG <7'l8(&xF rN) WMa]";dh ʂ2Zitr*u% `I{xG 86qMɽyox7dDc6[dLn|hsT&7"-Joee|愍LIY% ZΗTO+.)*M./Rp,HU%,5&g,<_M$_P_ZT:y uZ+a*s( ww^jD)e4Ei_(QdžpxQ2k HYQ2 b#2 E/?D&;ĢK4T|?|=(USriA}HKXqd3cu) I5pK q2;[T5t_9L_nǙ3XfL :.s \4%?sSeyNio}Jǃ7z 6iKa\)LGWNpL9s  =o|4'N;ik_MUUM7Zˠgfx׏:ļ-%m=xpWY!'cFJ?+;zޛMq*vV([b[fsXVoXW/p zՖ΃ ]q eG9>|C.7E2n+xi{ _7KL=}Ex&/MK)_MLhNVMb]7zxQv/v9\HIK)_MLhNQO&bBT0T.ͤٓ|0 ,HL$EK7JjFX"@̭,nްhD60Q况5rlǩ;Ɛ<< *%7mb$MqG-h^w[mKg2:N&q,+q 7rZƆ].痣bXېẾ:}:Ϣ-~{i%Iq`7ϴ/$+`dV59ǷM%{מo2["5R 7"u#7gލT[7Bnl.DE i=]?h '>9*M-I2?t ˶ޜf3yEsw ɻOvO~+`(-3CI'XKOym3ZK'q=75(?4$5ރK 3/.x'WwOxWg`.ʂTy \ Pl@= ~A> :Xws#?ٕV871/1='?=7?%u/ .)hs%fطxksګKrxX1 ൷TB@4K.3#^ཻ$򮑦_34"vf#' xnxɎ~`^lf;(.qysM4X~Y'\o#oi7ack[X?ptl^188gq8v60X]/7<= #$ ]owXr&xY8xȎ>mfk1G26p/%092Q+\-08g܃=(gB"hX-p ׈̷EZ%t." װ%>{g7~$OwS|d=~<` 7'.IyeXWdbؿ;׀~߿O? Aw2aW1kQ{)=;j #ՋE/x/ݕiJu^;2?Ϟ+eK FaK98K&L:o x 7#)Xؑ*}D&b–5 ɚ;HtÇaf%d6oPe1v&VbYp2j_$WCR 9KV7Xn~Ag-pޭa# c-@R(:=郃Ys4<)U^Fs{ $S: X Ci<տleMkL+ ՛7zlS;C)|݆gbk/$$Om@NMDE#5Gn %Eث 6ic݅NRA]' 91U%gmW#&7 3Ӎ~#D> tpDCBImI I! Ԟ6MںA~.0. a(P x'vb%z Y>i6kZf6[%$H'f 9q ̐WFgK!dc|8u }ófV"$2Zk`6Cp`3*!ŶN!%fN1gm?; ,jڷVg8Lw`Gd`m_ޏӮ ES:ᰕZ(QuoV, 2$T'% 9)&BO.Cc&%>[53zzCqK%:ղ%dBքO*4ϡ>pK(&2Ƒљ\ăSȘL$S~'-fiR.4 jybK¸Q=lȩ@S4 KL< Yt gђC#W|;J UoEa(S~O1LmÛeIf܇2RYfŐW2bt@p :+W Dɲr@aIUYJ}C'/rsΨ;e9AhDx"sVdͪ`L,1 *8A+piQ37$ 1I@ԧs:@ i3[U0"=}Ɋ*mt")f>t~$T +[кLNO]c!8‚"b)*\c%FP񕜩8K;X@ o94Ieq1>biO+{m`8>czx4?37fr{z' CȌþ˿[zOF7폥JQ9$8˰n>? k<Zp:m.*mkMnCI; ,F뢞*6~vOFDخy`_QxPo.Jd> Q|r:W6T c+ꟗn3JK퍂` `7z.6<"lp{:.gCڥe)~,$q6;0H/؁YpKA_U1v`95H sfpm(GsӾVXΨBBYiz:9v`]H5X=0 g:L(=FL{hJTNm٬6xx󻵏 MKYa1̔aQq-U=ZLmdK? cCUhr&8Y9&M)V1QJ#9L3g4D gHlyH.HfH7pś;6X@;"Kp0;INJ;[=Ί$YWAfhZX^ڒd){I:mWvu )Afv_/?2 Kn(˹`5 w <[\`yQ !$H1.DBcKNHsU[DUz[>~.dTFД𻔡K%c94r,% yIp] _DĊ黁Xwx"%ƕ`B"~)>K;ZJA%/<1>\wKӮ7eK&/ /Hszɸ'^ӥeAxWmo8#qZ]J!DVd!N9t Pk=3s]I/ǓK#xʈ*Kh`e0DB0fvΘ;W` ф-4nn~kHmB\q d\03- l jʠǚvkd10*sYJ,j>.,B[2VڡLUʳCL,SL2M N'L8494^%Zr \&0^6wXeF@9 AJ&%\0Q19 òB40~b{O^Dc+\e/әi*3p#a7\0:!0qu! FA?j_DJ]h3*h,T5xFa"0dH!A͍ٝJNʤw[<c&aRٲsQkVB%z&T> ܩȢ10~G(K{e/7 E~U=ҿÐ.³6ßDMxk3T{H $z'xqKvp!D.$}ƿ=nu#o  $50dKEdUǧg=YFX-ѓ w^? m7ΨתldIR ncEm"jBS u׈%2 GB ESbP7Lde}Zu ez?BB&t"բ2aBбXWΝ;CFE n{7Lqn2"s'xם[<5iTtO?)g2}$Uņ8u 5̘3ݜl{ܐ36zDUv۟tރtlzi_]u-#g+n5v!4#b\m)}@' Kyzhc˧:("RAV>~2-3of"܏-:vaIvD_xxDLX_K!8E7)]7(8-1%ufN `7GŐx|,!!NpQ$4.>)=n\|zjI|IeA&rJjZf^{ X`^ 3 ". pI,.F33ՠɬfL ql];y':PYX*j= $\MXV5J`Dؕx+xUl83S4,HMT@5QA D_U5'aD2OC'KrA 4ЭHmy y% )%: fFjfzF2@{KdiQZbr*vOON,ʇ/QЂ0'G515/yR8Kմ,+d$ȁ8 Rғ@-@W1RS\J]\]\}^L5m x=s:r?K7Iδq؎zJKNK E$e?=]$H"e;7KD|,bwahw7ߋ ዐ{f}(?X-ɻGy.<x1.ԇ^@eAZ<,Xa6<]Ȑv\/l a;֑.`vWpؿ;"XL ]< üBǏ /gХqp9Wg;>ǃoGgtF Ift9"i|.Z{S|"{ Sbʱ 9M:=f0CAqLҒU쟏{swϽ cK~xeAOT|([x-)2Ͻ2p_tDzGwMz=sM?^nU7{KfR: ܰEcN..W1:%zkOdTq%b9D Fd,j%d&$𧑁\2ǙӺ]^gGޱ 9op$ۜp G@H7U殏e/3E ɲ) ͘c{ g#l6q/a^*]5hRd>2RLL<83A4q^=>)d2E+i 9zaeJU̦IԼR%T"&'YIgTnzIn1⁵ Z:)maPRc`Mtm=tlF GQ K%\@qC+@;< `C~p7 h8&NBNCCKa]h9hƲDM8M\F&( D,0جp,DZGi0i E ̖f#"I:8cp`=TX v5B@xI7JB'5.?pU)k%:ӖǮ5\ oX@+9r@^}ҳMEG7.3.:}DnxLb&]ܟ<K/<^c֙ek/B nѡq:ث\,F۹|>g r Q, lNGaG V>mum\:YXhE0NC,W܏\Rd9 C֢.z|PiuAIZ(X 6I+"a2_TiRWHr滑̅,v瘹onr3Rr=u!Dx (r;@<.22%2S}l^;wf%dV4)KU'\S + 8#K:%WX Gmvn˷clw *&ث1W@.TtąE)W' o9E:!c*bjZCiVh($rQZ3)" M+|Gܡ禃:}r|(eI&]T-E}Z@75a~+YvHm GeE%e!)7>y]cyxxGZhx=CAESˏ+e;)o";b"⚭D{,% I7^/`&d\*1VQlNA1@2iFk1f_vs҂rsFͷFȽ]S uˉTDQk;;]閎nZf;]e"$C1ic/ 38={ ߅Ͱr?P܀é;~?RgWMcYL7&0$t"c d֓ m2l`*.}<_ѱ('(6/Qh=cR]w+'ߍATc;MgWz9':BKu%ꏩ%:QN!zcᛔM kyi>~6?٭g(ie-{"m^43\ɤ$\n/_E{~Ƚi˥٬@S7+5 K-*x$ZdnP&6pRPIKP1YH?<  y@F^S(4QF 6P:1z6E dv4#œ Y[H}vjpXdC8}wiea,L&K;K֑|*d$kWLʣ1IY7% RdCd<(w>V5 !Xdؒadz+PG ($w$st[rV-~ kd"bD5ZV|C?? ]nԷ"+.$WS1}QE[o?8gE^_Ϯ[ۑS^t[RYnZL黳!˄AH^) Z'FVmFhuijdt~YIbZՆ|yovp5|%!]|Z` ~t2Ƃ a`o>&ۛup@$q~ImAKXk$CmlkW]^",gIfk9f r NUxQ|&ijy@$$ߨ*n)0YC3B ?XGHk:d5':k@POO XB/hi" $v? Jȧx . EIZYV wY v}(U,K0D,wJ?85n˕d;!RUgL;jd!DNu|1*ja!cd)ϢMLPNE͊fD%9}Lz)jQQH_1r th+3^4kOQ[$x}kSIgW, c|u xƳhI-ыvKvoܿwGZ{l%vzWVVVfVVjmw y!E:$<[JV/.V6i_@t0/l^MIm__\ \o1Hy6;ʳt]e<E)vvvD'[2n]'q x.KկoBl?y"<BȓAZ󴷘'"x:xu`:|Sƒ'ِ>NދӴ8IIŢ7NOE">ÔF{jopWr 8t_$)c-dGuZ[l01^`f~XCM6@k0t<D,dPRڽ~{Z&~=<&N:Sh&syva^uěKq(./GO/ˋζWIZ_VĝI#t\,`hへ?&$Ee& 5 br) \tήtãT2Kѻiit&ꞟbݳP=9@<0aAxp. "EhT@!:)Ns% ŴŐ~ F ˦|`Xix۞? s鞼~ni!c ]Uh-; >><I=G0*``z2;r?H [tŀTfs_$ =N-DxdcWϼ>q\4fSDk'fyNy<'Z&EV a\xi'̸j0Njqܧ0QXڗIRG,'VKF':F˦<8 chN&6%(WRU%{.T^̤uD䍲A>SKFP=sNu@kw n/jNh^SOQs u",8Ve,dOP#B/L0p+%D@1O:z85i<>9;<} 6" yGO&H)#ajMD@%# H= '2)Qa`@3C(KQ IV-.VƟ<)cNqяY4)goI|I Ww9sa.iuwY/2:R.-SۊoP̶ 5=+v)q_:H@,c\T EKr=<pt_HZ+^@2T $g x<&YLzSiɑ{? KGsU>#"Rg,Fmp?=r,5E,Z9.F91Pxh?>[#go,-&:(ÀqJB'.oqA8ZUHc-}pǦ)_53Hҕ-q+P.–JcNFW18nv[]RoXQ* szdMqx骅ưZ9ЊxCU}qW73]tpk1ҡh<]ʲ,019#H Oc^Kͷ;{ 5EcgcY9*2#UzȠq!gNY$HrpI4-m22;Piq#<8L]GC4FQFrAwEFO/vd[FӬr&5X dN, ŏnhR+ >B.ER=WЮNAJȓI1 Yɜ7@I)1QRijY_ b5܃dӧsqOuQDʳt;1:St2YH6TeaHՎ=G#Z+݀ڡ>T`a60i&k95`ca`l3QXT `f"2@R(pp5] ݁p7־_P\T)بkCaP;@i`w4%ٖ!|Ak pT)8+98/n`w#i,:Jǔ'c#nI&8)!FⰐF]{T w#AfX S>SȢ| l "U<'_e /`0/uh"RՌxmi5N?XfY)pZRHH UKpYg-M#4G7QZԖίbjʣД}Gr֮uFY8#oJ^ ]oXĉ>Rbƪ0Xಅ٪5(j#ABDvEF`РuEYce_ΞJ 4:'ͨo4,8ʪRMm{Rt۽[9Vh0 NhN@ųD2䡃HkTR-mB#`e Gu!i4R C51^Op $a[^ȭ.49uMh@uEA ?ܹ{ ֱ+&Gҿ-Dhyv~z.zwC[-h6(rOKOHA%Tsk,-o @R7mad!z2$1\<p X%6a)g^8#U,ʟ{)k AZ9 ? zIry֖MmK$xh*-=xe`ă[e_x-R܈kmQ5z{)ǃlrT6v\oɱiUvϗT,sa!3$ sgv'3!ٙ̒ٱ4yZM_--A4ٰBtb4RMS/Xܐ:A(U骖F~5DA mͶ|o.} >Ͻ2wN 5mZґQ7JeCAã<̱ἩԱ扆xR}Qh\+s?*<[h31rՠ|{~鋺~Ma o6kqAHGAc xJ]ݽЕ?{b(cE܈Y£!o֭ B9-H(QóޱXDy%hT@H\9sJd?jChg_+^gQM! ϚZY'=xmKr5VAZk}8K^1ْ_{*Wa jl7t'O=gtJXNؑ$qIA7w.tBM^5iʼ=g;xhjVm=  |ΎF@ĸV74C%Z"ou\%gol FC%ݍ>?Wwxކ;Awkt]_vvMgpO1~Vj?Gv:p3p>kNrAeb#h (H '^^e)?DR ҂ǷsH\8ϑfZ>fEYUW./:/΁s*4*h˷'ژ\El[ڶj2tVA"#! xQHOIY_ya)/,bAƁ s^׾iw m"\ {y") _֝xfVo{p|:M&d)NK}QqS-4?b~ dǙ)svx-Y^n\ay ۑ$1&d[yB\ й@y}* ) ȩKBҩg6R$H+eZ"v-\ͦ9޹?TlkPT%.AqwQ<9:~x/IޕBqd%F&$V[ѫ;iMLz`thR/ת{so&ԃE՚Md*zaSHX"vu%YM"=R55_t| e*)7Xg2J'ajoOz7&y߆PSp_KJݥѕ)ՠLw ؋^/ksn+U/2>Ԝ&?茵Q,z''`@zsLmz/o j p43ٕN:K ;y80af$–s<SPjT3t 7 M,K$e3IydKddZ*SɃ#&|$oצ*n6m'.^H(Y^w߄`ɍctK#ݷSx8Ykjkv>VҒMҤ@r%-z>1NwtݽP><[)b![ʧ Q6z\):77_6c8껇d2(~+^؀Xvld\!$B|;}n{L-@xH%As l$ۣmz! ЌhB5J>$fHE+SIOtMo47#M~i=Zin$vsʺO|TQxĬ \(zڶHyZ[ODRl@K XjDίROL+Hx,|ۈXK1"F OvvSu^vM`Ì]!&uD}nTCZVI"8gL>W#Y0B03dkjwtfM/, _q30)7Q(38y꺒b3tujƊB.7A/{oC -ɔYǠvDս5Gd_}ۮl~RPS9O MòI+vF]Pmt6otg,'Eb;ܓ%1T+biM \9/%y:,T[S,K~$u}~T&آ FYn (N^C{U3D@5ush9ln(~Oma;6Æ 8+8:Ljv[-o Y>qT|G ;2Z %eFJ+b4K`ў[d\D @k$Jȴ"|bDoN@4|3g{LS7"}zU9ѯL^'mlBʘ~ZGW&eCXg~Dcw{Gl9L^.djnRhTXݤ,Vjqq+; ޛ;^2 60}ξrKct]v?naϓ\*qR Uʖ,'zAXBǗpL%;Đ mVDU*˚F8<26\D|yt%iXlT//vpkըX@[bf-AHe.Mo„Eq÷=@لJ2e2Y˴|Ltvԣ3R]ܫ.Χo=7̪o,Hxb]b:x0nWpBl87DڋǥP齌k: ~H[\)jc'(XYT7V}pb=7 vUڇd~FiKb",1k1)tyb/aSJeG!.ɕ4]ya$Yye^9>w.NӨHJy6T%[ځI1-ڇ1Au8 J(_6A{B{egBP'Q՝[gTbt.]d}_<˹5|bq GC21 6Pl95,+b>8we@($E*R2_|(l7˙AOrQm[ˤ)dOQ쉮,faN-Oi]G/d_=0 Z>J 0T RaŽ @^VO(ŌCq9|p|8ai̞N5dm^?-#\,ׇ\+1Ic=EoBRy] f)K gDW-]Y/o\s`do@BB&[|V\ՑjdGz}:b[8/Dȭ( ]B414(5ZdĠV9\ˎ^@zxȅ*-v&,.vw qiMhyjk0}Do4TpgEcxP.ч #=D|l+R,z7qqQdT^OU=$8Rc4vW[IKt ,V*Ɯ#ʿH dQkӰʓD  ]ɒz%žww{"]kH.2H1m0~rVM~W~k ;%JGjy+FotȤ/! Px nK{Iއ7DF!~`j厔[ eȥ#͝2гm)Ah.z'i"iFz32ih4haֈ'jj$p)iAeH_9M MM fh՟K`[{2_{?(g l[ÚzuΫ~) lTጯnZJTk~FKopmv2ɮ@V\T3UtsulWWOP@Ѕ|x4rkXxxN4Ur_B}y#Uq(j1:KL2s)lxÀ/ _42RӟW[w-Q;!9pspfú~e3>\u0[mXpup@yhTڝI Nlf+NȲ -ڟHX-6YaavrS6:r|WFpsB~[`xyz4M=;k+=<-GֶeS:tRy7#qIF;0FiV GǨyK|ɴ),1Ny[4Gz2]i.uºP Cd|PKB\}AVDgvOd2J?&}^s=S 4/{&2o^%f:&]:[||3U G2Ftk~ Q; }&G M"ugw = 8 5gb D@l*TOulep_:Rne섔ʁPamhr+FeDNwM(-k`)wh4 [Y%hq2ZH-.3.e-#bRVZ]~EG+|~]Ԣ&'7*TAI4&؄DQM,]ebՃ(|n4VA1B|N4N[^-R/<0se+Rλ-b1!=“ǀ'^;a~6El5)+"lVӃ(gwb6+}ÉR&}]8BY^0, 7&P#M$zIy¢|Nп +6C$\f_k^mw#8@f9rUi)H5.|.v^yVx|A J`u)4|c $So4M[L pAAOF{19J@ݭP93=0G PV!_2yZKHKb-}4g9zw佖07s/]QGm sD#Cʴќ)'v eHCWP`aZ dPqKl5z]+Mܨ21-4KU~^`t7nW)b &U uQ]YcA=mNlx14v( _"Ƙ)tE32Lgs ENP?dy5L?BZ h 㼠 /'sR@a[~vN'A!҇H^M&3,p;G 5hGftYu-,k'\{Y1۵<~2!P)89Z5%!VD#!QUBKZИyA2%/^:wޞ ߾{Z$05G)G:yH(MyHu1-%ie]$/xڐ'$sp,Z&p2۵6<)ˍ$@{‹m[@RyI]ZT]˒FN`gҝNYM#y7PFvTJ]Go;U4Ũb4='R\KzWl[WbOYs{3c<@oHmөޓJ (:β[c=7pvRr@"RЃC!NIOx9u@l&zTJ?fln )PE l)brO2' )QjxU4VEiEhGE<PZdFlj m!B#t@3pB.%/.QXO\EϬd!nuUM&){p^fd95 VxE96 1vT:Hq#$j|nm uV'[ȕFz]鞹&)nTC.w?ohx^!hA*GB ͑L';FZוVA2mvz-U$/ ւX5/TVy /ʨvf㧐7#˛B4 R0b,~N2)jcz|ݻB=&Ha#ijV1iEXS*)76Ǟ̿Y<L[o _ʬzy4[zjjE(I;6 z4wV0rfS@ka$㞬b 3tjhgtEdЌr?LAа]9j Ƭ.W}ΝڑJ}ρ0/ֻVX #n N6#hrWMɐE%u*ZCA&bjl~i0M>rr1x~౴ T K0։$=i:CSc0 M7 {:GZZ&ؠgn b1sf[\em{_Aw'y"<ږ?~/"bH72>$L̐vhC>t.NoɷW/? d\@۰x6˳{iQ 䕰:3֎eLa;|bAG)`.r -}I%v {?6D?]RbHچT/MIK[}J$H{~ٽ-:{MK촅!5-T/u+|n⾓ή\8S %(HD޿k*}s[C^: FK5tA|`pEo 4^__v_DwqMslŇbz߹-ꞽ9'/DӠuPj:##;y[agQ%}p*v5@˅+OKcaUֵV*|P%b)[ 7ًl ]/m&#RZBG#;[+o7i!ie<@91$24aDU5S۹IDӼ nyXgS{aj5p\o-T,uuja#Dk*Q gA*֙Hx$s~Hѣݶ&66Ѹ}:vf`w$ 4* 7' $!Y; !0 x&vhNi,*#k66"Q1;Eh@ݽla1E5Ŵ=#5#_$|3ekSj1KbaO,ǸZ/L5U4,%s/HV&j vAMHԅ D/h)s}Rw`UיzRq+MB\A`G*fS%!0Gfh?]RT`yd*mv%TR[ 4 Uڞd*հPT5+puE,sEy>wέ=p.T \=wa&"KQ6amC^u-ޭu,5쭮RTW@D.a __µghZ/&a͗oVޗoyjwLXuc`.*0k`)_ů_ǿ0nyqX&B\/?iTr ku݂;44 xo}:tjs]!KY2p >v:@V>6*5amhٯ@f8*1w2,1=~L{RQ>!䡚UCūZqK.iHUTlRSG(M%dUV%VÕ&M~-|݌`П<͜u<GxϾ(Ptfq#\ Rq1x51tjِgrZv^-\ɚxWmdPp[-tJ[D7|s ھ6Hx/E\) V>L }lm9*>rWPtad*Gtrbͽ7L DՆ_͂?nT'X~ͽ/ת(%߇ӜY޿a #836fRIN= tFw'N.hq6ڋ!t8<-8dW5Lc~ϝEp9"KstՔ C3eUp" fW`' I=ȗ: B%oCLx#&Xc*>Y>c۠JC嘅E'I&4--iZoً;{Q{fG}|m?/Nl4S^I1aߥ[2I!)&D^BThǓMrVJXc2E_:s{~ ϡ.r0d}54߿)z#O 'A2ɥU:V)͈!Z|N_y8bKf= LsSmʴj.%)u- m%b&}ʼn'$8:┿ Oʵ'W92djH)-Y2=y{ڤSGW׾ZZă f沾r/yX^_ХV]N|.e|8+^R>ׁ2dx?Ҥ= TfToo_Bٜ:aM@2=%?8Y/-U~2Xu 5UD3O#uV%z sH/rv9h ;Dߘc8ԏʞ p*/&8 1tuqfK͡eh-} ݇o(`BdOl8Ye+`J)K~nb {XF}n!gr~3>dMF.9_AGiQBtǾ >~={&,WZE /UnKU_;_$'@HܤW6kRG&gR{:U=Q 7E)TO[Zci=87l re!l0n`3|Y%J&:YLECGlIB{N70tXa"g"$WWӲROQRHOMtJ%LtQE:@&z.2kf㸛G]՞~KB< fQy^<^g^5`N+ :x_WA /?^Ul%ZC?$R›{zG`S Om{ݗ7ؿuGࡾ$f֓N:}ԕ8^%?<)؄ڳHmC 1$Bfuo%"{**C&| LFWsyy~it⚞}"bM/ķTYjEeTs7\\}s+n6z#LP/(5 ^#c3sF ' MX(1{#^jU^{Cϛ-rc+ X'{Ն'Wz!Ώ(ĐbOyN5:ODƣE2~P'(:LZ,RN(<‡ub qjg联܏ Χn("]myk&Yua:Vxăl((ahZY?QjK^r:-wޘ ۵q=RV쐐ȲJa(nvIV8oU9|)v1IxF 4@ʓ-- ~. m Ol,-+!H ATɗrƊ6^W֎_H~tt/c}Kw jN 02x:" org.gnome"#"S&).( " b() (xX[o6~At,E1ٱcX6<DI% xߡ$+i CyxuBܰAZ-V0.̙Twaz\bqsMةH:׭{`@ܓMifgkOx3"˩k61g>_?T{>S+-=fj {u㭧,qS̃KIT@}֏޵Z6->:5sF $d-U1g`Uc] Fdb6,KwE -ib!n>-pw5'M1-ю=4-JĂV TϘ23%ei h!sw|0ZC3s?OXKrF鰝v!$Ȇydd&sjm?"u*vlm7<XPR$dSPރaKНLk)3 .D: ;`dpg\NGϚ5;Iͻ{"Uʆ霽pS%,oWh׀zP[j* *e&bjn} CW(x/醸]!bǽfCB&UT9Z-x!ݞ1Ơ?5)Eyt{͕Gxpjٟ.nd8h=fo7 xu3YKeyʾSԵGDe2#:yO1+O}tMgUR:چ:$1sTuS.DT_dL=-t ??tOq[)AJLi|F57ATraq"ڛ{cζȎ*d븨uΎ3@H!So|B.ZFC?%^Z=ni*_g`ጄA k-'`cfxϿ(M]RmI6)TBW1ŠY:T=b G7.0[NɻRo *:]oGY~|n}8̯N妒R x=s6?ꛦ*#ͳܩΖ$IáEHf-: )Jv3Z$Xv d:[?b'lҙsI9؝EcFNߤ2 Աa-v/pvWِ'?k~4كd|lij_0spx= ?fM%<, oVga(؏G|rdxJ?9xfNE8Qʙ"%LoGq8$,~1!|O=OR^1fq~',^b&~w~>HLK-9>9ljfz7fG;v8W\ ya^e> O~.GY384qNH)b$y"[{Y!m1"qv='uh^>h4æ]|sݨ %2o 6(OίV8 8ٛL#er//ΎT@Bg;Gf|,PӠ./$`IU@;4pᛔO/ze)SM櫀IM^5}8<S,2`9(,ۇJ_~·.4XU,nA7i)^w4 @xXŵ޼alHfxgHdsXίn~m e^M8to?ؿְփMnyzQ z i e€ _8LNt9S+? А5ښ̻S݇<"#EX"VY #LwTdIzH3{2F 嘷$ &I:s7^ /eS-xȏxHVִJ8qZi渾x-;b0/01 9a kQCՂ&w=?o.q[Jv*4ZrLrwkؔn3DcޜSKǿEox[ݒ*-x0l]`6O`F#vWbOd3dITJxJ"hHmO~y{x `A܁w?{+ŻhF$~X؀md6ո} `g&#rtBf)XiEf7q<؆gdɎ w&$/&% IiB7J[gC1_}F~D/4r*&Y67h2m.(*pw^ꉷamm U3I k龊a?bIRBIG{ 9a 0C+ZU ܀FJ~aUS!9L)OFb.0Dӹ?K8W,]V/MMғL0Nqgϝ u/ 6Iyf3nDR,JxtoxMiIBoeI 4Vf@0K ?{nKJs-EՒA]tC7J*%^X 3-@8Hs9ܨ>-*~(Ed-N#a @#EqYb;E][Bg;$%R0\Sތxаy :2Dś@m$LR;2{Vնtəsl#XqޘSm̛yV4h<PBcfu@~iHUdh yB1B'a ܈)Qb϶i n5% H7ċGz,9r9nGXt$X-!tW*5ǾvH:EV:uE4{:%XhHd$Tc![|rnGqeRnȕՠ^iRϖ8j"S~m;>xwq^Ĕd,i[Sk`K'' sF.EP-Jbհ&>fBI=j.y~+2ap JB!lv{&ȀuY'р&8MÑo .ebON ^ rYXeE^SɩOU;6y' ILe*2Pt* |YO TJD2Y8A$:;rɜ; gk7о˟"g) `fDwd6Pv:q]_t?z`;O!rIF))h;^hݑA,Pȹ c`E?2EUǤ~I?seK:ߋӚީ՛VɖXlji'm4pٌ U19Z~aoHg} ];a[e$vO&`Y^}nyT48}a3ށS ߁] .>6VI4|nisۭͨ&:T=N2%݌j)y4nPx~~ 0Yplܚ+^N\U{WN yꦄ|t*jj0|.հLˑqjfeŗv.,5Upd#0R(r$Rډ?K;D:!Gr}jhu08?°XPx5KiIYM)IR Mjxӄ7[|6mh|h +>qwQ H} 7R 5ʭ#oZ5`4vX jNs5/ e,|b ?B| T]mE|Y#SaFp-)%L(YC rR!4o ǰU_pPD~`7 <Q ,];d&.}ceT Z|kVLRgaCQ2FWQAѫiV&S1yy^u:e0imn\]RV(J#5{:.] )aQ%rZorr%w80߱LqA`㸁ȤԘ2qL j{ ~[lNjVi5ϺW>0 yo j/L$B4i.uh!CUX_gI'!AwGUQmvxǣ?L"O؇k&O }}0)Y/`Kg}SʾӱPs󴆀hIǺb.} {%5R) $8fHӐ [m,#P~ c;@o²}.{1\!IfArHv}'۬o kF̵Nn5x;wu 1:GOx;wM 7'+:lq9W#nnx;w 7۸L;xXkhFzֶ$zkwW]yWZZoFZISw펤W̬,%PR'4B)Ih ɏ@&u~64G4&PH >fvf8 Tٹ9j\O+ ZDh+@f#@U J``2@\ᇁRSL}a0+!)uE5:NK,T:à}@MԺTRr'~y)1oq}̂S2{څ=9FlC>%Yz) 4=өWk]ih9"VHyPD UZorB b 9//iehO \:3idk|ljzY\[/ 5W`nY\-Tj b>/4X^#Yt*15YA#+{fdT*G.5F6EdVnHYZ,}xH[_{OM,WTX7LQp.J٥%zM7@ZX,J+R1OBEq_R `#^UuS);sUk42 ޠ%!dSޘoߝqp+aB O0S$E2~ ='#A7hMMɨ)%!-V9*FZ.su!2;Z/҅T,PR-2Elյ̺#dѿܗLμ鎛1.%RhY7H[Ӈh Ԕ)~DcY#B*ǂY(N*jtO*X+ 8󃒲F^ }$*9tU^f5-޿95y`Pa<Lx rz\7;ye,dvlQ7v2+t_j+H{ +QD]`HUVׯ5Y-R"f4 L%ɜ;e٭lb3X(x*B\$PٯRr*5 Wְ+@~:Vn,5[ z&wKib)=f1a~{;PWo4OM?S'8bxSMoQ t7 Z#L!7 mZ0L`*f!1ZWƤ tcE7.r|3P s9ܼ硏ѫ 7MWTJZlz tqEyjK))=ؿClҵz U[Tk k5U7]|BgQyxkӮ߻gqO-Iҩ ,"i:4LE֔* ]Bbt~ s}<o0п\n(Jel gLsU1{%tcQnDl0A(9Rȯ }`!,?SPv䉲p$ |{'3P4U9m,!rn0avД8~f1e+'+VI'&EvebUx̒Ԍ c=1_u~ hZvѣ>%CQG&90<s9w ?{IpsxMόI3__+}~PF''1L/}cU1U `C7xn@%r""Jp1vj,h](DqǞ$$vLZ!T-K4XxLcǘ 9sXs?ml+).ރ je=xj\1MTfumJ(fJ8˫V ؁ i)` ㏟]~tcf@-x`cBj#TxS{*W@/;'V$-I'Bu^PB iS+0xhbH G˟ܧ.xD\_֥"7ntMv#Y:u[ޤb1n"BEŲaqQL檻:rDBqz*Jt|mu"_y|.bWVЛ AV șWtR|35\7%`0@N~-O@̀)z, -dIH"'I|H^bPܖ|hJqWZ8YZ+z=DUkBq|2S޹q'AA]hxmQJ@Oe@67KnHZZmIdiHvֳ'sR,T08=V8\N+W"m m+1 ibua5nfXQ@=Y\_XѰxZ{s6ߟMH~$U')JE$p "QSKRN-D^<],v]:=&&鋀]E :i.xPDI ys,E ͹i 1SˌQAjf>;W9s?Y@arK_ޖ"܈$Dӌ1ik&$cϋO# 4 NEF@K>]J9063RD,DLKwpC,ah>OzgIHLPё:8#@0-HZqge9|'WkDdRHRTΫKb3+,@$ظqL&s6 )ɝ^o\b >;c<60*{dJ1`WFb K }kl^G0tlw`9 #cMx4tB&bR3..VP+?]>2`GЍ7O HB47HD 8K!vUNl؉ 8.<{~S߉JdY9q iy< @͛ #c%q:xi{ȳێ׵\o4o ת:L܏#˳k LJ'5hl)EHQ!u`6սm_G e֫*1۴wi@}:Z'2m.PK2뵭=Pi0pP: PF m.P,S"!, Vգu6Aqu{ei6n@H. i&f$ΣE%QQ :Yx .m?]~z *CpQ9c _@>D!Hz39 E B.4$儉&P~"Pȋ)i TOߥJ |kI,&^S'hrymm)8)̃DWɪ)_aEԌt+D^r{rY_a/X1|UVOãWvs3jG Ype+ER3p¾T_>*f(GFWieF>)Y$K>W#3xIu(~+iBFӂ:)6j+'ã:ڷ:788ڰ]}17,_~r U Wjc\JYh5Ԓyk&N5qlY "XV@L6G.z60ƨܗ١SіSNQ8MWʂ ݃Q˛+!\ 2sٖ+6D* dlHxڰ-:cB{iy1-faU5[Ĭ(#?W9+0mjm @Y=l!VЧAqD>3,f} :6g%iߐٓRb͘a ]am4FePtm 1@3L Tljuc8HGuʇ䊗3М ԓơTs cyX$gD "9޺gz 7UmOĊ!J@pGz ^>,UBhg%ۮ!DOC Uw ՊQ^;D.jt)7δ`&\/)R|m!H8khk<06{J?xωZު*b%iR  B{*zV{,={QM9Բo$v#IфrtZOU&~s9}QxF;|TC Mc`^=OPȵ?X42w5P`S@*RQh[e%޸; >:A6EX㳴tXÈ2?wt`kW̓PJ}N^00xJ}o}U/=q-g g;=KU< 4U޽{}õs՘zW T$= ΩL>;&+UkuD`+%7pΓz% w*R8 d ƓuP}#OI-\^ o-9Q*|i9 &cP+,g$ t_;m{ݍFƁ嬵ߓ.^N: Ta"4+ W]rPjr՟tO欵wA> 7 .O}&-n {*%4%ShuJgK>~y]^ߋy2Tg!:ROrrYaU݉_6S?p%\nE\+_&t[_4?GS^)V(kcI/ `lgDRW,xj!(씘fil"[5:96mg5Oȡ/Te_NH)d*) /,USO aο!ӟou!Aj;SV]!Vk%]$c}ecVZV͆*ꕜe {L4K|<j/_2#a#؂!YG56:RzP,ۥUw1>,y뉳d ~8~mq,KA<ƣ,2UZa:NE%򡨮qȉ)j"IDH<~"eU W"[yP& ,$W%Ťԍ %YRcfv9Nde"!MayS͗˹E̡JlO$)/ħ(x,B(fOuǕ)G"H H3B*B.t&e"fe2{ w?~{!O?wggpuS td\g^U_|n<8=0!F@<QL'J17O6OCg"+MUB~`I鉿@8`WPde:_ 㝝퍝?o}MT -0T7 'ϠڟҬ? DJ3h^nҝ +AYf!P?zeyu4U3vGRzWm>'B.>Hip(:>8<}q"z~xPj1O^qۯ|_o,ygShq 84ϯI^9^ ]nU7buY7eZx#Tn BVۚg4+n-'l9H16Rr6 Lm%Lv!9IT<Db)9rV 4Mv,q2IDm'[H}Pll6A=-t 8N𳹹)o ܣ8J4; G'15IT2"MAo-Xpz_gmA!ŕ!oN!0uY;D$D?x 9չ흶&K,z5K>ٲ)E/fқ"߸@̪U\ R› Xj_.|i}FҁJWq!iZAash# sClzRݽj>M@b֯AQKTq4O(c>}(źdE':a|Zh0*$d"~H}uyzI?Y5U0rQ.*ק<j"s^8R h!o^{y~E/_F.S(yDe[c bg^>bDSV5D]qYx){kA[qT>sx-k7.ΒYoa{DC9|(|SɒY%UWHY!ժ|,:'Nߞ6g#>3q2bR$tnvzZOvtF@)5qe`4Oq4Ƨq1oDoiLАzNתР:'ܷ%J%a9SvׯkQ֢(-y~?Lg|U>HGP^c?ˍg¡OaZ羐 u~@3`%xHh"h=a~tfIzkW`THFhؓ45(kUjIkԺ5'"hDX\xΠkА@>{}q4&e-SfNFHFX]( rUdXJҩ vKl*՚"=Q^KH6)ݵ!SJddӐ`JAToN}x:zeW텿@uBdА  87)8\,jSq9Z_s;'$&/N,ț#tql+I sq(r6VA_'ϡǘ„Pt[AP8 e []ltEn2"I!GpKT{ì+UJ@&]F+3d41ǝ6 B{Z1( *DŞ+n:= q>4喻ר-|۵@hP{xZy-P ~ݳ8>=?=8/7g޿89JD(a Q_s2k_ᐅ}. ӄ?&,G{KLyT'ӤHy>E{":=M_Xv(/,.+-g qF1pD{!cwؑLԉퟝ{E]|_hl{.]tx.$01zNkD?^"` 5PfGDŽضCN-Z&lHnk25pwԥރs 3*<0_?xfPd 8?+  iʞkZ8_meYEf;)_Aaͨl(FCM &M5ةv@Ա9S_K :̔vzDPݩXcz@kN_=KUwb)a(-F#PmG4GDs{IB*bcPbiAZN+qxē EQ7+{kz8+N?8⿊L:f CK$}`2癪H{@67ޏ?weHf*A9+kF-#8ԘK'rW]!h8efsOf2ytjg_!}UbST.;`<{@V˼ߪ &dԳ[c2O/K$$J0}pocv4rKF3O{*o G׾v5F{_mhy)@Fhs7Gá&ڛmLA(O-͔/O%J"}XLbr)\{S={س,:N| E1y[&=Twro0]o+h:iĺS,ʑNdb]28ΓR3ocɌS?!rq,xtyٵ5bkqdP!6%s>=%ǏvY08j;i[Pa  XQcOd]̫J+Q*Ԥ8!wPҁLYaZ`*cW6˥;Wvy_}3;Pt!;Ю)]?C!ʺV AѯQd'6f6Aб<F#xjd#AY=rN3*?ufWJ`WJVx.^ %’н.jԙx+53Ǘ6 PGǛKr:;;TPt6ƻMF{S~LWS{/,SG;'vOUA-)yud8+xor YZkD Y:(n:e6reSj:0ΔV7{ dn|aנή`̰w*06PgQc^u%no-b4 + : ЭEIZE ;'T㜮'~Q 'ڵs+ NOO'S=XYIhTEGxxoǟpEo& ӟ˟ܽkw}7لcCd04kG0߻W =l_nl߁v'~ ڑ?H?< ,3Ԗ#^<).2XDIҨ#! ZsB;GgO[[:y@@ҹ|УLKz;߆@C $l5=(/}V7Gˢ0N)hE%uĔ}(RHO|ԗtǏBc"g7LWЌ}-ź!F\ȫl |DK EG:-]PK)Л WKͥحxX?k.vy2XE n  BkJt Pܝh1BY6~Q Mn>bT'0~(%_OZ;*ChѺf,fNzfQ\a^6^W%-˄w0ɚ=M|^\vhq ɢYpq3+?fcvz@=OHjq)Dќv AP{-wLQnR|{ck"I?w؉X߸pF8VE{`V41BWǙ-dNl)V+Ԣ; +3bj Py%_%kZ]'/%nY@G$]ܦܪlV%~@F-р=>f1@}:Ы*}[559o7M96MZ-'#Կջ}&p6ݜLP+bOZo R yo:` ;d ''ѻ^g1rV]((%a»Mh8Wz[/by=.'zW?Y\OT]&Wn%Tt5fmh=vg/K &ɮx/ʤJ3l<5H9,ǛlYUэ_ nEĒ[?N Ʈ8!.d(#tIJe誦]qSgiEF4$J P=2\%/{"{I)5uRKʎJK^ޔ]O{Zʋ &S AKNW5~ƧcgXT&EU.G&tʩsx /31l$m}WT֝հf E73\j!|CK@?7xPc(9M1E~&wD̘.4VNPpj5PPt]+ gqLod&2BLBh:^i. [$IQLIo" @eU_weUTb3D"ߨbBӝ.%4qER^WtӶq`U<._N>?Y@؇g¯j7S`&s꽅TYoF@LQ-\H#{(WDz{Eriꤛ&V@ZL u#9T'53+?[Vg V[4 '<o @LaqH̬aʞI\rNx]$ړ4zw baV6.t'Wd#slԦw2j4e_7%{1-G*ٷn5?/um":;A(?9(̑젠| D3 QBTïNTb':zp8Qt%.pgZ#:=/֖Rd.88`[Ugډay\ңc5I&a[SL회:mR[\lw{=MGWN9N*塻AKO'pppχTgm, X:zejPhZ'VIؤFOSbUC|=EIM\{>^v!c|60£YgK:U{N'uK-JZ_HVgw]bX:?fTjOY[dkڹg~ʚ_pݺt81굚$nz--eui kA4t\VHoPC=MEw׿; _cWK0hP/̊IY;gzSd/ð|Z$z!exNfftez7 C;fTZxƧ;@FYoZo؝jZkylۧ/wrmZ{V7mǕn ;Il SN3y;k@}ڏ->X:)xdIWQ\~W4G)&ȰA3T2P28ƆHMPAV(ZrߔVŬj?{1)qxȄjsJZѪ\'q:=>b MNOe8dk9EX"_g Jm"QSveu>43;O#z܃{ucDIW%F3H7 sِO..LlҼ<70^V,&5q(K ې}^]- Ԏ8YY VrQIϚm`uQJS@SĂJtnuBql3Ai|ozwfIc'RF)RU1]߇DA=rS:a^-ƜqդD͢Kuc5v7_9ou8AK37;nr]4d1sI~B"*'7BYkK>;1ixvAF5ZM G {s$C+ Yz6 {z``zxyh1W{]G;}%ؒ.,kl5V~fFRPG}WVK}oŕP%YJQ}6,Q124#$u $W[(# N.CP3O!? ۟LE''ڳYV.HhFx:Cw~ܿRWEIALk./֞ 0;&1(X@L&vJO G'BUI5%4_(%&أ %l_$\_pls0Kn  cc[l2`iG<`l:ݔ 3ZfS$?>e4D)Xf^]¯bǟa~'8>-B4;$ms:I(0,=UG0gj)a77Yt/ߜ~Ow]"m7mʚ$^YPݷ;?k#Q|/+oJqۖ<#zEm+ht^_L ctgѬ&M 9f7lt2l8LwɤB[KJdVZ$B{< P4b0꜀X#Oo_قqӶKEZk 4-p 8(g|-n:@P-m# ӹد夺Mdƕ\+^b' A4u9s"FIƉV|]se0DO-`[ "GU8N4 _y|/ Tn2 Ht d48ȈtL܃N^Rd%t}*rT}1;Yt,lQs:sJ5x)=G|ƯцA($3P&wO4N,۳dS,tT0TnYC]go-Ԕ1[ n RlǶU24H2avңvR.!co2#Z*259ħR8 ,><0 mln]kwY[EVW,0VKT$ռ$2oP^#`tQ3 cl2L)bIa`Ol.Q\ZW̓<的KLS)}kߒb:sP,20q罨~h/7-?Ƌpܸ. sì?_w9糩{p);BmC]si@a,S[qy>eh$VVH̓0 A|Lgɨw7ΌCH2| N|+?^IƸXBa! s. g.҇ˋܻ2 WJ|@&Kb,~b | ϝw,a`:GޭYBQ!,qe/7?v&ޮdK/z8jRM iL)AL2'Ug=bA+׎csqxw+(׃폐0F8m[];ډl9njz-f7zѰg o<NjxBxܰy UYl?*X-\#xp{3 E2Ǿجh60¯N׺ c}f32[_sޚ5=13P{†zG7-[R-0ݠ&YpGD@"ܟ[{I[8Ժ%1^:`6h p\%}.-2gVO % **#[@A Thq̣A1'Wb r6Lj̹2Gծe/.y@El$&6 n4( =Ŷ- jP0Iu!EUf C޴S(  cF(D&Qm9[6<0lMe`7l'А lmݘ ϾKUYu^dz*g޶`JNZh%3{˸>&()Myc.!3 m  s&@kcsv7Ts PM6t[=kК(?zN{rJL_5f$~?H)֏LbNf~7x,aMO5M"3A+^ i,O[KU遆]KD!7=|]ǁ# y^(:9,#t #^0=l,|1Oh$mM*mn}hiއʓ~,5K+{kq1 ;`!ܿxX[s6~^~%0@.} %S qx-HH\ LM;ΑrYYiM_RX_ *5kS"_a(zZD\_8f& 2UsLB" BA)tdH70`SADR_[(h/$ _Ob4`R 6]* %#XePa+*~Gc*H4b>.4ԞzQiXv5]b4}wؙL;r{gv*'vQF~r$ÊFw=CE(,*; pⶆrDxX{ջ#lG0`4ax?4xm &}EDo'YYL"'E&F?2KFA4vpf |S=h98vw+Ϗ& \u"|33bR¬JrQɂڀ$<[V c;مO>h.jCeŴj3 9T-E,oBaې!NǴ|kMj tNQđyV$X؀k?+7cX51Z93_a/KiN,տ=@q8%MuK:*i)}L)F/<.syM9(^\q,>h9 bDZak2KPk4/uzF (T%sh#|F2^?6X5/ϩ/ c/a1Ugb? =߸g˥7g=ύ:㕆Fq6m~Hc{M`m-'+X]>c8⌑f5=|x>|U>Ӡgiw Z?4.{W_wFzW.PV)PV{WHW^,Sϗn6ix FWF5F 244=e-C*GMq]U>zZ\GmZоgOsor33܄<֣b) x{ ={U=@7w(XxuS]k0}!/[V {v}+ENڒaO_v8Ճ-s?tϽZZ0*X=  rsXpAAes}}i9 aj`:أXQ[>Q D-(ft("Z.gvA_noM4*0L6zڰYrD2AnߥIwF ;=4o>' $嚽ڱW|fwa7x 7(+Ujls‰? !x}WGWɳ#woľ o1 g_ΜA F;32h>{zF۹.g7꧛b4&Vo&OdEKlg?:: ďq'6V_^D8/E6u"Sq^q{%l'(ayɞXdsя"OiQռKOO{dto i2'8&y<oWɴHD\`O3X\̮a 4$\|HX؋#\glB4ݖXLy )t`z/L6U"E2;T?\xR쟽?zgryAi!lB0< ;:9=|8:<^\o{'oO{ޛIHh:dAR$0qH`IEpZ+ q6ѼD' 1'gۧ'`2'C1JmY#=.߅*f uQBeG?gYNʊ[;vwwv툷 sX9R]OT|_~&/i<$~6ַ8z:Jwnonԫnw;YܕZrt{uFS7>ne6~F&{+\:oz݃acT ]oTm)lX0ogkUDoN߷h^ajO^bwqgx6.6a/:/e}f!h./Ů/aө $D.EozoN"Zv w?Cq=tz2:8?;\ SkQ:-:*4j]8.u +>Ukx{YZ[Kӿs6'ɞE.qdJhCq->ɥ,'tm p˂9tP^G:Aѫ?[clͲH RXx*X$v  @j5a4˓a`k;*n8], xΏ)cz#*Ӛn?L.n~uԲu:ު[+ XVKxJ9w ^V^*sœI,q~OuC(D&\ hv[[{BEO@D¿45ղV?wg} ʺ{-,2އy61?du쁔W݃V‡ڴԅ v4-x U߅^K 2I!6P<ELSº"R+ӫ.xšwJa+14!"EUFJ]XX; ߹d{o?j8dAMCe+Y2Ǭ3-4#zl ,A@/ 胊ϯ~V/D3r8&!S<'MǓYouksz}(D~2?i[l6hJ'Vn,ptr֍.߿Fx+W`pWtO<8:y{v]v{G>9;Gg9vk^R[ם[7bcI ҺɚD:6;h XwD옎!61 ZO7~!o1ҲKy>-a0,ŀ,_Ini?6 oNιsO8Й<0pdm6çz:BmK]!#.8h3$E6L?d"a[F\;4Qxģi۪v೭Y|#m}-iX8P`YrhƔ !fh@U OIƪ(@Ą.&XC2b>߀Ytk=Uf/yrVz|Rd&N>N|ڸ5Cf,n+^Naxj40:ri"A_ [_[_>}t}zPZ [%lom$?C5@C{e=B0RKщW Un-ysjtx՞>0z 1">R2_jJZ 8Oq̢U Ŧvo4.~@zt8-Q(k3CiB8FŒ$UmU*16%.m%WNuWkO0Eu/ v{ZhӍ,:?V(FQd@=My|LfefAV{ޮ"ĦKH3D3Bl dM U%(e(u ^_05XhWZTPzz?zKwB܍э@%򬂐i䙋'vuo$7x' (猽SxSçھQq\f5m+fv/D FVu& *ȓ24nxQH,آ_.kD9A%z/tDa{aiNSm% (2Vg7hm>Dx&-2<۲S7a#."7n*aƇT ѶŚ՞D= dXU2P%, BS\ņ G̠%2Ą%EU  b/eClѡ^Q M PE0LDluɮ~ `Vưzg!W{+:-Nj:_wJ2Lj_\mqZGimԫ^m/(1љKכ_KRw~Ya <&iGQ+{)+YC/kdɸHy=&e'^TԸ <5ie'K9oo I+ЦB rXd-N,ٺh_l`Ԭ9[qgYi.њ΄h,^@l{s' }@)삚vq"X;hS`/Hɞ%58mFԬj lD0@Ks/QuAܿ$D5e1@ l<5o {G4gE{9[S4+()"5FI5lluiX!`d[6DಶpB l|$oc6 ɁC S0G}M^1C#(S`O1;,UJyc:屈`Ҫn(H"z[k-asyMAg6 û:}A3$W`2TPM^YIؓ.ZxakUݽaFhM07/S &90#y~<#ZȿZ^^K&w,Il*JQj3_٣c)tc[:bLQt0ݰпsq&2j,q֔f,X{8U_u&*.AU}/Ao1:^@ U/h T+Ƕ~^dX8մZ6ft8Ta( vmxq(2]a#6/T  vnX $_qqez!TeG4ڙ}59IT<~qS_Rg&0#x ¡_:bnXKdwB5oڽ q6i6e=몺=xo=YW5Ԯn_.WQDnmqixqͻ.yG_Gm4@K@؉s \;T#XY;Пt>ceLSn &[/"Rw*"jB92nK1 )7߲?Mįä_;V ]d&&jʠv3n99ӾkO#t{M @KkT-Kpo[=] 0CNN>mʌ71lx25B',GUc\G#3糬`)o~N&( SBk" (k*ʽd]H:b(O϶HT93sʛRģ$R=##Fl)S_-zݽ?ƫG~٫g9U¦h=݆Ɯx<-rA/ 8U$S@ س6+7aW<+T #!p& !fa2+aw פ="W0NGFYFK)JJI׈FSɮw)ʮ^(C1jѤ?Ώ]X\@)L'!О3v[kho+:e0CI)IߺKtӈKr4e!-U:tj RƁx 6+˰k䋮J"[>1 B۷Gu|< ?~iO@)N- k3|I Y=;W.wݳӝ``8Ceh~ k`xkoV֦$ncuJpthI8 wDU0b;*uZSwQ@X$9 Ji<2Ve_PK˧oQyK1jJ[ vyƄ{}*`_xVz1`3LVzmz\]?BSRH Y/6Gldj|fy5r5_Lg+x:g m]:C [/ vx &Bи>[jDM 6a4@i˵! ^&G|Y 2-n q%\._%98ϝ 2DI:|ѪOco.! avkWjywzrH+]N5 t\j%Sq4KȷɷS!? /SĠ?tj9xye;8'7UڤX(ezBYCuЁ@.WQKlQuܽ)?1h^`{xғ#c4hh -A"t_څ{֣֣e[e5o<}\ݮ*1M pFxפal15> "]u5(ŬExңTЮ,ҩBipBҕ"z^weW.CU /@J??;}_)ܿ<9z'gn`q\WXnH7-wZk+2dYttһv.vQI{Ye@`DQb'p2͋kOASڐhݹv,~%y.SXl,Eb#k+n] e' !U"o_r6 :xIws+N +XOYe9G4BHXh{dz QJoLM=lj6)[6-E&zc<ɴٰ(&xN(G+xDfN׮;@Et-D ZӤÐ6T?)PI<@$Lá#slb1 ^I1zSa2L~Fvҿ5pL`W'VdvK?:ᓸ;5TIZS]m>j1PM.O8 ?sqN'y[_:1*Zo?|]zF gpL;i)_$@tl"йe X%=/ld"D_*b~ ?WWb/wEI6Q u>R J0A/5T|qba&Fɽ\N%t;B̈́)|(ziOCqMU@BD&[[MuT}U$xYg.WԵ+wfe9Kibg :0b # ęu"3H{ 2 T+FA^̹B`K+ha4SO.45j"s7N^@'DkXHI"LVPeO.9ckG#8z]taBQ s2Wm^ M/cW-4Тz7XaW)q\`JwW)grdCJK|bàb-!L|붿]4Kn ^LǂuL3wywp*7͟}63xN{nίo;"cRפ|M}`:U/qWh ljVP+p]tɸ&TU7yoFiJ-|ƶgqëM[Ķ/.|,4-p]4fZJQQb,*=5}m͞Z?$m<Mή8j R ,̾`0n yves. <8 R4L7IzTK ޝ~<Ѽl3EV # dczQCSf2mķukMvL%D:!qO{;t98˵{L;aåU%,՚~k-s`DAx7B}Hk(|6T FTK_ex0ԹemHu=Jd\]#bR;@&UQ0^0D A(ުTVP:,X=*wE"&QT=V_C]02sfqڶmRU g,Ee˓LD2kZ9NyngNg,ReA@J4k,O K3-[)bRM@]˜%)] C#~QZ=ub|G% &S~>~/p"->ku0ͦ[N𞌼Wb%" & ؗ+IܽmiIE3]ٍf87TPzsWq V39$&@޿!#ƸqضN*ޑQy a^Ss; M7Le<$ ,0(-)TpK\lwO?Al0Kt& nH[*z@Ϧ?Ec':" IRTBi]'6[dRhrma/ %I(xlCz+s UKhU=Z77 Z79 'ht Z=YtbWU}IC֯;jTnӁ~yZ0Ԡ7?E,7g"B9}0uX.\> 9aO+tŚUkk~"\M^DTG;ٱ?+Da }dӐuT2u /wS0(pusl|Wi0;us Cq:ObfLj<47Ǵ 4a 9jALIwNGc sɯO,H:/Ě )f#[!ۏqIǜα;n$ 3NёhTӴ:`PPa?͢{`1X' Bs'G X Uzf`e):~j;F]tFpu\o{[cF~0FkR,K_Ãaߍz?{'"bwwv\h_/o/̙s-%]" ѻqnl3?W= |az̷J2R}4"M 2pYS&F rhl߿<dgN¹\|7[-ZͶ|9P1, V>'IhQF%[ۓAdP&ŵ|y cplI@mu2$Qan NTk{s;.G! tE["K+rWqfzĄRm4[LV1U:63c٪* Aى}FmOyOIJ%XTtC_Q`Og,m0*h0VXG2N,տ.'LzV^]ȮԢ@Rg~A_y9a/]ҥ xsw(`[B=>/w`]0b$Ǯyܳ.Ů}dNɶ-Kj JH+PCۮeׄ(Lh1]^@8lu3.Ri8i8rZr&%^`5>aU*^Tv6v!="I/um#׹cv]&ͳUQ_r74D: 'I=5mzp(po`~|7ْ*Ӻ<">[m9KJ5lݑYA5cmӒ*sa-J}Q DF-ݶ{#ZE ӶjF-U_ MH#w4 G?iߖ\W19Ă";HhGI'Ne4Xor[6ZK6<;]/٫>:|1CQH(bq^+MH.N6{d#%,5vق h +QYdEʁ$kJ<;*ɫAߎ,ZM+Z͊k(>ԫQ\OW7#GD W],5K[k^s 0F'<? XEϫWVSEҐ/{ՊRY3C '^8bUhɰ*cBNMK5j-ܚ*AAJcDH{#9WH  h1˅Q(N:uvͦ 5a 88,"$c_0RsgGEoSkqvC<e}4kz-RCr4~wln W֤8.Kt^gpe%^Pny jU 70$xX{CPlQ6pʼ4 '9=f&qm$sZK"øn⛜WI=Ugɔ:V&~eF k[R8siu=ۤj-PdywDRX,<,MKz a'D?}\ L9V ‚@@QS=fT@Ѝ?!1ROxaО!b_1$z4%udw{:&2dݰ_,XÚWdvOٻAZk4jd,9SsD^R U4HxP.:BGQӑe^;8J!Vp2Byy֨5W58؇-"*xqgV *З5JF\ Ӣ兏Q*v]aiU Z^(f#!>yض2_TkWs SņB@sCW- L=6Q;E.Yy \Gg&[|@쟿pX裩 =2ϱU@Fbഢ~-7;?g*V@xzW]$ IT $Z«KhIaƭ)X%Ѹo k#z)5E!o۩s-Hm~n{_9= =gK1xL;?|Z.*=5OB |d#zԛ.#7RSE,蒂zS} pɕD=VQډȚ(x?YXX('YSY"[,A!WkeE `CwoLF} ͻ=֬f>a%2O'E{oG Sޓڄ7q}a_-g 7#ͬ 9]]WOTXrc KıJ|^,GG)־ o+}a [Շei[*s"2硥JtoDSDտ4>!T{/Ǩ (l8 ߓ8_4?Lp/,Tӣ(}xeR',|8 V a_ෂu/Oޅ48iw2ڍx I|Q.u~Q'K<]@uR.QO#`$;"_u1>orb O4g"G Q$Y#>v*`Ucԅnd8WKߙݣS8kEWz܋ Qj7jdQdS ,[!b᝙,v_w./D^v≻/fv4/*4U_5gŝoLHXw!tP(ݦ4^&!Xuz?T5H2SAhdx5̙Nk}U*9OF~8M$dGӛtvՔ}U>4ɹڙ5ȔJzFN#;pn;sw"NTWq۪1`셮)_CR+{.*hP퍎@X!6XAY>(. 7ɂPDRN5'e6y<b_+EV2( OKY тotB?QkC [(wQ "]Q2`}.d̤_:Ю ֟rˆW57@Yq=2T{Q"dg)RZws_/f{4r@/%! E3LKu)gJ>FQ&By1JjV\-h+բNߜ,q- V^EJ69.3)ƺgeM=F"q(ȢX0nmMqB96?$bŞv:E6z<d')>F-l:F7l~wL0b.d|G*wK` \ЦӑTN0=Cmȕ5>UJNG_ z;a# rqY^ݏ/4_* 6OT_\WNM !]aD*MIbp[mʳ@*VzegLޏW#;Smw8" ./&;y ,^ʸ t+[;vCp{ שBU->}tUñNs]v*By:ڶ+ d A~4N@3~Hjo:++^єbYf2kU/4TTMN|&3VwB\T;wl6jb(Eյ\UœIއ7>-݁L_0!}ÔIDFCftZߵvNuw7y?kjY^'@DY0ۃ0RE<1O~=7{j7p&ݫX.F0/xӂM&iIyV8Y5'TֻCH;^Uwp]ϋ=b ' Ѿvl`r9'P~[E}=+Y78U\3bUuǠuع^{ZA nKYiF7l-~621Ev `E Iec|A՗pΥ$D:w'i{XɰEmKC U&N~рctj&S٤D:&&O R&&k8c][uz@|1e_7O 9fn)>H0evsVCV\3.+? VCNQNZ 6&1%(oovuNl<[?ʃqֿh 9t^_:Fl{7zur~?ם^vn8/YfVFGSjq4\4 Y3D\l&ڣ)#X$U,t8BFI}pz F[j‘AqU?y%\"Di!q^I(]9Uyv,cف#-LNZHLE@,KODk&6ϺذS__ׯp~RM-E ŗ-e [%ݠ7g&x~9I1 ¸"&ݟܛY_?GF77^ ʄ_{"Ygmp9g!3D9# S8^ ܢ''_ ]sTةt#f)s4 @;Bﳁa;r3Č.+-VEL͸5Y3`س962j z}En2?}3FhNDT<@zYd$dJJp9hh·U)dK_A Y*lyߝnYq3*0?H* bXeUP 1e# ˬW$89oIت@ PUt|bYk~j}~{A`7 rl-yZВ!.CI8e9n߭!W~ ՜N8|-qpc{8֩e0d?chRbFT٣Z*^\k5f S22]UlJjs]tTƤQq"Z<DI lKBKr*p3l7˺S_𓄴wk2@~zN3?W{x o:4Ka3+~bP̥v5ʬsXd6ոSkGB3SbTI} nZ0YŠ@ḏFEA p7 Uz䞐m4>4D"| CupS\@H}i)Z6N1 ͣs!<ӴIS|7T[j7b->GcﷷT|++g 3\1a9%S)ǵxisHs+:L#S[;oCL`QT!:03^wKjƮdw4'Gw#W͞9e9pf^ԃao#@<4Cn*d@"rYG=g$rsC~=re L#Xu|ZXl ޮH询;3`d<#FxDL>HHf$b&$J|^ߐ!X`d/]n12b$\3,\q4 f}0!|&ϒ=.D6#< uq([z\~ƥ 8ZJK![nQ0y7Z,Hyן׋}2o.W`zG Wl_ƣ`\|N.'3'l1܌32M's㘐9C"hJh hn0uM-[m&W"1]s xE1".yB^ 9}vvv; LYnl3Ҳ|oŝuK{0]<^Ԟ? En! /;YXJ]xrgjg?{yp _dny"7i9a="1g:,@Yl^3H8JfCmAx߂Jl=ɕA 5xu3+WcWVxd\/t6z_za.֋>.n-,}e 8MV\sf!~8F|lʾ@)&80Rixt˷O8 N>Ma\)JLmx|r=jxQ# ' !ϖ%!LlH'F .KIـ9ltk7KZJЀZ J)݀(Cd&@bo&_WbUe1 ~IS:;⃯_A%:v֒o}nw21;TSu#_;TnLB4%m훀Eq%5&6n4MHOPF |q2| gUNˎmO&Xk3oB ERzQ pSքs*[P Q(r."8H$6Sַ%-y&kC^v4*k~mH̷W^e|-!`lB:'G䎑MbV"[36d-<5ഠc%mʕ*u+F=vj/Nk1wo6-ʳd?0Ѵw&o-q(Q(KP$"&~`=!9qfwH0'^p-f.SnQX[U7RB4zp$q|84c,g/VѰ< |>vdQlcg ?iޓ|#E>JAtpS|'ԴTCA-Up##J*Q5ThˡBVC-6'Qɡ&=dȖ'&|~<'J0M{#CPh,<~ƾC>T\!kBq-C%V{[vZy={f>ڥ g-!y{os2R]H*(Q rUe}Y )s0Bߪo*L~>e;M_Qډ+nX){TkWN) 9iV:=N&j~Np4Zͱ\rb-8 i_إbGEƧO?U23]꿊t.c q9E EfUr\bte a͕1  {џ}xz?Wp>Ŵ?5fUjBDF*l@:|e×o :.ٹE8-#%@A'*u8Ժ'hwX#OO&a|GݵS?7V(0Dk a+\;rMMkc|ȏcGt'',ǒ8Uwńؒ?'5O6AQʋ󍔯QZ8>{%bZ̖a թD>ۂs/n6Ķ:ardyQDi̳86>M}&;=Rn7tWcHZ-G͞ )E#r 7ɔo9DHE$圜'?*)ՕuuNx!j4뇢%3 &:͕&פeOʩٟw nGC(jp#9r$0i/!r %bjŻ[QF>|+z^7HD!! WVbBNr%Fڕ;_d[ Όh({֭[%3Be-_Kc | uDZ]U\,_H˛pDK$| eZJ0a?Π P^ oMTPd0AeT=Jh{HIS5ΘˎK}L*i;>6]#śWu[-YP:[[S45 O И 8'ZY5VzKxP䞍\ʨXt\|]C&0 cb4D8he{ edeV[o(< z ӡСJL.n R]qT5#Q,"wG{lwcpaR:j҅4fyMIrJ[..jyp֋2윁\\.cJ!\ 0CRŶْ$~6o4e]YQeZPa%Y~Z٪ -󣏪;Ul*=_5y/f2 x!xZztItw~J} z#x;]ztOXLsSSKJ2ҋrE7icy;x;Rd f-֯L96nl*ɸ\- ޽nxTMo@+)x$AlSxk1RѤh};_^4@i0=cK(о:3֏o=B,~``6Gx׌ #A\~fNj{BWhgk7};zL"{kT]dGVYYxDc$?9+WV(΍NvmtXyJ/qx[s6_%L,5777c9=ͤI3 P]@#TޛMӟ?Y1gD\wN~_~7xyǧ+"dȧ'dp2c)F.G혌OݐĐ0J% > `ah^T6TTzN =ox2LM:v,oR}^ 焜If4aDМ `p.dΆ7L2~Ιհ>ӌZq  499)W,di0k_R5oVTq:؀ru6"|_(+_0q")F %K%! 杺VBdk5s .3q98A59㷅Oz# `TqɎ (-:.<&cbUq)C%N[YiZ:Pl}l Uyw9]:Y PG '4rsyY, >Y(y2b֜ȿTҀ-9uDL::,6 ~QeC<,gO>򁳶EQ2P!䓒XV Dd HܾCRS1$,U,-.)`֤\/3VL @LI>0&kZU1hrp>ak,g'9LJ :zu( wJr9&NОl8 i)cd@PJeڿ{bVh'2<\E`a ёC /KGyG"l-MĶl(v+̍fb|. lM7UmO`uQ帢B T<$pujH9u~#1&%ٱGƝr M|K >zFE)fHL"E8R,Po*@¿M׎owl cRLš:Ǹ*v{6157ÿ¡. 0(ƄROp]( Rxy~C',-re3SRN*b*{!rvef5DziWJ'B lt,B `O _A䍫ӊSm0pjm}3H}b'\/9~BOkF`INgKdAXEUoP|253K',Yz-6&>ekRB| J\Q/KC3*g /]NįO`?-}1iyޒ'l^w=,|(KJ|h #xa5tM#I%"ޞ^sp5 饄vE'ʦ\Sy`rwHmT88|bx$9LT#myG"3>.w t|k \@j "D0x<_s<̕KnI! ːM' @39k6tȹ{]GV噛0a8;7<Wܼ0VA纎hF>}Cx7ͨhr Vn-0uy>Gi6y?@80}|+wIk7{]+Yu2$.Iy%g7ax̳CM`sG~")(ˢՄ 7:+Ù*AI l7#9-T E4xiHMX ۨ4m/p(۳53xW978fSJ! X; [Gpmaw-Qr3/қ5:(|لG#YcX@'W‰i>Ix&w`UQRxhxg0KpS oik1e&ڮ4s&iN􅝛~թ`񫺱J n]01.E<0VpFVӈNs RNzkߋkwf+Cb f2+&U-G8K A.u{:  /NGKRxmQk0+ZǶ A(MI2W]|{w|RfKHF9g4pAkZЍ5z`,^׫ A!z )y8_ÁmY; FNv ɒCHlr(}i)i¯E/)yi RIwZ_O]^.{f4͂P=J5,:M:D!x}Q=o0 q!!ZT1TL85VUd]o_6ϳrOEJ+_$۪H+{K%#H|x/T[HC\*lS#DV&1,8 F[Z Pr?UU cLN$6 |-:xwRa"3ヮZ VpԶ-t vqEad xyy\njji0:H}ڄ1<oD$slݤӲ~1n|)!I^ot9Icͭn)\g 0&О_}.Q̏f69J\Z٠i$x{|줫D:)ftC͜H?<ټur-mʻC`$4\=_y2ܻvIO׷gt& 'J<}Jy=dWd'}diOUp|B$B!5W+]N_̓ŤZڌcYŭ=,ha'unʁ2vsd7D.W }v;6EblZh;x@mh͖VM?mgVȺL{N2%˖Zfh7\5G3|f۳S8⚴{öw"s/v"ͩ20tkg%L 0.$0+20Ub[rJ#DTZi~ҖQTǰ -n*QaDlґ@'t10z)]Ap @_(ju:~{ƛzBBsK  04f&c->0]g.zbQ6cqqgRc6xnDN۬І XJ]#UJDxgKD-@,xnB2 -%eyv [)V1,cuᮩJ&N0#6TϮh8Ʋ%WWᲘArhwUZ`:cAʥ勪kA c'\[6UJ"ך IjfDNP~st`0Ǥ 8 ]RK;]jt9`U(_U5>f+ `'u*baWN7L"fґ*JHj~5 ,+S󥐕+!$v K|D}$Mt9I[PN"tYr;vx/4lb 8ֶژg8M@,(nu~݆[ߙ_잍oōY{A3LGPu:^{-I7,$@4xsTh!+ÉmD}i|y(vcg:Gā-|<הU ڠ8#ɺu/cP4`ohv ٽUGp8wA. մCt8gm_a,M^K%gF2\Oާ )uĤ~fFnTDO'n Ǖ{^9܌NtM7s^a7WK , 5lO AJƾE"BQ.VCqYXUNnK<̲w%qvYJ'Wخր-߆1t uՕe1) Kub I@N%ˆtN曾C Pv\lG,> ֡]DcK>xny59݃6~4W}t\j֩xqEW?އkH•մxw\!e&-*S_C$!DmZc[M Zԭ :i <O0%px.~[ 4=3/>/17UV!аR8$3/xr WiqJ|IjqI43'%%HS y9I^N" 1OkPݚTjIN""@8QĖ]8֘q(  +&0)61~rģv4qN~)x'2]tBfQ65&OR:{+\*ФDi9œ+U&V|[ 1ǓEWx.QzDP ´6]TFi56d܌ttf Y!$K53-3sΗw#{9 T:TeSa=|~blh0ݢK糉!r˞"WUX5rI65 lpణ+ZK e\,xb3MS<ܣV>$xH`~Ԋ 3(jɔZDp6FKw(lfBu5j$fd6#s1h̊L QU rƎ*T[Ջ|&3߹L "\5o;俄[s>yZ=?{Uiө6^E5߃]y,oӣhC!KV!/ih#`AMY,48Hwqy>3]mx.}grNfAR~bQuljp^N"'g _&WNfBG6z8O 4=3O/>8E!Z[ $3 dd[Es|݃l&|Q`nFɇ9 'p#S_7݇9QtrtqQ:YdBf~,l'r)#gr,,&p%rx.-]S`hhX[ZR^<9EE8%$$$ rv VL/Nk]΃)MKLO-K)*^&氝xXsfy}NI*n>8Mqqtq,U_TY b<$K/'dSlrvnI*F$' Ab. k8،u{hzsN?9SjQ;yl}\`8'?Tn<ГQ{z['?Tр JI-\ɭ2y%[ܲ\K-Lx.DxtI,0mX dlox.~K|h9#p0x;W/G 4=3/>/17UV!аR7;2)?(er=UZ_Z\R rv VL/NE1C771/1=H/|2Xdd\vO6]M=)536FIIE ;=%$1%HS)Fszf>N~!nK}8`M>X &W3LgRφ)I;PEp\\9I 6Яd'֊c |N`.R%I9)EP\,/Rg7GwC'׳N+>DNsf)D1h6,P%nfΠD aY,Y2JG'1Q)cXUjNupv  u qu<*6x;+YS`_WX7QZUZ_Z\$`ř^$ZO2$ 2YV/h0'^) 3NgFR?$c?OՌ2ds2IBIDxQ!m' 32O|(ƚX?ـR]h .A1JJ*@)EJ1J@GNgC E\ EEW@;]\:"dY&, h&0'2JO 2sRQdyVXR'frqus488jrxOΪ W@3x;K 4=3/>/17UV84/e\=UZ_Z\9+rpq肅usS2 'A@1uvqt @w-sJiBd&g\h5"c>7XPZFLJrr2 zrP@q.$$ p2 =}X!Ev ]*`L,w .>~0MTG}d_]N?sqA#2sR!C"*6KdV@GNa4)'xk[_S`PŕZ J/N-I-.х ă!Aή@1\  ļ" , dT0h5P]$IAr^2s&t,*?9Yy2zF~4%3M`ү8;9){ jSUS$MbyItlj6":_O{D&E,203Yta̋,j5Xy@vh@M`eK(MI-+*I-N,]E(5-BS}>XV/ 21P7=/?7U8$3/X7%157?O`œ9ƢꞬ?xkAu HV-F+cl}xͻ5f9 z$3xK 4=3/>/17UV84/e\=UZ_Z\9+rpq肅usS2 'A@1uvqt @ՓӘ&0ONbVhNsr)c8D Py<U>N 5qLf@r2 $rq89( z ؽ]8hK'1k3*LVg4eT" V0YE}r7 U4N\"+ 7, W !=~Vl*ˉ94N(-3'CY&7z5tqus \c#P38]dU6mfɲWx&tgoeX6co`^lyx&ķy~o6}O\u50zP@~B b$иƒ %ˀN>1}$S(]J)e-<@;GoJz hD.H?hx@Ȉ"Zxʤl4i[vvI3ztb>U P8a$8nOVybD\w?1&Q JzdD~{O. ĢoG' po,ǰ&%-u`ޒ^p`~yҭ064mk{gWKt-g~G}aUwk6ͼZ73{'|:/_oH:!iᇛ\ pREtq+(BZr]O\7{ g2r(~?!ȺƁIAW__^;m|v]ۣHzۿ_ X{pvHJ|7ԮF`('m(`2J=0F`ηu:{{ȥli9! PL?ql1B^&C0AФܕ>CgMԄdNK%uӤfum ei* `]eFmAmۺL(-3B݅6C!ý+ ݐŘ N,炥"9=ޞtYϫ\\1ZTTU4l'oDH̐C[mC՛mt#m4vr͖-4oi@js؀m%*ʸhQoa2霦̵ؘ"'KߑP5zxE㾺^4#iZ`͠jl;7qb S-VA?ۉ4R_Hp6\π9>Oљ¶~v?/,ǕXR=ghmARlz%.֨]%JUWk"&Pǀnǡ[;P#`RHdHܥpg̍W!ad3Ai{ @d*B;W<o#;c ܅:Bb@6ק73g寄"ʱ΍зx˖ G~DD 8Bv4wrWhTꖝ&}3FjF<#Uc`cڋ-͠⹓ԡ0AN"]g % |t5.#X/#X3rX%APZ@A>t"5; g)/93[^9Rl,Os}T1r`vuf8gӖ BNX]*fǫڈbeTJu%.- K2ҚJ\Y*es]YK}:lDjy触i>Kz(%-& Hu׏4pIaΌUK^ MknZWbpRqgg=3+<К4΅;E$s~I}ݩCM|lÉObOYʭ(r5/HKuB2![yN+V5JٱU8Xy/0DE;\BWcg .·o4?jOieEJok<0@$|e'XSb'/hOW#hhDb|mk+WgKgx%+;EƲ@kChpqw?~zzZ)O[GLh!,b$ *-6`g#wH\zF=0z0>7dcS{t-T=+­">)zDƀjaq=PI)Zb=5`! "5o3lHg+bX=~t4XuxVbG:bk)yԴ-ME-OnS{ά9nic>yl =ޟd1L#Pbtj,Q苁Нu8I3 <R0eKlxV,ErҪLss]8穄Emk〮 LE5΄oИ[k>\ J?G/\i7 򶨿ټwQНaW\v_;&=j-{D[~5DwB^~ivN 7,Z y*v*mM\pjbY5Fʣcl݌^ gA Q*7O>tuG/LJibSW#蹀7-}c"G ;`VObav]\|:)y-}Wm.F ݁΋4P.]<_ "A@GZc|P!|/ωτ*ߗyN Lĝhr=>㓊/LjKǧӜ $:JJAKyJ6bhmca@m+w\YL頻)IRF;ໜ+SijrE(y?/9Mb+o<[a,a{ܝp38 Y-c.9ITU>6Eni-~T9tEL[KRN˃n,CCe[׶V@D<UL{t,Lm:5G!"S%vqFs&Y@ eN`\&30;!7%1#뮪=4᫬R5kf r4Y&pQ5cX(0yd:oz!o)s.l|ɦ%mrXEROkJ)FxKJ2Ѯ~l!T [j7,*k^n|DT\YL9#GY gh&_ ^t k8Ecrn }l{L ?kwj:NJEqivTm5:U9%d7<ȣr;>]Jدܡn2P<__*q/3r&;\\`@v*v􁷙Wʋ&| N׋wF "]"[O$M|G()0"W(Uy> /]2;ߢ:'Ejx_EvO(83Ou:QL@LA%CC:,8'⨞:u#j <0'3knmdBH9 &KnXtL,[,&B<,ˋ$oL􊔵ؖIv rn xNەdm] rvl>/m;2v#aUW!Չa0p|$(YYP=X g![J˝-h5#\ƹ['n'JyRЍamd/nVU֖(=jx["F Ki$& mы2B O&M'Սrm:v)+qTu̮M'lt9ֹ-1-aSWTz_1C1]sX0e~c( Ƈ<~A0(oX,=&` 5V&|jy*bj<%ac U9bM^ ؾ[|w–0V.@xiA[N%ĭ Ft˜eWiScE} ]_(6D Xؔ_$aRtyu72 ^҆5V2z(mQda#q]De= `(s=t(KN% KrEȍW@`U᫳K"U=3Eφ=Xs0␚je V &6I:s `_}o>|M5b%7v:s9H>VIJf̋dM}v&?~(A*J'y:\͜(⼶LȧWx5ֽuG_~,tIG#K3ry|kY-S8."y _;-"-xXRR.}%7ָ33i*zTuW|39@(|=RJ()c^ e%X!A0Uju 3ݠhB&wjP$`7آ)*MPZWTp7-Y!WugxFrXa_QI͠kǷv; ZŊy_ xSNIMKUs WH/NNLO,JMKLO-K-R* q $I.upe~A )Pu\ʙy9) J@ctaBPBRRZ\[S%KWxQD9%5-3/U5\!8%>аr" 6ӄqZ, C_Cxu=@=Żll\#D)@1dY^%KvGLj&3dndjyd"UߢTQ4I\ E:A.DXkJj&ء׎:&k0}Dsc@f5:FUj va99x=aFbHKORdQx}̱ 0=O̜AE!kWNo_89.2.?9b rLa*ɶ3Mwb}MY4$oV&\Pa :.L9D,SM@xSMo0<_8ܫf\#d9$0H|$iҦYz3o޼-5O*z'0!֬xsu'[g;oAz i%.$rmeUfHPú=l{]BM'CawߟGN`ZmNUSUc'Êm%)R ~JqB YaZ%k(! nƠoZpuiї683,$}eAMOwкD{DsQK peMMK}τ/*$TOoVrۙUۯfKD/AozRbysʕWG?jXحc2 yWkwu"wu"Ngnƙ>z>站.g~{]+Jj7`jݵߩݔi.`BN1a,|Az$$|TxR߆)M$vqEjytNp Ѿ;ۀ8贷DE,UWT+Z%U 3z%kLX\dFYqKÓײcNYIWqIӷJr٭/<5& xks+攺l]`Y*kK$f?Q1'O<`mRnew Ƞ7 Cߑ u;܌[ ++rAps dBwIg%?=&sꐏV'>`ˍ]CkKMH) yb[> Fq讒7&!Zܛ 2$񆒘ۈ7OC#Wsmrԏ(`jmÃ#Α؊?!ԅ!aa!"X1R`@8Zl0;XP]#+J$^Q02Y~]/1J1]~=xSzG9*w\ -?~h>CdA'h 91ȕ1_NƜ\]ϯf!! dQDP&%`Cc" (ئf4g-3F?E]З8(g*'=YR`%We< ">9 !/ Bxǿ%za5 ;|G4 [x~ Txh|tp+׷ġm>ܴbsW{rs];Gk}7A~|{[:w4&޸Ej*a"1-DJ` l[˷4ԃW1/Lz9]O15ƣ9-ͫ䳱u.׫9.t8R@SB"ǐ]rBdg;:x!{''K2]X#ݱ?-䠕mQH8;M0}>\ӍLˎ|t06@^`r2LFyoQ?Mҧ )yӧ3@pccd^B,+4Gl>8^.gӅ9$ﶿ}n#Zk3Xڱ VF:|*H.kOe \~$ͧuݳeQerFt[ }/C퀷lSct<.1+bS"ԜM8ϸ8-#I 19ux<0GkGK֣fApzIXLijV{d_:ys[–@k6eTjH50K[u荰SNlo&!zAn}lQL q!~ʳ[2<,rO DZ}0iجQء(߻:rjϦ_YԝcZ!LFX%O*$J9P ND 08Oa`x#Qv_A`ADAnmB́9TEZV10.1<}2JrT.[첖I*j4MPjWJ]zNS8} 'Yfax |>:hʚnU@ 5)K@itR|P;boqa2SxRP~1d.Wc)4gk,bI)?.Vǟеt'PU`F]Y fP㲴rJ4T*z;| E<`2I{94 &6@bdLN龠 ,AS);M%IsٯhW q;v}f{N9ˍ ލ 6qpVTlgI=)@Eba.C(A#/9\Ĉ}X*y9S1F:R:WU154 wՑS,wKd erQ[{}uX\e6Uff,*1Yl Ooh?hzZ{mC8]ZkU2(f TOP} m}H>R \zLVH2ض$G: ["$@٥@vh=hm֍wsnFc.4@Y ssj\H;ׇ VJ-2IFG{GLVϓOnO)XKj/D=nԳQߺ#uط}*7jUa$DW:Uk{u.,#ƃmL>Wo%oUD>X^~VtVc  j;akmEgt{0KϠJذ%VrK,yAK6jK5Ť%{bQy0aOi<6 4nxդh~Wj*=(GRԷIAѕхמFWoJI+|WEj>ugs-OtV+k_MWu5 ΢c ],E 9#`;&7g׾mӋj(xW$gػ/X8;Oxh/bڏXtLúo8OpcJRb'҅iW$^~-&obu$)9`Jy != "X.SÕ*`MuR֤.;gyQrR:0]Cq8OCNr$ G_#%&Yh=Mɨ*D콟5vTFwFa}A4V3.b)8W}a(q\e2ry4Rmcc(Td6x۷ z,IśMYĕ]B#"4sSSKJ2ҋなSKřyE ֓ 7OVc̩؋qr!5q%'!̜%&4sr)*J'rLS59c9DOQjbJ-O>b2 *9Hqr6z&9̏Isd)hO浐N/LK̉HKI-*O,NKM.OOI,I(/TG!71/1=Hs`6L,jx_x}O r#MߓC$ (8Dt8*/ ^T-q6 AP3T{+8 MZ` NS.AT'/x=w8?Bͽ c\gB\2ӳcltv'U$[e g}JRU$Yͮ#{Ǻg,GMg]/LP$3洧v;>RhI0!%n^2Zͽ` bUͣtg3eQ^z Ghy&}zn';mAC0Dy,G;Sfs$:2;t0l Y:X˄E?c}/b;`7i;w0񘝰$sjJpGa,p`aQx<cĀ;9bQ@v,Za&;ͻʩO0Ub{gy$6:A A@c`it7a/mg8 j0'@!\nK|p5`ao==|yЍSL.KA6FQ`&_ӿy]=ֽOF`һ:KkٶEbd GOa_iFm`9itZGW[ɰ} q`*ʃ `8Ͼ;s65m.gԽyN /"ϵYTXwVAxìZi@co-~RP΄PM_IhGlݯCYE~r RlfzA3B-=X@v586X1&)EXm-&vھдKqh=؁[ eXCt`o޳UOyj(ԗg'gb%۞o&j JY_ٺ$N=@mk\|) gAw4ƃ?3^!D*/|`c W,+lt11~N$cq=ljFE5[hv 4;Yp-F`w7Da&1GĐ͉eJ{F{q>o eb`lM>{" |f<忡 V v!`Rǚ>Y3>B=@:5[5fCsր(I{{ Vȑᇕ Q 2'{ +F9ŘD;ӂD583+ɝ9%Bek^vC7W2?aA,(t'tBV1CN *JB`s*idyX_GKNfJQd&h ZG$G;Q! rb!]]BAQźw'_^֍+җQ4,,٪?R<%k3Qe*3^Ժ2SAj/\|*C+y/ȟQ \/YĄop` "YVXAs5iX+3PZ Y57UMOD7.S3j1}68Z3(T L qb>e 4ߎa#C}La2,zE-`!J [Fǀ%0'~,UYh&;*r >&JbŅ*Ue lW5۷Q$ k~-fYAHEvUcK੬ҷOQJM +A8FAы qL|%*6~& N/NU!S-MH6] al5y ٷX\KR$/]ܢ%*H `\(Va(HV8[ U=^T\2+_w#&cN* ҇J-#E8u@=݀ lwTI9$Ce;`ڙ{ZuQ|HҿԏFqفj(Dʒbtw,ώĭ֤џ\Zi4nYϼ&[T[l]2iZ?Ͳi01>E?lӷ:JlD>9F"?t>$/h9iY.ƺXq}AQ"Tb@{<,"_&GQw.˟ ]? i'&&)W|ۭس2D2P<$ӨmR@ ]9(0EQj'%;YTU) sy2jǡmd{_Q)5f:>d^̙*AE@(#9[ /?o cQ %c1'\D ˛[Q$M]?JH_sY.\, 'ObDI>WwZ$`inX+_ヲ.ڐ"J)Lb\H!PfKbй'PU7ا%Cʍ#wszs/8b6Eֽi k)&EĆ"_wTY:տ2t_Ba(<3 JƯP W1R@HtvߴME\pV+u5oz0nn`Յ[j}۹:t/U{m&'`w*|9u'=!I⹬)s0b:ޭ0~shA_֔ cL8b+핵Z's xG^JA_\u~>p lómP...?@T8.:{6^;`%YJl&3X4!zw/\/kn2J~ߌգ8vW Sgxqi3j5!yO踴m{w_S {' q"5\2k %7+C6rzɉ[&;,N :`T.Zrp)kPܜO\(kbV36/fU1a)"elmSbl"]L ôQZh:]xg5TfdoP[B E]zOp`OuINx ӃҺb]X=:+ltK.>EYHQn?7۪coZ Z!'Ll!CS\|D2B[t6ZNNlѰsX3Հ;}D]>ɑ7%o"@5Cx5YȯRZeVG͜Qې!k9X (B-r6LcGO,.',%򵖺@K& +K VXzM|VT=sQ}"8iFTH217^MY"IR{}-ByNB4ԕ@RȆe q͹@qh^}%:RF32AzA!tt|WglsFڠQSԀ eݫz3ÏFsߑfe7+p>[; N&qiO8Q2?Q5УQc:!!񠖥Bt73gm&+`E >r\>=DU?&9am ))e>zA^c2G+R٠)Gmu`AQǗ(oC u/ꊧEǿi/|{'WɫW`i`kp U,ߓσuXx|ؗګ9>A ߁*$8W:#K 6_PcRmă1K{ŃT584(aeEb#|y/oCFA=p~gǩ?7 &xzp<~qvÑ&y "͏>0lU6u0 *ޣ*5A)р`[m#mKLȌc?~,ۃLVp\\DCr6Iz?0dgFcku|(1 @Mc0Zq~M -KSGS67`-Y[Q?5W~ߘȓi=(>=KsLDw:S0e0Վ|!/$a$ɤMi!ZQd%lb~QO26 rV`͒eiThX^y1 z|t.正񎎲Ȋ1]2F7pt|%{pxpsA,[%GIt`z@ºK pگ W_lZӗ4jf#x 3d㷝Tk޼LS_r]:M3%F5(+K.8=z~~oBKBvި fCԬq~wcip>XҜq1f';+s\z g/ļYTd7a*f0RsDPORx#c>!3ۃMVNT(]2C @=L3]ǀUGv y3W%V?>Bg20&_32\)9VsLD]t0WIПb:B cv+L5qQT 1j-dR<;9 ګel`QT,,Qf6^y 0178.c8l; )\ s ppJ;>U=`5YzTJ\U v*RT$il0Zw~] -:Z⬩٘e\gOTXCD ; 8A~ n ꚏ@P~N&9TdGͩ_z[VZٶG!,znkpy9we|oik[+a59oTIʯ.+KsLu,{GW XҐ08e@RTS6UG&f\RDQ!xOU306% szOɳJwMC-1,Cfk9ȕn\Ρ.|T&O$/aDĩ2i;hM WxFsA/7pwF\;'$Q׹ˣwR|&WnlqE%&9\/J %'z >M`5`tƬ`EWC}upe|l㬖IDL8aRܵ;3tSj*(ǽx=j0D "Hb֐8Ф(%vJ뿯^vf;אoLQ6i;*|$z]L[*(/VZh׫miNMUGu1۞P(GHz cO&;BQEGћQs* ÕZos8nk{fXuW+Bf^⏲UƤ)mؿxvuUN-)K/V)M̋O)IMJLN//KtLO5KMuBǻ'ed!+Mr,-/*r/,L(T0200 OM*,Ib3G&8dD1|Omf $IH;$+ >EUw= vDVJH|AG 80^d_``3n1'Wm<[-$3`C "Y^nB႐0.2ɻ._V^l .A)"p?Ic>yׯ{|o]r6N>{/rX#Қ%ˋr窥){vU\7^߅qnz'xfnK.JӥQ&̯jEd74 6_/9͢u*^^ `P,My^\d< OlI-ݥDK1^.4gb}/qEYwۋ潛0ͮ…ðw=eւuEZڷh=-笮?dYqZ%jUZc~VcZ/h7\ݺn(|$H߂m8Q}%,yrg <> 8]@.]& = `K|x??Lg?=_c䄟ZuGAQj(uʣVGj$ܡ|UVcvi]^iwF7ɲp4?\pptFtrEehz.#M,fO1ҝe?(&ӓp=`E S9c֜Fw`<0}Ϟe9m3XNYN.gWa *Llp o{i "Y7ѻ*M|b$/8ֳ!?(uUU1kB]PJeTByxInJ| P\ܕ٬p@aER #ae~eVSer9QEOl_.AbNSPyV Ą5͹gWiy}bJHy&EfW$]>/8/w[ͳUrp_Aދӓƫ+TFD8E ?c?H:\zk72[.)H?7<+ZA8Tq;;ƍ۾o<`}I!g3 TZ [@; ix8Ќ6Ş;̣T~)#\#ܣ;C -*B[A$Y])8]GA_ kЖ,Jiv$*w왢>Dew+1DO'6(B0)*0z닋RnfNA+7)faj/d{!D|PKfYp3k/\ZVfےM/k:G,ߡ]F h=dyt3w@2AWIKA\ox(t7f㤤g uN0x9(+3Xd+ .ہrA"!l*69]=0+M]$YVO{U`8'$B2MZ'4Q|ׄ I&bA :oK+%l\T> F5Ge8{%OjqBāGWhZ[ύ((0zĊ*q0_:tV_e[I¥l,ܦoUEQ”%UxsX\x,* Wamwn5bo6Y9a Tx!q ~օcn׬lj`Kk t6.Ah%)܋.׊E6-by n@A ͠[mp<ʦ lV5V$jmN$r+<߫e%/p#Nzw= lk{m)E.W է}lZetvteG'/^TX ɗdtr6!46Ӹ^]2Q =@ýQp2::|/r8Ml@Z/Em}@u(YǬP!oj1rŰ>_ױK(GOE{x=CZ:E]$ze{JId u)R;Heݴ{G=LUu!֣rWnijN4Y]%K<_f1(tSQ|=56鼢[V3g:xqv%Zh}]_%t5Th@*l*dJ|Sk)kcFOޮ-\f"p1Zs&QՂc*6i!(-Z HCvAV+X/Sذh̗RWxDC]c f9 W^Zn\ &(Z S{; _U,}׸j) 2Wuz+yC+2\%K{N(?V^!I&@6]Qt+*4wv%Iuen2V4?m >hw42P]NRte.GO2t@߀`fD+cw> hnOHGY3J-A$,Wϯ6DX _UE^䚪nLcUgY`_ocqUNűU}p ?V`R;V]&dDrmnc04@mFZ)_];^:[N`!yRw>뗩fQ'N)& "7zmo"z6Sq6nG@N;s{i.3L/G\/!a9%}(s>G|lCTX%LyLIZ}43-]j|/ϫp|ޛ6Z=(m&ZŀZ2i!0M9i}_5O$ZdQ3ThQd0wZjۓ~*fϪIu0HS#{S!, [̋8nOCl.:JmPW7suT)b_᳌".ZWAd%^lvy:)(U (Tښ$X`-@Q( _ a%С= 24h4F3B(C1fY!2>@vejeAS\dXw dTW>69zڥ] Awg(-,DžHH'#Ez~'kJ)Ỷ`|(AʒRhCu-E9^}:=^ &U-\nf,o;#SAқyt=5hszWwKj0(vCn 'ʘ%lq, - +֖ б6newq>꩗7[8KPwhK~&t ۻ[K/a`yvum s{ 8UBrYJѶWavȌ"Il]j.갫T\ITc u0ˢ5zxNOlnHʯzœ2Û^fp>:c`!-e;*ČOm d)NwqYj)z>6Zhdk|/.UI/ vD/O񰏇<=;=h@B;M {==t P ۯ f`*Lq0#; Fbư0QC!$;YceL1[$0%MQΥf2.Ÿ5}2/=8Vv$Һhf*"J+݁}9%]ЙKge-?󦇃mKS!(ׂ_+/x"7TP? kPhI~BCsZhrKXDz/Q2by/XQqi`n )Y)1mikRb aGa -,$S:bSEt"c]UhY-"j&SknVql'V8a g Z_`PCj_wѰ5G"Q)g'6/@!ȮHI`6gG'dsnBoa\(QƁ&3`T? F"E.dTe=k4>2LoY @9ܪ%Umqv=]FwMqqˋ[-SI ̧loR Wv5Yٖ97(LG{*v{%bή*^N ϦhE(L\/"* u=|)iތ1XH?hvlxoit-ĭ;*((.`t2>Og6ϔ`23VR18[0Vl--,[nWrj ]̒U'7]UkT) doj Ѳnj^򐛇 fFR#OXbl5ȣTVXW=`#sd퐃6"6pyN4';ٓ(WGt%G[2|2])cȡlorX™272fdmm~>=JyZdouJ8B4}]eKSoF:\+`Tś M2 }/-+>Pu8؏yl&_k?|J7STUvH)pW}(qɈх j: nnSLpe 2+T@.&q%2f*iMG*RWxzM* ԿKK2?VR]%=tIOj eGĸ4#bW7ϒhC,НgoL#3r"f#\}%$o0͏A`FM!] "p>T;bl 梣 [f%[(-d_uXUTmԴW8Plg4Eb(*znG<_XӄSHS^LZő`0fXY@})-K7S<@LϜL3VFt܁~ we-Q(6d+fq5ᖶlPd_tꎧv}8TeTFA*U\Dh(uNAG Eu)p(f*I)L,aG01@/Fϋfn`p48 8J妜hrNŚWS=&P謲O)ݵn4OJ ZOӪ#b_8(EPV-2McېL@l D1VVRéG_tOO7(tpP]-VtH4G5Oi'gip6b~<c4{US[-p+&Pm3&u|emhg4:}6^)"maQʐ[ԨrB<~mMb|_3@?m4Uiє}ebКX i, Sܗ'1 E<_''5`kroiP*˅? M="=i7&T^*B* 9\S%YM\+眡KyÉO׺DB :b.G,$a,x W˙'^FmәaX*Y!j?K%ڙ;8O4'cOpe:}HrvSPŐ;Y Bޫ5LGij.fWoǓb*|Ps.փ"oGܟɯ[Uw2N4Y෯B#E!^ѤzH` ɯlÓGݣ@{ L ٣H$J FDdsqv^Nъa0pp<`9H Ȯ$9ȃq[Yh'0Qsc*4`׬\ijPRZj Z"Z~Uc1p?>\鲣'JEy0T% %"-0z)}4逗p捛%#^wm~k "izkvvG$yva,ayQn]ЕНY^(4 ޱ>磝U&>58MY 6:GWdn$'y~i/N8 G?ӻƶ3gx|J(US qJ!Qʜ@ Yp Xq*R7Q_GvvzR7RbТ MlL~MMWN8M,AK,ddb(RF@DevJdJ »Bl.V< b*:8Vx^-Db@y )t6KޞDZ~Zj̰.{CXs𥸠;s+7gkX!&i$=[?אp0OQ\ʯd}yE*۠ԕx|r]eX@ nb%}? grbD.:#'ݝz{1\zHDUɡ`مwܒgY,P45"CiKKv)k*9  nY)b7 A[Zb<[0?Q?hh|/B!e^e[ #SD.LG?DLB.«e2CM5m$vA*nL}X3{p6| ' !D:/\9窇 ?U6B%MiFo\$:}Kؾ#VP'@#E`RZJ u$P<&}*'ϒAэ ҋë_>Q*v5na]˯/374^ϙƄ- >N5xymy"Z%9 tޒe u+hŸ@b)gץ.r HpS]Ǧ2C I@np(m5gfXch%/Z*lRrۚDi=^QFLr-^] k*-IgMdNxTs~jnɠ#6D#T0*ٿD9P Hƾ2>2ѱ]q&LUk pgd1]蟦=),@\e nS(sr\Ә jmYxlo6]5K-lVA~AQN/ɱ,[ZnkN0XTmCi/(:}?],6C,C%&((vpHzjAÏs#GaW-x zt>`?7T#J?4η &)xkp 0.FH 3 IS2 Yaݒ w2/[ΰ6b@7Wb:  U`!ǜ6ܔletYɤ90G M&r%%fuow1_4g_OYԯwDǓuoFm aPj1 tolO m;XW+ْަĄQ.-`Q0Ǎ,c=ztY&JG/qSGdɏwi;lӋ^oBݛQP5kS(PA?"b\vF)Ǐv7SpOCѨB(ކuxOݧl_\_^Ӡh&X;IJ: ]k/Rc MjRsm[;`'V?7vW~{X!Zev$4G- ܀N-KG谗昳wiޝz鯗s1:"xmSoxwRQ^J2Kz$ćI/u2~;ֺԅ^m+0z*n'@ąIYyh\xM1aG|:3۟HȕWaX87@ ̚BA関>*j3EDivGx.vZPz%$2s VۘƖ K fٲ(oaf1۱ՇTw;6=ɃXVo'/#wbA0$0|i sw6tx͗(٘qPI)8$S-&'m4!#Vvf4eI'PS C@$uJ]آ"u_> ۝6ȢW^5@PS m,cd.Va%Vh xOyWVt2MYՓ/~9ޓ qכMkoeQlY FLPF!]v_ [M$BMMXhT9nV0tD=GZ^SN͌^WVӥ̣Z›a]o1 KRzhqTXndlÛGHA T Lv ԹK-\LE9 4~q1*%ٔX|Xɛr:m7VbYWؽsϿ54ᅄ* 3EpG)%0A)J%_!>, :hvaMSsGᢐIxߍ33h`kYnt t=b5=[=$햗ͮ;w\Plo o$hr%xCTfe$0笮8T"ZD7qC72zjcBuJ}R&O i"'84p4禐2TBO_%secaevix'=U[Mݤ5]=U9d;P%**pyp>Lj\Wְ% )<̕\Q;ok;]J7X@j*D3VJZ[Tgw*nz Fu1ie\Hk^5UI@dYK1D1: Orus=ܶvMȎ|&YO8^pj4PG2Sma[~t<ZHh(^ 1mC4T3oӚ)g d,6^/[HbumF/A1 Hw&'̋B}:ܩf E-ZͺG YJ-g(œ:OšPSj`'tc6=ְo,W'b2bk옙J+pr\sݠM/ӟ]r Ox|2V '{#Zԝ)Yᾞ||HGVs"[3 5{ƂflsUzϟ".iK#o񨞼z GQ9A2%Fg% ?ӄ-vkO'E :)떐:"l$*okf^P٦) 2I_.ꉸr⼅ d[Q,uc}_s/TU\ƴ7mR_'_dƗ4q?NNo:OKNQĎI_H]qv8A@hJ^7ns>7n.Z}3x6 4FoW"SLIL~e ǘi>}=;4Ǡ;rg$=ɂ2, $xBQ˪y䟯<@@fz$1OK^E_HG[dž-s?䦶$HɡI..mp$0~>99FS@ N1G_iK*U1k̓1Q*a8)RMwh̊qVasBm;Rޕ._U0wKjMWj9`})}xiLJ7-c^)xHz YJ?xKuEOjXR]A=:.aD~%=כI9)#@ p40\ kҺXhn\$Jm B  ԩ&Y$Щ#x_@h*K*j%jy)ft\6S-e ".WwNP &V(tR9=xP1lr:) uXܠmtL0=ހ]ip=i NǃNrŲAQprrV%|GZ`z*'%rռXRe)gj(Nz R@#meT懡fpf/_ˆyqI ]*Z3o,$=3Cg3 gԬnPC]h`t8z*N< Ķשtp JD8a/%afWrwދv\7ê)og{~fƿ7%j2iW5_41#>6 {gJ\pz(znD.dJ T޼'"oeJNl8Aр0y" OYt@4%[i| Uf |jmӌm''S%h9 M{"Z5~`~lzwr5h?@7hUiph\Z-G10zoI P~4ӫio9wwE؅pdxV36#|7GSLl˦4TiyAW5OG0=tͨwN걃_t2=9;<zzk=ZsGX&P\1f>~ܰ55g'.\'1.4dC>H:-ڼFC5oA< c7GiPaܴ"G''gɥy`/舺qlQ} iQd' GVq=&yWR'? %.d-n8<#ts*Z6-WkutJj@r å8G}?Qz/CkTj_Uo2 li|\Qp .A9NWlE~KnfoMq>=qc/s(3e 1Dl⑸jd xixr6y®'jjģP6=]#V3Oƿqf$íݧA 7VQ ]rba$(Sn ɴ1k=#MQOيl}a%,%8u5k*3i V-ژ ??l9n֖ւ3Gɞ)OlqT RJ]3AoF:k=ݐG?mrj ]{00gOVy6:ߊʝWt$*] eH/[`qq [wd{9 +xYD#saHwؖd,HV pY-=r2`>K|ygr?=d i8#5(|b@U<TVt=W~# 4u{I#TL UͱE8<AN5Hc]B^aCw=<1˭b̬d5KQfi!;N%1(0 vRP< DJ7l]'jO Ē23u=6ʖ 94 \,7֠< ~SAyCà堷i<%qMq } "MOi`WMiq-jX̧P 4njfhXYM8 yKٍf0S1髣[J=a<;#DS"FGL^FjDnQT:R-$RH(/ }l) I,|IO>к"tK>s*fQ&xQ[ی1VCSUBrl2k*FrCbxF|T"7 NI(`+,Hvr- "X2 9/;umF~,X6YZQ3jQ䴐obp I7S1)%T3POi)zۯQYE\BU-[~աbUfsFP/Z)^\K֋9 &˒d2[Pw<фHX<"3+O`$x| ո(j,~C1PodF-uT=uDrwU,eNK^8mZT)x0kgun E)e/i+0:YpG);LY(dr,@26Ro:itcP T>Vcôq2_GwY[n+0OG1ʠ.a~BR4nk/v: (PD^9CuಗJ,e EJΎQ"/_b&*UjFa]^*}r[4{4Py];Z$$Y9]HSyJ%O.^9@ v)XmuVi$ LFYRWvɣvataF.3s5\R(JtZI~0 ' \EiDS%,M+]t H#Mx%Q>QLhަ8z ŵ$:oc*h0QĀ UVp "^ Neyi鿝2}*69ZQ&o\r{g%zj[ּa=(-'^^WF[7-a=Ezcz$b \XMr)!CMMV(z`ɟEgVtKD7%124 ,aBuK__Y]hSRJռ&cɽP߀[' $ mk@í-FSQtߒ/s,醻PxI]Ó`0տavGGO3<"wkF,5U2d*o=iTo"Vm& ep}^h+" R9S1$S;ZύRLMtrpȱS>k:+" ]$mgu ıwsFs;&Ib利aq \Cb`88 CnU?C(\텶-?mb9׆Zk_Զ=2S)EVry:Pcm,tM۽/IE䔄Th+Vy|sCGA8ڞ >ӟqp|v4(ch"En#Jdee{1lU~".̓us]կkܯ%LuD2GV4reN#0jL Vez-A]RiPZD* p<ыjFTsYճlOIUNAszUAfjmDZU.jS01ip]}:lKd!ˣoB?d**f?۞&ZM>I+΂{ҕGi(~XؐF D 2$Lc'VzL5>j+5Tt%V1e$-b ` n1bm]6d9n'ɇY}? . )kmI5 {' mkt;M Q7b֕ߚ6D(UEyY( ԣ矯[ύkm޶pBBr*\Hv8`NZG-t.?q^hvr+e0; dVwJaw,[%6 Z=f!^0 q% T]] R\㦾7UP `sy_QZ7+K1nh` f8vtiA^t)y`]:WiC]*vcػl R%έS BOOjAbtBmH //1G \< Wj1XqO>.S⟈y"^HuQ?_/"Rj[J#-}!QGJGfWQ=2j&K&IżMR‚Q8n9o;dy谩PrxTw-%5R:eׁIM˪x G͋8˅HU^"Հf_y,hiؠKI@X1Z+(tTlW.  *lҎ:g2Pp߷<*+=Q4x*Ot쎫G d?&q?`?_F-,ۦ*xA:|g3?0-Y9޷Hiߚq2:@72y?*DGDek3 B)4cY} jy}Aso=p.0c:{YWzΰt1N.m*>`:j@sXwv;sO)"ᷬ5wRҶzoRWc_?i.Yg>;Ӆ{IO&<`S5Y)\̀i.ywuZ/|gK F^SzܲcJ.i0 jSL:/6* Uߑ~V9av(a'l$H9avc͋hfHW2>Te[])b:0I,m2+8LA ?4޾}ǭaOT/X$tJ Lu6>{'CدL SOk`wW]E`J]r#6s(G3օԶOϮ91AC=P}m#]q,RC (>UO?'{Ph|R= YI{BK39L1> meߖt/'4 %KfKcnc96?³ܤ:%j*bżWx:[pus%R$.  "%˖E4#r ,]tw!dɏcI֝$NbzԚ84b'3M\Uitj܏ZOү=w_X).ԁGX qZVĂ!|ݭ%xO q(][J-z2)Jd:.C'5ysוY$xd.AVhdN(rZGyOJB`¼( xxj k3ܱXtxp>1΄"5!rTMIǴl(FspZ4Mj  zX %z\<fgSeE鏜*&$>ɉ׹ 1|F:5P=%]F)x_+G5$&7|;Xayq!rx)n.Z՘,I©1E$S"5!l0  rӏM hXx }Ũ/i\\9D)c^6@Q9XMMa;\.&T&&*'<ƙ?@K`eD'e> J|LKh)*2Tj"hi"0)K -j¢ܲ&? J>Hly/ȓKj Gv%-I'%!JC AQd '7p#y6T&cO'Ue\Ą4!lqTraK8*!%&9ltGcIt>J. EgGFgçNOp'FOp#>mrCU'6nX4L^ZH\n:=ބUY.Gm"khhg#=["fgA3B!L붜KO[1<0@~Ϳl|LCooR4S~NGSSLѺS]{,8\kCq 'GM?ϨSӓ#cÿQUoD"~ӟ9MS\JN`Mø"g){=א1{Ζ#m[U @9hΖ "4rgc\ t7hAzRC 4Lk?6.h~zrfʎ6#YN y\ !HؤC^Ǭ BLTwmSo5Խ ɩO54(xj w7ysN0c}<9r bQ9@H,Љư9dǓ@9n'=nQ1yW9/5hK:@=@fOWUA~mC$UTID"AAHojJ/,ONLpᦖKGQ?~';QtՓg>жlFic2G,A:o!7 {Qs ΜY>L:^:> v54֫mdvBpZaw~Bܟ]9lcQa*ʇH:mQ{S%T^+K+goo0u$Ɩ,(C"+*]eMUeo40FE0t {@Z+ }|5E~r)[Kqљ!/Xg+]|.u| bXx5wQ][P Y$jGo@˞B31jZaM?:pKVM7aHtlr(og}@Cb ^*bDNv|b3h'cN4d8»]P=pUz]?dՏS[` 4H݌0OwtY6tQaӻLPmC j*/Oy:enú!1#:|ax9f6k5mAkZuZk-*j BamApwvGJWK bLwp]?d;0&UFʠ+'xQd+հMQ:I,8G8Y@o8{uEsF_y3%hdFeo?`nj)O1BK+dF\QEnlqE؉9>^/TTmy,Xf "CˁofkL&:sJAU@p_fowoS J2([rV+Z8^C^kp} ':CfQ^95ƞ.Ǟ*!oU]j7.fleפ[MȰfy`0'F ι/V|?][߲z SQ0&Pú*$ypkQ"A [S9$&P< 1\п\,崂Ͳc+tJz֙tle.rPwC# 9UM:iƃ,b{ PM L/g"^|i\ie ̸10m ֒bhlkOك|8˚ ~9jr7~߱a8yr{^0^wӷw|J3ywTvX=rp9<-=[:/rɺ}"yz˦O 6QMo8MFJu t#[lJhw鵰z])Ǽ20&%*Mg͉W, h)'v;~^@\A{+:ꥵ?AW;Ko 'q}6>`VFq?A̞.yzבqաlaFCΏ2Vq)z OBFÂJ*q9o!L/4;Z`N8}jyʦ:= KQs@_Gms_k'7/:}yx:[pus%>HdRDRdٲ(fėr ,]tw!dɏI֝$jcz25qZiRNgdOZ[6鸱ո&5=_u{x&?ᇴ{9.O_BE^R˅x@N*b|IV`<~ ׮$<EI#C̱)nnf qQnQ&R1I qI^:czZxRdOϾ&/erps+rJu.+ 862=971H _Dddh~иAgJ \Z&F`1?_x!raoPdU]A0EpRJQSŸ'81:N51bLWc\Zd<+t<[}^WBT e Z*-q0S)޵% P85dJfAZ/OLhWUS8·zە$l(i1ES]՘t([GW]d] ̓gK?Px8hFH8 AݎBy6`+3G1#Plg45Ӑ؟߭wqn`,23>;Y_˂õ9G+wrdts:3;=:1;u<ۨzx&Ӝi rlo|9Cw4Qݸ.z bY[mu'CYLbsccY[~ jȝ! 涒rݠ^ A\zМ0  ̺!h8Юpzu8263dsy u_I\RZ . lS_̽ ɩϚݐ4hu2 Uyp7u8 }Ԇ\rcw_K֟B,k[̩)e #EQ!uT]@Eמ>?7YT8ТE/ ]pgB`"{琻bEiK8hpOA^$c(jΰ\?"o5)]ۓ?BE.~8%"jo- tfx3Y֖Y,u`.MUq LR~y*8ڧVL=e{>R\38tyk/2*ԇVb!* bb{lM%d>-*2TEAȰdْPK/}wHS]O6n7ߣBwZtqc.e+t2O~|m Cts Cl,Hmim+s 24Xz-&=C?jr,Ê$=vys:4%aܡt(dct~u a,vj]Ϊ mwc'\'rfY. 8W5- 5r Q ڕ|ujݤQ#4z!Cnw W;::| C^R$yZi +_Be*F}B],օz[ t,j#U(|`9&}ddQ+0ME@vL%+k>V_ՏYoBwgw>ڥp5R|4 ˚ $'$p!ד`.= >!<+"V 1``&jaq %yuEBG_:fƻRW!1/C ϣ&1AC|طgB v_.ћ=|0ts jZaM6?8A~+zڃ!{GXdz421k^r(oѯDF%|i;ӅԽ?\ĈPOv}b2h07cN4d8{=~s(ޫQИyg؂3ÄAR7c;|y*!]ֱJ&]態(0;Fޭq&dw!E5We۰nMHoъvZ}6>0vƁa\ݵɚԠu{uZk-j BamIpwvGJ%^1n{p]?d;0$TFҠ+'bxYЖd$kְQ* Ic,8K8Y@o8>غ"5R/WU=#hdFekcnk)kHQBK)dkF\Ayvlay؉W}}Ľ`:0bp1K6.;Gn7rg&g9}% Bp`ߩ8:Ѐ>mkva RYeK_ yE˽ꦷ7Լ~^qs3ÐYpWϣ:ijtryhILi#6gÙ߻ț;_aSHx$L;B,XBe1uEUQ"+ 7"&1X_wEMHBjrJf/ۅ1( hgE U=,:nIHT9ϼ Fy1r܁eIG׭Jv'RYVA *6^1ECO5J9gK+K %i+HVDb[Ү|W_XU?ڌɕ|;2l&]./8*AOܯ46]OfƁ5fB/:ҋ<l"7G?&P?^Cz=Є7rw^#?G¤\E{陫^ >Ztxο $w2w3g̶~]&?740k|db~.@9^GO ^wus$/Κ*r~ѐ#uz~u?Sx {DH^A[B.B[' `e湨p]G'~p e__G]Nֹn7n o[bd)@2?!j\x~ EzyxPx{xe} 43x:mpu2?A7ŏ%$,Œ(ʂHPM Hc;ȋ;@dęI&8IINiVbڮز9:ljg&mJ;p쾽;wrno_)ߠGfWځIJ"ͫ5a!GyՋǤH{yYٳ2˳,x>r\-'-v(}s 3ǖ% &p`$73fS?9"J8 qqvN< (yC^)"U$WӲ" ʫ,,?'P)p`/ c ? Px?n?w 4=f&4OYqq?0 kj3m0a/>hLTE^n#*FRלK* ȲOJ> D"B\P@%`/;;%Yv1+$%|k&ͷeU 5if PŞ;@6ȑqBnjh40NY7)(%{ K AǓ'# H,CCwrwft@5 6r$\}?=C׾*>3>8}fXu՛dR߈;l4e1G2ʙs^l&Iy6ȷ7T C[ Vן xÂNQݠݓuo>d 7=LƇqLdh| NŸ~Dfe9.B"}xǧ YgZB8N~@HaR1p49A(.E~BWV~K}ϣhsXSYTGoU?2breYa DžSSؕ0Kϡz!rHYTE?7ס[Vk.*&rV]@^Dfc+4UviFNEU{S-~yB6nj@?8-Q 6\vTDIT͟V{L^F&ޗ&O͔Z,!"fζXx ò03ʜbc5[Mrrf*%QTvuD8̅Cl_.D`BߵB޽n&ko룻oE1HqE*Mz4NIV8 =QkSؐN77ZfeUzR `/GVoE 1@Cih)(RY8V&ef2dm* Ԛ]Zk3%#\Lce=pV{2JYbNYjsX&\b¥V| xe%f"O &ujhj׎4 !t/ưKåV̲cېGncysJ:ȗϷ1U 577P9l ,9"ww%Wh,8br|MQukMV OБKrUMD?~?V#yFgVePldsSnUn">d)^ڹuw^$lzmmkm5 5'8VM ہY^՟#rgyv\yM6}ܙa6rMQӛeL&T o5:'j6a!D^J^8ȾKe;}0gS "'E]6GfAzn,NUXGc"(%R4f🴃|hMi1«.}!0\q:xOU^uKQ UP϶x8>emXF$~ގ*Ja /[K->H^ztx )6_@']H'KxLU" sgF&/a蠌v SeY˞u ; (vorf ̔d{^kEim͜峃iEࣜZyUU0lcb\`>zr#zqb6;ݻЀ>c*2H^á4h/s;ˍvD ̲b1;:B>.'f0db. ;2k؂*0ߣ^̖;LLYlaK*ʉzz(K'(?jHFKylzY&ޣx2Q5| b e=m;0o}Û; m 9 ctb5{ q 0Zӂ}kjwZZcs֯#,qۤmd~H&>_F'E#}RXBY4]&ϗQ3cUlڳ|]HڣPq鹿EmJ4\»*V(Ɇco,`r v`֟Gs9GsZH˾j퀍wBI,0,x$X_S6uů6/EK2'2|xдH!dCoۙ= IåԓZ3ϞDn`]"mp8<AQd tCp:'QK!}XX3CrO?1`i{aTYzjRfvnk ($Fiwץ Pqh7aǹA{j9 ]<^>͵xſT (#`6GHnc$9 ݝC Ak~Y&V1D-y;j63t|jH?/^ˊ][7`&m4.nW͢?wkY7`4E [ŋ{66'M=}e{[xq" GY& *q&e(mduad*N\&6wE WL ZM:,]-s-q7 IOPJ(/W9BEZ#'@xRKKQ&hC(nA:Cq IzY`-.]0=}˳kԢM-e hiTНGDVs{rpup{6:L$lEEKTJN wW3jUM$캍N kJpQؚgp"+$N+EoY]u$hf"m0X{CDV$PJņ`l{IÜ3('4p[uSGy\lq\"#bFY2b)!`m`sר J4 'S&F 0kqDLl\-!޽H9ȓmY)+m}p@8.rF&4 6PAf]k'k +x[6q< άũřyX)kdCSK삢J͆_U9$(xMOHqZ^s6mM -K)IB޽{c֥VՏz h^.Tyk5;~ϗϳIX{/cHI3V?e$.ws3@*?Ĕ|^˟ZJ7L6Vs1_KWX|j*x֘,VR:{v@QXWb@ npfw@'m@dO_]0bь}h>S}N86pԌT0[E?VErn _yi=и {Sy{V*T~OWFOȒ*+٬b)삗{[霒wdΒv9tZB>\Ϩi+l'4&MXA xq3&|%$'ۨlu װ3M?˨2_tKvFWRPtONFEBRjdn9o^`PaxS]lUΡwnw[r;e I#ֵj42;{;t;LH4>րpc4A #4  &]YyA&8;[i={s<,ϙ(Dz/qz jZg6%S߆8uTmvdR5%S]ܞӊJI2N<5J?9,>b\sqopᶼOxRS]*ݦ6'RVĽu|QR@uZMŸJX";mPTԜ^k1f忨k $l/gLk>F AodR|/ފ7['¿/8j0r 3d. )AK, ÞGH1HG.ýs޾{ԍۤl\%V||=౾>SVWfUpq]cg8؛`Bn_=0e-dC<'\d;m/d$Ӥ"+#Wj{_tERMQdyIH2UM)G7OK: -w# ˗>qgVn_"$f;rG&KrfVMn:J!(vmz%p?:lr2VI8WGAW<9F v=dG7.;͑DcOBb"(kʱ֎V,CR1vtjd!JEL˻[~H|YBԴ0\߼K>0dSɡ}z+b`a9nUdҘU83~Q}7 ^.FCV%{'9Ng3CinF鉺 @%Oa,|aT̼ԢĜmKe3v !f&<ƅ񵶯a, ݞ~_̞Zx}F-Yy{ƃ+Ld93+䗧$dd&륤g(((Mt`4~?Qxƃ/ x̾fLBb'M9N2?LͳFgf/ #(7*Azsu.g9H BPƒ]QZglѢVB%{}Yv(/HXq"+[U8UK XiMy3v=}z:9=vlnp="ŵnMG"!||@ERhW3W.嘞:&KBFݣ2{>&S>C=ڎ-^RّQYξMO|9\[j3 %pLZWī߭GidCHA2 nIW*UH *$Q8ċu+`cpA.~H$P{T"+录M,-g5T O,jیOX1Eٝ3f0hW!":` òi4b :ϭe\,pfŝئԄ]LXUxR)[HL^$W4i (9+}}g7yX9V KK3$PXE_1*$&ȃsħcO?y1xMō=%'7'"nome-power-statistics.desktop", ""!32ZDHD5+x?D-["OddLHM.-IMKLO-Q(3&ьmr px? rR)iy a> ffze?n}hrCG7 W:PQy:FY6/'5&?wmhBc ޾e3Nbg4yx?}d rR)iy a> ffze?n}hrCG7 W:PQy:FY6/'5&?wmhBcN~A28%8(558#$$1;UA u&,*22UsMweާ=^Qp%F88:XQ|DR!_F4Ȋզ?`Ů 9& 9`:'k2 E4j2*`W΄Qp-FMЂ:&- u&[ nf ܾe3NbgZx=a Od3cTWM-/O--.I,,.L.KI-./PQP.hh3#w+ebCx1,řyٛد 3ZsM~(1BFYJ2K&GNwBeshl Xtt3QK֊̚n0QjL=jM\we2 Lɨ1c"F\I`<ʸ7Qy\ۿ1f~ ozG68sS4(7aFs0Q?#X3PdbMXPg3>W7mB]Φg=Vx>q| >,gt+g%甦*(mgbNKNLN+,\T2`ɉ> j#bQE9j6_u`RJ/\($>+7s|/ax>q| >,gt+g%甦*(mgT2`ɉ> j#bQE9j6_u`RJwu8x>| ڳo+Qvx&:??6j%Y?S>@k@C- xSNIMKUs WH/NOJLN//KMKLO-K-R* q $Inp~A )Np\ʙy9) J@tFBPBRTZ\[S%Ob x]A 0E9ŀn\eQZ.DJڎ@LB2YH^Ó)=/XLfC*j?fjz(A% *lH>oERt*0 w? s$̓I՚y":s$3ZHDJHx=kw8v+vi:f-Կٿf- >a~\Mu9{>"H:1T1(n{?! hb< 4n6)FApv>8lCFF)W n)q/fLY0acM$ '4A/so4]LCt[ 3Pj 2+O F@އp&NxN.Gzɰ7BWFWBcL o*g8e"&6-ghðS|h Tx9&T QEqFv0tѿ`@FWK>o7o^uч(IIzhͫ?wѧqOpop0z>`~x.=1yHӇ5N~*O2ўQ& 8iS2K;+OSx*US?Vq=I Fgw"h)dh6 s͓to"?П gëGw;Ļ MZ^'@~ZPK:0xbl Wq DkJ{C7AIǩ̖8{1HKufG3ȗ~IG ?j}<;@)3Dj(Λ`X5h"GXIB&Lydc9 'Q8 Xlqj CηSN@G4|K\XAJkȸ"򘙦A 2g{LH} ˶Ƿ< Bcst&I:wqE +&MGkX2f\O ;苶:{?.s^VZe }0HkУJdPob8uOW|z#"ZE!*4wu\Y" uI Sr]rv灭$ jK`U[Жf±!\_Am|uϭҢu͆i`3!Zκm;=.Q( YHϲS)w{P1xPeZVۯ޵TtNmbgWL}ew®v0 0ht{ x[##+"3=ͣ#IJoޓ'V4Z_j"SޛZ=HKr7-U{k71zM*$#S*7#%$(.&Zm. Fmg @5)S7w6l5Q@/nx&-8ŷ G~|i'#+zF.ыƍbntl2:kqp6l3Fuy~ix 'ˋz+6E MVU^|mro}iڙEWRya e .JK]Ə*'Бn'ƖE.MIZ|oB˗_`IGa-JeR:_%&Uo8ryHHp$d0aK9DlFl)~ƎӅ3ȌL!sg'BEAһrEʮ~9g]!;0 v!P OE6E,%1J8,$ ]B=`Kiq-kmIH7$k$8.mqã1lS2}P^x= 5F_Oq\e˻"U_~tŠ"5zV]EZ^-gI%%-L;]NFT" ULNos00GFfA)KBO$i94O({EgԱ &(Wrl >ل62+pfX32SXM *vҳ|W$9UPՄLLɢ&"% b,>.+w!k$X^5ƜgmVۀQlAs.g! [hr:m-,"L(;9֚򍮂$J$%rN; l3wcw^Ǒ x5]? A.W >eQ+!eQESZ|7V!]f HlMdW"h,.*c`-TEEoFHP#b ok%I(zko<>:]ћYC(+LHknA[i9hn뭉+њq$P4&kU&['RaۊXC iPE<͸ -\Q+3x)W(3Ͷ&1P4vYhH+,[.í5WT[ͪ=c3Gj<߭c~8 f%&|ZDV-9BQ%IG kOCɴXB ]i*ZvηDisPVʝ2iۛ$Mly0\ojaeW849zij!{\O2$w,̘ڤaY\}iGN}[y Tf@ Of hn)nId'J%@=2<}p#Eޣ;"R=WBҕAS*Oķ0uM@ ۀ-b[ 5A*dx>OzƄn9Rwٷg];|r*'FjzDK{Ȫ٭sV=&Dқi wmpۛӨxBRbgtSj([QkchB.W*IKyP,-o$Ɯ;f$m<+[sf_3弗i4b5G/dVA]W+hKںMyTgp^=5c Axtcc9>ò]ɲ&},}_U$"(J.˳) 텖.ᨠa(+iH>OMQ F2)?)H2b^,a̔lrMTl'!M#M=ͷF XEy#;_bE=IQe QڢS3*CSJݖXV[)Y$'7@MwE2U/7Nɗrzqś0`"> _> X=I)|Fr ·oΊ]5dk4fo\q@zIm֙kMup')e~J.km_ZʶvW d*ɿj7})H:_-aEqgB`M.n0YD'c;i@;~k ](R/y0L 7TZWYJzq2X5ԫJ֔`Pc'%K3܎ѲehJaDmO [^~T ԲPjy2=V-O@RBUKCW--jQj:j{SIW=^F4 ܒ*R\cJ۝m؈5]<0OGV^C<%Ue*̗mduRw2R:=ytvw,ShC@e.J x^jQlEװ9ӏ &7_<7_^LZ76lHG"zgw0c-|d߰"/V6*3ؼ#[FfML\2sZ%.f KtU~mP }TIgcUlؖ4Z1@6 QY2vE7 U=8s/=#T}"}C詐Lxʆ/肧k! 0{ǰ˘\xP| 8;b8l|o{8ۃ"(ȅSZrm0W <#T.0`.!We_+&$.Iْ%DM|Id9zFBn:xnJBl<0U#C'ΪQ%G0rN ݺ>20 ݰ*#_S"HU/-' xcl)ەmVjZPeCi<i$D4 ksާj${Į- #SF(ܽ8[ӥhBB[Rwz@J+ R' ! V+< |z?MR%!@|0rIufobxkS?--W>p? @/? Mk鷮 ^c8r6{o0KZip j ?WikQv%+8>k_C+}3PZ-;o!DiY\@G'[mx$T qñLF=J hfQ')Op/Lw f9 _xUϦ*g8S.籘SSuV@YGVٷ-%7V5G l5vkbisјq:̄D|HX{VOg3-GFvOQOgڧt d.{ Noh[SU:/Ա_"1S)2Wvfvod{)U_+'4xϻ%0 2H;t:+)Oc2#wĕ 6L帮-`ŸX'pj>kfiIbO^]\8@$[LP& /.3(ee7l!*z8H p 21w: ȹbUUqmŲQ(.۾Nj47dѡa28_x<#@+2[VI2'{ֻ%j18:vT%M\݌aj.H]KuU~p7K}m0ytBRKl߳D5>Z+Uc24먢v[sX!t {8`ᆶ.1z.obKznwFxޱs-`e[۱/`sXءka,|Kn-plֱ`{˴ o!c肹2h akX$X;!Q_ /T57B}i"LJ.1 6Cs tE׺s;5-dB )ۓ\גAJsL'2c+C"/g hpoH2Y84'Y0I7W-#@M<׏Eq >dAO`gmǃ T<1D44g . eQ2(_L: 3 "7܀W1v4Iqx(^|Dm:0BgY`6s8 dVOiLfmbRFM*r8RblL;*Qͱ Tfh^5Ҏ XФԼybWJ"t]C'f;唪MdvL s֠,n5*_X Da+ H];77jS7bBN*1Qkf=ތ,_vՎw'Z4Nd|+š[{FBII:1@uT \T*VTnƷxUGMLSp)S3J78Ӑv&0Uv3`92"F_/Cl9Y>]'p4סσ/PUwxUn6>GO1\Y=5'E-Jr=Dڔ@R>P_Oʲ9 "g!Inoo_!n \W_0)kU[9 Sصj3j;]-`ƽ #rwR;ሱi km=<yUni_Tn# = ֩ N J@?Vz#u6GXfShmuqJ?kz"Z$^^_""Ⱥ~Ur{2[MȏM;e;YFUSbz59s [}* wnH;`/lX-;q^'`S 5u[E^f%x%!_& {8rl<`0d~wփ7eA@z07`@ᷢc[##ֵ-p=g܀:F 4AZBl_ ic$;!I/RngG2QӀV nh{.!C>G~dnӀwl1&XPPoӜzTx˴Ss-5 iXgas;lLHepEd))ۋ+ðT dd~guу}1AesR9,dw-`~8|^o ChtH91ܱ `\,ce*<-3;$cxDbQY$̗nK8[EI(T)GL{kpH1*|q6 W;+RV6 xzpbָ (j6GMϮH%y2}7]+)eYO2K$].`kƟa+S@NC5w5:|N;pwyO*g9oP'|x)cz<4^r@J'SVo_!.l K Y4!<qxsƛ7$5/Q&j<ń[A?r LUiTso \_t~|Ю@~ R? aQr-sS׆c9x+ӅmKۢ %ǘ[}dLW;?9flT<:mN箽HOws^䀯rڶ%9eKf 9ul‡VޞU ǽ ULpSe·kX ]Y)nx}n6O1ܴ- 02muAhL "'; i "g`oGp kN7ӯ e;t!n{,c`2[[ZZJ[u ao}{Kh?PFdxX>JދKŒkc;j/U5|,ՌẄ́D秉M]:೸ӡtxG>!+c+wďcAm߾.п)sx{{R_KAK9(3=DaW~^bIFbSNb^JZ~QMVQCz^~n^~QF&zҒb+,sq)g奤);;{{p)E3R1%ZsJSRlSX/Î,?3E!8%>'?9$5 ?3O$HA=%;8(55OALkZ IKLp[JFlxU]@}vE>MF,l4B@MԔwlhi!/3sfxes#t%+J6 '#XvjK?V4MIe1 (2y 4$jj^FY: 7vRPy3-~_2t!ҍFUYXy 3~`ӼM]VVI!s|i\M.+qP7k1qʸDZ۽nBd҇nE^\tɖ@ak70V hm*$G˻Wj ژ=QnKe%*m UʍgO50i'&ivQi5^ MEws'2ʼִf$HFm69(0W2JuR<=G:PĤ=TDa:C? RSCoYr"Vu'UTQbw2>ՊP|~~vlEחRw S^|/ "^Ӓl)nr!~y# ;EDܽ({$)1U L|+y:nlZx;ƻfc!elxk}̳qs+A xUA 0Es@ZF,UEkх R!h;e,z$ɔ wۗb. ֫;E@%BaiuY[Fh R㜁,kUhz/o܇=pIȺKjjxXCxWmo6kkN[s];؆B%J*I'w w^n@т[7GH 9$-P.ح%b+D9e >לz_Nef-dcAɹ« I$+ܜ \D[LWˀڙ|$\Pe𩀘3[!.'sIl'Ji3#uKC V3GKmGi y [AwP\9lʈaI^!dzKSYh}|AK+AUT&P>&w So6]>U@S4/nErUzF7=:bo/(eE~.Qm c JˋN{ʯvvF#;X9Nm;OK{]/bsZүΨ{y96n :hU͕vTo/$hL\3]Y@L z:E,ۑy=Xco10Xt`Eo@2#;|)WYY}e<{`׈tOcYxbF# aw77(wm GY53q!dAQ/j,Zf#t9 `6]/d, :m d840‡lġ7Xc2n:BF /馶 ^lk@;u^;9#B&Ɔf`fɬ:2ǓxW31# !0N]$JD!k&v+0kFa,+x7P!/%7i*ҺJA Yc+I\gȡ؁%I#<(}5oOQHIaL*^%4WYu7)oRr8f&lol{]-;}BaWfk }?c^mikmߦNk}:md&'{^z0U<$(SJ<ۯrs2N:ux̫=Sg$Y־LSoUQ bnjK]s2? &78\ '[<Ũ~D$i۴!ˀ$U>b庸:,'3Sqv\g}HU`L0oջ$])QG14K)Td+WDt+s .<^i+d*AP/ qE9Ka\RB( FHYWt4o:R9ļ><>6-1s^ +H-='2W؉HQB)2mi2o=e47{2kU"i,Lr&Ԋk;q^hW?t=: 0'~ϙ so<ԴP\q\eb<-jᯔ؂إ$l1r>NaJ&ITho9zQ}Z]f%ق_~)H㔅xFx|k,6ppo?ڂgoD'SݯN:t/'OBe<3KP$O,C++Yqi;j<0xvglh'u3 ,&eUVTifqڔ 5[ûΟAoС`i$]eN<{ㄳjdUőwFiz살{rNi@s!L]`zKy;{}JHt-ӉTh%g'K:QUp2ڐBwV\53h?gpV z-RR1HGt4L 3)Sn;jځ\Q:p[ש t^NU<'w}a߷{ZsCj< $턻м8QPmrPsH5HjuH f,e"<Ľ߀,z}-B~:a*,Q)'Y&8ʤʸ6<ϭ{{#1)v }2aKjU~}^9 :Z}b2k,c2ơ*S}}r&+UYAt#ќ4l:+o[R& .VzrC2Y9 BbJH%fZN:eU75 /[mj,@4卧PPH7Z 쏌"yC׬ZB]{+[E_l:Ax&8!R`c ogrJjZf^B|;Dlf3g 3$2W@ɹ)%% p#hkN.d5B2GG=9%7SCcpF6D{eC,ڜszZhҢea&`ՄhD=Tk6~ }!PojCT{89"`q g@a^4D!"PYX 4o SA>.u`kԁ\\ż(&aU&d(*XsՂ4b?MK(JH=Ld!-ʼr"6VB9E AF%悍@3O BӚ Ԣ<~+ť Tv Z\\5AxJ@i ^*VI,^ B 1*-M.1ٶMRX z<{"EIM83=ecKNlJUJ֐!a!,AM"ښ 2z Fp<`#P~ bERfGH'aX-+ qb$ųĞ!`EX.qGe1L{qjR*Kdq% %[OczD?DPc5\9<'Mm;_bdM:4^%Lқ_XpPuRջHuNXLlV$ T@))%iEE%% p˰Y4܁6N"49';t܋SB!A%`YcpFw,RױFbsNbq1 <=4= A %E%X (,qXUBwUl" 9& y4 ߁N.v|6 ӟ7Mm^u.I&1Qu&HG`AYܻb:.CV{C6 mΙmá~{3?d}[muc\>U|O"΅m n%q̂~0 džF= 3u︀#&$ܝ{Lði*f,)aAGM]Y*l#X%!%r=X_娿D;g5A#oeCI`UHÏчZ+5&3k W|a z>Iz9P 8팺p:~o 9$'rM3ayKůp`=Dg0c710&<,ǞJ5xݑ8&`;~n];a%Vc{xYG*f_[CQƩSq wv70ԩRY?S:I5ˎRD&GJtN3mZ#䔑O]5ZݶRT$!~|5gPL[5[m4:+v-|m6p+|Gq1]0fܸ#X$m @ƩG8rXǔlM6ێWw9`hx'GhEU{ͭ/8wդLQ]YA jbCkwz: wN!ʧvW{<y!I+h/sZX _2F-ya\pZ~vz]%Ao.kmt@? +􁽓H.DcSf5tz6'y9hu[gڅU=hms뼏)%hEyq^'M80zk D>Y1#5aPF=[L}:s]1*Bi;6Fg.VqnmadгMGj'7֥zS] o0.>ɱ:CiYP,^$Bƽq<Ëįt> `m~EV46J(#E"[> s=R?})8@5ݙ)b,?('rbaDViJ1enD֩P1< ed"3V #LQ|)`,3C!8~{I10\J$K fOd,2hS=o'R 0@ DE=^46iX1wGm9 &XeɪR:(7s"!3&r[t eLvy̲hcQ'khX|MX`&p/-$l g)Y "fijkW4Z+BQtnüzcL 슬,q8J†oTCIQc"}dbw؜9(WHJHUPGXUG!] !Mn8&Ge%&0`l.[^I1f|$P'wQ>Zʭᷔ)-y(:YRܓxtN/1luR#Op͙ШK|YTg!.<)7TW|*gqDJgii/9 u0Vlg]Jj.Ë"|}tjR?v3;yQҮG>36j ۠hp8lzATOE|X 3x21*J 7٣т^n|YQ9XIVr**7]Lis裞o چBe*v;xsLն3Ki|mf^oԉdp>j5Yz՟adWSq*cy#ZYW͖ 5\o$2tHAҮ+̗ ­賙q-KvZV?[ֽ~A^[~F>V?Ѻ@ szsŒ2Ӗ]2쓋Ie$P꺢5jQ$!X,QĠ5lw:[pqcrp§sϡ{ a5!#&UQ :i&Yw7EvHZhd/R"Rrȯ!\Ht0X2WA߆345 suJ `J(&rEK'-6f>SSަCd6+[EDB/O^?,frZcSLu٦LR|^U-:1Jj'5B N?f.]JV(w wJz~կ*\Nl~6xYAaJIRSo0\$ [LUp+ i*eSR馊N!Ulgp#/pTT{i7Fjڨ? "{HV6Sp+YCIj[pE"ח"R ZBq OJ[xF[>A!yS)Y閦Xa{c}tɅ½"j'oÖ^~H룈H7yAcg's'\.{8j€Ό]pjGޓ1yHũ~\[]&Z~*;g69}9߳˻\'1Vޓ<#Y^*R&*fmI;&f2IY)3o.@ cy,| 3P7y:kPCy~T*9œ3_>_1eP:4X./.Wĩό a1Ӆ-m*kƫ;a) m̓PRދWW#>jY=wa As7_[Ip8&En2"}UWgiU 4$>D(Otz 7^'de 4nN#y >Q%J,7;r)S$8u4|SE3>{?q-WrSZ=| 7<&$7]94sy&QmiVT?,.R+xuۋ(>}8ݖw7ɷ xksHEW ;W[u'#X8bNu~3#iB;pLOOgƯZiuʝ7;f73nsw2f9Xe7q][D \iG0ff#m:x]NfͰ;xL/8sG E=qϐ&7Ljv%_&vNz Y(/g+ O8ۆc3e8_l4o-~v] \?W]8}}vv9LWGG MYX˓ձҶ:ޫ K\wpM fc &ܻ^^r fh\KK)@\_ Ԧٵgݣ4 /DG|.Ecctys 'F dm٬p="-!y:uzBhgNO" -'Z"+~w/`q Tny%88O7k,/c>3p.,["z7`<҇'m8M(n) Ŝ\Wc!y->'=Ue,I杧u'ފwӹc͒.-ѭ(R-f*ظI^p<̳ԅCc /0ׂ";zd hJT`ɲ*5-nKPS!аugmU dzw-oǞ˦"`уK}xNWҸٌ͜@4]h`4I,4:"-I(.NȂg#bUy{G {t aB*AL`rj+u_P ϥI>GEO:DSaT6ͅԥڵ11vB9&2]ΰY_~Li=KM08rFf*2'_ɈNTeq2%E3Qۨ`DÝZ*{O~2Υ~hvO܁NřT$QH.IUY&Db %!AOHAHTj<ӵOh_hCm]稅D)5 |w($ ; z;̡O.)&Sñw`23Ζ-(2/qVsX^VQn<PmT*ZF<ɈҢy,d6ruK}2`-\_u(gRH3 ۊB^v h1Oۊ4RX >) +9O8& 3]K|(LJBhܢ)H]ޢm%Y&T 2؛h]i(4_23#;vg͌Ғ;G+ 6uG_7Vc}4g}z{5~z2O[!1Dhd^JO Ida&GD@NX2{dchhv؇bN~U;.lݨ:lAq 5*Qhf ڡghl ن\v j⳿)^_dzp/ sx(sDIUZw! q$68oҢlP#ԌϿq P< qP<ڽ?~h%#CG%ϝC&&H0^躢.}UZW:Tr}?{Hi;uxym oya8ԩkNf,6&]T mVΨ>ٯN>h|fZ ȯα G#s;dr\ye(;d`c'USC2\̍  rP)QN$gƺB}aQ>{"V# tBrگh/j{nD YmP (>y*tm(r'{?8סz3\ZM,oh;WGy O̡c63$qؖoxu|jlbboVb [ʻfTJhފgtXOqv%N]NN:#D+ݥhm&ݾƺ6'g}4Y~+ Xɑ~ivcŴcUWm̾a y,.%:z# <9sǼ;>錟⋟?'Vwғn}_j`:vEi.Q2áZlၬ)|K}қ߲Xh=ۅt]t{[쭢t;wےc1ͣ HvKe4i"+832SkzɾJcO޻[Zx{ }ij﹯>Fcj'=rj HF?P\>(F*UpWtr,X oST&o7NHn@G F׷0b)MŜnR.ySX** c@ 3Db>O^p D sAnT FƒFHqLĥ0pKD#>0 V${l-ʀT6ȥ"ޅ֏̱#Č"y KYŖ@g8p;|L]u$q'˘#2楈H \ 1dn<0 ϯ\~nv2lX1C/H䧄2L`Sd53 $"D睐xR[p8֋jw'kXк3qĿT6WhӴVӁ(~ƙϠLxX0-?ma!>.=SV?vƜ($Kh_h..LP{w 6M.5g`M`PWISk_v29E^<\+xZE& n?G40aP3>|PII)u4T XfZI_ b&B3h6;n :܉&<)DviEc5Be>/x ddO\~V%H\([@_,8Yg?rdrr*ȸ`$ J.%f\Ԫ3id]z]9%#j"RmܘYP5-"qh]pF2yLrX\$^,z jN{/Gb<% "Ƒ|F~J)۽n^=ºnҖ~X>Wͮ`<z$*/DZ'WGX!Iݺ zn7ab.„\IwEnh6ci囮2~w>Md~t7=iv^pgaWۧ4ݠ,uإ~Igi{ЖSf\J;Q!`=aUp0^pP9Yoڛ6NT '쇚gqcl[|C!P(x}wƱ_aOlJdiҼq.M2}=J׃X3.8icڙlowF-d{wxͷ웗,=?Le"axf{WnO$ Z&e{qpgSX5 l!r67}[2< R(f0ہwku~LXtM?.ٱ`E0c'5In|]Q;X a"DаQ|٭'𛽐}{,c -4_1|"}`F7$ք]lEޱql%No"`Z2+v-ǃPzt2I7p2aoǬ.hpyda@ i" qo}X\6j^;xqxxw{rzpX{>̢:t/p~-AQsu_& ̖ɋBonxSj=:Ch8az~\Nd/Fa{ˠQhr Oi<;és1؟;wCg; %z7)\-39:?sΧ7t{|y{ˀ~L3'cl s'oOx3؞.,z 0!&a /NsGI]m@V ^m P,̓~"y|z\ч{{Wˬ S{wF?_,kV̖&BlW`C;Z*j)_ Q_?: R u{7ٍڏ'8;PWQ0$;K@njC|'Opd9/@/z)Imxƍ爍Оpnїv{gEc+Vj>o,넷;h17!zat'|br;<9`'pݤ{8ȣd?sd>nVߧA Y3Y:Y$ Te|ftD j89z,kd/bbS3_ü|ؽ_V)}Z|`NGk7~p(¯WEQHX$^B߱|tt?;OXu:oAؘnb@Oqț)fg8~D4{Gy( ЛCݥ&I9:᦮" Fi$Hak@xFX0DqeIh" sQ~b]1ɽWpr)iN'%(YqᎂY{b_;/J+ d"Z˯XVn 5u@`1͚w>* /ZD}`I-ӮY\z~AV03oT X:Ytt*lx4:"äc/uǺvU?E%Z=wW@ZYudfusRfqh,e'mGnt~ >ib:#e)\͖l`j4l{m+/;ﰜoPA[q47 ߏ~pH8=?:?q0lӕGA]b!/5x&ȫ‚%e eQ9D x63Dx.g$ƧhUUN jm`yHu^?> GlwOIA?P.y˅PلB0NOjWp PϜifUUD4c g:@H)oEOIJ]EQ `)-1 #-r'ϓIA^IEa \N 72C5ui&{0w:RbY ! r,mx:{x2[o#keuYDam:F{\uʱcFۦ( Ҫ |N^^(A|Cӧlg a qg 1)G1œ: @!(0*;6-j 󖊧oI_Vt6qKQm ⤭Q_'c*H9[NO[ql+qsCPM]^FCpQ[8JHקPO|Z7+*V4a۾U^OiT"Ζk8Oh_!' sl5C۫T'(-Ly*t^]VRTctM<=L^῀G3=ܰ^d0XCػ + 6_VJ}p_*mU;NE,{`40R5kV,&0  ~/Wc0rȫ" E&[gzi&+䮢ŵk j:V ilfomE-MQCΌC(-5XfSo80YJd#c^ ]ľ3CVAڏ*㫡/W};z9(e 0tHxiL^R13mǡs69N$CJ=Y8i7dy:i>Y6FjqZ'>e*I_ E]Cƽs+ZF-cB-T;cT=8*vJ%|IC3bŞvѷy]= %7h?xfVCѪ(}i|#8=hw ڬ|dhrFN-q-YBvx]@6Yr'D>jQ޾P y\1^6IQ5*x_'+iFYĜwfp>j4n+f"!+j:@ZW:owGrxt[svGKӌvQ-@40F$˗Hf[0_kֵP^J-nȕE䦌+ܥ:_ g e]%r5(;z+`{ʼQ-509pM  0rmpyE]\ 'PQqp{<{^~Y 0Uus:,Bo^÷e?K){ؑԑ|??(cKD]r]CD&~|JkC/)$ww/O`9=PwCvNI*@nHTRu*뱧|Y{AQ߹ N>wf`QOfNVx7|<: `bgM?xx9$@_s1I0pZcGz m_)Q ݗK(;DОeE/+{ _!>y]^@!}݅ 銈J1P іimu2[_`z 0-Z[ъe@i[QM\/:Ee_8(3CR±MT\Cǧ{ƥ+Wr֥ r/&G/k@ԙ7J% [XzPɃhZ+v}*ef ]HWKRŵBU<%Qj=o[t1n438ʜOQwo`X?V98>Ɛ^w҈ǤDGibtW~ Ψyo|Ѧˡpa@  w曱`XF _!z|8vK̹12Y淽_y;j$SЈҩK| wa#3oа3Ő,(6Xh"A 7586Fn!CVJCQSz /#A)ZaoXzRQ¿tFЫ*&HX!촌vE2kx*Z"mm{4EBԥ?{ؕ&[E$Z[HpeJ FYٔhhA) >fAlmޚ$csdz)Q,7ޖAPhQ#FtX> Y{/ U̿97F8ĬۆUIhXTq; qD+ SAhgyttt]1.gՁE:NG &DȓucZm7rXbVRpJ5 IwS)Mrl[<9W xkؠO y?xrmO$;Y md{hS -ȹ #5&|;~Ņ5o,ѬZH7\'jd⨢A,+/ߕ %GY*2y9.z=H%d2r)LúinyV&R{4{j>(Whڠ-2J&&:):;}S- +|ɧH/KL\~@̉ \G ֩"^MsIʮu^3ATDį$g: \>F)n'+]z䣠 4o £&zXߥbjUj//:7s#t0*'v=.=ssE*U{;S+(l6W1G1㕸8I7q_d`募E#;S pMH 5ʷ3C*ӗ*{-}{uV{W>ՆY~nl*R={L{pc 閂ql02&BmkU>u#Y +shT;BZ}YtbMq;ht\Fv -|~b׍C|#*i:cԹRaT9̱-ԾW<җ7|yZr5V w#:B>Sat&'wVp :RլZl_+=aFQm#V-N\hzh] Ob3h8㩌Q+sC( ))PY׬g1rϓ`6kY]4oS,^sj(;_)`N;?S L>!YUKW{C\6rI 6zF+δ1V;/̱̗6Ub_az͍;dk|rEv-eUֶGܖԒF[* .@ր38$.ʀ$uG=W9-D Z%vH- RL݊SWF;ZAEJ_q??ݵ*S;\ 24U^t}*sFg2Zq= ܡW-_?WǮc7T-S9ğ9eMRz_vMX9d{kd B̖,k=aַ֌aq!N KY պLBVy[s+g͓A+Yu݆$!GAb8y"fZ;uJhD  +-8V)L>)rY!yjȧ2 ފUUJٕnO<::s|Y(;F]ncpm 'a|/k C%&ܝѿvfCrg6 e>q[ZŘ1j}ېr`{cWk#qK½$}p#_ܤap NFóifـrY(^M|-] \ϧ!8Qoy?GϣtҞ7һ}0j>ҙUlh Y 4MOOT_F?le |-FpOy@4J ?[I'EhMͭzdJV퀪G#!LꞲ{a,p%eOI/SXx4mJlicoqHi}F'4%8\/:7X?}ҵen<=}|4f 2/C&jo#"(fn=;LM68Z0 <");x,|Uh:fj uB% kf0dr .lAi+-~eskT 2iZ%^s3tT!z~'-WDvm'lP+ /ug'|'4tM񱘢eNb ޞNz\Grv`Fvn:ۆ:?Ej;WlbаaF* ol Zpw09W5ߑhUP|a@7<-4Pg!8dm9JOT\6w8׿Wձ2]g O[έUk{Gjժow'[:쳯 7YsLU!QÉ\Hmnb w_$%ۤl嶒tAM*/Q3Fl1iML0a6\ynsyYȣ0oȪf:wF1hnon;BXkec,~sTba:!BIM80^}<\_1Rzʍ\#"`xYM`)ot|9p!'e?ϓ΁y}}_ȸ2\< | l6Zi-) 7JqS7͜R*".YoQǐEA>Ms[ِ,Y/ @+E]*t&ҵEn6]?SƢƺż-#j gOWm<|8 =G0`elvB8SШڷgЛҰ+#iENQiZK*FvtB.;"8:ox0ئL6Y8;)U{kv1͆}(eR5RpkQf+́is:eE]B*4{لjc'?A[ccdk1Bl<;lѷ%`WڂT!=!i[W^B 3]EY[]1oZP<`p"YQ C7u7;lRvo(`C lN=Aƃub=Ф )J%oXTxaAP$ Aa %I1/7"pnJ}V,f^[f4#jxY=y} SXpf+^botuVFdS R\dݧ~[@UJ,zS"l[O<C ) (V`jIGm2ljFS[g?3Gx:k6QWQx]wrK潇': `<8Kzb?3"P"T(IDX׺AdN$:-PY&9O2 cuA{KXh4fD"ĺuaAx:F7o_\87`_ bV)FUV p~, ҭcHU M֨DIo|FdpW%@6x}>]:@E8S_B0Ex Bai#gI^@ |* 6ģGH&)ZheBV`403]\.39I eJ!{P FD {;Î22?9rj:(Ks9> 9'?YƜngX?=Oi~+R%x>D+1az%:G&#WFwVN#xZ\VjԫTVI)QNΚE-pԬGIL֐E9S9cZ_?}ce=em-B0ec\ޖ`XӧJFqoW=m^VE#ő m佄"-)͊@LѰ"EE}zht8_D! hdCR)BB)k 9T5?b_S]%@"K,Lx"Tt&l)y]]˷ttvMir zxyLfAJJImNqczES(.*[TZTed ~"!bʾ:b3rY:ف=Vr28NSry;2*)$Zjx4sΆY.xPb n7HͶ{&,qZي4vy2ASnovrlW9Rn/].2lOQ5qA,*1{{X]-k2irQSKr<<p xJ2 Dֿ/ˣewQ,78?,uk_3OJ MtVg)PHϜR]Cl{ueQTLXWpˌKx»QsdOsoV3f8UoK1y%"X{?P˓_QMCWPw+mGVq?Aר/.M2`tPSv1:H ]/,$v׳(=8O[a r?~VlenLV+V?XXӧ*J 96 2q6iŒO7IAZml^9&q4d'NC̊SNR4}1d} ,ú,XwLJ{?$jier9 oxXo|3hἛܟ8+WI'0S5N)eFzG:"rzDO}/]u=e".F8J ~ f U w*}{_juPdbZp/Z= F\g(I(,} \ua=&&6]0"YҲ}2 =+K 6Oo^Xmܬm#Sfi dU. W~(v'Rhnzu :XpnaYK7xΛ>@6޷d< mQԐn\kP_lI f-3S`s|x p5߹ (*( yN,1j;c~wry"DHrS.RRPh,RZwA%|lrel'(IfQI%\} t/W:3}^Ak<-rLK!NطluM۸\Jn-VkDi%6+ca_y[6 Hֆ>Ģ!D,rΧE>m` (Ɓ,>jØx{#K23,^:濂A67 @ GlM%edU~Z&%Sl1دxY/6ڠxK>;P!D侚 ot Lz%ʳ?dH)b_ZlBKdD,Ř߂ ڔAQgQL1@qW5>j[0iOђk*6{ P\mixjB m0gʛw<}DQ ç5 DE@*k^|+п8WyOSq|v~:d_ 2 XAXK]5F%(y~2i1Dd0]PFꢕU#oa 3P(L@);@7p3U% h\CY r="K(l>2vL&i|{tAcf6X,% dBvK1Mf[_}z3^@Dm??qL$(ES eЧt+ve|vn W)e!`fXG>UV[jURƿ{2Z]r*ᛴ3= SDeѷdP(O -q0MUE;qk<!nEopwmYm YR ˨PкI^ro%pg3b 1x `=9+ k_1?)`$t% ݮfp,UXr'ÓAm $_I@wSuN:)L .dGQ3}B> b<&wENJӭxt)VX )RR(M'r~bHr=̤:']{кn-N~,CƸ+AyGp&B4AMKx-U0)!? JE3z (G+PTR89(9xkN{Gb ȪCܝ`]sh߇#8DH0Ex:%6'VvƳrDR=BPKS?he!kk㫶MIcf5U=WLp^xt ,;5x.IosE#,@A ͛1BqasCZoK8Ń'Jn~) wx.R{_->0q3_mǵ抄 {YF:кqF{ybcCx[Ǻt9lVf?--YqY*P٦+mj,^QQ{^(2UIѠ'ơ_l(Op9&2BwG>1$(J'JmDpר;!x97 aNΝĩDz' PQ>ee|}zGI ݞVQs@aj{H=xUTkHSarfS+;kJIG<ΖG!* Qv+H]WQT-#aԾzWǃW41!D`4^C[pxx5%55ث9 "os'KDJqoSMp4D|ZAإ VK`r TB ?R|8dB =~C0a4Uz"!b2HL?To{"CR T[ןXL`mM-Йg%AmBMV)Ȥ +&C7ߧLvGUtDtuiYtH3@VX(Y%YUWZׄ/f : -ջiG?i2(C+zyCuT> gs3pRzg;TJ- S(@"otq/~!yYByҵ84\ᡞbYf^YRz2JvTS ògn\{&hP7wanIZG64$\10%p7˄=FTןu#Nf ljSi,>Lb(Ub$  {em+%x6Z:| 'd @N 1ɢ%pN=λEOZ{Uj9kr,|+t#+v\F!xUTkHSar[Φ]dK*)ZVP+R.szZngˣeB|B] ɒР(JS0j|>N5xLum3}leiʣue*aq \RE. YvtT9M!p/ġ$xv""XIĆ3uZc]ќ gʂgR?Dm,LF(MG# -bpqfBIT ,6=L& 1n,nzF ^ceib#vo8BoO`Ԗ/ FAurӫЈdTCcS;dF'tCDtcYIt5.W*ݐn-L̞P)Qԩo)g <i?i8 \BղP4Fblx╆GJ>a NZj֓@͘gazp}ljɧyoZ13}R>kg\ 4pYc Y߹Jѽ҂S9kh|M.e|ҐjF(k{aUnI'ʸ&DJn5T&xb*>Mΐ>h*MfRGa銡by(5< t*ЭHz.:9QB$Gqy l \<4 F F#|7' 6ˡsכq>W>HY{erP%$&T7EՒ}C𼣭TPKϨֹD*0ѻ~t^ȁa"gܴ5<#K r4Sue؊V<_yMjxk>a+FiPxksHs+zZX8wcZp7)FHsuCo0q\jh4ӯ^:\&{#q2x}c2'c_.eQeg$[P.5PnU࠱߀X́K`og| ɱÙs>9ߝǎ``x̴a @w=DК, A]^s zض 8 tZ3aЈSa qS:G, ||5X# e= =p4.փx c*M=sH A"mØAIhv7/G90ʚ/l !#]KD \8s^#p^8 fi]7л.ZaK h@l_~;ۄ~Pn7 TG@tuL3xֳP_7/VKح!l`PAH5xuhB`W$jok/cءɠdĚJƷ$\%=Zsw {Fz.@v!ި, 4ͺE3f/'P6rt.{WC{hև6RwqUenXrBuSgsTpd-f$8W7 /Ek_kՙ^\4/OJ37Xᴎq'ihCm؇!\"tt$dqw_`:v]*WQM&n $1*Pp T/Bw! 8vK ڒ0*8n4B>j Z-A:|Ո +[XNQ(jj2\d<č`lE1׃=De:hFbs9`OЄtUq)7c@AǢ|vvΛH23 ֗"CY;))wpNh@'TɁXz6҄ <O_hП!A4@ȿ)T4jId8j:KJ'O"!? r;8dq1q ) [ z }e[ UJ]h1M.\w ʥ6 #Lzl?J󊟥ZNS`r֯1k vBMlEBy_hEYUc̓Z@Rd}Xm-G-(qդ$i՜_+~Ѣʭ eXð߱048` |펇F 4 e5wa p}םR;Z j&JJp "7} ȇ3d޲G |0bqe>l+,ջ@6z#/H/$Ɉؿ U|MG+x 2qjFL:?M2l*oaAZJsOr,$T8>K( 3:\.-#ے|J""y u%?2 Soh486T6Af3nhYIhRjPl.}W[_&9QGvZzo2陙~Ct( @WCw2)1L0 3LP@f'9+)zJfdǨu.v EQњƍGboq:8LVH,86 -颅L՛π$V[N|[TZ]yw@v:?Vݾܐ}l`3ц]L"D2,*>>b. dykT7ߟO.a&Mq8:A_ةEH[QЍ!w_w u}4I{Z=c"yCXiV yKǯ$:;5ª/0gA{T@U tnjW3ݜ̃2><@ PEz ˚30D9(3s{c( kR۵SL N٘xo>W nd Gfot&ը8#(NXG)Ky%Q^jŁ<8"7/ȳ+>U\.Y py{z?>9V?J}sfr(QP9aSy'<.zu k񜣎(z& HzZkcczM*Q\2BeZo4U[KK|!LP}Jx~n +iOu|ɒnGkAܽyL/$F|~I4 4,Ag|Xt%p 'oz3^r^svNECuޡ[>#Aũzvd٤{18u宄+Ph Hd +؉/ 5B\7Y,/tWSh24(.趍x\_+uh $;B}h2U XLJBk8a"O -%}AhڝvbqIB!Zaw̠{ʘf5Y&\̭og tAէE'[S5_[j%[[J.SK E+bdy(ƒl:Cw孻v٧,fw05WvxA\˒e>e^CݦHe$Ȋ HwʔKlB~yrF [rQv^hegC՚˻2z`|V_4x׌-HEbաVǰz1&I1+b:Ѿ,p!xHDjq93 }qשx*HUmKK%n>}L ]( vWM"+FG;B.qt2+ +d`M5YQfzz-)d{#K"(qZMJA>j0X dXl \3 "/<P<Ľ*#XS rp۷ylOMJMHu*Y;ț[NE ~!{*E# `<Į{y)Ҳk όu=TQs[ui]EcD0ESŶLXxϸq g~Q^z^~nP,gs$x8qfP22'Zp)($hZO~nm/YZRZZY_\XRZ`k`9v 'Ρ8Xxf7ͬ}քv #uEI6 UʶiѴDɸ A{! z4hɒ1Фt*p{sJT0f>F"Dc(NO<L2\f`> 9BA46"H Bg: P.׌Ck9E,f, w0@Ea0 `(TAЭyD¢akaVךZu%gpG1ȉy:ewbakW,CDEId!7C1{ۻ98wSg<蒱4#P2IcI+ʮ)|F 8WЛ? cw6)80qsw7t0Nng) 9,dxYT26TXC!DGM@@r1Z4ɸN$x J5D5[[V םj.x@*ᮒ$#)'ln V,E j!X[F~4YJ74IܵO٘;гr3egW.KmQ1P-ǓASgyQ|xA6>+bNbb6*P<{D}3A?./oK}f_ 8fh£`D#!*?,ޡ~"B~"6چM8f|x*'Q{i>lf+3GOxuOJA誢."Nx&j^d+; =B3Z>9|y9x)ڠmVVA,y 524V&2%Wa(.e 3?\Ot(cՆ;&|"4̅~:NBF&c37cp"[cл޴o/صGS{p) < t(uIFBlk!DRr@UU(`fΉ ΍x넒378m5T_?S8&LKN_π}x;kx"sEzOx kx"&'W xlEQD"5Tذ3t#6A~9~h&A 3šMbܘ~o3O%Cb"↝p;s 3ƒh{Kx1Ж4۱ ]#xgoTa!"1R`@yv6ݘ1t== 0!1>t.gIWG>:.o:y}l^_7/:\rGc0.x#Ф:ku> qsqnkdWNyͮn.G9i=ۮ:dž vYZ}q=.KLO+6OgZQg?;p`gWp bxv(F&zv:i76WV8[u6F{\ A~/,|ʕP@o7oO=;]Οb 0ڼm$~3t{>&:ǻ4MT$3b`u}uD@#P` ؁Q ;ݟ0 yR:=\? F$УXsTwnn _zO>-Pݓ#un ռPhS b@@N.DF.H~wV.'~W:D6\IxpW2*MCX1f3OXz +DVUؕ342R M/цcf#{jAsxay^g{ CH.s#.jnš=I4j䀔{nARw]9TRlLc`li$>ti)Ձ%dXI<=pHSm=BOzA'p{R:y%Ar~;ԱGױ#^ҽI*!`sF3O0l”fc3.V޾) Hf5"2tb !OީH={1 (NkJ"B Tģ>70ez]`}1FӘ*A&֩hLZSfPC3 5e0iٟ$8d:nDx?3RwZ'}pC4["6XҶ^ Bh!YTge f)ʕL1+?ISjv>)w/:z6z\D+(q*5 @16UZ"5<5Fs^ !uwHREq:CZ)꠭T504 )+J@HtNV ͅ*+3\1&&TEŸلԬ^:2]ּ}<xќչޕpYm' Pd{}U~iO WlڴIaZB#fRWI2`#$쬨{{\s zW_G/M.6bkk<E'^IXlYef eXo=~-!0^3Ē*[7U0 X2run FE.znn`Dq\ńECLOb!WO@.+F@! +#9[ԊHX Hn]eEB[ORFA@gƝfҗ 4gBRCYHpU-Trk*4wellWZ"nޤ* -ēAqQuc>*\×Ҋ@d%u-'{*7M=c đ#t}=3*V -K%` sP7/E`ϟ_T-޳cJ/ HpUC Q̈vm#21 p z Q̒RJEqrˋ˛xfժ,*#iK)K,Fn[?']DUӆ %ѤDи!&J❕3PW1 e+$ 04rm(%p] jٺkb0_~ ̪lYXesHVSu:cE5Yb$ 8NuW66s~bkR'|HkWĤ9i͡2e bdMKH9i:_JS[T] H79SdY3Um5gud5}޳g715{)̷3Z^ԁWVP0L1C0X5| ɚLY=dgER]WH\_z}uvZ\FBo#MƷ̂Ռ? )8+2 0EܕR:,ba2bhXuN{DrS/@@JȬ|q<;Hm3Jld:Tec?%hQX7b)VBT?,.]M4zKz^d6k~!/nm434~YB\F^M/6731'C|;c(߻L_zjzMhʁ e\"kM@'[j^e%LOh$u->h&f dZX.?mI_5_;*\!RE?.hC/Ǽ`X%?+LmYo$ȭ4%񼤑K=i\[3KC9/9%\y!K;[A+xzʡ8yj.@1dPl}[mI >8Ӟ0qVxȾp'?ObE|%N$1#SŚ3hɔ EH#n<*Zn"D5S/j$XL: dLQ֬pځ0w}d/#B5G`Gp*$ioȣ͞=Kp,i{g' #S"Wcl߯%Euhx;Mtt]T4  xj|@5k((&<̶Y}GlE@J>EÝdRDb 7nϏvXϸ{OVl}<2T]gAP P.Jc9d`N{?&3y\)+)yal^RԲԵ2)[U)U /P\[LbC|!mo7-(-uhPECMPՑHJ( bw7s,95(2659 Rg2̞#0CU\oBõ;aLzA,ҰP]ӨJ#!f2%WyS<^|\?LDK)hQ"RZ00;'~@w\[0=?(cuWSz_ DƓ'i[hQ呁(:٩6Դh,/|}"ߜ@[d6vGp\Cz&OzȲwwoK0Ep.[nc"H=dlMիIM &J:W! ٌ%/Q }S9K,_Kq+)3 Y 3Q E(b=y={֧A\VѨò%:3+-, R8lX)V$J*4QKyR*.U UzK?˯XqK!U=; ~u 4*oL;<˽ xD5҂3:m:,gucc\sI$kzXc@ئV֙l.B5 ۺe.s#sy윀&.7LwEsb+%!h 0kN|n<,ŗ ]f`a::=NL-ޚd!,āu0Mn{E_VA@g~87M o222Zp4p>f3v2%=rӛ·QoJnn7vFȌ#ZTx)l4"@`gd8Xƈ_x^ 2sH%M]wbddhgmȜ8I7mrx>v_~yvC^j1m Nc/ٺYY|{l}4;ب@ȚK|8(|i7^ |s6ئά6o+c0Zʴ39K 䆞'wڔ՗# ͘'Yaz3:f2^_S7Q18:]kד>vk5@3F+|+T(Mc}ں憹;jE=<r5+kS0MИj8w[&jWڳ˚ywVޙۂS VkXj Ͻހ}0 fWtt5&:ЀϽp1dzyo Tޓh ](fE F4$zA6 [(\7uݽ$ɶj`oXdd:O`IkS*Z!P)JR?Y"^K0 >,'ploGfaXC"͸o mԯ~Q,xQ=Vbm~{iv7u np1fr{#?(ڤQ ֭x1$0G,0zyV.cOA9@/9VXO5-"`cN~ZGoDڑ/E4s/:7۹=inHQB}J(%,COBQ1)p#1yJL{J}r_s+a:+_Q @wa2!lUa.v>QɯE\l( 0Fa^@BHCRD2!1gUL%3&ÈDR!ǡR'`nܵ!ALÅ}1{SVdp0Xtk@#VZӽ #ٞC̩xCj6ɴ,BYׂ-*hzFVKm.25KNEJS4Sւ8;TDqb\,C!7@>!4!DAK lI U3ʮ䫯`("Mau,њM  5a>E/rQq〲ҹ}ay< GgK/+ vÀ#o{ZfL&_,]xGZh1(" S_K3$pw)g<2)ȯ%m"j}519#HW4ԃhn?FN`@7 Du@QwMG`SWa0y 1Fڵ6b&o˂T3?RɗJs/DT\KCG}"huI :hk[a m!Z (q:.+o.ۑ[ߥ-uX[KHGbu.lX˥ Ɓ˜X0a(Բ/E*zvo5%pW4K zbxY.-mCy( C$n̨W UBz +x2L_g 1˵\&r{;h1:4Y> l 6s3,nO'=Ṣ&-LFkSɺaNjqvZxC݄s`qɮZƙe-x~\H8Ĭdא.Y\~8WjG ufzCR= 7O}o哺3|ɤY :KFf2}Xi9]WbpX:!SmU bp\>W ?{ñ6U|Q>3;uU]dP;r"I :EoLO3 \ÆG̻-pB@;oqD⩈g6㖐Y.WgH&_#n>\FKm&HMP, ŏ[L\X[}Dqi@w_l$r@23>ՄT$HHUEv?䄨 ,] & `j}-E8l>q`1M)N>SABBPj,3Uh 2Or_> w7pso4#Dawtxa;q/>w:]Q ̥ x9lĞOӰpSNTU3Is#xJUoK/v>?5tmcdXk?]P/JK?`tyvx{LNƏ>ŭ}o;nXܞ_" 9az%>bT(^-AKa~&xlQ|3Z^s긔 }wRǍ1Lok]0gnjWW0D'auȍEFi{(V%*iqct lfԍg᭰=庹d(j7;l@\΁5֛fKee\^-ڗ./f;\ɭz)uuEvP?Qƴ?Sd\*޸7E+zj(r.9W~x@STSVtyOr⨅GJ}U {%p0;k.eu\+-hxꕅqb- * '=?ƱZr(8_ٖoKͫ_q%STx  KG1q ckמ~T:R*6"]"ׂ׉r?EIퟻYx" 9sS7 x I%xSjA%hFI Ir$iU *b˲Nf&uv6%T :_P ~O~d3 Eܗ;39˘UјS wp&<ķ?2w|!y p=x>,,`7a=N)](f{OIۭ!} A )S< ;f5mۇPW"bL_sS/\+G9{>XP/ y.zR|6 >E`q yOz"^O7Z]wW1;s}68]c*0BlA"F|F?y Vab<\5qҚ 317G yLQCl]i j]>@Dzia5޳( 4auN{us1xl ݻN3tIs(6_D QWL|@ WblE-ǁ˛102Ʈm1nǣ:pEYЍEJ6AvQ3`%r#<B"Lv$v3/RTê#o. DaN>~<H5ڀdzpSM{B܅!x^ӻƞy3t7J{CӆQ\( (:D/OfM>gi>d~2{W;8hK%zQMo 8&T FJJNd{/U S%t.Ӕ񭐰~LbXU ?ǽMHz 6MȌc'7E*t,9>ff &YW ٯrfqR]u+A4_6ZKii+2Z<*\[8H\Tt"DDt'#|r&!a~$7vj}g=S%?9p M^WŹDocN5|:[(a)3g/ Fqsb~e[3/FEq|~0ry. c1/3/bniY 9<:1/ ^GnuLNʒ0>^W&gmt/MA\9qϫfv^reWסzy}[j.Tٓ]Q|kaū9sT]g2/y@'/E"sK@D}If򧧩z|@!,Uzbs{i7Ϳ'r*"xAKAM`>ڋ.xPF%e\ "bvfgsfFA" ^7:JV3;1}nTBQhɬWr ԇ&jp B8f?2쳃Pv!K20v 6֕vԻ Ylx(zˌ֐Fa^[X%4`CN/+A%R YxBn P .$8z*MLDy/5< )s {zPB p/ "_\#6vS1ARY׉͂I!{>X g6V%"I*|(+fa:U?ۊxesB2LA.Aa!\)iy aAΨJ3sJSRl JsSdbiJf^]̲2\N~.>\\eɾEΉE)?rTQWZQiA?YMKIдBR5Y@BTdZzjI&!-}.)_XibxesC2`@gckrJjZf^2P j69ũ`24%3Lf;).x'WwOxWg`.ԊDJOmR) UxeyE`C4|wrJjZf^B|{sgkPɯDy,/\h$'畤VZPbVY3RR+@<)Uyy9@v|nbc2\XWhxWMoGذ-$1!UDXm d5H8V=Lǻ9T:W.%xgֻ6iWJd>o~FQ'544=逝@΃~62ǿi_JfzFk/ Ґd.)%CWxx`W:T6ȔGlͯXtnNR6l"ߞ3>bYء`Uvgbo#6ES#G-|fT;цZaX7_ɅSE!4 ~ :M;yU[jlgu'Nz$)h-;Q<c㧝QkvpZsyE!,GPxu^Qwb-Eq*WWxcc[w9ޤrռhK4#fTf9R'A,*~)R6HlT8YS>oRt|J[V[N6X+ 7M[;x/'e Ex[cC4vpHo|@gckrJjZf^B|{sgkPXTh5rw;N`7}pyʬlW+.:gs,' Bqy8cwš.;'I[3 }t~P.hU>0DXY3^&B'k%Y(4 fjFv6y z,,חB/HdA]y!eUJbf"QHt&$ft%N̦rWI:OF2^flVgB!Cc [;OS B<3dV2&B`R Fqߦ5v}\׻UU"}h&t9W5^9n9~.g 09I1-LTc~/Ϻ5v{><-;v^Y\tՊhzxƳ!3(]/=/?7us*jfU$xmKk0ѯX?0mNUrh{(P iB$'197 VGX亼7]"d1y b]út=BP3!!'4` \!^K+Zq~V㋜6[crp T2CB ϚgۖgGLʞU4SMM%mr >)[CD9ͱbQtT[Y^ݚUkuRlh>@uUuV;%C 8Nf`w`z^BF#K`.x*f!5 \f G=LxWoG)- vO{بٻ=x8Icof2TUmyVUeupNdvUf*y(/ x^F Tr ޻ġRWTcI1p8 ()f +M8aRl* LN]lqp-D(BE\S4<Sc6AzEԁiO\i#oep0) |}tW~]cD.Bb`J!tz ;t{7N>wN|Fc ܥKC1DƸ k'>m8}NSvbMktr[ e[1gӔ(2WzXϞu]9T8z746"*0YhYjQӌ~U]r:5de)rlb 2Qg"98*.yO ϩ%[R$Y OH6dGp3]AףŸ/8Ua3\tzE\f*z1m&=;&sp'G]wKypjx)CW)XtתκQ4nI qA&\@0,$<f2zhEY:-e&umqMYQ0O( C%>pJV׾{"i}AzUVb*Fu>v}3.0@`Y-n*8yAryw[P]zEvk/GC5{sS?Bj7{[ÏqͿW:x'ڪ~V4rloj A0c(A582*Mp_0A-A5ovCzfz2H0&x;'RS`\ZT_4Q^>3'3 IsC]l99 ӋSt!ryEz83!%AayXl'0 #iڡ;TE94(?hFk >Fɿ$=]\l'˳JLfƤ39H{ @)Y9y Lr1JSKRK&H E٠_a̵,P<=4LZ|r6i6(w>PL7' ((-3'`9Al&A4LgS1X!lڌ\yMdx;{G 4=3/>/17UV(57$U7% 'qt=@^N"WNfD4*`ř^Q771/1=H/|2\ĝzɘO|ŋ"01M5& Lvh*-N/I-.G#ƒ Ty5NPvL1CY&"ʺզl"/x;{g1uL/0a7{ox;#]S`P_Y\8QNER/'+'3 "I rv VL/NEըZL@>U^NdL'E&QMDs\\)%%hCx: 4I Ѽ^%Me/ՓcY_kЯx=MjAF}̸NK ƅą i+.V2IHњQxkwF;=M?ݳݸvK0&46x''! 0awzK $F36t]`y#֢@~?.;9ţ݅P˖ˀp)`46O>]9xpx?pJ<3= `l|;Kؒ?X>9'myܧ,g> t$X8`Kc8! .ÅKm86#8pĊ3ALg [2>?cCrFk!OZ p6MЃt>_py5{3""/PuTlԹ{ G,Ѧv+O\$89$Z<;SΊjv`{?`NPH.]&ЅY( {wЁ,bE~ԢpϨahkIqrlKhߊQp z p;\Ժw1Exy:8RE::%P&~Xx C ) <r$Թi{ A NTN6yF1D| DCW"2g-{=1zgg {GP4ظEWϢqYńVֈKT4Ck81&#yR.Vqޛd4cO0#xX1't4<ݘKڨ5X|OH3LJ`<&1|O'_)~pqoR6@\QHձm!Jݱ'b*cX+0=αT%(pdivbEMkB3)MUdC$*iғ侵17aD|y:j{Ml+[06,Ll^&<40MO_?>+Ʉ lެ+R d"(?iLBb̅V"hQkkeaU(aV"ÐMt:ܜ]]^NټDt 9EG b[,izAbIN0jwNhH~lׅD$PyTUB^f:+Ga1җz N^I} y`>ʓ6Q9Seۘ6s8ZC!jteK;4T>o"wTl՘w RU⼳~ %[QO?MLBXs/ȞYj'JZg}~ {7RXS[_\n7Ihd*V}Y*Zu_rQ2Fs+"yNӯ{h%=xN$]vDZޗ\!1<򊣆쎒.v6LUXE[yz!)݋e e+[ { v9p+o =X]T 84 c>={.TSQeB-=Mbvi6"7{}$zEaXn^F|_ULʹ23*,nWǏ2x;1kf}J2K47* X2x;u3cZԴ̼Tw?_x``PG'xO.̼ҔT̤Tݔ}/3%'U77?/$hr:+X@RN0)=9^urd3)K'PQPKI-LNQ ( f+PlŃ 祖ǧi!Ņ7'G0B+7YRs]əFgJ!Xx;ՓT`ʓ? ((e&(lfba,#zq4_^jy|Z~Q@(ٟk)B >[ҝ%ya;G| Q4v&Yw"/q?J#`'}7ѮER`vm.o9an脱;5[fq90fvfݿI|f $>J.D8;S|qe<E(Yq? k^0 Ril4)FgFru[=ᘭnV{ _#!x[m F`אO?PwOxORLs x=90E9H\P,bB(ɉ#{\H\=}=ZEpg6ΐ:Zul6!`SJCXӽVкҳ,@MUK:s/τxI~]laiD )5ǯrk`! /@ xksH;@{Ʊ!+'R i9 H8n1zlUTkMt{c7пOw_.&ZLuFg3jtłgr5h?w6;.W4M8?=;w:(aJ7 cNl]eq?.\B9 Qw y.n]$.vH ފG5g! 0$6a? 6#| sC|4Lu:]w8q9q]p6ҽKwB^9h(GjY0'36Gh~ܛLzٗ |KDE3궷C9AzFףd>ft n'Ѓd6_&pw?NE8/.Mb!_pcRgҷ7 t`:lG/ERsaJf.uY붾$nv*5-ƦJdAmT{mڟ i`MnE{C6pd74&4@޸?PCg>1)a4&S~# s͸٬պ-1зoNx~ޕ #JD{:[Naek`)KM1d#M_oT%!ǹ>s3o0"rh|$\-wCFe!0灒g.l9[Yj#r6 `ѥD#-%1 DA&wEܯ^/r9{/]߻y~MO Xġvכ}%;Ugɇ䮜7 }n'ڇP} k\qj!|t`EbfLU$H~g}ǶųhLmXTyK*셣B$㷩{c!ơQ/QgY \Q.x~ ;FxӮ [ ~@LjBq/VimUX*ݷZl\ALM>M*Uz87ϧAi^T\CbODžx*[D{;URCĵ~a4IE4in}П5Xn%!N7N[MVEV3HPA5,8|a%44 =cVҺ ̌@Z.Q"jHE\ tMX㊈OgBj) *U٠ֺ?GdoQ wN;nNs:(E8+/q|{ I;<~N^aUS}Wy%Ƞh:RJazqR,E]6GV9j lqX4Yb@9IB^JHU3aGʁ.B:mS8, R, RéqIHln繱go1X^Zek!YÍ'a'Bм'3 'Nn/4ƥCtjoY<łpyMP3Q*Z=풅HziXN67jnźbA^@2O‹NLEOF["aċtt/1 ]XˮXtKnQ F^Ƅ=ۥhC_{q3e[/m!ɞG"&]z*/1ANʩqu umT7u>索/roLړpD-T]r{9" k'A+ |7 ˽t:*P9 0]OeKI\"]+p'Cd|Z2V:N9 "L:3H.O=ZSϐr]I^kRf 5, p0v)RDx!,Di m$/_1|O".vMDc^y-"Dϕ᳃R&7&bS z@gS9Щ~lR~A+ .΋ Ψ*@(=,Tx!)'4͔[QrS*j|okjgDl@/uo:FxPLArz/nĜT ;..̼ҔT$~zExJ>WJM-N-)K/23:0Lvg߼%Oũ8(RhA5oNff\()6h.Iaɜr'ۘLf,=U~{XbQfb^VQj5$q&gR7+Md1@rPUZwIN6|_ar=+&*sLWf Ѵ|_M#$($'u,yiLy},>`{r_)O>)=yϧ%0[̭ՅuTl6Cn;ɱu's|i]n,$LtxUOA F.K`-Tb m Ӻe΢!=y2ԓ z`G=xg;twi$Mgg͛oiP6=6jUj`IU@I fkH3;fJ'_M\jJV){ؙg\"\a HfC^3Vg/l!C^. F c #CʶVM$Y4@Ŭ [yuOǚS,}UsC⛒D7Fp߭M6>CnPX 墎>5 $~JS,(UkGp}6f˄b0xMW5: _ޅIM⮅SVNH,0S&oʂ.4(R (rx(#qDlP$@0(_++٥|ndW{W׷""jS~hrٶsI6R9){eJ{β2;0d{[ļzF\Mi8'!C 9gi#lw+)ixpb{́d)5]vm DN; :T/VÈ=Ơe@^M ;;r0CdIUHW$jF\oL ı KwU>Qk4ξg

OZuMdG:e3Nualp}TK.}Zs(Q !qa/{측xV]0}B}/ib+miZ_ ~~:3{Ik/q2fz|RELww 9k (:-pHV 6`єUp_:.zU Я$)i-Դ,3Z%mr '2DinZH.t𠫢Ƞ%Mт}Xz XsvrJ'RS:~T1c9J:*@uB4mѓh߬9 7ik}4"%8!`4XE JG+CXNy`:5 P8oPY\:&kR1\ 'jChsƚIY9δ.ʐNTF%DI1.0G F)Ça8oRzXR4).ͤ]b|LG . \ލa|6~6\&BGGE(!Zƅ@5!a s$L(a.4BHEͻԜŪeuʖm)I]wXz3&uPVg {{^| >%oW}s`86aZSdF7A.Rl_&4{\G?hf}V`;Z~B0 `?evUsNL|"u{VK*WU W#>w#2tSŨV.TuE.qKBy_&2Dpo^{,̞W7UMxEd~$xǩ1`W Eq#|TB-- N!!Af/hԉe36x(CxX`jl^xRGL:o4eڦ M՗Zv6mr5T&:ɤ/ ?~ Wv=6˵J:Rg.ӭڠmNv-7~:+|#ի n> sU[Tټ4\Kg_wdSfGnhBӳ{_cl.nN8/$%wuEH_NպLD7ԭx{$73?@{}~J i8O^־d)hef#Xu+tj7څ n uruxUko6_1uWmt=wFZZEɤ@RI{l9=-R;Ùwy7:+B8<إW.T1)Mٕ!Jf!VXutXr98?:dhNÒ!(qOo,ÖPXJ,=>|}r0rTrgٗYg/G2|7Mlz>^0]bp6rqwѡ]&IY%NcLNsa-b≸'qs<ȴz,mrpHB ~6zx]Su|=_%Na u>f`0 .ج^TQVĄfU"idu`У{b!WH:JTRڍ>?Igbzlrxp1T;+?WKepM#?B" 7w9W>㲴/ۨ=>I^8Vs%^9]\QL6rQo>U 2!GeNtv?eU\\K?#Hg7 `Ka͸? ]b+-aN^{:nlqҊ\#rƄĈ-;<}|?XK2%v~NGݰK3o"b#HeIIUpu0i-Zy;fy?u,TҭԬЬɿT ʕVU| 1 \N‡}2McQ#%YaWxC}rtT=Ri-BwH^$1 6xykB_~YjNg^)8d[)e%(T)ؔ)T{9mr2K2*!Z P,QPJ/NM,-.HLN-I-.QlʛZRZi5y`qJ|NJqn|rNjb,d<x=m{㶑W`uDr$ۻisu"ZڲOM>ɼH boOH` t:*;#7<~v|sFȧQցigɊDAxFfN<49" W>~ oy_c/^m`qE^~&a ٱ(]gq! Z'Qw5E/q,ފғ %$^$ޒRKk2"P?H$3Jx'7ޭa )hLI2p/a|'rG/+#b-%.{h±yK &>N_STsz]{gt莝|̫}}Z;߻nqݟޘzԛ*];`0{ǹ_WX`ǀls 5 E=9 ׋ 20?Pj#qozz2s;w la{n;2o xgPiwYLWЦ3\3 -H bPs^`ɻqNF${}Pf4ۻse24@sCWIL=Iwɨ;~@Hj~'K3Bګ;W7WR{1)X Qgtz Y  'eɆ~EB7EnF8Y\u# y|Va8xS9©ڠj{N%3Yi@>2QU¶@_5N``*ePxKKk;A.umYe}U7V煻Bݢu`:Ȇt D/A']9 z!/AԶ(Rb w0O&R8)ųZ' `]gۋsd:+5\bQ֛鶽kY^{i,{ `D1G^Y!G8KC(yYv7, [0$}TZ>+EEiqٻ&h>nw2 8 ƻ1ޢ /P\\_^^.6c_u0-RC>X@ib-j,,o,_ҙ.7uPEя`!o0y>Z X=/$ኢ0i* ;s VUV]N_E "{9v*Ld[딄W $(̔ji4|aMM&@5/AR >c{h "<+Uݱy1KMruȷ Ls]`Jp^nJb`.z˼(`߃-W ? Fl<6 s2Om8WX'1-Sї`@KTy2u,EFV+P(`L O}xd j&۠ ƨO0t71L2,zLg^,hZ<:LdMpvgv\U?k֣P>ʗsۊԂxE#N݀6w.'=mYǡ`-Fga `J!R[Zqs;ˋpw-_%FS|[KL7hM4#Mn<7̣AҦ#zXŠ SIn00Ad?Fx3)H1V;LxG3oez*C"<Mxin[xm.%U4Ar}T"PM8|OQ0Oh֥W! ! Ei/yM.c~/^^Y^J#/sO=93}GueJ籆+,.b3/ 07puƖ9/1 1 $/&[,q$e!,Ѳ9t#ܣχ1|E0"2p<[!H®u4Pfe' i\!a&j1`I0{^4ab 2^F'>CGo9\R:+T Lup2>vUjŭsҙ 8nv8ѽZ2r\\`;{6m,=' \$4a hW.< 㧯GfvV.K9r+呣u)a;J}jEʔ>Hdmpr%4(}*k@u8*mJ53 gz1 rIyPAGEh1` qL/* _z$i~Hźa\i fjJ{# `U6.:yћ` S#3T3;% I_*$pfۗT5Rl5 ĂUW xekYxţ4^'w5tf(^`aSa񿊵D%M<8L^9z.2* Zޒw21 >ԑb.f2.e;4+I6Oŧc(\1Zd?g"<d 96AV}:]/HOw67l|: ,n'ĐF tX6)My laD|5 R Rut3WCM9MO eޫ]td:&\z.vTPv0 ߭,ح\رu, 4xƝ*𿽪U|AbC%S6踸F%&c[k_vkխ9,TEzIvo)k6(43Mu H풦)Rܧ4B|;3)+iuEow;묦P|JW;ڀMMSˁYuʈ-{ ˟HϯɒShkɃF |fԡJo`Td폴ݑǽT2A>0~`AƒIZVH #h^0~EjUnAa/?<Tzd1t}+oAm[' vBbï heosPNe<`Id|&0k&+`:⣩;HNJջ#k vsp2 }u!In{u I[Ri.+G ]eɦBQzmL`Hb(ٱB e%X,X!?^ɟu(E9u#x Cr+`[Ӿré7L#䛎;{9(fv$χ&#Ռ㈝BK/c- O|PnhΏàIȃkI^yj`oFݎqCxZG[_CBů3*<c*@+%5[d2[ha p?Ǹ)7i3SEvF)M P.B,]p6isO黽w{NdODŽaV* f6hj02Ks$ &S4Mnoػs{dZgx39cܹ^N,[l+Yt4u$SݛO~pBz8v7V-,xs||%S4.fOoݞY\Lxl}%uCux=4Z*q0Ap1Yzӹ^頄wY$\!߂Gs'~a9yz|%"9UPTNVA>Iumg,.9+nH7iF)gsLD=E6nݪhOij&ЃQnx4_Kr/WE*.Dʶr>25;&rb-[2]EojNwۯذںVZ] Tcfy{CL<guta\>O)|eo~.psy)e8 y]Efꝍ߼ʶde1l5ˡzwL d & I(lJqשA/ *f$T% yDaq_iF|AJP""JB: mج/bqGdnW5£J",rYA (3$[ wAw]8ʂhm !+Y0*!Á՛Lbͳ]]Vq\鎶WA^U;mlNь C5ʮ % dЬQ}P܃ּ 3%tŮ3rz&G9 4MGelY l"jb:YO1ٲOg3.t=3\ 7${pcb#6}WG9/WogB[ HnV/9"_{>jt|v^BF$"ECTB 1y?чI3sP1PUC`G)y!2~\ //\`:߮Nk^JډN(I(nKz%a 8pjE=vm73yG^ Mw遝S-%YeX/O,ɞ,8!ʢE!}`D[#N%˺۲X6]lW=1<M|d~ ղ(P}3uXyA I2qߺhY/sF0]a(7\ST ;nOb',~>dd$i&)(yA5v P"0$޽$},]4x61`>^2:c#x%;v%0KY :&m3DZ\) dX,U m+QkyrGab_xd:sT##xbLoUr3̶r]:lV_9355;@DiP./sͧjgtֲ4[f`pGSl1Ku,RlfԼjsZJeoUTU{F[UֳҼH#GBPק:4'@"5,{fo͔۹yX>JN|{Q2I˕=IIV*SP^2gs@1 Qf-Iy/\ﲇ)`Nw;eUq ZJjkL3c{R/חsq׊ȭY8@Ydڋ#%Otw$.APVV=M! MñkZqk/o WCU.{vng˔2QElY?"$SYnDAxl=J$)hHoqwpiV Ljl8py>2g_iOƜRt>t \;Gw燤93Ұ*.EBrsAIRIИpc5 -0\) TOKC`szm@f2[%j&`^D)1hg19&U<.br9X1\> '-jC{9q lҎ\ڸKJ)OU&Լ;W('JqDž0( ߧˇ | |:A^➊73ե%F򅊀t9_,գj1F]Zޑ8D2&hX 5Pv"m#Rn bg7ϑ0dVItSʶ`9~n ?uv[gX"0,FhCP8n C}}ԂU -L! '0N?`FwAv.-X —LIx?Lgp4x <ϖtt=?Vi4aL}2Ti5SF)f|PCK>5HN,RJ Mq% u!AXL^9$%[׎j7! HٱmO,!$AqA/ޙ!q3*ZD+Q\]Vs*J"Ԯ&Ґ|ѓ_Q y$YRlPcW(+Uz>/nÜ]Hj˰*5)tD8@̡lx G%Flx[s S$v.x}kwȱh3Dz$ۓd&seuG@$HaL qoߪ &3EMŎqbU|u˗W,IVmrkNEt.2mITPx6?/ntzY ٳاt6K9 ld=pXo{fqUWL֌ھ0Khx +.,r&0t0pqvavve_7ZyqV𱅣` L?3Nwφ{wdzӓ6c +@틇ij<4p H@ r"|rwYz}a@J,%l/o}go¢Gًϟo=1ΣGHl9NXogt}^Pޖ;")/XrߖUlƳye4i65%EQU,ųz9uz7;>5z[* }-uRlQow>U>#'4C :9D? ON9 ==xdv1y5N/UῊbK.;[dt\ O`σɑY:d@ΦV¾i9JD4_bYm]&JCFP[rfE|"4)(3Abkg^wgb΢Y?Fg?[ߏ\㽁C>5Be̖C9L}O F=އl^^LiRjR8Ü8m>Y/ww?yt>~׏z?d Ѵ_?Afιw^ozzM%WYML"z!*BUU]E-A߽]@o)gK( ;5ⰌNwTdhuw騡Eom Z*SE3hq~MbB'_Þvh3QkK!.b$k[SlӛjW4318L |4S`ɲZɆ7lF[i^&+@+9S%9'9* &.'7u2cMyș6̟)ľݤnaGQ|ҟ7WH DGblIF6먤?_Ӌ<%- .?}\p۳M.E#;@Y:%7%KGbv ;&91i0H2A@ls 2U-U#Pq8jsS5 {.ama$͊>!ɡy*{Ѿn 8y@6vM9 FL!M#L_)NL+ gDÃh_?2k} 힞kM|[@6}$-?J ze 7{;nV1qnR#\ [ǟjniLOڰQ~49$uYeّ"ӊ[Ne:ׯ֧Kɂol\,[ܠz64RlL&nj=~͞S/GTcM 飆=_UemM*5hގ'xJ s%I|uIa!fqw"b1ggǂ_3Le-jEtJeE[YB%|+)8.ȥ]j*)2ovΐ.n{{{]ŠA#ڊj0 3+b!aU_8Jc}NS- *%(U  t(sW5P' %?)7]pA)4W;E;rN#Y_S1H,lT3-$JШR#@_EۍI_ QИmRd ԹSճWXC18KiIJRN(eߏ%AJHf\L,B׈k|1_ڃ{zp:o꼱 ~.ae[w!k+@ y|CKXfӤ6D 2oʃYr (\9wVUIhD)*¦VI(26hǥC(=$gY#瘋{%Kv% ~* jkƁ,`41x-r=0 e~mH6tU@DBQl9BItk)FqΖD(H` l:D[~H+of4`Kpxid!j0,/rE${€ hBM*BC0ey&ߴjדC'xm|hL1P)~aL (i+I v2Dg\$.ܯ ÛEV mA˦{C.#|ϬhS*ΗV WWh ڈFe##t3nbjԵJeT%ȲGKX 5q׌G@OYIH9?г^X 9n>BoIr!azd\D[bYxS΍K4"?_^SB?Hs#=J(;Lr  Ns4 n]lRFlUF=e jajU-fzbH`6 8Ɖ"!]z<КD9$UjQЫMV# V̀.M14g۫M`Dq#Ja9$0WLfMuə>j)H Q&fIIbN-Qhiރp,@'!Hq%HF`{rӸdYxf$Z:T]8гdCF+5Y%ٯޖT:o3Tb(-}@vlch*a6yGz)J\=13g8%+R㫶U%~X ''/Lˬ+‡R>`d ofu۬O#bI lTs%a n%;Xxa'*崑ykErKRtisV#<26Q`Uy'zUr肭0KL#, nmY[$(娢V>'hJydBm2 Y3w6M87Yja}vUR2 f |2p'fʼn8h0|_ *%ДA#Mfqv!ߖQf~iS"M#sQxĸ-Vx--*2V*\]cn;6#=POWq@#ra T}cp`hRS>4$k50R$f̟&<~pߝ|Rf[Tփ61:}_f'92 9h^ @<G˪"W-mPt&ĴSlM˳_ߟ0ܗ NKrz̶tm)^|˹iu5?420N&ObO ݲ; $Uy"rҺp.N%r,KIdPo34!moQ= Fq PB'5/+(j"M 7[YGOZV~8$?#V惥po% p,F <&gclI'` t+ҬFz޾ԬsvG-w uĄ4 Ⱦo&kxgGVW@nuiҔ7U{mҋU[p2Y5zo܏47E=~ÿ/8Uы]su+ڞ-5J aB=ז k]4f:P:ۙxpkМ:@%+v_:=uWBA&%RyzXܒ&Α Y]X&>!gǼ;BpvxJ8k#eWHh>)&e#a? HCnj+v: 7A ǂ  t -UC:HJ1݇`?rǦ]B\YDD<Ƅ]xόVБKB9_1;7:;'71DbP\_|q9duIa`]{iY'>5pNf{-(\Hmk R->Y$?2!ܚEYyRO{<ΒY}tݔK<̦ъ:+00?Qcʾ_kwnUA G?Eß̖ Poy\l}S L?)?XN:Mke[[p &gڃ$06L|]EŷK+o)OcClza=6}pUIFwwۉPkQIv|<v؄~ʝc/xshH(No@B^o<ݩ\fV6y^H]%Թgx}B;d4s@=-+#'0a6nwS"4%+ߍLl.?\;T`!YK4JTJP}&nIL~tť|qG 7 ]d3 d7=xΗK0g_x4)w>Bʓ$N޳\ 7i?)wnM)=eTjSV mh<`b]R5krJ?Ϊ%ԟYɉ{3;omæ)#نքٺiX$cG>yGF1ǧZ_##CyTs1\@0=܈>DF{Y((iPEIР]>T X֬Ҩ-p"dDl#{I˿=ʟ,v>zNEj2iTM2v)[äaD.:b$`|hrZ'z .G*W:gf7 f{ h7Z mȉ[$u@l3E G➏K,3"!>2 [+ Wՠ5l0*a4+j^`g%7VNhrLҡX"&cI Gi| -gl^sd) SJ#BR*Ekpw[En``7\CË bsBv. o;B^>r3Sl<J9o%ôm[p7_X[L6)P¼XN@Vih8!GO_XvF;nʷfɤbˬJgHPcQSU M,:$ r|iYYOﺜjDs&v"<6 "H:hcX_klhlR_} 7N " Ob078Rͭz<F颫xc\)x%5Ʈ܊D?@)J&E/0$>6 1GodR`aL!s"K]I1#iMv Mk[Lpp6z3bѳ jM2:p()j ח_P|T d^v!kaZ)}{99ߝw:1>VƉj7fȽ̸lDO}[dֶpȐ Ѩ,-F6/Dz2d3_ V"I;.#D*D? ~ ~<FG'Ó|0xQ'H8Ǿ=9Fov>8x?9<<cg{Óv[M%6h1hH# %>U,~f =7YLjfho ٺ~q?U_>{3|ڮZ ds,bw ӆ"wRUd3cdw887]PgNrfVRGaMn2&[\g9f]5`icjʕO _Zs&3?hF. L0jȣ֨&I@F-~uQ[./ egi{M!S!) D+/& Uʇ74H2. jZ"vФ&X5& 5eߠMW_"53jUmA5-`{Zs:>t!Сk f#ާs_ϲj[K S:݄ՂחRVL&˚[=qd[u.fjucȧ#91[A?Ysc۠ifGq=ҏViFrbt`'nMvRAmv„LL:o]W.oK:n9*9uɈW~uBx $.3qYĀEHLC~{=y4=28廜#P6H na zފv'PT ܀}q6 ԊuMGNwՄ܄jK%jnX;2}s#H~BFvdyE^eC%lcoJWJ2yZnlFwy0%r;<9_%{$ }::*h wJIm%J,_,b֬*ݳbf.5mqS*(o%{@)T]j;ɶE¹J'ɴcJS.Aq˳:̓h5¥H1 bǒ͈He%^`ڜd.y>cJrI&ybގL` `y];47T^R$8It/ћQ%_rOI>%,gݛH;K(G&A;-U;/KrijXwW]UWSUq4"CK n^[c;}'pumn{"q(]^A)ְ}7@Nҙt+ |e(K_Ƿ=oxqջ|k;ti~Y/^cHA-~Zʛm13-V;3֌a~1@^kj@?: pcC-6H`5'#u^ܳQ*JQ\$w{죂@)i5Fó^հ CAK|:`j!|Whyޝ{ӂ|g;vOPUxdo)$oٔ7̶t#^ ]@"7WU=X\-eU-ʗ;;P,5bC41g M+vNX O=J5lx ?]FVGdJD(d-"b^A}/AJnL!l[~KKPaoNa*eqRqL&*:"O"#]K@kϚA'ħEc_q<#ΓBFdO6\ ~:K).D/QwMD_"Kf:cD H%i]^" nY}QZoQѦg?84L;6\ʝob( ĮXFdI)o^[M=-m9 fmMVB/1kպJ59F7KGr&뗮fj4 x^,g6ʽ4Cs5*S ;"1l`Y >_'WJ[f<_>s 3X/X*uT=zu7hLLBb_:oTZ<¥SiATGC5$բ$nRN:Bz:M&o(~NɄ}y};9)ŔfGV%>& /5"m &'.vW eh 7T-tq h$4:3eOs4C xEi̹qk "m-vZOPwj1͗hGa@*bl2UxQS?P/B%<|HjxRu s3`6d^h52 KDD[sF\0O;S K2lN>|bdS nht|vNςOw>?n_Ŀyg[)B<pA펏)0JpN&4J4a4f54q5 >3c2^RAIנnnM8ғѓZU&:ƭSrQnOi 2%ǴyB.n"آmsI5i'd `C϶V&?w *y/ /:nPuPNZPkcphŐs~W#fۃ. ZѤPTL:%zRviݰn1^W:(%R@&"mdL%KVcB K7&C̓l9hd'\8#c1_5tў u' PwtW*/&<گFtmXRk8" E*qUn…Ž+;n\^.a  u͕Qchv'Eۇ=`G釟|QOu-`yĘ1 v=tT8 OYGW5ta䫑~Sf_3|e#"9'42*g 1@k`pBu 3(R/a/5Z)lɫ#n+b=8]Wnf=e~ ڻ{z [9Uf K`ׂ0DܮN 0a?S;O_:|j2E=r6hRDR{4>$+['-[ Om#Yvp; nrﭣxY劼&uf4>ڄ<`K @g&$-Y_*7'x9% E^*hX-94.᎗ȉ5*rf4LK}7~0;}6aNYָ`\؏i,-gb#e~\7 t%1JC1'< v*A >v{n# 5{a1GZsC54d Ы5<9w8q35qbBhE<t٭!8q%a|$hC$yL^! [D vQ_ėyܲU:M'd֋@sxBXk;h_bh)Z >أWAQYb `RĎl ݡQ%Zɴ>'l;UF\Vޭ:Vp S8<ˎqGffU3r#8р2o]K$QҘK:5 /`*s9W@%6UfR>Y!|]v-o\ rB"-ćڀ?h䰱u(uu\dDz+Г0/);rqNyD5d@SycO!y,(-C P${kҒIQHsWF*Ժ<H[ mq38[%3hyI uvClEYh"_Zi/z'8_B)Nv`sV% &Ӓ]Be5_~e,I`{r =暯/(Gн,Na撂N6yiWI M\#w|sGH-lRC5_!x-@* A}ŷjtrMGf#Ä@UWW(+:i 5@SItm~+%s2AHRWLBjbw:Uz8:GvܘTHx$D<4꾒G~1F64K1WJ;u*!(G#hh(M&}t\?3rhĒŢՑ%жtHW+5 VWdK"N"*p qG/aO;yNa;II&t")^3KT(ь;juiͅЍpiLgYۮGcTC7շ/p+\Dt̍G爥Ix2ɋ( |ˣa?$k +@Gl9r!@Y#j+etLg-E] gPhu,*6(isɜ0=)֦}F)xNQc]̴vqAQgGsg6iId&ˆK;lm0NԄNלg)gM}z]S6)!tcHq$sty hj=jú=alj7}vk;bXk6e,B}-2l_tvZID()a3d%7ݜAڼNe— XIZ l"@VԮj ;l}z) ;$ʣ@_̏x?ꘊ9›}3 JǓ׵Ͻ8> yj._|9eZ-/-.')M>3xyEMB9x-l(X\ 豑TۉA9z x&hm$d`iFz7/84_KLP4 ݀vy[xd|ds|hD@@}M$~:x];k\Z%_nLub8 ^ nn5cg5b2k?g[l}]alG1q\ qWTMO%|z}=3 2z¢k\ϴᵽM֌ٶ!IY]PW0q/J"hS6)9A>++G;lm0# w%(rxwO*'BF$RZA~pYg<®]+ -1B3Y[L&`MN^܋gS(u6Gy2NjA!0YS]99NW;GObpLjppvd &fr2G; dL+^}_:EZ{NeQx@#{dzAt68:y 7E)5Љ֓:-yR}Vs t-d.pk($PPb dB#J4+Z/(q^X+A'܅:&7H58%|'k;ֻ2_ WIX9k@G2^ό7γ]y6XT&8wO 䑧Ki" 9,'{5uba-IFRLV=YuY0Q>2zsMȍd}N\]ݸT$5"-Rz r {2ښdyZ>6r|1ɨJA7P!<`V66a;2 ]Ba+,b"v?lk `U[r@1=HnC%ZF`@E\T`Nbޥ?č[[=V1du$[f!o@,eG/NLK6U*0 K4ecH~n%7HJ%ڧIt6uBLn+vcioŠ*P!J(jZ׮o&Ԃ\ב|tu+ɤ5?.ƒ(u=, _f TV 13IR y&j&>|'lA$\L+g}k8;1}" QIݨEael0Lx򓗦?V~Elړ<sUL3w> v~ړr!c pD`GR6ָ1=ETSX~6Y3}^ |.R+e,$v 1 (\L]lV;(IyKtI s%ml}=+y2ɏW)&1W+(nkC.h:^~b8&ڇQUX2wd}[ *4YzP7Js[nWhaS B? [NY iVyH(?x{Q8?nOcw8(~zu##:$ wr4x y|4Yz!Ŝq9Km)~ ӹ)JWvkZw2> >up42Br=6?Q섰L|(G 3 skWZ74:ȰWå F3BxOܭg6Xx؉+o{OdJ,]} ~mKLMEc |AlDȯаw`:k@MQW EqΝKH<UITh:蚨)UH^Vda,"#UU~vgi1!$m mֳ <#(<_h7dWOzd^{\Dv?<8~"X]+S7$iwXsjb"!wB2&rn+{jX)f Tڮ'vYQٕL߆c-GVrQ>)e(y1&n[wq2ϳmy^ߺ :]v+px>?tWz={芃MYl]7Q j Ip׋9sKz>ެwц25 Q㓤tSqZk];g+pv$;mĮqVpN{7V#4& !Q) 10 趎_ ),!aе'!72尔V4{`Ο18^gVlDTYbGEgQP$FOߠ4*E(xZ%V_ME+Vɽ6V"M!xRn32].ΈQT zSxa eE9/.@yHݺUj1{كNIQ'=U+\$Ӽ"FaF|3:hng xY_l[mܖ$6k;NZ MiJ5q(m.7m{{yilLđ&MQ u&eecۤnι-R|w~|?:100Xx1 щqx7<=J.>&rBL#GGY(uйH IB'{ \.u`jkM7}Z" [lIm7l W笜aڵɚq=LϷO]=y蟶NlbSgي񚡩E*{^wׇ?N}w09>[!p4SXjmhɞ pM$'衽qƺjagd Y6l%/"k㋜xdfɤb+}^bk"R yعF0(QV8C 3r$PU5=cQ:K+ qsO_|q+(@_{g!򬴷<5Y6Lr0"wKiC9pHggPULFe?-C<\*GGxppPt!|x$e_xW.O *|V=PS33T::E#Kl *܏%NY9v}džR|aw πXh- gЅ]APzr_mbG8ag?0VC 3k`&[$y/5a \'8B4[.Ht`ݜ@OFAwb@<*ǝjٻP Wvqd#T s"5@+8yßT(v lJU/dr;nHwGzث9Q\ }g.R$[&K.R5\}T|qz#㰏'vs1᦯pCrTuP1Me~vc/-6x\zC'uVE~ ڔŴf)DZ^?lA0 Ja?{k_ER6+έ8c7Ppr5vQҀu&7TƊe Ƽ᠄hƃt</Qkkm~z󭇶áMr 5D{=YJ6Az'aM$ Q1Qe-t,5tVal/[q*{1'l.V .5+ ejLE*Օ˅@ua-?ltm[߸Bp9ůS<[4ҸZbi(@:UyXl9)ϱhX8Cje?Lǐ#KAӳ*Wqz][Yx58PLBE홈BhRf(, zzW9}m]2$X]\[TC]eJJ S%=­6pOgnIjmX⃬voֱQzˈVfvjx?aP w2fP*+p%7k9|5;;ZPA Zc/)_{-V\"U Zp_WKȦ׾ЙKgѿn5-[Bz&׳{#L|fЫ2 >STQ7}z]籭t< ^E_`Q{3'yT08q sVUmc h]v-0=KT]>j/Ku?g&`/>/J6P{0k<ŷofЯ1(N{\O(dy;~24ylhn}*U h' v]E4z}l S^gS5+KI2BS ~˞PΆ 軴/ т޸z5Ρvvv6M礉`藏eW '·4CWCiY zX/(HwAmurgxo Dba hX#`*ot뚝9b%9=Kgyxl(- )b޽&[C`a^ǼpO4 @17sSIU 5F xOorSx {Bekc z>U9F3pr+@, yC)ϢRUkj܆xE4+A﫴2"Hɶ:ıA[F٣(*h0p}?v H3BU8pg^ ={?NgKG:joh݆[B0XUOiKzqΤ䉅X:'KF`$lW JSh mᜲF !zW)Ut'k?\!7vK=wl/riבtuR0ʹ>N߸ߍPhÕ(V p/l׉@GL^Oϣlԁ3K_@Zk͈[]wжޖ|/8d,auss^ww"&DKąԕuѾNaB+yzkZhϑ?YfaMuYYÑ"{ MOf&Uե5UU5U /SYQm0RIL?Qbb.=.D5< #ۊF3 rymrLfa& /G1\pL$U$_9CJ,iNͪ Mq,MU\~X+VH9n092r^ӆ)HPJOUPGj3%{R\BFRDklO'a<>ό:OQ' kJ?lAXk\x˘){* Z}r~'j@vu4h,Gr&\ \#gnFg! _U@vg\%mMvYfeBO7!`jaXk 6/&hhdoWP^u0OX@CȟAr)OGVV%L֡Tj?PƌPN$ EPpvюx!gUUUV0չ-aZhI@RmUd8/`Uf |;ӄ7nA6-ذHZyF8R񤑊b{iel.h-6}ir8WiAK( bHwyL,ST4ם9y9L&Rcn7v&>;٢߰W4aϛQ+A@Q@t%[5[}#EA0_񐿻0DZQ+{Ԃ^ u"oU=CO8epSj-؁2(fSHxDCڡ Q\h|Z NdC4w*Y];$'dgBv|hxM:*RdȀwݾb2D1i,҂C&L>CMŀ(fqʾ i e/\<MҷMAĴ4'|,-U\vhKD^T)"[DP5)Qk҈ _ ÍR-nH(p dpXc$B3} o,ܠ17<x/ ;\Ƞ3/|*x,2FDŸ'j*,V]kN0Wk*mM] {vkZmMfq : 8-|cilDDe֔旕/d~qQYICoTD Qj$8^ErA9\Q*CrBWoY *ܱD%0@U´D/5dc,tj f?rы-Z gy}3MH;c;UP팂5Q(-L8AWpE  NXZ78' IQnD54ExRS&d`Ysms 3415G>dǴZrMe(Ҵ.LïS'yڊ4hMi>|)sH~'T )w Rۢn%lz+i))ɣ 3D5>}$8P4HݡR1}OY@C ͜Kr!NFV=뇘9qYp\$93Qp^%%%&Lu~8g8lMEr,wXhs s/},[6sr xy~; r)Px ?L寬H xv| : MU~{\d hS7Kv[8\K38Eƻ󻶉1j?^&a&)h_,Q&-RG%#:\cɮW+᡾}4W[ 5AQn7,>¥ >企6؆ $g"I0 2&"o_H.5̻?^ubfd$Y|rKӄ*7>qqDWb{(:Dľ2 vs\4G{rd)T?ݛSaT0WAkR?(|)Z `Pÿ(9 kLZNH?rX5 ` ϻHdgvC)$?p`!aX@K5vrcv4WTٝV9-K EKkIwF9]I\J_B\c54,%3er ,e)%`ތQbG-뗱O~3y(dYMĒb[k.(HH,RHMK640ٜq5+XL[3 M`;cW8St&3^*.(5@GA"3DarKF#dpˋ+KRszy2ZNR>+F0@jZsrq2@a=э;KqrQbFB[2JMWfT8cTf^{Ux:ۆC}.A㳠fe6JQXn[r6xS _8sS9طs3~b  x{S YJn= 0Cx{uS bĶc1nmz~!٦W2rOa䘞 $BD3ƈOrPp:/5E[Xxu O jNK?3D!%,395>3EGa)F\,e)͎%D 0*s!O(59Lpz H$XVK 3ssR b'_>є1~j!XFf2L.5=qk@WMޟ(.U\P#MAjREf^AitfsF#T0WhZOai9&9&Dq{5=f<lhܡEF~:NBvo*#}f?MIܱ*8^3ּI4$gYgЂ9DOmqv{)k)M ]w^iP6cx}̱ 0@=_̜CE-VB| T$p#sGVOK"xN Fx3۠R4kpw=KiZU=n 9Yw'v`@Q99ۗaX2ڮLڡ jjKե~iفe`ܓBi9 DXH''ІTMCh `_F`d#\(r0<|I*7&Ha|Ip}|4kJ=3pqGeʚx0dD,8rDj$9'a잔pσ$ĽaX !꫎3ށր6[s% 9KS0dL@'Crqs)_%%RF8!W_k+ Y%7m$"8>JaB͘[uUmjfEaGŠϨ'qi@Dń׫#9{Tdgsl߯/!t;}&Pt]jԑ۶ZXg*E)'ĔƗ^hZz*nޗڴv`ۅ*r3eyE1]V1;FZ9d]XZYHj3R4I =EJF(Rc.#]XnqiXZX[ ߤa6Bs0%4;&I*6"H(61+V[l漄iTnv}%\AK>+q1;So^!m@q\"JQqR-YeҞo׎1Zԣa*W瓼]K dn_[1-$fJ&ΘdaX^6U͔iS5gT@fPWWsWx@ }ONsceC{Ign ~I9lMx)Px$lx{(KpCd~ x7_`Of@ Pl=x{(FhCf~K +[/N~!nHRy` }a28vXvk %m VO,=QN֒(99Q% X) aeTf(:y2w]..zP8Nkx2Pb92+GJd0:Aa4"GgG{I_^ @(0y&:# lr߆00|2n<ϓxF KB,"qw'`ÊˑeSCdBr>! !/;]XG^~ի?s\zS{[[#U4uKz}v0۽~\{hb* biwaƴnLy⛽Y/>ك[_~6њMx/؇ bӾw{w9{@?dv0ɓ5ʟdvr3F A~}{w#:LK0AEOR٫i2ؓ/)8gx!@mL_dud3~20["}LtaD&݅SE{ΗaZdE44#QJio!̀ki$ѡ㻳šwq_ >dl{adž};ن a,xuuFн ҂upnA0d@hy/#ђ xT\x~oLJe-=)No"w^u֟'%xA8-MzN.OEdZ-w0ӓ3 c,$L nYUVT)rR"DZp>"D ?2ʧזrl(.Jg}"D Rr4>;'}^pkrY:~G= V#y?{SDFy"he-/7coxay%f8+PrPe]^GnPbnE8VK$> R29ne O⭊R bkl $jh JkTԻ<{'%HW cX[?Z}1Hw *BkWzdTv3+s8<V͝*յ {(oqVUBq,j4cjϞ djW_V ]@R%u, mY?*Rjy\eB]}boSΡrӋOu@7BF6P ~R(_ Ld Պރ&HY&[ǠE LOUX'L<{N1AʁM(3ySP} m|A@Py^V=Ww]&G0Fa(3^7Wy(Q==֎^^\NVq"1+ S{d uGɸ5PBC>Z!/B2 D'yC''2ݛyѱ,d(-W*'.k J($3t o,eB\H 2+Vo֟@DKi2mk LA ^6[6;ğCxwH)DV)ZϲgJ j[UMeVK^vO/^LGOSvHS,3,0|{2~+>uu&ʻ#I7 U4唢 vEt2!qpkMtO`\3JT7Q\G6ư euD̗6.THyW\HsʴtKW9'stlfNs d}u?M)+i§* .C0,m\[fl%Nh+!4E֯b ^vHG7X lTM6*0 T+t@v_5,hGam\us3p: ?qŶ0%i"/(YE8w@sWDCxXYay:9mŎ<`eDZ\}'>]$p·_I@D2d /x~YDMB$F^rt'w15(^cA[h=_Ұ{A;G!U%Rߡj N~s>8lV Խ08`&̺ }~_xG'׻ax]t1e 5J k71PIEfp3Zro{wSMmjfۀy2IćA52AR:~C?d=a^Bow \d-,)r3t=eNOoXc!T2SlS4U֨XGσUXU_lLIv{[ 0E05 5-zےdwOZ:i/d2XKF)*\(7iU#BLߣ/0ZVTk"&I;"48oĶ.Io,bi`>ћE7TpFfg Q-AFĉX|D]^NI(1 N^񠨏Bq ̓fЬׯMK_~Uw##T٦o){sɲWn0~W2>|0ju:* Qidx4jY[uD#IԲ!̌-[xym ,mm0M\m2\F7d{(7)+XL5V,R>}zMOЃ_j]]2{7M`on֋ldo˿P Ÿs1eJ@BQ87V  (3@jϣX_m.v~b!կ:ܢ'X5Cε.[D8yc#K ye5FLjIvfWF]];8~Ҟ|FwG`meOI:: t70qvaB~&5]4e0-Q-~DYJ|;>^ xxpGc0t\jE&nX:Q`x*WgT*ڵSDˎWXy^<,:ږ$# )*hܱ &%_K^-t7Xxդma[L2[֥TUf2ю ۨ;'++POGnO 1y3o0Ӡx^^5 WS X0_G1EwU UmHpV{qN+$p}}̖β^蹫W0.Jy}TVH I}/WX@r܇Y>Tʇ ;Q|~xŦ0i5WI}H/b3 z,>9l6$ 롥.74Z$/ID'Ol+~c*+2 /j#?[FW? X[k(uyت1^ᶲ h`z}Sqϊ@ڢgu}g[9fό^Hce\a#cLorٔ@X%v=Z۰fk'C|gD;)t *[5=5:MqH#f,L"!eE+W*5I2)Owlr[Hyi1dHT 2#CVv6G*45Oݶߘeyu+| $!MRj{B7q(',YS`L9+cCu|t3 q|;Oz?z9([d_ }[]f ~t#Y٢ %ct%kHZPa@%7y=U1aʼn|XD`<.1xaschS3On E|FK#)M˶j3+S.s}!KlDכa&yt)ԋП j)^=eb{ --Yxi[4#8}#C>Gaʉ?QH=فYnLOS`SDQ daCvVl>ݢF ŝyEѨSaxE K)`+ !ذk)p($ECDc `kKZGqM;/U>=i< Oa`a0 z\f>|[c^o>/fWQ[݄%2siEk: aI=xE*FvDoS+46YY.\%xf2?1gq4Xy/qlu, x P\ lyDPХUA4}t{l2q%KqrTC}AQvf\\!݇eL}nze%Fz_DU?S>K OܼGk<|8 ‹ fWJ` 6_~EYZo% yh.,;zrJd (n ^+f$/K XG34X.9JR4|& SwU4$o:G:7H: ◾}--R$,Pg7ii.d sK֫аA]nwPD}M(oK{ᱳ|stx=M-0\3!<_7+`|ȋ'ƱœFfŁWD~۰$zm5 xVַ4B[ԩN:Q@M;·qwςPȗ}(u3U[vK*T<"ze.J=# p9 Nybfb|)Y:=bxYxӞϜS;[=ٱUu7&Ue9w/շPfnS p}LQD Y&㐹~xM9t&Ҁ햒4؈ilG+N )lGNp<х䠍 i U,'q.tF յѽEk/+debN)IYy ,o(,XsQy2b%O}ϭZ v?ZcfbSNBY;cU)}yvx^˴욥VT ڥKnHwbCp;ۇA2ý6T*s_gg}>"~IKCГ'~(Yk~5Cc=ǿVȕ [2UW4 y?DS⚦N>hBm`dMtkL= ~>MzCAs3*N,P3~0H#Sw .l尤nL%D8tFL 9E'$Mn\E3~S5( |dN0Fo}:<..f7=v@#,%/5\( ^%$E(Q[LS2:,=Gy(M-LWxLOlv#_`XJsHT" ^qW'Ұ*̸W2f3=”<ۮsKonUtBF2Uv& †c-W[.P18p6=hLegM'׊hVhj5wnP2t8A WjlP ns B #&SJ]q8M%, 4cCpTLNy=с>=1;Ugk`"ؤ!pМȚG[ lو!(UK)gq.GDž#,~ f7(<4OhI@ݧUK{sDE`ػ/l79O![WRgv <]E,Shb-ݐ;PA\qs ۖM3ƛSNw$[=%^JU\Ve_[}%F{5+ykU]+zR$ׁ6' h,+6oDՍ{W+GԂ:<Τ/:bw{΍"l*Ƚ>TJVlhJ?:Epܘd9lxhlcdm7,YݜOغm} O.=gcl:W5?lVT{?ƥq/ƚW|;C6ex울5ܴv>llZV֟n;BȲV#㺮bS wrCrh4nn4wcd=&A W.4w!"~b+iHXQRUq_PF[1Dkh? "%W~aMGDRjD0\L!b}_xΆGc`x8ǃ!ؓJ;[Z (<c:yi.VYHGz/*|7 d{GG?: }X Q_bvWkz4CjyaTo| ;%#Q4ALaذTRj:.|'9i ބ%5-OC{l]%^J. ۝G$@j\+ o(#lM$yG׿hHq]; Y['}0QmĴҧ0Gn>Ac9n &9Drnk0h}>,,K-6`&G+:ؿE4֛QY![ z(F9>iC=%/k%Vhp$$"e)N] !}-bt|ԞO K,|V& c>5^' &]NM(KǾOy3AK%׷Uu$WYVND Ay;ܵ_2Mq?!:7SD)f/+eTKdk |G>q5؉r r'J]ؾ-RL:l\Ei> OJM249"!gYΥRxTl.D{V-ãqP]NP#y^Mk|'ΔCZ""[&Zc*pD*vOoH!{ji+Ge rDzyz_\`F#M}eZIgUvVUJNj5>䢅zp(PlX !://zx (W +ӳþٖ`KAOCEa?I#Kp%/ww_|.d_|%qcsY{"~W޴}䂂:7k< ^NU% 3[[:Q6%m(gԽ*Ǐ yba}Ox/<+/ygܢ;}q⊀ou|n+%uj8p^]=l7-TK=Yuj_;-oXs3Pmðۊuf#Ɋ bPIUqkXvɓrx'T;ARyP%Y׈1B ̊] A9#U%zmf%vNl:,c4ujYbW*'`bҊ"#OiNbnZBO\uJo.@SS\ uc4Y" k8NɃà9vrf4wb/x!|p10s2Q;eap#W'*!$=@wgjslޕrᴋb|'R FaU4\$a5_֠8giQk} .lc6BRo%;+ɚ}FSti4KĤ51#bBlavktSt%%bإ,r^gPIXKH[X"isyY=3ߑ< %@wQw*R6 2M30Nb[uğZ $mm`5w :ýr"IgI,%<xСH׺-j)-\߄gϊ0Ӳ NE֛,I0aA@#րX*QH#Nql}O@}j!?4Yi%q&{n!{AdxvdFjRL9EG˓F&&s\KЋ@YEJ.[,hZ?=hvŷBnHV9b6[{%?cW6^Pv,"o_Rq.&+%j?F)3Zy&Կ3eeq ~2pł;-[HAY6qThYĭ1.ɟ8cK(лZF2mk~VDt_ƧXy_qA検tapN*6bYph$j'0sLL8.WLzXґ`:mKfbʤm 0vɚ0giU=WiGK=~a Z;r][F0d@#٦#?Wlӟ2+Fcw|ZG2א OkEU~mScHpP&z%]<7SˏRF 4F}58eBdV[(XzAzK?vX)zZ츏 MCL11*R,c)\`0qNs3oqÃSG\GSI+ O g$l%T; PmlQVif:6褹#52fd݁vDžqi#YbXp9. z2^]1@"Ic^s+pѲň>fm˨hjܬîUpUz5+*9 , s6ciVE?)2aXRZܛ 솃 r0.fQ޲\F#`;0|3SzX{m&C6fڙt~`߭ScjP;[''*ˈŤ.ՇՆ%>HD[fYSZ)yU:M^Hwc|MG1, ̨~n%d }efQ8wTi(41sdAx)ȈΔyq- 7Mu yT$o> Q*G͔hu#8dtBʬZI YW:ƞxS_'̏8pߖ{ve*)ϓv}Nʅ87B ⫄˵MYw`> 9*jJt?ZL55o,% S8s80bCu<-kDSϱ5ӟy o7<蟜+5ȣ@aSaVt2m\W2y#W0 QZ|. c ۯ J,<,LưX5b< R<~pZz?<t:u)DD~N0g|; l{}âmh!,"ŔVLL/ew2Gyr&Ng%E;*_5eG^GD5w4V)"+QBl*MMdԻXj Altc12 2#d!' .f,_&w0= sia7 P!L18>_ݖ}`e@)Yh P˯τSI.F_sBCej4_|tB34JqgCHkkma=,i6bUC&S-K5#m^⣘Fu㸂11̽sDNOCZZ?CWoj|U^θvpI0wT6js#@ULepk"JWBu Uy5<eL^kyPo8+m>e*|$4yVF*RC z{Z~W .<ܯUgIOW^7@zDX|cLEz\eB`8ktA#,!^vG3Ewȵ\M-q(Շ>b9eUvuTڧ7zc%Ô}SJ P|<`&h.cB_=krG$ DR={X13ׇ29CA{j5՚w}<nFTZ͌7E\/`5+4d&Pر Ĉ]2ȋ6<KSv2t`w<~ N1%rIUeXll|)Pe< ]羵lMIs,DUm\o\Y%x<JX='Bʢ'U,׍T8jó>^v~|vW Yq_ Y|9)Z ξ"Ru7\6lWxM]S{-]5ۤUTr bۖ c3:1غ8#61Cdpyb<C#0<$bY*Aza6L;xØp(ҫI'?@rlV:57 Օfv5sE oKQqQ.f\a]ސU\_w7bG)eQs*l/B?&eMO6ˁXAr9$_5='[C^s+A{,k4Vcő5 av=3#S!OjyOͼ(  U)Yz: VJθքk2{2Fb+x(f,]zGdc, [O8S,a89n:թ }VbeA`_YJ^O(x>qMԞi)3 Rc댾~( :QU\Ǝɲ;Y.kB<bBXW4K)NGB1Y8L/k\VQ]P4 E>k&Q5뛥Sb+]{Md |05ŸUY6%^i~8f땭n6嬧ʅYĪ9VZz% )"Е\iCƝ-pG=zF QȘǎ=sdau3firƶN~qTWҾ(* bXIo4"۬`B*!AMn22cb%_Y[0P>/; "UP F'= {ǘ6?+7樦YvpBL9LC53TR ZCR+? 9VHȠ:u+qԁ,qVP?ŋlrO A S:,+ -;|+').RcGSV@if?l= iZ|5~W\ ,*ӫBlXr&+"5|H7aeF0Y?v7]Hݨ9h {Z {R {pKąΆX C<C?56exԣ󳴕iʪ 񥌦RR5]Q17en:u:bϝL%.oJDmk"Cbvmn)1 xuR]HSal͟ئsV؜ bs;nmgc?ZeEXQtAE7EtBEEDgc]<>t]O $r31!2^oav©| 7?"2x0K}LXo+;s4]\;Xxy2Cp)>~A͈tQY J@VL G7rx[1"_54 кc)!B)NR5m1$MH>=`PC1 "帒J;]91乄 +~ñ=<$FdyvosXUPx0u<ȴk 4yIN'7.ˋF ~aagѡ Vji^ay ]q `k(* _m7s zxeL ?˓OubG.Xo\9w=./Bf ه#A[*+H?3"_s:C'2kݨӨnI};զ.T{šJʐ]-Al7йqRȶ='xQK&RFY +6-9 \m e'+xeQIhQL2NH6folBC4Q-uI2MCV`Q "O A=x҃Q+bIOtHCm{k5NHd31wD9ypaؑBB~i88G0 '@pg%%:8z ג zRЧp(cPz'n)ݭL;3<8lT&bf<\(Gݨ|"'Ӣ$L޵dTkƃQ8- &0PS͵:_1ӜTzTeЏ]A xB Tn[kLǽk$ anU&sEnøV8X%Km4걞$3\R,5 \F1<)xy(\96s+n>^u;=(9@AcaRh^fI"ͻ5N.~7b{Ƣ="bx$EsessionH^ #Oh  xk8ʺW6lϘ7q&dTn^ﰑ%3xr}|rZNrvrn{MriF>SK2KR4&)7y,smf_ω. ,0ykd7oCN A_%#`L: ^xV Mf=>9|o9'=;d #.O|!` %iə%yi) \=/皼s%&h4YK^^2&Nɉ'ϸ,yeQ,kx][Hq9kMwM]Yy" %} L5.(Sz.ÏćAn: 0% (^*IC|?s&&\EWd;-Ǫ$n\ސ[*Z"TPfm8;\i<Աii q݀ QI }iEV2ݍт;j×5qLXaܚ,$'%Nv&Xo*Xۄ0S )4NV b.wB7>g&98. *cY&RL3ibv5xzY5=΢X^˧jOF;3L%vN#[(Ug7i%]{ k בJrɈ4)VL;.x#Yt>6K|tovWn`x[˲u 4izxOHql͹Ͷڌ&Dk0 B41uB:IG-n) )>T.܊˳ćNtI' &.GQenU:Cng@p aFN2RN;+؏zQ2#mmS<Zuk;>^nCbi@4Vxa` $'>|;bˋJ 0BǾ)X)0=*d:q3KǃC?j =)G JX9aO#ciE%5~vH}ǵ:8 |8r"zNO l 0T}Ɖb=q֋?U՚y 6s: [u,fc?(ux[eƬRʙy9) J)I%9zJŧ31 o>v8%(y]fۻ>kT ,xI\X6 V[x{y7 /VO^''Ys?e" a=x[~(W6lEUbN/.)J-0PИlP YR`k`9XtOɱxUko8ίXmVeZRhPZ"'qƎl$i@J=9V <ɀ^C x% L|  @n3` ~# DZ]bn..<Sl3 "sPQ ZfImJLżP`ZRja-E LLP5 a4*"ƩǙCS)|y[ B%ähex`AgZ TBU@&֯rWٺ6q2bs()[ y6w3lbtAs*6O8CfKaV(2<#t`:M&v3tgÎ3~jeQKAìJƀ¸^ը-P;Y¥0M$kBbi56&ne3iSsݺ-Js&|ʾ!qyUf|o;)&"k1FG(xkǾw9AǛH_*^۝̆ {s1AP.ʥs*pZWl=Txz 2 ?h6~dA (ߍqD誡DUS-}zy7QPkj鄓Ԃs_`)C"r\Vj{Öy.mlIpYPt f1rAC~%D'+*. *%kI$1hlJγ9{Pewp pvF8^\Ȝ1ChZnW/8cϣ"o RdᝬʖqkI;Qݐ|抷 QNqy_6,:a;"MIn_//눋l5Qn^xSSvיP@z5yu`h}΂8Sf,QNyw|(zDQtAy.Փx}ˎ6z Á7Ed2i@M@IE"5$e\{H&.0/w&ܪR-.3 5#ax')W%C#ޑf5f'PG/3k,j,|>a#u\Z#LřߵIk{$v[޽Pdd~6}m~Sq~x /zhLA^4rBݟ?(ȄRqBE־8/ֹ侠HwP/^Iīz+XI,tmY֦sjh:3PPCZʊ0 2)AJ &czmEqTSOziSh8],(,VuD> iÁHM57IGq&V 3_"b+|U^k38U+ȩ.d5hv $+ jEmm+@{+߮XnI-AgpA?霗KQ/$JIƉbʬLFc^r KZ"v'< 1w;H"C6s t?xW'V#ͼ}Ns؜MӜN mF)@ǀ$}? duIZ mꢑ.u$ aI(0} S# FPDY!~{r@c [%. $o%ZIn!Y.sjcGnXd@&jp\Pov 00V b^z/CR>$K9i`W>]qXwdW >3!ylR`YFQ  _5X5|΁Va9EAj$.#lNI1D6v@WZdiERi!@94>hu 2VpAy]Ӧs!+|~(~Π<<Ox<<DŽ*FN)|oOZHCi$yU@Z);*Nuʎbb@V\L)Q-X"U/QŬ W<6zQIeҾaW*.! 2N>+(A P8ǐ"hI4dPH#6O !YD>|%>J U{)N=璾tQ c>|~ < іWF0xs|5Pjqq J ܋Ynწ!K}DHv@TzV2÷clQlѮbE M ĵ; '‰p$ƣD8%h*8,aЌvR&j{b,TD~A`IuvOOw9ۃ܉Bhp^HF$avI!%h3r&'_țڌbC kRk:o}=vN нIas  ]K|m&~4/10omy6wH}n_߲HJ3`6u`d?`Ҟmj_lƠˆ{>:kS קuS>&nJ8LH7Ȏu\gH^ghH aňg"}hZ[pwU?&gxrPNG  IHDR@@iqsBIT|d pHYsnNtEXtSoftwarewww.inkscape.org<IDATxME5|.DM#H(W<9p OzGA=iL< D$ Q? +]I0ay蚥fv&;dW .iْf>m(6d x vUD`p t- ǁ;%P@еpor\NIPPX*NKz?N~3 SC xhvC fފ,Gqh?o~`A9IY00@"ۀ]uO+g嬅]@[,6`w v"*Y5|%bK'5YY`Nrc} !ۜ@2ۇ&n`jrj}1Hڧs>;یa!IN ȹLݾp 5,|&z:M|P~|GS{dJ*5)Z,m0 (D_ᑬx qP>>)Q듂B{!n_D=Bөwd^ 8Tkq[al[b])8_I:KRC6zf`s% ,I9cΔ/1IrE@gf?g 6@c$7p0 ޛ"ic~ ج$gzewdIUdD?zXH6S[=Ƙ}9{ 6#r+qPn69U2֑-d(Iz(FP 9sՓpD'8'x$-l6 6 K|џ>N6 >u^!H4@G޵0WңL-cNCյ}! IY4)IE3+po*e,t*+9$̃9m5/d; }Ǟ,ǵ1r7&I ȗ3hwo3">H "I LkqK޳|r;w:v.f)f maO,d^4͹,1U4fmg JbvWVJlt``#?< ຣ30.ӎ=|ػ j{ܙB7t4vXKaM@a.]D@iJDc'Ocz5ֺer΀rOh@-],mZ\#_hWfd|i*ksK%)in ͝1:qAZCx+]zIzgJOBYjۦI1V ! W[PrO$%|/P@ٞsh$JҼ>NajjLjLIENDB`[Ű]x/PNG  IHDR@@iqsRGBbKGD pHYsnNtIME:=PIDATxKhE{#4YSZ|!u!nJk(iDtck] ҅(E4ޒB >jF%!M VHLdr{M3g93"#P 40q`0ӬGN`iR`!/_ԅ^+pH\ڜa$xZKr{IO%8۴3q|Bu \S0PQo1Rw 䁻y9+P,[`h@[`z 4+WD9 fC#۪p,/ tq vQ)|_z|xWÃ[%dZK`n5ckGJ(i2Ljʥ5n=hD͒<R^E綃d f ; @WsGآ 04Lv<&Sc)- `*ףɴ YL0,+0nIrd=Ydei!n1Y[@ 8qSmeN#Cn'dnP <2f. VY@1ǜ(T>W4h1`SfmZ῱yt ,w ~_F`tx둟eӽ2\9*8^ *!bs&00Č,uIh:ogMJ' ][bÚGVk r}Pw! ";*1iUIG U Io WQT7J0r\{,ֹ@( |ؙ$p\8y @ҍ/P@)}1qh#jvI^1 -q'HL r,62er_ 9Smj<"Id{L.K<^>%-{Tv!/Җ„:'N(KSB/M%6 l絹 3)\R&/ stTSO8`*K598C[{vT ql/SU_BcoN|H0IENDB`'lx1PNG  IHDR@@iqsBIT|d pHYsnNtEXtSoftwarewww.inkscape.org<KIDATx[VU6b7g}g{8笵ko}Y{*4GdI㍟$&I{scte6lnt\E VAg 8 Fx(*b36H^%|ץcBM%QN~%S`0 ]щD=]lBj[;̎c1g)>fVf‘CEщYpfa#0$`sU` F *$W3|mon0|)$>YlLր9$?[SɁ|7FzY'`/rRB:XcžR c*p0k&!#Jw1KVZ8Gɐ|ׇ#iNr&3W38x0]o~8(a:6z%{ -F|(>*A!~,/RISTg@-ToԙJs+]?J9uGzm]́L4[ p9O0K{XҨ޴$1fUԳ{alUm- Bވ8.c8$OݺM[@q~ PM|"r9I`uoJPS3b**YBEp}̓Խv48-wNh|AE7bIUm+Z SoVU 2ދHd$e܋VH:4Jz_~ 3DR)2{@5Hkkpm % HIw/sIpOJ]wyGa4Is$z)ԭSι'Z G ss0]+m+>1{4G; 'D*tZ mi+e;%؞E0Ob- l>^-@:Ou/c'>XIq~b0[ ` ?l 0Ep lbhV Ֆ୉!r/b]~Qkr.PX$ IKLhs/pJ߈J:;v_Aұ/Wse: lr<@_y`xH,]]$er)0`^Q(2>xKe], rDd&@hj7n~67O] R 1?k9 oaof|Yo>V3Ktrщ/\ >Ǹ؂] Z*T)K]cn+Tg?|wU&IENDB`B, cx7PNG  IHDR@@iqsRGBbKGD pHYsnNtIMEPLIDATxmhUu9 m±ޖl}^VNiїJCQ"(KA&RӈF\&Wr,Zlmm>ܳ|8?><׻<ߞso<"n%@(W:@\#qYlM`@!IɰO .PL]A}VN\b<&*p)e-f`Pƴqkc鄒4`^'R7ğ%^4R3v;1l1_/p%A=meX=)p^ZkɬFk M@K`D^e._n8CmhhDI50Íu%aE MPxV'Ц)tU\dpLPo&ǛN8ھEҌbԬaLˏEw+|Mj prb+$A`uD~,m P(0LhqDPKG.PHܩ p*d?(C!hNmw:4 L(\ P6Zi=8c .3*^ƍ H=+)Rj x0`Jϭ:@vJ&́;oI}Gs7O%U~xc m` cNXr $Fb5K8﷞`6ļAaGhU#<r0{qt.)up<r5km(4S&qrfwJi<U9޽ʻ[ϦXIyr KoxMl 0{~B;xxW"H.T\3&FGHT4oG*vGk'sʆbھpɽS< t,'.o%:EqDԑ/>`FQ%}poX BxpD"Vn+[ǀ ʇfn\k~Gp5F" 3\j WApd |Ϣ#ZBPQ#S%B<7%tSbv*yR7 <#P&*S)W]k:QZ[Ui紫4Q(HG:`KhLy~ (JkGcė [O-8C@mȄfREg<8E[c}zi`Լ@.h `)$ -BI-5X',WtB]PC~^\4՛i ksM;;k. =8z#͐'% L>df"`zsvJ'5j끀Jа}dE bhUw}GI8n. !IENDB` ;ן[xDPNG  IHDR@@iqsBIT|d pHYsnNtEXtSoftwarewww.inkscape.org<8IDATxkUGǿ"F4"RЊJK6BnSM?@hiu!Db? آ.]"j(i\(qc]SlJtq癛s_˛y/ 9sΝ;wZ$O^IIssm pX`X_ۯq` <.{[t^}@Z]wIN ]֏ -蚐snFxR+0н߷+ewM Zz]ÛpBXʘ^J@GDϑ7qp8ߞnϙ@S(&`(h h {9Ƕ A(gTk_ *Qh CڼM6&ր8؇e@_{/ 3T2OڰDŽ*^&€{:|`xb40w{>gDIؓxCW=Yh 3<`/k EznßWXx4QZF6 jzmuw$?X*I˙]Js'#Ӓv4YTF'Ӵa?g"BdFAOK m{śͱx^"Kb|T42< @KAɦEv&S`fIӒJA#_J()tz+S|+ȜgAkSiL4Fnbd)a+sι#l\7&)hԀB=AQoz޾`CZ(cJ<ާlI:gkcp70i45v=m[cF $)7)=Gh~ wC(8I%(к~k{8g/ . +fxuȌT-K)5{P2qKe=AcK{-҈&2F4Q[<4Usab!=t9K2aA:)zmnI>Ifn[)VH9/m_lLWyROI%K%iv@?rIENDB`賮Sx9PNG  IHDR@@iqsRGBbKGD pHYsnNtIME)zIDATxkTW?o#qDPl ĝBlڐvZB$[Хk.ϡJ"EQ$Cmi)͹3o2<<;sν{~G>( `Iiy_ x% ln |#p0B8#0+ }}y PX48)PhMG~[Nu6^J L NA{;-ЛCϚ0TR'^UnL`ZR!hk, \lX`4%80}\RiКdkg6D FpaNj:By@_"}'Fy =9,&NKc6Q>I T&]'"xxQо, E$jANe[IpO jOe8(`Uk3Z.ĔPsin-5F |Erԅ_0 %GK߳HJPa4æ)p" W]Dఁ2) }q4}%2Vtv#ֹer1[(#޹cJry&tޅ ew+3sB.MU6ziks'Z-䵹~m(r^|'\Yo<.pEjB\1i+:sW[)!VڊX:JT.+>OY>% -u"IENDB`wB[} xvuUN-)K/V)M̋O)INLO,JtLO5 (/,5KM)wI-N.,(σ*r,-/*r/,L(T0200 OM*,IH4xVMs0+ސ 8qި^\_ڞF#LD0x$i&^i;Ctz[nhg喀S4/ضn^=z"Qv9NXZp2\XG4*y;Nq ڑ\ȹ$~ f !%ݸR|4znxƓr6<rVwx]|tnxWMoH=ï@=Zâm^JP>,O|H㙌=lɸ꽮8!E&QE+ uF#-JT&UY>(Ƀg ^߰&/4WDi$W? 9.O|qTOt>FJJsTIRT l}OsG(&u1:PይCs+ZMuU)0bI5[A~+mMշo|.ꂕ~ShK]Q<x[; f= 8 K a=RhZ58N2Ђ'/oqgzE-4kN;]45nOQ.yR]E3 cwRJLO~f \YWE<|EIsuZԍ4QܽjĩB 0 Z tK' Tr$Ûa4:WQ] o(sl~N-?t"t)d'W驍鎱hvj&0BmC}Ϛ'{H 4*@vvWhBlGx'Lj#Q-l'_0lx{&5Sjmv,#=m-x{&uMb%6IY;'kpޞ̺i2&0 (*x&q 4=3/>/17UV!8 * L(IsCA89 ӋSt!ryEzՀh,,Ϣ49ŒIs!?TU94(?h284M^ IEP˹ 'reTd$= r`M..ܬkaAVZ_Z\ 5<@2Pw49 ? GM(ljtkgm0S+RS24bJp ȄRqN``O`9ykS6%Xd F9ƻxдܺ9xKE?x{g-eXe6ebڜÚyrxUێ6}W R$momsE@ I)R ){=Ci7^0 9sftD8Δ0:&i`uS0>qwih.D?R" XM3T)uՋ9J:Lc䔈OȖaarٖP Iqt֔jL;2Gd=Μ2 ׈xڹpO.F=r^s '=56J*!OSpqL 'm CTҥf_~^w+CQB)+F0N"Mi@HR҇6,0z@E7Yg9L1k50S"bU0GBR ߨ?Q!vҫ×WKK^|C0yܼf~}~ :D*TK4 FWü[U!t̩f,)FfJ0Z,N"u.rv&ӓh2[7W'|'sfvJP_=#')PN͑=#Rpk# 悔- :#)13-9Y^*Tc#&k֫ڕ^ąeu&y| U]/'M&Fd/Y | ;։_Um2~x٨[O|PѲ/RD(@wSP5e~edy˨$B}هgt ۳x t  sׁP\7QxoHrJ[5jBE: {u7clC=Pk|{/vQ+.`~|@ 8@!Oכy+^ ޾~ԅ[":03fd-p}4<&)~X.}KW'Yu4~~0>K ~ _Lg9X{lMh~bq>RMk!e+"ؠ§w(`8K Q6,Xw70NƳԾH[bܡЌ.D&Q1.#E;=l|9y>=&gcf=E EfJ*sF0C1g㏯ONBO\*C:\2l!FEv=PEE-paq]FDFiZ5ĥKná=Mv2??zL'bHh/1 Njlǚo1#$Cv|^pH}RGÀ€#vQDb;+A;̧! hnSͭKzWIai@>_AADƷ'Y8klXMK$Mf4[ݯɥ:FshAPR*Ac{y. J<KYd:=@E>`2G)g.XUw۷{|:vFCB( ۷J? s M| .t?BF]`F6_JecbJHa+lԅM_a:Ba-2j"c2l^Witn6BUppK;FXf)F$8&^jth쩞kͧEDPԇ5ɘS')ƹ:LuXIh˅|kT91Q&kc3 Y)I`$/H2NlYe܇ HXY`xmIsz',2o>kEZ[Gte2SwUpӈv?iTh5^A2]tda #PiBxMz†,p۷ù& tvr||\^] Egu13/rֈ?d{rlMtld 0:ѐb'6Z(Ԝ5HY%";r2c $YPSrq^$T7c]ȡFMLi, َh\ 9 eDAL=*`Rw1C'U2Og9V|3#f\}py-ljU2g_:˛|bX]Qyh+=J\Y[ݶtNˠg#۠g#+:\pP Q3X(кAcmn>gsk:Cy I\v/3'JQsUN(}ңmiҼh|ցCM"G:8d)e٘~He<8'ͬ~|LIQV:jknY soe0m\nE6xIC'<[1AUb[C2ׂGd*ffpl`spZA}g&m pQɡfzCC)jTwW&d3vGl~PQi/)//"ak`mn\˪au(t{W|BЋ._~@Rݶ$y H\:Yuf}D_;euC%Tc""BZ,zxbeu7'NmGshXNﻧAԅwޝedi>,">h+;n uZFcn\vV??kY]9/"f cU Yg e HJ7RN9Q騰`|Ȉ\dZmcxk*޻*r21|%n W"$iO`2IĽʽNsXNX=[x}TMo0=_f=V D\ d~GR=Ey͛33/+ng[K3c33lAIs6AKLF,8Yf] 0rV6d3&L"䴠uWg`6/I[yF zGa#7~ASkAh) %N @H-JnѲWsN3p…*W{@Jόq/j\GME :ֶQw0^ԕ>CCÒ)3M 7Ir^IF){\-چ:& i'Pv7َVFnp_/ꬤNYx}"MSr61 Slo>WoX$SjÕ d2`/l<ʍ0z@Ղ n{D7%a/L_.R?m.2#`д6V*ܹ4-ݳO۽m\ xqa~Ȁr%0ї:̕(F\]`س 2;C 4@RHFRNP'ht`8bJOdo-ڠHq%8d3$s]$6wٞvqvԏP})adz!y74{lП9Мt1NIpU%e^ Q;υ 3tu`wB=3$ |pHT*5`;|5 Ab0àXJxʀ;Ftd XMee9/vp m0r=ؼ)qQ\} Wi \\~Gi eM8Cut'<|ћ3zDF9%M;Ӷ{b?L-2msܳ}h"HHh41wz#ZEDۍ>;JVW7Z/‹`Q[`W`~(1{c.ې.VLi2w8I*%wt [8n2\R?[o|}hm2܏aF-cGO~Ш~[0W4nѝC!>f=Y9S5gH%&˟ Od 5[?[7KGeiOz6tb|EB-$`Q,czC0s=) gX,Gn od$0K pITK*F#5,Kv-*b8HPXlTƷ g sӭVq% 5Q̡Ge*g@ V/suhY>OokC74$RP;fDe iL(%OאKRAR: PW@v ù:ov>mm;2*)ciGZ-ND|&e;aR4Kh?s͛KYFx GC{tb{I#d_?E-EqPG RS_%~lV% QQ=k|>k P~F?wӽI94䀡yGG 9^$%&>{d\_3Ź"l2*Zr1lw=|`g l- ~2B;G&0dCd𖐻dhg4-MqNSG]Ue#.bS7>_8ϳռ#,g+V=|vdZSY"tPZmw^V4KL:>5uW^·8#TMp{.Re9`YݣZfU%me}LZzUȐ9g+nM3@L{ރ hgq=@Q{L=+2D顇T9N*P;\ʨh|uK^B}rQIܷI<-/L҄j*H=%iq}681h«n |6L ͶJ˒N>3[Oؖwbናx#wWe[J#޼ Z ;Hr(^yġ=x}uPp=XbiLj wmxk u6.+.$0PR ka+. 0 5p܁;7p`; Hxr-[Dr$^`.5/5=ޣ`Iw7 Nϣ'?'N6;26[@ȸ/3W#.G[\|3ô?[7 7|x0,xťlԨG Ӎ6~u:S5(`wHZx 1mK #2V`^ųbeɶadGmۯ$ S:0ׯm`zՇp3:>8aQ8D_P|zi,}-T zn%9֍7V'c!'w;@kypz($t߰ׯ1P'&8ɖ¶% ģiZ֏?.FlǛ${vgp P&q]Ű7D%~h}e4{UPLLfVB$/A]/IUA7ͻr>MxhI^m8X )`46Gf# @l_~&n4t)x &$cҡX1-8"AܪZ\4FrGLX)+

u=Eъاmȣ3R^n D @BȼAJTbTn4je{(YmiS:Gbf񊧜SZ.]19wTuGYFMWc;Hф?oKqp'Yx$eo"] pwSg !X.AMo[*4Ap؅wdRV3WHm0?7"^Dڛ-q#'̀X𧡳o;ІN0L3(ɔnXZ0񎿚##IIb=CdT3麥(g'Y20 !$'I܌m/AWiַW=HAYap,M$_qm6R7t·fQ=/WLu U)ZhO*\)z֝8H!Wx/ &ğbGgߪ .:C4it)l|éLØk2,* s2;cŻ.>S~'^g^.u=BiYOUװ w+II|'gheW/CRT {x0S+W,'kϭ,* =) ߕUj_idX}?\)Wq*y#0[+Gm)-ǹ\z_>!_9_ P/ЅUUSg-2R]xPP7$`9?: q>-ح hxVoEVqb{hqZ&.kҖ8ĎMu+Hf=q$7wR%q@_V\8scNZ=;y{?738d~:Ж\m8MemJ0FFP֧m4IcY-$hV ~XoVJey1_J[_7v}wUUQזWR5Lبj6w ^A$O qa.BקŅ٦'\~$bb++r~Տ6AJyqOMs 7)mT-rq6ZM"Ӏ\RXj,;p-v-q5YC }'!$]-tEV<0A rqX|73R%3>#a# {*,g!.r 1eg9jGFA@ 0$Lb̬Y\1A. jcǀ^p.|W|/vښ il lj8z#K3|}&wbc|ec9X U=zע{~F2^⃙ -Ͽ8=X)I~*5|"r4V _1xza|IO¾R~ CrUt|X/]:) BoKXln魢?roTVo-VˬJ`];@ w+\]M79-P} oۗ/x q[xJ~aPG+(5'}TUQ?U@S4%Y*,MNgDwtOyaxWQoH~/DkKUd-5):߬c0hV 2373;k.j`$B.h2k=P})-"S,BКł"E5j X%jN./߷LiD7a#RV| d?gIځX|}y1Sb.1~&va-R@;4dJK6K5!! Rd*A4 "ʾǏЧJ$%,! (W6#Yc,L n & p_ŠJj#lF\X:´]A`b2X,Q% (Fi4 _ã ө=ctE_b0DF^X ¨7uľ 7.=L=Оq:yp{m8(1Dm?aaF06v>hrHlF} Eò/-݄>G1I& (M enFudUiu/o£k., #_?ݛ=w(gm4iYKnǟw7#M?=gZ[d=Mz;Y*~@dϩ;V(lkŪ_?=vzPCf{JO3]^)P /NBs5pyU2jRǰwȁ+xTrd} w{n!6)LvšDN2Ywd.%9Z'Wgxx#F+tQ~c,@vq ܯUTy8 P +ƿyk$j?) }UT&mw2Yf6]gg&TU[ >= wj@h!`8῝eq._cY t;#"4ۀaǽ3!oǪ)s˴iOݺ>L(-d͹) VY}|6qm繖L8uDZ{V]9Mꂳ8:a9 }^ت/t^60q~(cUJoqeNEo/X~rp?x}w۸7=IlWΣ=~fZ[֯GvCKF"UQ׽`Îi `06a0e{o,ܹM]7,͆I6ہΘ6عt_] J"'l4ͽ-Wk;H,If4ͮ'!;KyV?_F<{%o=~LG43v8؋UUO|:3`i~=4IX_nis636Mi1YKxI¦lv0`肽OdrA:H"a14od.9p&8y%)|Oɴ )ٌg)'Xo {F3rC &n$P.6/ 09~잞v~g79|M>%*OF)@q wT~? `G3uIwq=e''g%حԠqtTȁ [@FCvJ`I N!xg|PD$+@/:Xg'Av!:a.{ׯ_ag]1O.0aP%E 1})-rbKDCo@Mpf FW)|E) xT$SN(99I\| u \^Q B }+Lt%*n,; C ڝA$8E(wקaw=uO]~]<:ڪz|qUw<8هW\ETz)VN݃;._tpBȁ@Lh^g`Je8C ⢀oӚ=Ķ?Pa 50J8"`Ƴ{z\tSR)ɪ7ȝ j"jo`GZ(4q:fѧPt]1j?3d)wV3&oQ5q'/m[tŢ%vũ7S+`*Y%[im~>-.6'"8[w`ąIlZ7m}_ΣV`:D-b?؁q*s4d::O'QtHj1cNm㿁B'ɔP`G/_pTmeoYTI*JX/0D|ksTqJSD9j|Gs .tVR. i୶zpQhHI.Jn~&ᒾBW<']¶wr뵨L^v~z#PHMutO377j92d˞(a:qN[$omi|$ߟuF9L.=.r Or9uǦ&cZ4A nP9T𴮖 $em,vd6cUV ƠM W>7J78`ܺ"8SRsypw~2؂MJ/Bt^{ 3{I% &ΖRB=Ja;L GVIъ!ЦD\{\ )7PXw!rRЭϟh: b0 w-~׺--/ m|;O^MߤPր9Z`@UFΘ'zw};y6s+SOAx'{/_he2ϟΟsmxe7Bj|-~`8SNBwﲠ J_ c+|2omqS!Jay۬(DTAZF @EL-CҏJ0)KMB!dVpKduz@ۢ ǼǗh6!t 7օK*c]F%~rV[湱ˇU|8_>=~ eYg!%at v2"k J2TW<ϯRӊ~& 6w*8}&7k +z8:GZcxu=^/J]W սܖwX@.п'C4jBa2E oh:ܻX'JƩSLчRa7M߽^yx\cvY#Dhg^vy\iq;]KpF) M)᷾ s402AHI$FN(R:drv0"DoE)!-nTWr%nmI0DjV:Yا9@g@ÿhi9>X+=_[;|)=́l7<d0(~"J:凕PvWc3P0&0HXE?}mUEu飫ڇ3A}߇yfpG}f HF-dKkį :C_z:.}8DdzehP "v 3%w9k' #˕y[ FOBX2)frU9N2sĬtdz ,о [~Vۦ eOn!>nՄP01QbIqR{v  O/q>+c`ݠ6RV!_n>Pʺߩv&-5Oժ >Qu6&Kv)>'ܥ;BqvUaͭ {krZ dőbu`Ѧ ʗYvZ:8vU탾 _8IG4=2~4Ћ;3%}7Lޥba< 9LK6وVA 6b>)J.긕H8C3 bv9'<8JLYo`KA/Х{K9#@oa'$$ib2  Cut7bTy8ڣ >R!@K >4ňMn{b4bA7HtSs!  g:jJ{M&$ q& [Mx*8&GJخT4S4 oVpiilbi ;"QS7SɎ/J3})!o\7% 8{UYFGJZR+L1v[Jb%R užaѓoZ} ƒEOz7P?m8-e\Fֱ^2ӭ*6MO . yc 9:%mig?KΟLΣ|t,QRqzWCw_=_=_u= y)zh[zet7/Cu>%6`eZ^7HZ) \JA9@صIPFJCPvoyukmޥ(N`.&hz ,[s1X`1/S<102CzuG)g͍crWdTA^?(ۯ;㑶W@2F UUNMC}0bA\A[ Sq$3ʣ3HĮ~ۅ.RE{M1V٫7~(J[yō泫?3 sd!fNE.am)KvYk3m\}|ɮʥMbM1—si^TkBǰDftm8& 58Z,RQ4o8НL@1|܍V| _%8%p|xa4HV^Tu\2T#-fH璕RhIsV=bX.^ '`V"/J,a$Y"I [RCr \j T2\ ]pc >=}5񛢋2jE+`Y'r,)21Rڭӥl ^"{##]O4Lzΰq0?{Ԩ5eT{nxF7)mp^١uk4P6Fw0Yxi2rl*r!B!yfCrHҕe"qYx&ɀM V)T;פ !Yw3b} WL`(iy2~mm~}7)/wߑf/',|=Q\ixǮEdq3dkW"Ӿ,wDĤ<k&8H@<ڑJ^Te6ۮ5۬tex~v4>Փ],*`ǰ'`% *ݔ;4!c&Ӫi b R_E֮5[ $^_>W1#0.:Aݥ;h{p}wﯰ ÎKo(2mrjOʧy-훲:aˋC+^ mPUi9;%Wv(*нoU{mig2UZoѐdI//Жv˭>kj˸~}u/~=Y2)^6Ia(Fq~eWք$ᝨp [ygU whº' `\<8|V"|=-~g0sZ ܢeUZH5Ys߸q- '9*ݍ2'RնjfDŽe@6RȽ B5%lJ}`]B "DOH,[_S`# S~,T ;*1n07p/l NTT#_"h8X m2$"A ,ZjIٔTIC]:l=4k MχS]X\buSsKȼQ*!P*`Ԛs3yzB=} dCs\P`mi0rMBvŪ(ׄ3G잎x=fգ4*-9]-SvM`ㆦT"9:d/zuUMg|vPZe¦ #Ձ eRg4d!.hG_ݲ2׷4go6v:4qk җ٦lmYcRGuG;7%)g&(J g +ze_rjqn˰<9qG 'hWF0!T.v)E:Ü4_0XmfYPOw<@׍m R)—A;v83oFU*nB&O'a3Pb^2͋S2$.HE6le"' e$]!6\t!n ګ4FŰw_0,<1LvlEG#!sKPCcBd2Keehyc<"0USv)#ݗg.ȣ3c>i1e DA%ze Z6 Ig*9"N(ID9npj}R z𱐸Q,l8a~Œe>Vu|樥|N}} m#mutXVϧŕ2%U$6ؤxq1I[ꍌ\Jwf Vx+u2iF\%uQ"};\Σ2|y6+ uףpmɥbJ;V+ [%+D nHtu Fɪn9=-"eSMWD|z>Pk> ~I^.Žb /bX#rmGMaj~$M(:Jpi5$}h9*2"!5nl隁ROilâ8):WDea:RHPMDg;ηxN$D,x]nj{YpxEuʅ\ɤ4(=iuB<#"?d \ld]~)uIO~ zHekDz!0Ye͔EiԂ(O$TrU:l@=)eWcݖzL-GrT%yn!pIN )YGf(FQܫ14 #E?>h=XV!cV!ZAFui =3lDTR \b4'kR<ӔZ}AvTW@a\ql+H(.K! O'|£W95K 7}1ʶGbZG|}etQt=m@Wi7^[{4chi{rr{hwNi |JIA_ħYpmcX~E:h1χiQ ]3(eS3;XXcǒOI6 0ū4y3VfpQA-/lNlp2lK-ޣD/f7aɬr\A׻ՋfAe]h#Hmp(+Oh{ ]_ #3KF;'Ee߀#Q :DgG'(v@<šE7H& ,8,40e"}H}*2ytMr} 'JPǘI:ԙHl^8O 3jx d}q/r_^ݒHcN>!DNx 0 IM'0Kܕ ;ZB6o0e\==J~I'Kٟ%%ʃH9VC00:g%lYĝL@p[oi55B)ZXRCdrط#?5(Y0ot{r| A^tt\{zEI<Z׆hxwxKnVǽ{;r.ݹ*:yFÚ̴}pxHh S3BA;h6a)#Xy(Wb)+ݘ5=Rn7Mu8vۙPw`5!O,]Ń= zDΘOwݽӭ⪀D nj/FcDMmx * B06 LFeo#{q{{A6p|pGqx?l^jt+0);̋-c:Y ЧɵL$_܎ƀP>ܚk1ai+y[D@6"y!po &hVBtg±XO_hFQ%;%aDOZ+pVyM+FSKNuZ6 g.TvZ)MO ZlQڄ$q?I$6̥ޖGÚBoh] Rx$Nqpk^i\cRr64MF)?P1/3i<#8v߷791pޤ٧i(#8yG/҄5֫bo}DH}p]#Pnt'n-o*NWx+;O\ߨ00imrjZm0C?rT8I6儷 c?u|Iw5 EzL;J6ElKW-cZ?_kR n-mZۊEqlFӷ2o'.'O 26!+P)׭Ww(ρ1=3 hg,wϧ6i,2Q/ʯr)Yza9+ӨGbM~\]ӃiEU|i:GW]+.vg|qG>LcWWTм}U9U:h[I_y*j޳qjZ0kJpz*es| T<j< 2٭7E>_Hv~;o|k/aCU?5rX6Sr O} SXM%.f[GY׶۽+uS{.,QVsbj(wX/M;+R{0CojO#i"N9:P $8~Uf"mʦB-춮-2٨l1y!U%yukl=^.P2vDdƍUAOtƥ0K#*U /P!"֜f7kjna2$%~fKc$ #}+·d#hw"Ƣ_T(ڛهʝlyVR3j~*.DO}{6鷋hGXb^t{dhx#6@5\e;N#_a1r6b9nh2I26L 9g0 >^eXj%p16暆{ɞv;:pBݪoΚcP.]6#4ag9{4t!H2Cxq#ԋ0z})4K" g%cq1h+o&i)j$Lie'eZ%mI*,51)+oؤ |_''ylW}'uG6ԓM; MWZ5%*$9=u2#їQ]sJ_\p6#T[c1ZgCh@e qM%Er⬪dBbo中I1t*RꐪowÒ}ǏlWjDقk;4Of$}S8ѠfA0;hdQ^8K&v֘BDDbkE穝 Û1=`9F$,'}&y (D໿~q7fw 5Db Fy0UDL^_Avdv9Ց:)V7ֵ=JZlE,+̲ dћBdFJvw\KPvAj`7ռ5I+ `\؇ jF7I!t4&g5s+&c`ԱzPSh2L"94“ȨFŞ*Y\-'|̬k (uuHw" Y%H_1M'}BP"̐{dd*PIJO(s2\2ZUk\{iv  z& C(I.(}rYeJ.0r-C|V0Rg I udTX{6mKvS]ZYj뼫BTJE=mD2rXw\ǃH]L%Q0B)G$C9_ 6|ؾclso>[p 0r%qd fd%3A}{D5a,M`ۺ4wpC;p^gNFAnX4 /T]5DK6,g`+]5峊?EgF|:a낫IÒb)TMn q$,a+,p fD'=)%zU cd iԗ7U]X;f0.o8vU`oC0ٞc6DqSOյsWkCjEmXz76 B) %yE*!+0eAH-SXˀ)b5t`LZI}ZQ-;`bPx( ,=^#;[<-~ͪ{`ZߝPf8DIBW<裂x.t&njcIW'"6X½Iam7]{GlSAd'΍ ?kM,yyNOa?m^v'8_GZma79`Χΰuy/0us "=VؕhmGt\EAk=j!tk.>OM0nZ'q4>t"q>*.`$R9k En8%wւY ѳkc-_ RČ5U,?2ޣ Qu˰VVEwwq.]-dέycFH>&z45!BY] 7uV0JI=@Q_]Q}S)Ԑ5!&BDa:|*}n)Q8Bڨ&ZuÊvEiR郤U(l"I@n\/F^;]›ʱkE{CÆ|%E7֥۩ cv D ?l2R^۾B{wwGGc fېԒHW[Ek# r,qM{(wnrjRFU6s8<4 f-& '-g[]1K وh4N@6 ;ԋ1oJ^F ~ 5Y@ofgc7ܱϪQ}|bWOejߒr67X|1ZgXJ+.R1( U"(±_/+̺lOPZ׎b~fɒZe9I5\) il O8*uh ݊hyrq%@ ʖHi3Ve%B}B>'ӋBj<{gJ}AXJɂ@t=Fz]0̪1@ΓדM(چ޹%Rֱ.nc 9]QYY2sw[izeWDzMd`?ն4Y"3fnC~CAC ~-փ9%g}jfp@),@|E.{3w>vwulԭ׷V5=Ҙ/^ ])׽Mڴo}R iOe! "RѴQGR޾P)2  {[H(d "xui!k>ԟԆܯzǥI[9U!ۥO+4i]."ʦaO-2#wHl'UxJ'iVֻ9};'km~b g䥷 ޗU-~} UY=c745*U`@vf)Ime4#Q7E09~7h](OȀctT(c> rLrc%b B>Vk12RQOP#cGX{b%U_*}lHvR.~a=<5ȑOJ8ꚍ3gٕ/j½V!8`l!;d[zvKaGĵ혼3El믻ojBW_YM(h?_Luϴ3:wM-J[ֻ;Βf'ʖv ora"բIV,X)eTۻ5eT`Q:(FT_t"#\*c09[4c5x!o3tN:l]{z0i{a:a7O_woMC27BCeH<x3 34Jnf7@5atD[u5(0GjDQc`4jK MGQˢcM;Y+@˿h];;y؛6=ٳ"MbAWdP‚ tI01A&jEvY>єe[ /M[hش謹 ]!KW{}`k/ αhN*.(2c3EmRO;%6=5y9-_iי[)6@v! ݲ mh&[ɌP$oi)2#+Y>c6+X1E2ԃOX:#*\ډ R#uk G ?jt<H=U=7&PӮ]rD+.b(?MWdte 2-^ڈ*͊mr(oj |%ЅQ٬4Шo2֐f :=>''.:zDF>~qIz@x{gj{ɢIv(pӪOR(*2Qjt tޥѢ3\?9ϸ]BZoU?øֽIfg>_!bwiEbjՌs"QooiޠUn^mO^=lS} 4%txYT Jc'6 _+V48c͹7Z/)PXpYDm[. aoeڰ(nRK.[ߊ ijLf<3 OJt;yJ>t1>g.b;YZ NDž"t]_Ga "2݋OYpie^wj5B[z*g{qW`;:Fѱ#9UoR\0dD{Mꊕ),횯%=E6E`zE3%#3}ZYs[Ɋ24^P@'4a.m}Ғ_1<_zk@8~Ys1As~/DZM[⍇zf(}v5]|H,l%VͶCs(' q=J/UYw5`ATZngD[d8LF~WzuKw0xI^X=v,+eUgRQxUV^MMe| U}< %FX%Vr,ICZm5wֻJ)NH 1vΌ9BS4؂QJk&*tvWhy K@9 m$I2WB@Fs䤄SsZp~4OpIUpYzuEqm T==wzsߗf4ma^{r1 HIKF'3iԩϗB&NYץ@.2f9y~7IsR3Yq֣'+[D]ޓu9𓸄/ V M=1Ie[D-߸YeY@(q'-^_6LsgnmdFE К=Ķ?r$V'>y$H١yܸKhx@HU]|UJ3n+?* ^ ȵDSp`a8[n,t붨sM%Bާ1EelhePPs0x r\Kvv[T{=䗜?{7nO/`il ,KI^n"5;g:6=9Ӽ;=>4wsųAtzqA bޝ ݕ5uhh7)f7ǰGZ^XUgTF1>qN7y%]<9zLvЧ O+@ Em/C#eo: 9,0!'8%^ަȽ?\uzآx<WiRŋ~t _YD7wx8,IݒxYmsίpU P\d7bƔvij1TzK.߯g$A/6\U.*A3={ h= |]x1]i܎7Wiܳk8i[Iqw4X=Clb茻L~W?.//ˏ?agB [g͠mޚ;M[{._ 6_ǸhϊƳ%IDtMߑU`ɖ!bO@*)b:xGvĽ{AkOe.RYlS:c\/Ѿ }ɃRx>[A**}ĩ7aZ:XS6=s<̯1YӘOq? Ϡa:=GA~N' CE0o@:]XcOL8 =ѧ ^"?elT0QA eaڔ$цdyH ) RE+lj2IѺ[6:x*p}.o)0 ž7*@wހ;PytmJm(KѳꫩbNw{At5'c͢~ ~%83nEhB'%6S.ϒEWNCRɎTɢFvi PC)S4+k V CĢU1^hkS򚵍,lh}ڻ"I0TMI oOY oyk'b^E7#D:8jm(U݂DJ,s,UJtk ƣMܸw,I7gxzԧk"53\T$rw{9>{yϟ2GʎFcɟ9'ut:{2WKrS}N~.80zz(5eW־Nҟ>i 99)WQ:҇6($r׀T";|4]uUgrL y>i_p<>dDIOdi70q{nmGqa;I9Ce:{ 5e:J#xn/eRpZ[@ \O'vx_;7Rw:;U MgxWms8ί}9sR:eiOaXW#yl~+ـ!8P&li쳻VmH>(yZ>ւfܷdfLh@` MʗonnWǜ0T֋xI*)c2 3MY62 HY3EpT]FXLSPU24/9<0R4_܇G31Zd `ap{aVr{Tq)8ΧfifL5H*<u-Qy#c|<‚A0;4{`{꣱$β5+*9"c\)j5qpq80zcg6 6Lm揶 ӹ;̜kӴx%š1`8͐]@D 3Fn|iK4a>(TxN9EɗePx;x `S\#t̔6pֺ]m4~/EȗUeL1_\GǸ< c動zUU&1"vRNfY󔷁w_ kIb}bO8јÌoo} !`ǎ)iF:7/+鹎=jr\H3*u<[-٘jksVj)R`bvggBsvi*=c컉1گ`T}[XkQvdY$j\4HR420 qun@vfz:w\%*e*..$l4/C0Te٥4sxUk@쇛¸6 )+v,n0tMB>֊ȂGsAxC= BxU<8Lhsɛ{x=qeEM7]vtUPh;*DD)۲]'\qH,]zj}e ym3pyL ]f$Tmc[sNf\D.//Q$^B1Ⱋ@٩ ĩpi0ჸ5rSZ:`H ;; 4Pb_B+3M,;Pw2G@otݞ!|f0vT\pǼp.G `(<0*39O2H1>l~mAp=;JC;}~ƽ}U0ǃ'k5|$[wW[d˼t :jt{< 3)7KNaϷ=yt30cBhu=^:Ǒ:XB}fG|~ohnSAikC|1tqL縔-u3p ,YzxчD ¯˜/, cuv2|Xckşgnяݾ700tp>uυ0 1j7ƈUD-j(nۗggx[/t[pC w_@hHrJjZf^B|{sgkP|0DN4ZH/KͬH-/ˎ̛,ɢlף^ R TWPZ S,85O`UjkNg\* l* sV[U^[5؜ɦ"s|@QfYbI*lE%ѕi\}X!uZl0|ncp$O|É)'P2sxuߊ@ABա^)Z6&V44C'LZ 새S2Ij[:W̙~Ώg|'-4~ߏn} KN2l *@LkJ$Z@R6UFs&(DжȺ$v<;ص? GKV"Xy*%+S-Uo 9jwߴ cI z>E)3udx93Ʈ=M?uL@(VV̅ MH EnfYHb&[% <(i|\tIJ~MȋE-*]Px)F`سkRZ[ "qJvW=8x^ִ+ # cqEuZmMcrƟB_x>jtޯ_0w?4{!4JxB+;8(o3[(xX[o6~8K12\Z⥘91l]Yl2)PS!EYǙ0!H"\?^teÐzH}Otq:@Y@Xj`b/Q|{%Էy&$EIр@kA= 4wyiYgA CA$ 7tGw;tG]Y"9]EdKx,]a؟ޢJzap9pF.o&Ѕqw z o'i`J[D?Vgϟ J>*%CajFW i\?/JaljgMv3#F͙8KGْT@+v-&K;e2T#wO -QU8bLwL+(OTKqFI0pafNI|2Е]:>y@KKݕF5@r\&X9zj^Muho4(J̴6\y q^(nRͣ'iA$ -S.k!MC/RmYVgˮ i&\vrK9KʍX3E/{i/nN\KuXEI. lrw.ׇP}\(%4F"X }u UrlI7cx^tHR{!P-4O%ozur<7O~9ro޼w[p8o0* Ֆto0ʻ:Jױʖ6lۯ7]~C4i6[dgm{7g]M1ѵշI6$8vs`Uh )DjjV\;7U\ЊkىJJ^r&4t%597Z[TF1V~FQJm|' 1'-ᨦ9#{%Ws_t?AMTɹrSsE;Ь^$[n2#KjxuhDko'#lOETtl$Uzvx=as۶_^%=)qڹ"ˮ޳e$;phyHI9{~ $ ztRvtPCW%]&.{+Z%szbjA~}Z6g}^rv{/F(\FP ."Q.vOcA^D&KoAw4B=F V1 ]G&;sХ M|]tG焆N08A؃=( EaDPpMڵGIE/]<}G0xTFF_o?>x*'!VkЯG @NBh :Gp6CSGt>\hr3\φaB&jXR68=?: u v 0XnB傑 I}<З$4/$EyEhIM|f᧟}'U۟nf}֩7{o\0Xx˿Ɖ{w߉P| @ \{$o,?=V7~ |pz+ zp^Bեu=Vk90[k.^xv`]>l>ܚLGQš x6CFux8"$(w}p' S-7^#J{`8@NR%8?{ֶbL?O* Uy• `"*U){50V[ (^aec'IRֱ`":(,3j0ªEe-l' #e1^N9܅3֊XCe,;X.{dcs@Ya f=^uHGk(2%(QoV5%}|r4:ꊿGg5χ2UR1>~,Wg`:GRI2 Jȑi:R|Z*5^άL̠?V7UJoGMlПI8!\Z &֢v_%)A'zHF /;|m`m;CHxhAԾVPOgm_u hBumn|,-hֽwEDVR@<Y*.ZC9i2RڔRY`y Als;~3I)$d\Y(7p%L*yZú(re?XX%3ٔ"!? h9Gr# x֒ohڨ@ìY 2=:r5F)-oS!1gZq:tR0_<"2VN,um^NXiHt_>''s奎p'՝:&忤bpJAǨ (]Nl,&6"SI}0os =nh\߳L8.T ]Rm#M&m%Cb &b3qǨb8YF(1SZFAuQl^ c= &pj@zvT 4Wj'37e&W3 'X `Oֳac=4֠y?;jՊmjlmg/9spFDsp/IgDxt󡂚s%p&lHz9;i^l|MZ`/FҿT<(=UTSfTT襕vٸŸ-Qmxao|P\lXmэY-*T Ze̖@а箔eWL1w H^t)m2(>8* p miڲGZֲn>B>C: uMM w/|41E|T wxO4++GtJBeZt=7Jqr9*hV'?O{Gue(iTtĵ@$N57j}$#f$I#uKR\W|_8f 8h;$%+`ù4Hq)GH6M)Z(01*IӐzUo`'vXGPEҼe6ۦEyX)cZ؇&$}$d.A@`^IKǝ-]yݦK|rWTNx[|ֽY0~RJ~؉9,Qg>I*')imVL(}jmG|8mT(`eS&O5&}k4_X~>V6ӑor-KsOsԟJ "G;YDr%Kԟ89k% rbGjp_F/\DĹ;R jδsl:flW7 ǚpCݙ"./QKh (ن%nHC\EU i$Ȩ7X$Ay!-@dpW"lNʫrW;8_Rv8M3kQA)*x<4*,{ic9j^ !"ٍ vsbϦibwR6J wg4J wÐo@OނʣjgUTj}O*P8?_[D+U..N;9˕T"x]ۀ'#gnב5D6rT(:ӢVxFN8KQZd~NyJ/5î P燚nhf %j? p&_!{eOVSi*5rݤgyzȅZsYZLc^!j>owl+vRyʉۨ;*9ޢ;PG7'G%hؔ6'(dc0F kJ}T@at۸̑UaGՔ;"c^WHN2yQ>* ՕOp+&,3}tЕ{d{exp2{,e]5;,)]StMߦ# .}wZU(-qdnp  sg|HBv~Sj)nNDAW_]+|du*FeSyy|.W 0%SīײRS2 ib7#(~S=9KkHhmPj2@KDv_vפo(]{Oomj!nZ /EөfUg'-tN)$ݝ\h3@bN%w3'*%ɒY +,5@oik0Kݍr{SRsKlL@|ۆE*~tL\,Vm4Pd,Z2' $~f#󾐏mW7.:܅5Oat4ofp=Īp%Y{2*OF#lZKN9L<Ⱦ}-vw D?} P.UkG}3ee_~ "M 'd L0cso} ",.oøGu)Dc_0IKoiAEӞ˽:n Ptxۏ#/fi"Wi6`/70{j} R oo xTA-<=oR󨾣}RA0J .kG!E#W j%zyC5 ftɷ#L駟E776\g|BMbB6T_DMM3/G%U#I-W|c='WS>cx&dz^ϸ-|QPsJJ}[ pa$C[ $4See#1'bc{%PBO(o*#>mkdhDQU8($@HnFkv2'@![5p6 Bk,ɲvUv߲@f@9. @n vU bW'm>侰Þ ,a. HσrYtI,᭏edaeFg=F 9˓ W:OxnsC/Zχ)ɹf>@Ð49SU7>9\C&,%RFl&('$giYQ2,c{a˄dKJ2RO䒆4oYh||b|;gԹ?h^:/n:. ]>f!Qpd}?9r [z@OeM#[ ~s9OSդYz U l@%+j gafMp+q( (8$ˇcAY@ "d&"mt;3a .dQI4g% oe!R_6ZC*299!Puq}4 uiBCLqrsn#C21N,HO.8,cE-W(0p@@aE>}]IU8gЃó>\7*ZI7n+iI XPp|[`"=CUHy[ axfx1=4Kc{%ސ^ǂ,OBؤkiLU ROy/P ah5T+xBrSOSaMca_ 6K\A)Gޒt zﹰT=I )xi$] ]%N`Wzu^q>: Mۺ2-i>j7}Y4+UϚ-b¹r[dDw٬wk:ۍnd/Ow Khj| 2AvLx?aB'C]Fw?߸e4t_@ZYTlCPKH^p"ES6w~nCڮ(:PIźjl~7ee.J\-╆cXB1F$gj6H߀?VA^zUGMFX$f`tv5?(`0D?Q*DJ{k41/, -p{}Kע _j t5>Kc,14@ծb!#హ3?DB~xK?]]l&RSĪc u"䤱dtQrJH T5(d/_$ʴ:EBuvfLwlZ뎛?K"Y*E,3_8mDd 6M,Vv&0`%0/W[tж;[s^)DqG3ORC!zG.ιtnGK 99m2^|p00 (x5Z:k(a ֞Z11ok2u[}p[IG8'ъy%|lz z[p/3{/q3i`q ݒU.%VLu>݂} ((otL'Z6?2z{\`>!Z"._:yu{~ώlм„`sǂRn 75exL襀B-o4(ip~dS@)Epr*PwFy'/x%nOx^ބ?oC0/8f~`Hg1? }Lu/FkT";?bٿgqW(]_P]@dt2޳/eWTM^vx8Cu6 ee$?HRԻû5['B6UFgTC o"7` -{.)4Չl..<#T0_NHt/b z'F,C&W#^ KeHoR{8=#)FA4ݷ!]]F8 B|f]'!~kU5K,з sy ˘- 3e[T~2N'om'e9O5)vȋCTcX&Omo5JF qp>3,JTܹ,O)xA=o9xw,%r.+j Њe-$PJH~ _%i.% 2["Xr|NܾXhL7j_ g9ĭN4rخth]q<]6f"] u+mu*ԚV=Y.grgF&&eƞҍ3,Q-Ֆc&y/j}=À+[ۨrRKq:GGyFH%jɂmILWUTwy31 'f rv.1|+Hf>-rFʛVXț-@sDD9; s n ުoHTw@=oSuB~WX@#/ë8ᆉRa:R"(RH>Hɧھ ۮeq?LWp%w.[ D6kS%UA+SמQ$To˻7 `kV} B2B+<܀x)_F@u׷:PeZK*92!Pc]m'iD6LE-yyI 4H[b35KS![3j X뱁bD*kg&hșAi\i-zj 3dTz>k1,U|tg%BEӱhSRթPUAi` k<ݠeT[K.PR\|#}WJjbNo"ծrVc4C)ǎM^0u'9:6?m+$KE<+XhU{ Zٝ^@?MEU /vyA쉾s t䅏.OAˢY,Ӣ p°}˳UD%;֒:Dd[.|nEDSW;##j$X9;v|jV0 afJ*߰>t^\BcBdEq*R mE\Od7aު?6t;.fP$]M|"%(:Q ާ'a",,ܻYVOy#f- FBXnCP/\NUPpsxaڊN^fXϮw&CP{v /v-LSͶQ~d27Ꮙpȿuwe#*"1Zk> LOei{Q|G ^rnR6fRSz)mnγ[]!4 M=\R.vR?h7wҼ~RF{(]g4G׮Vq#*FRp"~w1>ѥh/$WVѭ]mX|`V׉=+8]aYβLM5X@n[kMTJ7g<pm b\iC18c.wQ^Lw|-<~/t|`#;Y緂`Q:nnp`R0t"8*UmYI4&顇sh<4( IItDU(Y5Zࡆq8h7@BCM/E2zz[mVS4ú`s$3BpaN2R&{Jt2d|_OӘb&T9.M9t]]kfIS ZY\d"DF ?^l7L\A"n]@]|'$Vŷ^ .+T3>#Ë ]}vJR<8@gw=l*=Sswz xM1 @}łpXmEbB$D^\+$Ԁb7 slV,h?C2u\K5`X&3LVVV_1PUǔ}J2p20 8nFG|ҘD2=3xMj09ЪXpi Y)=X( ȐW]{+7{S;aXaD*"2pnb^}W:0)~ 4Xosq^jV oem\ ?i"<-r3'E >GQ_b dv2!Q\Hᙄ?Ç=`X(@8<.P NtXڭQ;`/ 5Z $긦bNf8U{hLlMS+-R3BʧzNmP|0Rת T[W,  2eV{M6a<1džt,""g.=9{pc9J{p nK3怋 g'cs:+A_<Vv_Q.XCϭ.cAZu֝3w9WCU% \Up$ק #UxqNgt2 fr DN۷ucw6T;,ʼnyä(ms Es'$ϔżXP) j$L@3p|;9@XB!{9h98W^SК%H,ɳ `'H4@dNS)H`Wu^KQ'ku6[vhÊ[/?Ui8!+ a'}O\iEe |E/v ~rM,nu`gІ{R U{nz-Nj3|y8'^NIu0FW^0`6b099byKV2M[X%mDMyTݵ j>zԮ^xr2[/HkgkgβDXn¬ =ݰtVӤ5xt8CiK^%Σ>JZW8M943$'0GOZĢ̼Ēbk\\`RNKLS@oxk3d,?lx;wo͉3*xXn6\`'i64歃kk.lgYE$,Dq{=؞dGR)KvHk( eQ,zS/Ol.G 1}<{P醲ov%1 JEiW3[~ "Љ>}zF^7RY'HԠ$rR(%BPHø̽2!1g)766nS+~}g?Z\ONw6ݙ=;Y%/{G4Ln3vT. "񼭃x`F(>|OE?ﵓG 7ҋ|0MWÜ23Ep 8A' (^*8/>0:u T<2ړc3ӹ3菺~=]%@X礫EIWxA$[ޱ'N(9_< ET ;c/]eɟቁ5]{4uzr;v 2*@NGx"Try\eU܂)]0KB2tQ;Ƕ6q4XuQUEFCOьT5Z!"nHpJDڑ5Ƞz ǫ 4ROEYPi0w}L]}ǖoghH'kf l6fW jciƩ MBsM͂ +{w-jTMOaŐ)v__UNq1=|FH~7+ ,-߭!tΧwfՀ >-!?@5-Pe 螿UhES_ـ#x+֙ Bw^ӄ6q8\}43(8+*?]OLksa.M)ߕ(L0y7}0>=e_Azăת>78q  -nBYӕq:r:¢,NU(huEHLĵs9{r!oM!̬|qaxCuwv@.\ke{yj$ 8i`cB!’Ed+a-ֿ5E) "(-Nݹsk# ni!ir[pR/qʵg `l9 }5!3tO -ϻFwzbPR K*+Ywڠ^xqz& 2,)H<|wT' /Vj{x3)k?KC:0x;\qB ;g9'_ WSx}]k0+xcnc &T2[dWM s]_ƆHU"M”oH2 wڨYFoK, )7,ۘg,9<~L'~nyGS.692;5]nyNek_PT _z:k >]ѩ^C#HOkUJ7-5 xmOSF|RxMo6_xX y/6C;dmuaZm&2)Rl{$%ÆR||hrFRu^b{1?Tq h UCeS(vfn|G(,ALK:_쎉|N&@jRԞ'~2)>}~,O9-s_bUNkjɖ\:hӕEw\f x6rQn`c=Ҋwi):tZe9MeDfe2xbZ/s>L&c_}7[%Cv},̢ Q7&Ѭc&QoXTBŲdVݱǔ)}r&:Ãc.֒:[xDh/xтd'3߿{ܲUg/ "Iy/~!%A$BiEm4ñ`=Dy}_w299M]6܉$r\p5ǫhOYx ǕԈZHmo)J- FO.^=*t51) LHb U%,al AhHƪrC]B))YE \ ;!,g0vDVfZr50Mj,XLy?>Mr8@AblF ŜYz/5D_fT LŦjKV3*5xBڨl!2|AQ8de@qF 1kd-C ^#4 $]hAt`[䀾AEFhS  9u Ϥ/A0 n+8”haWY[HcBO*07Qt .¦K¿"~&uf~.;X]` g2ʀ<7])Ғ,<Ӝcho$ǑR8rS2:.=>{@[]uٓSkZ?ΝZGнLV /_Z(h!pB3SI/%ꀰc\LDiӞnI!k4 g\A @BVH(X#yB>LrUHG&Ga!ޒ0zA6P؍dC9>0`醢2Sek[v;7VK0г {u]Hctt< ֲT8!AԦm_[R!?cc G2X&"2˦/E=%/N, O;~ HWCLo}>Ww1< ri2pz6g:$ā.?Mr/}ƾ:٢œ1&uwMZZ3C^͌YS;3".w@ +Q^r&1aHtftuKܺ_M) O[P$v70_YNˎQՎ^+%eD207iӻ#MNXrIVoI.h;E$u@Pӻˢ>* tp LivdajzdeP-$r̶VW<ÛvS 8q𭙀o| Lۡ1%HSu_唻OuƏmﵙҋeϤi#*[5fOwВw[S?pFAbݶ<u+UjvH^ց a)΢M:L-ܟt YCivI>/ޘ̓1í+BRq?0-{[x[f5rLɏ&c1y:%4`g)KI3"xuj0E8&4RH(J`2EIhKd;gFY4𲇻XGu`uj*MZz?]ʔpWOQgMʱ̃)n؛%7܋(t|j0zUCIbC̦W t/\r%%Tɚ/RJD:F^Q/[Ku 5d| SpƏi5Bq$߉l&%g5rıxW[o@~v~ ")>4iR Ԑ YTdg3íHݤIw. 6GqgAxz@ʳu#p< 5"iC%8<` [ږlKL^h-ۻ68,'-q rF 8C8HR%HŚz!@7V~i(84Ϥ"bCx|F"A=!LhC C= !ބQh8oq2'&*HAΒoA;Iaɮp,dA\7k!BFLBհ\O1M_SQ 3xWftd:q]q]JZYJoWv~u~Չ/9$^p{(3zRÛ|j /Jev(V95Yl}as_ϟMeEc0֯Ƈҹse/+$06M[ULz 4ָZ {0Tf7g25,ƺ0n-.΃&=M+.Д>N99Q|χ wO fBS.=tXl|#1؝Hri, @~`d 9p 8p;]ɰi 1;S@%oNEVT{8*S+tji>Ps^}WCEBTЉ 8cj?zUEUJp(g.YׇR kH7TSWF 1# L϶͊?5VxuK@qh]Ti`AD"J!% XH4S ;8n.^r1v/ڦ4l-JDb\b@H.I)TV3S3u6kjN0j:gY20t[oNycXPҡ'(&JMStzb( h{Wt%CT eFBTj q:6Űs^K"!"˿?ԌS]l\< T; Sq#ɞj]fL˰iif`!5,j6e#hzt`L/OqAp+$S#rA^`Sʚ?zAZM*RE%"qwQ B=k_e909蟤XY#|\Pq%E{ÅܸOe| @ lxk ʽlx<,c7 xksH;7[18ڻr:`3 &JHcP,$J\硷ou{UZwf #3m< 6km\P5; 87|0Wk^3ײJ`{KX~ ֋4\eo/ZǞkϲo8@"b>+:8]9so80m600pi V̂Ŗ0xk [pPz1jb.-]N{mpG+$ DN |?栍6j)+/ 1A^o)| >a_ k lg)h0ѦAjMar5g61%_"R!%BvkTl9; 6}`EW1]m"p"So6KJf[0pv ~ 1L,"/_vZ BԠsv/;?jўkmt"ex{dP.kfrޅizҳno6خ Y5 ph\cp>:>N77Uv Mд}af:3ڻI++4:$ma0@N/oui~Vs BQl7 qp)#*a-Yg\w#u6zO8-3|zd5^4"šO)z>_!ԉDbNR4~9AfW/- N4h4jpa"3r3+yoFi41Me4~-`Z8Z(O\@r ȗF6- γ]z1TZ@caviU˅9 sLF[DoqYw;Z4=P̕d l)YuX==MK567@_M{46S.JAn:Jġ nI_=a*{MĆw)rO@f'=zStbH~oP< C${ۍX'1u5+p"X l3`p~,cNov 'ҡi%E UVdЈ5{CY5(1 $SpN[(A0C/2,+[8~1%A@1?IM [{=i\e|*|3y\XGVU;&႘̩.B*FBHJnRi{T9HE$-hxJva%Wa> #߅9/E +[%- 5ɀ>[bL[*F B46 Pkcb0sLurĆC׺t{!ҰSh }r<ӆ1/˝Y֊x HWG\y$ZrM']ȵ,F*4JYdzU0XƗ*XWiKIY+e3Z6J2K)v v$#q{^?JmfՕ[[=B*eُNQ2UuGT?N /698e|uH|0b{X̯XNet=%'%U9UY/:6 oƁ3Of+y- \EJd_2%::eR( WˡT gOLv%[5:[Vx#p䩅ʗ-9HL2 Q.|YgH$1S:u DihN CP?H!=.(.'UBwBUmu)?{B7:E#1_+yF>|U-/b99? F>G.D, E}>g6?MƳix|M[i6|'StTGF09|s\[CqFPlHIDS7T㯤⽝F+!1Z)JH ^sáޚtIZ_l0> cJKѱKs}_<݂g>HzOi $xO*/ѮPq&ʿ,\v U"8 xQK {rj?#FY ȕq{$ɨ+]#96Fռݧ|F+ KCʐFN.n^_Α/*Z5ULڍ dJ CZ곏i5nsH%37 :C+rN:`(M#ټT_& uY̐YG,6F~!W/\ߍ{|:9t_V^:S~E hRkc9 VV pr=DގhD!T^f0u;2lԓp̞\8pı]oljd:aԈNd|чd 6Ȱ5@2gm]SnȄp&\"¡L 1ԞАs gظT4۝$䑑PԂ}#3)1+s@-%] KԕIԱޚHcO`aSPW]I*(` TG*B?M<Ф/O N)Ya*],ɀŠ}@Gmqf.$3gg&RHE.9:|G\I_:bK N]YBxH|jР傩 FNH_;9G MC+]d \+ ވ-n2; .7ZF)F"pDevSz"t+2.BSn:k2*Yb57QʹD:l2ԮOKۈHڟ;{r!m}7R eO*U@FCϼ[%*zDu^Emt'<Fơ.O᱖X:+2L[qٛJNb;xհ,]A~|"Rt E- i\>4ݯO{^)bw)@۵z.(ǝ+,teabx}mw۶W zNRɕd;[7骶x#ɍs=<K\S ^H)v>ṷH`03 f`k6{8doe==xHdڻtڋBIA6d/Zl^y.E!9aH~ZL|է굨< Y,UL)I֍.Vz~*Oz[QLCtNIJEB+Аn@V?%G %.4o9%5 cy`7pP &/d`D1i)bh: 4/!?҃`(HK.)Y%jt&'oO'dpFɇ](#Jo(/ ;@!G{oã 9 ctDl0 F|tv: SD" _^6z4u M#sBOd D጑ sF_0J6A^Vl~dBI˗]KXx@_v^nKAi(iMʟ-O]-iҟ^ߺ~M4Q*bΊhZՅ+^ pQClOӀ!6 o˙4ٚ;~5f_{K5K/vvF &ipaid(ٺ8 Ԅ[(FE8Y-hj ]ȕLme1 >6ߛ`i*_g.|8) 0xNÑs08g_a;3p6tOƓPNP`2@>񎑞cNY@MNϠpfmiE]CPW0h[ `,Z/i> |`?PΑ#)sQÈÐNYx.]aIށL3M{*p$TMw?'i PEpxPJ_tPثYPiF4,)Od=I`otztaiAoAaS،'3`wtNGZQo suxx LF5h`4)V;LG#dQFy+tt]IgC=H)~ Խ)-#&ELFn)0 z ӿwz?}ajNjnH f+$}<gHYKϩW m"]uL؊y鱟ݻ#W׃W`Es :F+pMd?ټLtw# ,#+upmī0w]($K6jg|_d:B2KhO(C`MMeT]){4pAE5٭,Tiw`K(&hB5&EKA=YHp>q|RBPWj]+6osѸUD(8kɐ< ]SP /5ܛt2韉aADqy!4% Jܰ09B}0ä }uZx¼lV0NR& d3M2c+,Z0 m[\tz ܬözzQxS!$m]]~*tz~ 4Ԏj7 hi+ӊf9SʝjM|l[uj6iʏm(\y.I|te2s.:zs,twV<}rPgM+4-v.f|%}˔](v*Z@`,8:% m >8a$$p' ][=ŋGK(I"CA)& mƪrr89I{%u?.ő zl^^g jShOtjF,!g^c \Y*İ-|ߛxY=Iu?=o,5Vct4 $ Dv2[G@B7pШx<%vy;-thOHAR{Ȃ$@B ;!C m @n~bPb2O8Tl*ULU[يt+Pe52#/tjάaWF7 ;ʈǯlH|>Q| Wb/cO|`A(~$l%;x~ q`rpAnDPr(uMW>lT! (>><ȘJ^vt^[) /I#paA([w)(5VE0%ZLѠ$x$OD3w0+b5P0MAD]gtQ7"glLdP(J*\DJ -a>E΄Gp=9^>`+4&|2gJ 5/͡)9]6454`d}Ǯj$֟ɢj".]?PؑK6^ePg/Jf ^+ lUq킗D8`42urJ2yM L9CGDAd,XcƫB75! ~h8KUeo+j}d Apgr?H_AvYT 7߭BX`Yt]JǽJՅݬ(g禮eQ}%)Tш #KT胆 .t &d]~cd$M>Vkkز(iVmP17u{![dKvG.,e#="8T~xԾ"fMl _[2;ׯKic˿m3p܆~rE96Fy UhG-CWGڈbႰj7 :_-fD VδKI|BUipyDڼԇAﶔ](@l%Ebu _<_0ejV*ÐfI48~ B&I{lHoek0،U,f}NKkSFnPlu1eY͗ZFL[NeX3b|ߊj`e-4f0r#X3~WvZ֡y;D6[xmQ~,)gnp f!b8ocO5ZV[cIlDY>)1WXg?)%ј=g۱GX4j,—.giRҝ^EaGR&K~?~ Bb|Fl8~\fWA `XWÁGH1MQ`*6vg^Z9$:)ֶ0_uCN^qYt-$=:xn3GEm%L=7poQB," 9Pm/ t@[˂v߻D륿mOpLywIbv;SfC5Rr낼~eKJ._&Q+Ln #JV*i됟?Tʲ,US4F1@>P)~)z/> kCG~>@V{ـ : hoM0Gv:.yՓ}%LRZfV  @!C]Mjg,EqBX [y&jlIc5X0]3:ե!Th )%Mn:`s ^ĩ?m>c8%Xjhi|*fnwaXZՂ5 qAł9[NȌ?aظvW>ڧݖ ^{9jlqs*tn8dukť_zwV$A|=RY}j@ C6R =c y 2gɌV^~w4/aN#2u摯Nm_'v؂ {vi1&oLJ]y{~d,xb#pY@E[OV- 0eFNf7-1ʊ>y3 Ґl]xdL=%&;tDYľ+,Q8yYW'i˘pL3D] B\ Q669`%6:^* )1}R'iiI ;M03m]8 #&+ ;_m~#BK?+[W62fD!-K{ʷȾ9|ųS ^|?u׀`8?(N}35IBa{M|;__ 5ȶf:}EF0c]Mqy.kysJsbʓ4KDnWi[YڷZ'j+>)p }E}1HFm*at[<ulGFX3bHcoĻhh)@X3ikֺi:Lk ԉ TO1pC7Qa]"~F#tx2AYB}}MwhVבSb OcUkjK]6ZVQe+&*d< #6A8%Dgqv0yy?</9}@Nĕ #|:yGRC[U 8YJ?b@qV-DW>+:ݽGlhh.I颿o~El(~ !쟾y 7 F]>tm2W4!ғnl'$9GJyy6jUɪWڜyyW'VP 8Q5[?qW],*rXRrvaƝ -Ɛy ɏ%ƄnVBKE8RE̪3ψSTȶ;vY4 ><37dWvwǐoȚrwy.~P'6:`]Sw28RrG5vA֢> P0~>0-uP³X؝^_ն+Ԛ֚.I,Xk2+끦W+΋^wQEL͒N4wŭgmF0+;b#|RlU,,?uDݤvq'lE`+bِk'4@V̎~jWR+[OUnuBe׌jW}:?e%2L;DZ3)idSf44clY,lALZ ix"PB;[YL( 5MQyx&hCEq"Ė1u0חXNkRY^o·h9*"JPHs/6U8bB[Xd6kQKJ⟖c^U K'Lz6[*}5iA^ӄGہ0eǑgѩ <ϐOoT5@h+{H3l|z>BL&V%_GHz0;Kee q.ORqM|_UI6&`OWI-dwn$ET%DڶgX!d'^ᇘif(^D51~Q E2^k]euv_rIݸ$+~GU+m'il67'ȲEtshO n"- !S3;~MZ2{#큎" ;!RݟaXk%EY @~IJд-o: mLNP"%Y1jW(Jv3CUХ܌+| ()9_c.NNY5 pHa)5,Eft[L(nl*[Q<3~>Vڭ&գQp29<929m_,#&YIrRS,˯H.XNfYzh. 4 зgf';Í8FO?]/x;J +T]]CB<܃}C]ポ=\}sS'_.9 [̓qysoS<øo:FL&_3ᜓ_Z:)fs.ivX'rǐbʋ.8y{怠{,Eb3a19 HxsOT'$5"1i흼3a\~y\K;١ CbsDQVՓ e&[ǿ%!>y˻A){bs2eqM4 'oX dY3yVe&ɛ:r¬Mox'mw-&@;&qON;79_Hq#jE99%)J: P&GINn29.pM>sQvs9mTiɧ[Be&;y9 Π|7&280gx;y2 +ؤ}]]\C=B\"AE92JR7e{Œ SXb=}'/0y&qn7bcr|ԲTV9`&lmurdWԜԢĒɵ W:chtEߧ;9 Jx,e=f¦ks@6 ;t0㴣)'6;&[sN͵n~#ݦo21N>W΁4,'KnEQY6<&!Yr0Ir3Tf~r_Bvͫz#;pO:"+H/N-)K/ 20G9s2sJ2K*'alr$Ӈȝ(y9mFχaӴY) @.`tw& (x;yR wKL'9ٸor"`1=FZLtrL2_Z_ ̄ͿmױNʓZX76tJg} .6肓t'D oxCRLvLtmÆanfv4fdb{6`ĢtB& 9Pf]Udҭ(7 p+JnfF|xU]lSeNnkO6n·2Ǝ֩hRǭ]g{&2YN= i!"Ā{d ($E%GD7^A&:NX7Volr{y9W=VԪ<+I~]m~s#msL[ +xySprnP_ ]hf$n2}vH F^׸%M2HxB!/DCv< յsV&?\ڈ \4"f92- %,hK4F_r:),/ܷۢs%EI^BMWnr\d0QT`g29&ѡHt,Z"-\~Mp7s;NID Skk~h%rԤ mcG zVïEW:4&CFz\ϰ+iI4[o9QkBYG}2ۉ44Cpu\SOy34vy^*P} nӕR(a~g';]imMf`5Wg鳮t$)SkwpكS# yia!^a?~ZWHFc WxNe=RUuObjYzˆjxF=΁~lXl$+yD'*g dui:~{NRy͹;UJ+*֜;|ci3TqFK!9yJ^ux&OÑ(bB$Q]>:1O;~.1ZŒmE?0ߨpڪTustcr3jbZEKXv@LjRM]ӦD eK,GD0{{],+_I-YɷsTi2yUgϥ3 s=S;^ܽ2}3G/ BxR g8sS'[d fDp*-1;h Bf~:e(hZ3Cd.h.pB7X0pqkz, n 8'&8Qx Y3馄y ъֵG4[_q3C{DK~n6_m)txN?tS`LV\>O%ݏA70ꎧAw j0K@*H<\B2XA v =C{̿G\Pgq(\c䌐!6<>KJ3ζzm)C"1 O?u1JRyمΏ ד.zzE/ߛoksӥfҰ.œ9~ə3_aϹMѸт3<9dfi|N[Y JfS([-w:qFqƟf8Gr+z9MN>K䟏/ Sc|d *.H {DXN<?-vCbI2EąCǨxl> V0Cr"!'\)G㫑iOHHzܝjǽSkxr:GbEmB5D|:_g 0NΤ18$Evx"t~7f N jl5>g@Q$,u+Byg/ZlW^&(F`{F/F. d< |q z^\ZP? R'j/N,rۂFCXբ kC-Ü2 $Z\W%|p@z8|Q4M8 CA$J~RbL4tgm4. r'IJOZz3 EJ}7&J('V!D_p IѹR+f^*cnLNFH~E/1L8e3 ||uI%R3g|=t(UӯktW޴ wpD<+ιrɛSlmNsb+otR7:+U J[gWCZĴ x$l;ݔhn(rt!%-$\amo%iTxǓ"h bo#;C*9~Y'l;n E߮Ƙ\)ƬU&20p"iO60KxSo M{nt$±?ͬXp8ڜz"-̽=m]4_E i:@J֪OŴb?.m;Iζi0( ))6Wܾ~+D*R!&:%Gu:m%!O?;3%mjVUZ]96*6י|;EKl5lg{Kݯ,ZnX$V жNh+5`Z ضK[K5RVU8,In0Fb fg+"ޫPDV(}_KC^$i=s`hݘ*5Jq=p2;Y X#+kAN^\̀R>ohǎj&pф\qٰ ҈߁"\N <ߖX+ >JDKGv jŎ7e eU)^6*uR.,t%Iҁ0[ jLZwy,nkT(q-Q, &DzEqN9niHZ(Ԣsp2-{2Sa$0k5v[»-!y:4ZQx jsײ,ǐb2QVH*̼)ͦh ݁#|GD("f *mQW4Y!vZNlCv'?J/Y 'eN5v4v*Xީq;slD|U:mex$6gA2_ܺ#h ._| },4.@Ʀ*޶Ω? DtL`x^zw<{8Gab_ѥcz vh&q =ui£ 4R׹w3w@к?12rIEZS"u#`bTFjZۆ]N]vfdBX3aM{32q1&-ek3χx'XʕHs0EJ-ƒyqÏi#) UFnA]2sD35yC]M@e?hqhuC&OE=*"1{'9d<%n(%ǯJD gB0 LLQ¨u&pW/BۤT(ΧW,Swzݣl JRT29 X܊<*Fc9 $)/^G7ᖴ6J2h6.|Y4Qן:rU>VgrBk>;*8{۾I_D:Lғ*+Y*Φf2[ _oEi [GW*"gU5V+le7Ѽ ^(g=\oDg^eXij\VV˧J#YAyS0PQvOq"¥_Jo$> T_t'rQ컒oS%.P}r߯uc,?BYZ73yTs͞:ZPӝ.MzrX'򫧛SSWԗ"Թ"%X')& A֋ŒCfA솋zo ¼3w*۠D+%H|Wt,Aa2@l>:sdز Pع 8sZa_}_9JZLvR QI۝$STxXmo8\~H%۝NYJѦ$ D{8ĎN7vޠ@KV-j`<3ϼ4tEbH/Ԡ`&ц?` %QEBS4uI9Os>lxa !MEBg @,: xD\PHbI@d˙EI,! iHXJ @r%]f "5nYH;\m <zmtwq GP|iÌ@yw%%OۻM=НO&=QX,y&<-]c+ ؠRޜwC{@pk{p;c}tO`90.Pivfa  At3 p}}х )y?0uu\Ӿ9V|rgߛC1;׾:6M0"1}I(zf7e;4v@Vc>'#O ߷Q/kn7 Z.ȓ4UH !S0T2bܙv\Ow |]ZJ[vY1Cu[qsJdok+مwJhvbYCQ%b bUvfDԁBøiHd? m,8K) ֡G>)Y:컶3uG@˘Gx>,3\ƒ# E^pB aE5E|q2ShRGv:`!.}Zg?':'ix|:Z` YEb^{'.Z)(ikf)^؝ u6JIG0qNû<4ԩG&?ߖej#suEttU>sԅ4^N^`ܾP\ԗ <^{!nZ)P_M-;MVf9]3tb:MfCE@`;;-E_N6" %N*TWRNv!QcxFC7;bQxkAExȸM[_M찻@qc$Q^v50 R`w4c}9é09`<,17nsCB:qN'ouh9.hGK 9_~Nw+'I V|Ԥw%M|fN')Q(WRҘ޷MmҘ YczO2tlē0|yGQpb);4(toA3/A{Y[*m[NC+ɡ@[-y\~N0,$ǧ*SFϣ2HyY?G7,X^WPRNW96_~<,fŌ-Dwfl^*T~W~Xi(E]x__3ֶm2AI͙\KncG8wNi$ˈ8Nsl^1{U?Xh(bӶ.+":籊[%I@Y*/<|eL_WDA[ C|[P&T@46i0eE\# aBIln}{< II^7?_7vwINL" {~6zı=n@-2}N(9: Gԥ䵨ݟ7|JI…=rtO-;}{0)Cb֎"xRo '08Xq ȡ#Ԇ>D6|R5C' m1øv1t'=f@@ qȀy@Gs 0:W6O_p8-=96@| o}p>Aq i#g]$nӺ8nvE&G- Xݡ7!x\if Ys@A <#Ş;;iٹqk=<(MiݢUv/"g:)(0UyX>u:+05]sL9>3X^\Zv54OgGFsF?dgа g.N3E|~5f_8?M4OG6qۏ9sW`К } pm:sh@A\0G!njU!pAnb0s X3U(J6hb/\R66ưGlByWn-)͉bD^TPnMm46G?Z*b}~b\3v뜝j筷Le8露ںc1d轃q̘=w\#t{M*aty T*tGk03ƘV5Iu<'HM"J}rzq|6{ϣ M"Q,ho,`( j&"ܠ#6dl*Wz-C~ jgjT+-\VFJ@bq?H\K#aA],,V6lJ-'Y .Q7ci:_~H] d"[khrG7:>0}pzYkgXVQD,[0gơ?̌~e@v.|C'R |.E姘F5fIFԈ"ۤ"X)Y;K Dn2 >C~%j9|Cjkp;  8ͺ!Ջ{HpgyReXS"@$P(iC!M(^ƿjLo&GðJѨ$%3[MQ\T)vy_C/2!|4N148G8biǞgi: 北c=R#9tq>mӁ3LznlT'! [(QBV^yť37 H-z𯂲$XWJ&wO$b3@T(7cb_r*R^; byr1|% )rH4\ plA|oJD?wFmDΡSVIk:+&GO1Q6g3 -U%9`aݴYt h:`Ucw479vz8pbv݁>}'m xo0BA)K93 :>3,`䩦H{=ܨ`h:<T+깡PEzfmO_-{},-9` /[C// +3>5iFFS{>X dlbѱ3jB^+yh<0>0n.t&ӣ|!V;o@-"5$[[>]4Gbb<:Y= Q¬{}9Uj19 y+S(tzwf @+z7Z̹վJ32_t="[/}OL,^8YԄ ArVlXI8FsײMEk .8Yt0Gd^-Ý)+I0sPeӭ @bXzpBȥ WU A'ŨkPbZE>)w/ٽ <61Lm 0ay {lؘg) BVbCtC["^g[8.S_ٯQFGk.h\1>!T#3!5,Ob}@$G =il7vsSۑ kɿT!Dsl0fOWm!K|)!#lG>f!H]G0NMx#8n` 5H%z|,NQ8! api+fٙ"#8,] Ʒ?%/4|_-cSpi%K{PvW@%YTU$TZ MX#)@#?P!Սhccd7V580 |o VIƞ:;mm0Ð\Ŕf]󁸞V# }3;lPnآ25m7Q5 sThи s >10o^UY͈!ݷQ\ā fхc,tD b)5Օnq-Ѫs ݯK-?hkYd5R:)'"z|J$;Xo :5-mf0(("T& 0P10m C:I?wym- hLro⫚zb,]iJ eH6ء3e& aΕRx;Hl8BGm0c'ˉJ-?B5*ý^kaҿ^86+S֬0悾E*mbsTh@ kTqJ6U8hA o%G"ńw5gz~W}"N_ʉK[ʲvsoaپ Z*7ߍP4NR&W~h%BToDl ?e.s2.?l)b͡DT*h鸍$d:C*_;)0عt,WS ǽfWupU%ey8r6Z<~?^ ɗ}:oI}-) ͙9CM-LƟ>/-pjmAhܝtb y-]Ǽ \UՉ~V\(`D!eԹj Zh\n!X˗%,Lط܂LoR~F}Eywudu`$ M1aHm%4o4dH~a#x3?`p{|c @@: ǒYufy_'|"2.U"<E-H"1?-erR9)R" n"IWRgr" d$s4 ]pv#reh6 eP|d1w>Vi<Stzv|vո8|zT'ccxz̙x e"vz%WpbϧњŹVw|,ut{Om/0#⥤>t\UL!?UrH֊E!U,:YD$OߑK lm{{吜1'1h;?_ ,k y8s&|!>Ő/$ծ%,XFF鶛BF˚HAyпR4RFπo)vߖf:u{{{~<R6Q1r Nо3Չf1ƹ*Rx}ʧyjpPq\#_&+qL\)?N])Uyمtǔ1pŖ4ʨ00 ׏#3|2_rT)HMzsAgtλX%nNb2Ѳ"i]WpjU#3q uZb|߅ *ex9MqVu@RV+ QuCcˣ0+؎lj%7O5rlծ/u0w3KEf+_'yes1rtf&NPysIOܨyX 2ER9+Ri2+AHmbR=}[F""rA^VDR)t Wr9"PԀ-X|" 9lzW*.{)Y 0{!C蕥B]QmYO~dDG 0?h.$RĜpHzw`|\N†4 ~5k:JEIˮ|W @QR;> H~׎8?h.bBJa Qsgr,q*Ofevhl>l+8ǿʠ8!qSpFϛ:>42ZI0f52!4}*]݆_>p%*0vWT[g'2^ٖ7Š+Q67ِF(>zcwdɕ4- dK'ODkTq9#*סJ$c%ˡ|d]?DBvi:#zs݇=cR!C]5.b |S6țlB뵢e3\~2) 1u1Nhn^k!߈6QiݞR ̯k^'ԙU ,m+.۵/N5mT%$A[g%*Թ81@`KϽ㯂*C=bҠz~vp7t=vJ\+鞝jKxwdB}>NJ;nVljMishkw 릢-lalizESOѫY!y^zB:")('tE`$Pe''KE[BFZ\' YKiP+ K<(Vp"%'7js8Jt,?,ʌkTq[QU8T%ƿ8P2nvxO,@)9U^ٶU!?Za OVk"쟞D?EIJjS5Qj yJH)RF|VӦfd9UUg|RRZa7_I&URcobWWx[sղK;5%./F|X12().2/ !H6ːeDf֨jMIA l[~% 󁫽ďⳮV{ y ќBά i& nng%Z (X-Bl\q`<8m?abgU=;TZ"MK}-dumclץŵzq<6dv)ڗ'4w0 n!/zF9 k_{`Jf`\ї)}UY"gBkv|G60&kaJ )*Up)Bܟ ƘPG4~r&珷AW7D['`B>rOZkl.f56HB%' ߽߹Nbq V8& 5lL8n_f&H x=\bxX :C wn'F\ fL0|!=c7w,Q_ae`Mo88eԄڮ7\ko0zeY=ۮcٌ Œ06v=E@w2vBÝqP_?Hn6t?޾ypdy;x/ףs}86dn6 ޛ,1v-V cW5x'3AofjŋT6etfT(!C|ƕ8"3.`ueōHn/sXX$L%GH^,]O^^MyftbQ"Ĭ !R\3tmr3|3&оy_'!K;d1xca6ߥ*$AQxs_!f3LE.Ozek۷Dk$IE _0}ꂾW~ZlklHJ"K86DPܨ%+kϹcWræ i̦㽕ۄT?wY^pqnWAXgnG7+`a Z^(S_z1*Bn΍R ^_:dsU% @ʃVzΫ >"EW1Q6% 2+ G@Z8JW(1TTؗ yG*ǿ \,E@cS<'M67jfɑ6]M;e/̩(ŪgfŕOp*eޡsB-o]ze.|:M'A[Kpw_& <juN0oٕǂ@\ ,_?u|oVPTJB3F:7glLь"!9`[Nd5 hMKq 4@of0SãB B ^no:8;bww]ˮ LDʂ.Φݳy8m92Dd5<*pkD|_4 GT,'Kb%Ll'#+;0_QmJ'NkB|iDH|]IlT?w$UmFo̲GK{!&XA1mԠ νS'č)mMPM TqH:ٵFId5 &TfJ=k@zx$Y* Z1Soxe* oP#[{SSϟ~UO t`3 rXEkK#._c}zq5Ei+ p~ݗM;hf T `W*x7O1 \{&.;zϘ spfT:[]a&3]&8ơdyi|v>O۽"PHf,zq}ؼ8ZHsNfEMG, 9A 86Rz` 3tI;*GQ'{P6˳|e. VA\CI8Ip-rnOٝq\JFS=?FERE`0T1> zi[MdW'av@O1&8DKzay[w׫e6;%+8zFA?!(21ePCbw9)rO1OFLO}nt3zN]SoP[>Z03!QL {¦KE5VbKEVƏG9zCslPXr@t8 }<\vꄅ/;} %+@qy* QU[;R9S@ xY  SMތ#.35HeZCITy_A׫ ")t( #J]NH͜;Μ<@pߒ CVҁc_cGT1 qݥcp8aۼYŶ;#n9dCJ6m Nd3[gp3ֳ r>;/L#vBU\ Dd |~w8Bʹ\ū;pWҿS^=,q؋f;ei91U)oPGcMhL3]ĢM g(\/ЌpM.<*TdQkKZԸ7+S#9cz}n|{9t5ǭƝ : .X!Ռԩ":1>ɏǞ?3V!5ڗʥڌyȢbحj=3i]; @ՂrTiwNX|a(b.laTi>;6,{OzlG#RNBbb'e~,)kWnBqmmn8Y=σԱQ{r:=kEk uz,P8B:3泇-Q7֙&dgH\iMQ!Fd%o#7uƺYtuftN9^?2XF1k<|d)ҽbM//)Q;qvrwyOUBz?E), ѸlzMfPϷX}X}Ze0^d@B8qEWwkL4'ou'Fp;{u+`FobBX#;i{ZĂ%!wġO1q#&qv[\SL;Ŀ <4(f!(ٳ].]} h>C!qh:A.i}x9lMɄ׌iA'SM=i4RJ$1Sbp-D"5.)JΑ a, ; y|̽}owO?bBbE,X|cdh3y|;4*;BLip' !ekAd.AydsO' *U㴦~L*r͜xs%s!AΤyLr(%f=FN%"a;`7Md/0y݀ 8`/aSy %qK}hy鲵ڽVsƗ)@"K%xf-(Yx0fȼLÁ5_RX c@bZeHn~+ K%]>;-Pq_10Y;0ص RL ]إt)/̉#bcө 1P^>i %b#C,xͲeɟY*3sJSRҋSt6Zoe*Nl:RQMbv^t؂=V w&_أ l 1H~rˡ,~>> yWgAKL99=$ғ_B;  [t7ءliȄyW6ߖfDh׀?(DŤ ~M-; !.@/zd $&7,\x7#Gl'/x bn+>Y3?"zqMk^ByW4 5&$-29!1[0|{;rW,yu-ALa j?փbsz #(*%!E6Ob/^K{gkx9rUy晗YW詐BMm| 7@!OIrT΄8j:5ܢ$a?hR(PlV{upE3Cz3g#ukG24:1tx50&R)k#T 7kQ, ̴4Kos0jjL,UKAP$U%ξ:104M+&F4 E koXV@i)2K5镐$;3 19vfQBH LVsw0MmGO ·|WP"If]"}B4ﺏ:Qyp?p æ;ƏMcw8'Zi% c-ld'Cٜc.ȍA5y9y¤JMwRe+Ū㴒.uQ_$޳(bR)];e,PkNZ^ WbU8 {A7+\)?XE4YC$: L-v]uuO";w  tv+eIb.gXrD.- ?ַ"TvSW1DjH(*5v9^*_]>R+ _"B@¸9^{:fɄ(tS/q'Br‘bG:-GB #`ܽpUy-p&oID) D,&DOV1Q% ˋD_rh7KO__YƧ)LgSƨ|#5Qy+ (ߓc iB'c,fsD2ÌůI?Q*ixVHy@pMBbOn䖆) I$"&N▞,+Kzr yw:2xXmoF,IJ!RzQ"˶pd%Em(R.m=Kl'vEq!˙ٙg^vf~P"7׋cQ՗Dȫ\%z<+At?īD M>j4u4i$t MbЋo3}H Rl^:LLD"qCLgr*z/%^eܓTJ qy"xoD6Ns#J/N,Ղ&7`߲k,)bk^Q ?3rug:i -΍(NXHլyB-.X0҇3EE 72 i&(Ub5bЛjC{4j&W-EZXQr %$îč-g Q,w~or#7tc:MѤי#.!XZ|`verïXB=!Kbc!nG1ȃ9EM"/:Vf/<[^&cq*qRwL~Ѧƫ&]Iq:* S_Pŋ 7J.n|odz_?b{Mݪ#}p; 壞xUOH_eOws_vGN Ox JR,^{c9ڣEw0;vwR3wGҿ6:'=V*}_.3`ǡp2@s֠9 D"P+e("wJHӵx>& @or4W->E >M~grMFn\.8TSп23J$Ԍ FFZ·pпY [j-Y5N1(cWfu"*7{FoLj<fG<6CF2 Nt嬐,U^H4biI,dX 2tB2jbaε39ݳ|x8P{ JG%X}>p̩~r0ibU\d ?C4y85 0/lQ`B ۚ|#_6kd7aVX )BNͧ :B˗dmc] CDgC/ 8|-p-Y#)4VGӀrX;r,e$9ǖA#b>X=b]$ss=QGl4h+%g(FU=U. GιA~,Tz"g0aL:g[p{bsҲ?pfSbwf^lp_ :gC3KtهU(]0bxۈgHUhsl*ϟhdN_[ND↪y%]R0f(gEGщ+GUYD !7 Ģa^/mV/mt {|.&r3i9 uPWuVa'8BÀqVva6 {Amk-+3mw(}*N'(U|y."_mŨTn}ϳ/mǢyۀs~JAL X KĚgEscB?oٶ`s0J_zY Z %tLc\GeYkOec| |" zgm7gsJ_PL3ќےN};@| oP f5B?kP,_SSAJq`5ʮfXն3M'96S!tawל}4il6=U^%^c734/k[S~ߜ\^o I gb!SsD=#*3dJuƙo ,?6@>lۖ8:JwƏ D@/] d= 9?BHW1raov͗m& (*)he%nv((OHM>&59N䫗IOH,RЂ1 B}|'+rJm~eYafF^5L889!M (%畤 -8O:OLj,%&Wib0YGh9&K-A-%~2 J:qA=5gz|ZQj$"<sjǣݱxVn8}b>mXenu1I_ZI%Jb+KZJjl{HI[7-"9svf6mnA4["+G" x]l*wmEt|wŔ, א3G,HŚxL1]Qk%xTKI@(-ŪМ&Ǚ$(ξr( sQ1_Y12>+hi8#.p.Qv(ɴ\RPND(bYb@"G$T(I@@Mo ӻlֿ] Pb'ȈKToAP_N=dq;ifF}rڟrvf>͹qIqh4\3:{V$=p1g@X »DBJ3ݡG)ը*ۡIw;)X!A$d.3MNN-r7q;KIpztU7<4Q7>ߌTa}tu/o#<ӚPq.Em!'9^ĵ7 Ss<ͨ eRuJوyi=i6: G8tj^^n5#j5Qѽ@aXQ Vi3:?f!0I b u!SAoZjZ|vc9gҏ-IHK!O(;B8m؍c eն O=e6MG?MO*A$*+G#\TY3閰\g*+ެ(إ3C hE {"esn=7Y2XЖ%VWvez_qڤl lqPZ\Id1 QFMcіɵ!w]*V':`+D?՛|fmZP/yƩkŕޝi*W cn;/u "юn*aF۾5*vu*^weRSpVO+$T55#de-t-۸<O5U@߻djWN#`m/Q4-ߨ2[A˞4eI@>[ϯd|wCo44}Su`i+͏;e`=~ڏY݁ EQ#/['+RTfyHk̏oїI\+~U(zO7_ץBPx[(PhC>fs·LY&+s Nm?9g7 )x{(RpV̔Xy89KKK'qM>..*ca(Vx}S]oA}f- MaGxkcQ!Hmf>߽3df̙s=uĬVlCq"ZpaM.fkiȄ,i@l]{kQD.Q0~]BfLϨ4཰hZTր#tҭUw)60: 1C<Ϋ XK3thL %Q ㄋ Lޔ @B: ˄H+1$y)mpVTT 8㣹ht2.&ѬEj^L*ҬXo?QiD{ƻJqa`hfz^ckd7CA 7t%KK+1ՀЧ&İkot5C$R f" qWj*ʧLxƷm "KEnY=&z74# K v6mRN8w_? KF#s wQ]XךpMW27 |uĶGx m8EAc0tUpfs} @P`~xu!jt?kov1[僘''=$)a;$wzu /?,:v=*Q#km."j 6Ғa08xO@?{; QZ173$7S'Xkn'x;֚{w`3o>Fq/} 0bk#^P/; P(oTT(Hׅs{"w>={N0 oM-_8 u{3^ÿ8:KK{hZD:A{o/xao#7`pr*K eQ鬸 w=EaY|."/. hgf^qyE-s/.(`];QG^C/5vE1{BA+/}FY~c4Nv`y+l {ڦ_2z!}_+5t s"oGb>yQw0 >.SxFxZ3+ {Ф{?O>$wɠ7{#]tGYw]\.ޡ#+jP<#h H$ tлn#Xil7i^<$XɜL> [m%ie@^ˊͫ'$& ).4{Qy{ P/~z&ɓbF^g&x~x~|":~+\m_=/w^<'?,N"b7{Y?]zI{!֫.HokPUDsG@=X'g8}6ǟg0<<պ8+ ;|M,j?XB*.`UQ2,AaE:=Bj /Yߓt.`b=>YPɣ JKm=l[."g8tHt0ϟH'yGyY?>w&%xʞƟƓI#!h 8y1wTC :, '(ZQ }22/!@Zx;t0{#XLэW$^Fp(0=*[$r4=2/› aS΃) x1t\n,-qpsf2;)t'h'eC2x׺DER?({!;5@/"KUDf^.7O: vt<5|e3$2zT6qB JV?qEaا^q󧀷)*ofQ>}fk4IEZ2-@JihmQq ?nUN> 9*X;:SfuԫyFGJGxA_?+qEeq.W*SQ+aU1Cw i~I5#& p;1e󭩋73i7JY(?U'Μ&pܝv]oԟ|@ay'Gk"DCYޓ=xU~9_Zy WrRO"PIBVoA2*ZDWܟV^9(> X@B\!l&RҦ( ӛ_> G"h8P2>Gr˳([9H hTK$RaI^˻Fb/dd_i# ݭ:i#iqǰ]i \/HzJr9П=ͷq _/e=EI4]<.ш &_O%Oza#n:om|W`,h|(b:Ux0u:یYt.ɯЉrٻ /HަqHaL mbX|My{7WnvFݓV ^yTT2O=ӾA \4N`_F墇ĩpfj\Jbc& :5¡E^d:$edTfôQN޲e'>Ҍx&ܝwF Q)cY۩ȑ~kpdrPgLTS2;gia_ Uk ЅJ =/ }{;+{1FEuh#z|Q'wA4tCՃãOvK^ZrzhZxoAvDgQz;8]A iяxϫ/y;ߑw?Y.}ڣO]ռn5F,'qOAr?uzGz6\˜8O{C1ϊBSA}ڟ gQPԎE;`80G'ϬoGgÏӏGǣ=>IHŞUP3ȯsl'ə>х J=E?Rx,io<ئH*wB9_iG%䊴]9#>hf·t䣕w5M\zWTqn^_ּM"u[yKK_,qx)xIgw(# -A|i7U7LB76TI{ah/Џ2LB?GV]{/*ci_$ܺY*oVf/_z6)z A)?wG`N_;bsvR!RC6Z`79_DzoPxBR64  hM ZcnG仝}3ulD cL1Tsq4su|7Cb/-+ė¾!'U m4=^W? AZ2HЮCxA 8]Fycε@<%\Sa I1I%8Lp5 ^* Qל晛)SkyDcx0LqUpEIr:+y?T*+2*χgR\TK@dK?t/ Pm..ڲ<4b^ay`YQ j7C lzĝrU?)YXyGGZ?Bh@_KٚlʫjqkFإPJn>-jgYtߛ h;@TM}^15]-IRx_LܺvrS+҆۸i 0{^ %py Ƿl#i$.!ȫtOxz W$No'#B+D[+en{ Y^I\U%ܮd;g"uĨ}r08e 7Mo|x*L?ǰIwR^ZzB}NR7oytOmX56U^XWR@wgOQ bks<<⤻!BOxx8NwL3l4~G4wQ(`C]gIw7 }$/(Tz3ܑCe<ôgE4T0ԍu[E{;^\g8sJӉs@qcC7?!?DY j9pU]Xwebi^qVK9br_Y#c,,)I2XJF}}_ h*eƙEC%0@(u2ELV?ؕ,B~\.ƪr0랍{z,fR\xSN= n(^*[1xh`r*?ޔ=%av7yPAJhodS̤@i AN].V[h*!S]8Ii:H>ä*0/D5;x3h߶v$.}_}*Y |{p֤+'.X+7't}T{m^Žݝ^ ?#Žߩ*ٗONAs.ŽI9/L`T?xngpKFI\Ӝa Ǡ}ԇˍFIz,f2՜)K#GvAFԢ}Ӟmav{hjghnm'ipy>F{DD' *5Tu*W=y5$2^Em0mlǯB_ $Y+ PR΋Ft4rEFSE@E[.Jd4XLט JƳY0>@ƅc<$ıkt0ƿ՛e$x`A|4ꭵjA `Rc3_׎Asʷ*wd^df*VSvkXp]4㰊:tTUk9f_XN1H[JGsC[R/gR>Bd4+i:Դ]?Pd *)fKJ\JVV{vME晆R$~`kLXqű$>*jݿTP'mFf.<< XRb/4Ϸ/V= uE O6yQ::&'IXfy{aSg*Hb&8g61N͖a8u}F\ ~%t5rXbh~_֟O2ݬHC!"A|v*mtR 7CvJ~*/ܵkS7wZ~N[#݂=˱vՊйkӌ(m4}B$lNyT+wݍUhd^4I_M}Qv(+p-hOoؿ nT~L~E&qY|u fihܓ#ݐY4 3}(bϽ".vfᾌ3b9G*"~[H7<8㧨@Oj!NF;/iNvX#"R,3C92. Bq37XL@O4;=ƒ[:"  @*>C}2,%[&оL3̃%MMEqdP 4m=|}Av^mu Io< ?/`EptMa? f<]2){Ϯ޾~onzp=%^|Z+u$\Fмlx-Z!W,ž@pg(kdh g])~6yb|DLryZ_VCƉ2emfRI{>uHWוlfjrG\Us_,blyq-}u0l|)'vwĔHa= :$ߧ'tRE;? =9ϯ p$X-d.Q4`l}ΗqN{zY)raK}E8p.|I 7Ғm#Y$gr{!Q.֓^IdSj}MZѨ${/f у)GB!p Q/ %H38bMǎ^yCYScѦ'}(YsJBW8>I{:񙽀$Wp7Xx2Lɻ2v֒MBM͵ N/Xm`Xlq^I?)%̂$')frF MpAEBiKJp U7"dӏ@) H:{g0Es`WOe4*!EJGfLq]jt Vx/!6%&Hj;N ȩW窸/I$|s*VSQKǖWS=2*^B i~xHDN,&+fn\t`I^Gӛ-Y.Ϥ<}Ŵ#E _|1brj7,|k5!33߷S}2V+~2-{{^?yiRMƿWVuP0%_$f_-5I[%Ҷݣ߬?i=f4sB<\`N%Bt]9Wb 6ۗ7\!R*v]rdE5]G|@}Ydi.KU+(~+ _" +l,x,rZmZ\6lQC+=;hO5h辰UѼE˜PO_&|X[WY{(4&\S׋z@ O8 $%kԤqTeT앭r@խѓ&lhՈ23X&>gjDTމ?XZCBV3@aZ;"s4*~y蚓3c;>MH[XI.4qdtS_]C{ S+?/3*ŦVAN|}v=zݨe>ԡ,"mxF|HWr؆X_pd>!w9MCFYRqU{5ÔP^^j<-Ia.) uA@ P2 P4nT S_ھж,-S9)H;[:T_Iq|ƨJƶyE Sy4zzM?3189p~2xGVwp,xU; 3y.\f૭F~}bUww i+Q"ǪHoa{y% w0X:I3t+b7i3C櫦y 0Qh"@vjI?-g`F:g,sݨWn[30}'r `yL L780λgB񨥕6Hk[f&bNܠ LO$WPq8kܡ_]P^ *ċѡ9szUUZYan~=aSʟ(6LS*V˹&)TMDß骡dcGL[ZQ^]@pgs=`BsGxoAEopb|Ɩ4FSNջi3<6E:m9:ǣt-N1$κct^ hS *)2}zAwb\/vf(KLɖgzUU#nnќKRM1p2]9ӚJ:%z:MX vLe'%^@?A,>ʩ?bğDW\:e<:,}3&L7=b6;axlq^pGZ4HO" Zi%<3 y)@"H\jҕOӤj{{#X%u0UZP:y!&F^ՐVo9#wԑB 20 8ElkP1/PŸQ*T{;譥2fG%GK+pJ2BUAP{FB2W1ܙיwʰo@Γ,[VTYJICi>E`.MLJ؂fybm65觫Ra 裈ȮՅGBP=6:h?&.WMTR7ΐKaOzX#;5~re8ӈb as+/A_*]i8WfXltn:l=LdpgxJ".u$"nf!?H`WԦkSyJ4)Bh=TچI[ӹ%YGnèⅱj}h_TS@D_(И "o4 q7'8 >kAH{o)bNdY]LE!6罓~׿8~ꍜeM9WCcx=:M\;ςu<ͽ"{Lnčhyf+xlz>u"^[&Z!qrdM3M FMؿ/$@#y=\fFxw̿sQ;К"i1/CfjЃG3k*7!YҖ oe>g~|ZG'! }~`O}\ִ%#OxNzQN=7TM~ߜq0oT}7Xay!5AxlfE82F ^n+{ÄtS)[OU]m8GJN*s2@Y:OpXy!J)pBh5ތ *7-VT#$G(zOS),~R5_˨ BTEV64t LD+ Ym4 !6MjvRIJ-׻ES uB1#b'[ͼֱ>G75z]]:wm߄ٱG84y|yCsglEZ)eסSzx][?"TʻFA'2qJr$t e8eijuB VN-նjEߨVWE`.p/K,N+i˻ ~1{?Jˆwˮ/ _y m]<*mi&yMzy83\5n ֪)U"\ 響5=HgHL7?o5Im&(3bbX(-l`ş\KhA*FCZA%__% FVs""U e"FozI0C2j %;E$ %$ xwYUhS&Ve;b5徼Y/!(XJA .EQxAoU[MT:!J߭nMQcwܬL*mD>tl~{CMw$5-A$Uc@_0Kx~a?5apbc;2@ɜ$siX|->XSdQe` QVNiŠZɋ c+\I5Ig1)H&/t6 6Gg6~p+P[V6$ o o Mv; >tL2FU,\d]tm^8hZ {Rq5źʔy)Rdw7tiYY/bPJ!"*1G+{ 3_  2_>֖*p;tEHGQGY Nb90KT;5?鏏wG  \VFp)BwuvaUn3q 9#:m#>lBQצ&/x}̉DqZkl䭶 p=XuH$n0kFva)vG &zKO,1d=o B;Um!7rX;ؤ"){m٨ʟWba'*Ԫ9P\v R?eVEy Z}".i8]ʏݤ8?`6, b|W d[8YGQ,Ző&^P#:6xk &4@`).$`5Ns!}'yNOTqO+ ASkF,z~:PJAA2O{V],NRb48!ST̊x" z&O{<`+\j #RR)"X̍Su #I٠8k,÷A^NR[z"mlMfKаLO)/HeaTL8RrRX5Cm5,uMQTWZOR/ϋhzzJtd_[,sVjf- ל*zO/pyrJEJNoDQl^±|0"_cvLV(S)7DC?| W˜ڲߵB?8AFI;KFYgABT':q h} dƓe{]&W 8 N%qI }}Z;1ThᨉիE!k$åLj+SQ!6!ޢr9:; r,l [$:G{wrEiaO4A8 +ÏK&=^E؛8P$qlͽqxpfvauGgoF@,0KrDz_Oeڅ><c=_S\W\4_ Hw`5q4bw( 16`Li`[' Yo>ВgM^ 0& 2[i+dc>ߔ.0. kf)e'q108Tf?fm9h&om"(؃ͷ_dOKV ጗Y 3dV\Dhʐ&#f6XT>) ZqDpfVYqUDVGE0+ԍӻ~vGR uTaPąWWe錣⨜KFhW;X gaMqk9x&R-?f]p%ebc^6ں;m$kK}w]uC#{NBRf׺LϢ6P~gA*ǭMN($ "wdOj,/jU3: C댄.Sar˃a ]';[G5-h{_6 PD`w= lj?atL޴Cro~iq]1fOk`R$̕ g2MP&Ci&I4E&Mqz#=]sO% ʾLбuXZ~~lLv&P˨;8G?^!͒KJm fsu`Q|!<>[;{&Q~)LLWBLs# 7 >gA 7jszyPLIy7# ^x<Lv.## [^̐NY,We;`?ǹŞ׉EA&1zX0{rN)]k0 :QIvo[bu]|R&`gk,9=9@6Gҕh}Y?>{7)+ndo{,Yc.){uֈ%bm*zs,ZQGMC'ͣvQuacSE%rcH!@023nH[a0֧pUCKl0I<q fɸ4ᰖi7\R9k.iE;:L> `ZE1"om&Iv918y{q6r{ejXnmϸGyL@5Z*BK2rWt,x6.PM69"+qF ]%n][-UGvbpT߉'sP&//(u:u`e}"5. Ra'XAb1ߘ}xyj(4E]yn$i WEWķqo׻wGBwur`2ȷд86.JdCnj{3\m*n]i}IW0%%}%$Ut2k-z2&DՔVwIUu@'$㎪ZZZ:Hw'8bbQ6Ns> W;9㶎08'Rl;)}]~\Y=KYEV)78]bPFzUx\u^`7-)ip;$Ja^=%UhK>$D fwz@Ԁl9eӐ荎{IGc0}nw# zx(xgn"ϾQR*+!8UKɟVAي5ڮZ$VaW;?A=RW5|CyEmIoֱcUTFOa#lHG}i-A7<};Q.>t놴 ls wوʺ}7q0 %a`(sҵ.]jIF뺋KߔUcpU$K&$*>6vŨ`NV=Y*,x+xж6LGV G}Nʩ`uC~i%s0KV{T pDzOK(Ҏ@n3jr5Ͱ %V%;+؉ ,%jR9O\g[ҕ΢d\D<61uy|i*<a3;ħQ_XA=$CoNJs2ܭLj._e%g50 Ҙ$cKY9,9@6bmi4,, $' G i@zu=6\4L A&#K.8&OCf&z2435V G dhۀ6uDH >b6\p/#9gLS~1*wHD烉y05G j4^HL[*yzNɂ+r Jl[<_}ܠ/m9(bB{V߀qid'ޗ9ʗ.B*@ ~BCOy|Rt<s b|pc?Nn䧆<VS14E&;=HA4ࣥ=)[vO*lѠ_ML}jʵ@nsa"?ho$2w %6~-.qj GjJя=kw>ov4@fPA^ `a&',+XJb7Z, fx$>Kb3huIW2ʒԽ4D5$3 eq*s0p}o*M)j1; W$.Z\\܂h5zN r\GFO[h&ђ&l¯,[ឬ-mBj<8OPz-XםYqk6k0›C Hr $1.4,f)i.ԗj䖓fĻT1&GP 97]00KO3MI@7J ]Dc}MExO1n9_u_2G=a 4Q!ЄI05i(j>1Ѓ&%- ss#!B}L>M@VHC3? [i^<^-`Ç̡PGgʳOLHÉgxO)y$Ɠ,E  HF` K l63H3fU7L[GXiFʆ!Lo˨ ͗P'.`+IR+wXf#3~#ܱl7 S* p1BԚشyYYEFsz5TB,xW<κ0_Mgި^}lw/ϫM`?AY&mf*Fmr16l YM51*iGV_K$IRV Q\7D*d)Tx?RTzPwo=S>+HF%謡F+1Ib[Xsa5AQ`],bTFYIV 0(Ep_ J<  6W# wz'>1 f?%_XYn u@͋>Ebi2}1`WDWR:\=*n~ʵ+Pnx9]hG,k;(E{b|k:QgIMD~5QF5vmskU)kUbi@넒ZDE5,v!ݷ KBuz@%Izsf+nXswgL NCzk5GxuK@q(TVb%ŏYU=E,D~3{#bP㬛ٷPp#6.-BD{`">zvVfN-jO9Za<. IYׅ!&JUn ]5mu\HvDAzVĎ]W@)&>]ԶC9()?h6'Z( lBz`h\| KXpW= ?z;{;bBEo-QHAwCz{M:)@¬LrAG ֓Og\.g:J T#J|#Nv( R%dy 0( Olּ{셺̸Qfԏ_`b#5'XtԆLzAS>=]%+I3J /+6{VxlG@;ɔ&T=VU6Eޅ?Mhaz4) WجnFk׃77SHm =,rS>kOSRE͂0"U%ƊBÕ1kS]]aA~^DS2h_W_wEǝcnj 萵 8ag>gpPd깷#u=ٵGoH󩸠_;GA'8AS1 ~c]NS^) 6 n}$eQLarVӴzA#q5Qu͆ @i#Im '꩗T2(.r%B^|z |h4qwb(\-a5(fF)4ɴrx iNiV艴Paҽ)A:pc2aCԾcTd5&Vfz {=TpV$(bB2Lj\ܓPZeT\nc/I_qdf;c d>S.RQZS:48/h*D =zԼ*lx R°('QDJ0EKK  _`tH*E:'QtMC‰^!0W8H>PŧU*+Ō(ڶ XAftZ%⋕ &}:F](m2L4wʞd袲bFsv0}{\G{׽<`۠Zg(y:iop?'c+VZYp!#9R#Uת*Zc}D*}c&\BQ~^kxb8$!8rAR.Pi L135ܮD"u*o(l}pdZde-<)A(38l BN(&Xvoy&u#'~IgTY\!ݑ{;6&PH!JqU!7=41foS5e/=6p=_ORJ5Ac"T#22F Jqu@z9mMgWv߱k";n=qx@<|~>F+P&F5䢍\&ͅ<{-5Rֹk>Jm˕s-})|D4e@|"zMt;w(m*ROcMNNYRdB/iڼuضRԇO"”'yq@mPk)i6  ST<$Y\\ӔB/{j9ѯmIKKe0G'2@)ӽ{ы5k-%--qTHp< $\|GJYR"y1 <0a $ d-oo.V+.>3{3,̀vI+!ƀf lUL]ĽsM ]/@eD'$pHz/=7Tsq/A,tŶK02ÎaDX x .|[ovWm^e'_Mӆ*%:Ed!O5{vllH"S[,=~ Lќf@Y|SNjWͱD7bytD9_=~9v0Ѣ]B-|?=6mbUZRDjt})o{ Lü>F:@i699ʜ7`ֺ 6~+*'GT!~RjGQy ذt%Q/$t(@rX;]d|xfc 7sXX )~ =~bÔxy4KT0ҭO<+/(K +K𗂲0oAXXd%Q픙[^~h,m;p 8 fL,cq.h4hX-ꦜ6q9Qiۦ5RAVEZ?%hf: (Z%N0/{#¹ҙ `n?@H` E2dOo-8)mH1 wQ%(\F 3@k7p/^Yn!^^p܋ Wt}!eai% !9?hUb:~tcQ!T\goL5Ķ/UUe>sr2` : KbtR9vT' bC tg- )`>0g1`ΗzCvZOfEnk$Zx.̐5S<f5f=hM K/i6{)qX/=CQ~SC7y8|o"(/v KjG`L$nLԔ}nɉ$ E~f"G=d3CCmaa;Js,ƋiLc%,W\':7p Oz?W'Qw;YD'+:4MsLr⺃zY7IPo @hҠ,E]6\9Z ڝ/| M }@5h9<5 |&_ `\ K@(8D"/2 lw$/Q(pžix@Oıb,QڌWFOp:@]ʕ/7,xՒxa 0~I<fX0̋\yWs.k5=LX$n;$b~$1Rui@& qrpOLqdpRE 9X/_KļHWnJ<]f:pSa>7 Hh%lDw8-Ck gXKFKwrˬp_'!G!¦u 3PC i6M8LT ڦntA}2?ȔW}pz4ؒM-('ޠxmԼ5%n&,bJ#͑MXW 1 "6~yVhDDT3v3ӣyWQAhDJ~U5JolzŴ0!N41q#joxC݇&݀)6Pl'0ԊZuqn]5tMwpxYklH"LcIsc1s.asO{b;陮0\is(Q/ ]27!Tq6Z!--VY %iU5s2B?My[0/+'ZN^usRWo *."NFJˌoN谈ʈMQmZ&~%;e_ PuC˟jlkN&oLm@DTn=+LΘ({mHJP/a+`[H 6j-9J|}Ne^9 GB{$=*&ZcxLԓ6{V~KB?DBT)OHKX長s:!o=(Hw swsT tj㥿?%?+q[1~=[/h I&T]@T/T?`D/:kƤ;ҩ(!Mi0j.'%xKT7ba+8.ƭc}Z{V'-|Zڀ%X?#~MEz@ ? .g­4M1 D)#y\ 6tFO5>~:Ha`qcM"Eq{,ŧ-DlWv+c5Kmu!P"/`nPpg>!X~y.Ku{|m*ڍU>uH 3qfMS^-בxFO̍.\[^[]O/KL{Bޘc8ZNj'{E0.zePzܾ2xoAP qy=ȝxIMa=qʵhۇGjNh&i:L΢ fOԴAոuVup ڱN;?0ETұ'>ef 4svk6U(\vQO|M_,ZH%kդQƴ#n@CiVCdFL"˞J[|:ȋx<B> !;+05~VuBL-׀O{}~}@O˞Ѝ'/%Vj r]jf8 7]Q䏏Gޠ==6ֆz}}:vG'pVyNm1qg6WUHƘEt9ɩ0 ȘnV2tu)˗jsPnT@xCRUtpǚ<@^ Zz$A@4e?LtL 7[xE?+w-[cb 3)cvbC{w{ V>¶ԏ}㪗4TX ]æ_',bjiKTU7#տĆvBxa%jYm, z'vQ̘8Js;JOpD8B .lotEZb]g<Ѫ{a uz/2eG7J[bQT޲Q/I(0oh aâɎMra?]OQvZUAZƋv B0m%pW i>/"(4U*>2T[csƷ@c~}IMꆢk!Ej"_ ƬI^v.wOe$!kL斠XhA(ZNye~Α?`Ǎ*.zZ_qnt xTkPTec] ,,,,,y)vX K`0i帮ƐnZ)j^sIN94 4:%M~h(Y?59?y[n46إ8Prz}^Y_zBMt|~@oetX%5*/5B0y+^[D&!3$3+ FNjXNoǗ@EG[ռi89cW=aAaT7#{K rCE7i^1 PD6]=u99bbX%QE"TSͱȵ,H=dX ur~z1XTtvMDJ{6ctυab^0uƣc r⼾wfU2l~`[ t-"8f[Z!c}Z n p .H,(q&V xX:\iFFZ*K \1Bc͒ "?1B͟AZ{f6c\آ }kwzz_o;a<覎!)}HDU:>-Va(D,PP ݛ-C r b0΃@"n_jÌ0Q^ E2"xd`K%& *a v1U zg2~4 ~䌣\6=ThGEfkp=>#&1Af' T ov\:}{F59749|{u [P<L='K遠{@IcQQbVJjYfrj5d(dZsm1 F JLCŦGk rE{0 M<(=}#7;ɂ{'g/urR2'"_PRrH|f^JjTBXa&V &g:}wFylB}|/bM⚼k*nm&Ik1 nwg:h Uz4x-_HSayz3RN&1T4R]"8pk`Az/^B ;z#y(uWn&Xǭy~S_OJM_ȍm[9ȤS.}2k'YT8A.pfoo.ʎB}aP 3k 3&DNVP};ih…nސ{Pwv 5mnI/G2sx$3xOBBi F4F~:U;"t׶9=jNVZx2[C Rn ) fse[w$^5ӨuоƂP^黏i;<ǀF3MzxkĹ<ꛓ47qer$^b\Ѐ"-}.((J-QU(-OL+O+M-J,IOI-LN-4 ZL,~>>3O_ʨǟ QY\2}gFN0N޾@ez_ #s'o6 s1# Ģc&<}u*PeC\@7[4]`z?#d{י2O/23&;Hn9qیܓQv0N.2{Ezܵckd`LaTsDgEb4k| f!Fe'0fo.}Qp!&H&O7L*b,̤?2#XTs^&鷄'3O!4] #?˅bB٣<"xysC4;l\9Dkל_s2Z+TtxSLeAw݁q' ~pw ډZ,v q?tڬ]jevpmY 4kER&뽣6+~yw^1{uplC$~h fCkJ w6kpW0P Z(UVq,Q{>Ҵ@_&h%VkjuoT߲~2_E)K̕ DYdS*'х0I=mA2M6(ZF1{:{F"q:⁜5LOHDCE~6#8qtw&P D`h, VyS}QMhJ72bL=l ˃̀r~LqCs/K =흪fɾH{QD ns}IaNWHc9lX|V7L|4tn6ur@!ޣ0aISl%S _%9{Hk/r# Gq=+nCfrƓ|~PTs~Y4st鐜bŢ0ϵZʷ2;8faI~ꆓ^*FM*TK 'n0zg\%e*M kHWVe\k50;O ݭsFI<7NK9~)b i\ V:MJo7KXoIpM9Xn/OyH2ke0+fI2!4f1ХtmW\ZWs5,_|D[m̙>kO^476^RY.u@u,u$˥.9lf5r֝9tid%5A?`͕i nyd”t R\_W322EJf xx{|Ά-L"ӥę4I2r2iZoe $x; !] \`)#'P 5_ 暰^zx˹aUM&O2=g-#L 6/c$#ىW?KG([xkol8a%12qn8-tn&:\Ljk&[6 O?$4=*#Lx8_˨ Mȵ݇ p%7x0\Ά-LO's.Ô1T+ki^QjL?O$5> PU 񱞞Q(*(]Yx;Ά-?`:#v_B֮ 0xOLp:_`㌡1S"˂X b&+D2 9Li&z%`wL]uD/}?yOm*<3}!?g{} uٝ9>"bbwq|jTNH+<8K(%P_YW[ @ޕ#kK'MPsZ/UdL.Rr_&44%6xQfyl*x.MJcJO\Ѐn8b~R`We.l_A6bBOC2ZOfl+D,M5h ,-%WdTHNc(|c -Rr̆SPmnZImhTeY)l~MX`2טieng V4;WY3fF+'PryMm[.Bjq3EY($l؀+$΀ӈV x Phf;jkp$;5"?Nh4 l cx[{$熦0rN^qtjF ҂ԼԒļԼ 50N`a+LPQb;۸'>5fYaZXJЌ;۶xq1=FTx>zsÜ~aAW\y>i7c{7^Un;Pq1|y_f2(%ZXx<gC &m閲L1Jn (xu Ά-Lֲy1levZ %x]n0E,$A"-m"Y}QDmR )UM!s; ALބ5Z᱃ޚ3UcRHjsX\:^iNh-"OTڱ\2p£ ]8E) 7E~;QA >^G &MTY׏ƂrL#F|5y3p9gD=#,BGUzC?_HfQT]|e[9/]eb9H7o7iIU2itGćG[_>o:g)/{lLciyEF[4yصŶbM1!vUۧzǫeȓoEL 4 x]1 @E=!"E⢅Hɰ;,#y O&D]sp&U\;fa#a OsaapK6݃.Pꅣrb>HyJf,o,/=; xSNIMKUs WH/N//O-MKLy\P!A!X$ (5H8%K93/94%UA h.]zJ\H%%9y mE x]ys6ߟ;S)J53zqTU-!k A$tXc9N2 _h4d}lMb8E4B6NIiHF,%8!|2xC!q.z0Ow?r0Ձ>x6O$'Mn#'>Y8#r.!e)ήC!NgqCJ;$4-̋Y8{ܙM O:̼$3 Ar0a6RFaiggQ-Ÿ 0;Y9힟vo#!vv`Vf iZH%cS2݄4dN0F~k~́Շ6gSvߛw|zxdj`Ct05Rd/OW (̀E4)|#4 6cf5a7}{` y)ݓ]]4iZ!K|;s7rv+?ΞTP71&PqMA>9e{cY١O&ɡƾ^)xKMDF0Ҫ)Au?OL<04TÉ˅.|,I#+#8 ,3Iz0KfI23ml$xa.!-u `,%`U1& 0 ʴ&JJa>\OuT 6[qhz3]u?\Az(h"h-0 3?d<6(-G\TELabǸvШwDiwt|N~<~R9"/Cy'%V }2 S!؈BFI8"8d1BR 'pXRU>Ֆpl,; !URT@H$$Hơ YEV _%0M4 IzHZDŽ 7(5ZAv; A~r ANo~Lp(dW^="Uۿi02987G<g N&C#V'*Pҽ$Ig|+]uWT1ԡ`q!Y9[B4d?4A-wcU]Je6SaXR=nY8:xBحlQ`4"ÉưT+X,>8OA|OD.sR:z3pB>[ub ?Xij(L3F wd{.V,p9G?9nj+=r[ck?ik 3͟PEZJ~sYaD}q4c&aSXW+=NjIU.$4j1% X]dcKU  SṔZh>Q%rZM#MBc~=svbl >J T8.`BOM!_Ь&It߇& b^w՗(ecljTu0$׿r2%|Xh!3GLɰB<9*D) ¸uO;R}6jVŁYe1~*A~;8F1pҩTRuB*x+1pAF axL6T$hptf*C֪SM,t ]%WC)cbxc %0 098)%V `,,'x!A ?uEJVFHuIZK=ٺp6 WM \ Bb]W J(\lS4@,TvakhׯiIDQmK-P,_+lBSr2(gY,z nl"\YS~1`j, 1h2h!K֯2/ԺV j[l)^i6*+ي(^)R]̃gk]3oj*R6t!;~|$8nto`/!_I5EF`[hİkEĬ+YjWy Vr|V) Χw|E ^B6њxRK ?e"K[o^aNn:O߽\G?=%pf"@Lt+&u2B>POZmƪUcHm:Z7^Rl[9/\_<,r`=_>lQD%, F?M)D-FpnD֌@C*Ŧ1-piu&՝i8n__'t'S^ЉaRC^ 0 iO%^@-A=#Mi&3P1Y@%6S d= XO k5+iQ2dG. kv(9)ڷ2WjX,ExtEХ"I-9 QM'hBq'LV]߯" ^tSY@%nP؜_t/ܮx X[0 We Xtϻz j4ʜC}s(0װ\44}KqزU9sKCt;yZ& Oԡ-jfx+k( DIQ|1E}+zM_ :,턪CAkq$ݥk(AΏucyZkෛAX_~qf`駇DpIaLf:_x} yܜEzy% xXms8 *@2S{;ήC;Br@2'H.K&a߯%%d5Srw_nӄVW£=E')|:=U ekaH8 mMdnKf*2*b\Aۀ'H(piD9񨔿'ڜ)d$#9()fD V"pǤ4V½dk1jSP4ZH3BrT#x0̥\R ^sZq\ L (,i$>d{@DZH(y"| TwQ9k{FȞ-HL)ĒH@bڟ|5|hd 'gH%MDE0vE%\٣ddhpy= nѤ߽X#\6jg&JF*],)إlp1O !1sGbπ uO|Qb;=> E'Q KXK΅Tʂ'''?JT3G >c~{^+,"WV!'ƪ6Zcso,b/(↵tcUt|vo{s,s-I!M`8gLW^+ h % Ȫ 4J|8 gd_]Ol?XΕ5zfԿ&v]4s&7'ְkC)0C["HodtHTJ4ѨV1"VYS/&,8M$WnɸpBV SL릛$~̸^y"ʝ;+M(bqB]qqrBra)PKIar09n@Df3tnt5 4ٷHO&>n ]\ؗmW+z`N$)s}W;i=:d ?(fƯ0 ʞ!]ݙEb,I[tV*4 R k`URӱ91*g:>UN G{K4'x HھX"+wOQjw7 j6DŽEjhmf82Rwf}UjToK[i|د,R!Vc(wNݭ^b Lբx8TF8dXEM0$ӹ@&5Ȕi\bנQʑ@8 Pߡ2Ժs{tY>N Iɜ__lkȱy}ـ\sn n&}k9z]Kx5725zD/rrP_'վVKS0Yֳ䊻#*De-!(I͟ b*n}7ep`wyZ xgBzEN`k0~Ǩ]L a㽄ND,:0۴>/ph~(,:P_Q#^ $Is8iR#3&m-ўӵs7JǃB,7}%6#e1{tN/͎nL1t{,~[˿$\CvZ{ YqXah]6 7gZifN NLFnR#kp*h)EHBÂb_((7ld 7ϕ⯯S gs uCAltzҴ0Chwt5[TTDYP 1ǜ|#~q-(w{Tan:7tm)=\fСSJ0ʸ^դT7aF!#Q'X{1F`\xm>G^y=^ A<ź-Wvx= 0EG;* 5jU(PNm5z#usr=sB \4" 5 !EڛQ<ИWB5TqvA J9y< tB*[- 9dOX#xjcw ˫j0PÐEu%8>ezJFa^}#oA_鰗 x=s8_&@A2{_ޫ$ ՕL[mٖ!^sVտ֞5H"ޔ~ sƞΉN&k-yvΉ՚̶Zlh-F4?V/=_֩?8$\rouL%}>g2S Zr:Xxre.{MqaN)cSxa3יO)a,ؘ>='/ޚBħS=Y1={A8po DI$o-u <'m;ۢ.Ą[T&AFr`3=P ~?cHMfO/1iYNa9셷-$qKF&&Koi8&W=g*@˕cdo 'Ҿ_a7wG#r36yhǽ]{HQE(( qJvX8񯰰 sda>SX`πI,틇@Ls|8&$njp&?.`lٜ]J|*]YO)Z;秋rR}zK kvZ~ߛMaӖ?{o-MלS?\>;dTtf@ѵ1wwgܷи펍as{ܭyuR5_F?ԠEm9b~Ư+ ZTY!򺽾Z>;H|5l7=JBiGkxJ4k.aOϓ; 81x+4hQ1'U6y%jޱnaUj)p?l1NC،K[ J4FGөgx4!X l]eE\,lk:~[y+HqL 45YE3vfdI Pi'k6AM XiC՞.׹z }l[2 qeIqOv)tPRUB@+ur#LS3 \# W1 Ð KRRLb"xLo%F v-\ھu𢈼XbX KN1:3UU0zɑ̡Cj]""HBbVLScNÔfe6bO)K!FG2 r1}i < 67-H8 \\ёO!7Q;':8bI@iZ G#x1 L^C? z1v</~Lj o~a'D~' YOt w~f3tj8qhD&D ؿt~^#YRt9 omKx[y%˔/cҎN܈ e.^d!fNjp[vx2R\=6B縦YxWQYKXt6\jR vwfV!2\;W 5&]PO,P?#:C NHQW R& ASH:mߦ*&%d]eU.bg.AEmjؼq:,}fj.I2PゾG퐙Ry`? aX@L!/cm2@s:-IϦonpB@`OůL3 A1l2B13"UYC=0ssi2ĉ 1DRKtP%Qe\5ɞ_z!,'| j3WdtcZ.\]1ݻKFl_ A9^囡҈A6\_vZXEKyh)3TIl]z+]4aEu<`m7,,U[J_* ʆ7E@M p4p?QUTᕌc]h붇QnD5{z%|)AWw`0ijGe(J5yǣS-jMc1Odz'MP$bʬ4_!NA4[!9@d S'ħSqJw*it=[I.e_H/\d m©fMR[ }MV@76{q!ekL +EF~a F/Ux|}s ?˲-JܩafKm6 ۻ%7 H@< \O^̀?1 p8ߍq{m zQED/9?iYWd8xk8TzcڎHbz"#pkIfrIFZD4 o-Wŭ$ aDT%|cX$owe;7p'{u\ԭs|%5p13%rC` xTo]q r˗v Wu8"[ W^eG8kק1YԾYFq9%[.'cT6+y2FFz忣$qn(%MQSuKfEmg P O"2^ow|di0N=$ɂ~}I6|S TtTy;M߽eXY.6ns|X_Sx?_uŞ^r_t57wۑ˥Z?7kL/QX*23Cn [0udol|x5PLkY2E.Qe{s,:jp4𗢶qiH guIyJʾbrީ *Y'Sh(%W6DoZ0b ŝIV3h\C5/9o50]2yoGR︓٘-W+pJX`i( ;!s~DvËtR3/Vh3}+p@$xt)O6 k{\'2{B_m'iTvPtNT6Ɋq6Ywe#1JY ۸(ZH\+@3hDDbej G.b :xO1['G EٽFO2ctϾ׸%Ή|t\f6o&ρpן~N= w=~n!uW>H5ZN[ L/zƸǴ/3nИL;Cnis;hv|3IIa,-#qdQ!2ڰ4$*ڒgzY<ނԩ4[&<'S 7YM LE Lp3ɻMÈHNqzp;i}T_;s[c!:aѳ܍-;xyQZzjOsWҴv-| O Ȍsˋ!c2 י4"S ֛*?U-#RԌjUzZzUZ'S1AUۨY8: tfH~sN(F:NG?/EϘqS{j !ɴ=9 &i 3 k̛noA|+*F, lZuI- mьplZn KϜr%ѥG, )L S tq>yXBnΎYui12}iz˨,K%?љ62*c6Im4Q>w![DPH#XY:b4j &r *&WV")ä_P[>Q"T{ty2&)q^⺲6'LW8s1Gu "LE V&qb!#P~&JN4vBcJks,x&(y4PXjGWL_ӛX?yqs߱lą{RX3<ڣaԢwsjN+UTݵXhŢ7 5@IaF oҞ( FBQ,Pی1xBnnNFe("J -@; \yC8tѫR1id |jÍ9^M͘V/@ X;1[< aL3{$i@S̴SqoW4d^%](Pbkȓ 76ةa#g&QՔl+K)g=t;^/Qk#C#??c(KNG4ә- Mosɸ}~f19~Gd}e9}Vy m ZW:&+sJ! *N^r– eR"ۡ*{٠0iN^qZC.,uēE^ʦRµ-DáHBP$\mA4eXb-pk3)>Т6ವ=$uӪ6= c<gN!m1]͠L8ӇJ /1e1(gJ)K_9눺YB>͘L#1&czx~,tA9 V~ ]5<FUNWrgoUAv 1ekAH^MFUyЦ@ZބxV0m@OꇿxؗWD:VOOOXXUi\Lb*ҹŸe3͡=e)Hh6o()9lpH(S(K>pƱ2KHJVLXZ[ђ #sIWָ_kzIӮC *7Ț_*8BxN12dhE˓MƲ97T'ee!J7o ;Ag1blէR5mjꅪ1vǣk%hP<6r4꾸)E-] :`[M],S8-4n ,|3a.Mgej+R$)7NG-c1IT|&@;e L<ц>B)/ο5 VCu_$AJ bN3[M_z(:09iDעJ0'&LJNc~+ǭrޅ}_)YnSc{_ѫLȮMe}@ڰ9ʳYT6¸i=Ck>=K~?{բ&nx9s x=K 0@s/uE".Z.\Z`LJ2YH^Ó)vXDؙM Itl-l2CZsd>/C=U 겹}::Ȓ>Dh09,}K'|qs89'>xuW[sV~6b'y4f*0jD%0BGv I{vYi)F^eۣn=e"vI @-dr6/uN??>T j+%GY?R{!Z/I"rzٌ>-iⲐ*/Q|,Ey2\4i&-T$xIt2d^dr\)Wbf8 J,U,2?UYT\dbB,L 5)RF"`XGP8VKHS*Dtko}"H&1KJ_ &n'IO}f63||#ik&ct]ږ߲ a)pkh]Gà )m=h[Σz}ۂ-^ `V]Xc%0qf:]ٱ$2l:Pٲ =4QA:pࡶ3O?c]#]?v=]-oB,d 9zlhZ:,Ձgh[2YqdxJAa>h+L:FL&q ˤ|*^RT "i2Z\cAyhMna?0s:FjO 8GEAet\P6}qHqP1DV@x(A}[fxߍ8|S&wQFRqю:"jj*BW. qW$+]7_S9{MH˾0G{6<DH(^6?Bnk7!v#ݾCPX*D7DfڦǕ}>׏4FMpΐ)R9bjC1nJ ]<&_8:?H65r?QEI7Mgj~Y"bLTRd*}j{RIB̍FOHOCP敝jj?^z+“es1v@آ1V76wxkHFYQY[y$,r*M r{!RV:Dz "AZ[nv pe!!)6ZJ@'DXAlZw,9a65'vHCi1]i /G!iET.]<3;c|!  rJ8"8\ 3MUWzEg VHKURU*7͑oeݜ|kT"tͨi|\$EaTmZZSءZNF8 1>!Gpε*"AT",oD( xSNIMKUs WH/N/JɉMKLO-K-R* q $IvUpE~A )A`eU\ʙy9) J@#t!FBPBRPZ\[SuGVx]= @~O1T6[_,"ԝ3s$Ɍ)T솗2_gsؠ*y'P\ZG~o2>RD/ Cwf:)q vP 0~N{;$Xg~^ #A>՚I)J! Cit\sI 'Kxs?FkH{p|O_SP1(oT_x=wH?E{c &In17I&on6h"$Vv_UHݭ3;s{z뫫Nmr.;!;kydxIk$2o؛Û&a&}-W Wqр9\v.hs;]y1D2r(%qxܹ=!݀DtIͶ %^B` #z7IV$4Z$a.F \og7'CoNo]=M08!ԃQ r E1H~ @nu=.~6p^ @<'3J1-)鎾;~9*rPz{Ar#tO LdBίƤKqI E((! qAc9/dR`zK N@\? l8#$ ¤Eb*I6o:e=e0{O߼`oap-W5˷~8w}zz|v/A&llp:8YfAoȇ3O?_p.E.^HiZ\ᚶA/X퍿]zNIxHMh+7D &ə3FO?uǃOi6H™~;d{R-1@x1 :]G-hbqpo(Tn;O?x@̡!]ӓDPnJd0),|č@q64'J-H@SA6ƞ${^Das4?X/WAq o:.Adwnںş*jjxh+3 ?6``'wwGn`=9( RI$nB} tbWӏgԽoOcV;ucj Fk̒ML_O?wAЄF72{w6c^g.]2):aga_Qf/`{,ȭo%"GRLXN qC#X9gG9(>"QDE#n\kレk B-$GGKDN;`Zx#/Pw8|pg^i]a9L03V8Z7pd?qշTg'nކނ iQgqxКKNߒWqR ş<@aD 0?4ʙΐ} p>,8l=zMK$6| >'d)>%]Ԣ%k[/ؚFW?bm½1;F4|8'$KC?pwa-ؼ&΍),x4Jϋ~؋R^W.pYE4F9 :.I֝aa#ŵIᡊ6bq6@p}Єu-`Ho*,&Vh te ߀WYpPE:tY&"J>d!_Y-i5G58W' ]W/:7@"L:_&g@ͰC0kX&A9,_:` G֊ gDEȔ2^`(,@w lA gz|ՃH9v/Sʙ7ǬNY8 eMEœwBEB}swKcJ܈ PSHsv@ xCǵp[qCa=t炤xJla/PX3'Y3;$UMx"5AҽP-WՉ:OL^5ؤŝqx޼"uwK.m5;VGW-5a0*KY1(D悷Ubݮ,Tn>y7mIRZ$I%wu\kE% .f F[?-Yb#P}\/.zbeuOr)7I+7^9 *3J,;J/d i>PXJēs)}irgF5͜$BSs̏Q* .%)d=."՜"o!X'hq!Ό:5c)M6J.5{Z)č  D ŢJ\+tHJyޣ~ ]OgT$#j?ۇZQ ],j'k;W > I0}o#K? ,\*`o w&i@hߘ͍}kgx"&-'>22l@Y*4 aVmlfܻfN nI!ezjRÓ3 Q^3x-S킲ASfHy*ALO:̤㫱>u3;Dm@H-R@|pb=6 xf}f]II)ɢ]\'Q7{*{03d?"1q8ў~nYt]%l0_)l?|ue*l6)S&\ &w?qoNi^>)To W5ZeQ|&A6C?[ od'60ޛ-o% HbGCQ}T:7euQ/yu+5_bA&ji VfS ǛvMw<-4vjB9L9n`3`njH!o6Ͱpt90J03W^ߪ%{ַ` t6X;^P:JKE;Ɨ_|٘ M}tF~o:qAWVH|AgS"9uFW4~TJSċa5vKOmMO#u1>HBv g}e`|C~E=\?#HkΝQK~Z+//aY}^ '1,n%75r{A%%yw0쟁4 e?Y+N3 I%K;ea+Q7!ņfVfץ7j;]Lp0ph#\bծ$4Â2Y&gl'PX -l-6=>gǞaL-NGѶ^fWX q3,ubo LBk-97n%=tQfas:XXqvO(tU;LR+vuZ]!wc~LsVB 9,@:^7XAZvJ@uN*:˪_R\|Gl*Kɿ^3J͝)*R/>ρ1,W?DT~Q%VLyZ=e2w\^CSm^}ƖT۠)U.B<~z$l :syß {o{6[ѽlh. FWc:/bys5?xUt]­ -asy2l"Ig~TN~Xj1,GT#()P2rEx`nc- >eͪ0j5BjsCpE }qA˓XX˟J@Mɼ=mW(,M"Ց N\z۱oևo2њ7VwVjj3w0LVwg`x`拵[ޕ: &x̹: {v=r}},ΰ#G!4޻9H2L˞q#Mco ޖ+QX_eWfXUǾՔ΋ gIS2WF}EN\.^f'(v%̄5!an"P! +^╂ٛ"G<=f,OwP"3:@t5ٛH(?xqLj@E@ hahPxr#ȡ)2@Y6*O-s'AU`B +X17y)6=ՆY!I~:I xu̱ 0@=_!8iE!41`_%/߯b(:^=9Cy[A2͠U/%=YQ5c"s^b^~U'I^kxSM0]_!Ņ] /5V%0}>f$Z~<sͽ'''9YGXYsV&ψ m \"GuT MQF5J+6-!ܔM,4=dd,gqT?!>j {3lN>Bd8^wZ'-b,ʾ:F0 fr.pU㜚wwEy/@z.ޏ$ɩ?P+D>)mUz\FD tM ,d G6"p 7.$x=kw6+49ںő:$$sC*In ăݽ&}rOocrv|q>,Mz[dS$xM^L>LG'h2t7b0 Nbz>-yKç Y< R0ANb/nW۠|">9'tpT^_ >>ªr_ɴ?W9ykYeC3t8Yꢏ 9xY do\}]5Xp#׿_Ds$L nb A.j^¢WVA-QR8Xo~:%hb'G20(RVȂki De2X؞N2 CU ߜzH.IL*хN [+'?_9RPš,{bs&quyEYb0f!-_sU%1>h7M[N﹕"bN5>wwa'ow(!h᯽UG{!T B@^DKy)"\o7qۯypк\9!5%=|U>7G KP.)=lT7"k `#0 Ϳy TAλFc1,9]g<@{!#pXl 74{j5$jDyUM .ˁ T1 `)Ⱦ\s=G{. ^7ga-,Cvp1R8ꛭJJ_OM{MEZ}}6)'g0azUk=f x-cW6Rx+%d8'V&JS18߃鮩@oQQwWD%רx1]X dBvL/Jmyv@ED j9[ΚNt5/߅?wa.Lv(j+[u_!|m- @%$7m.VQ)m!m/6ST;xB9<$su7z{vddp: G->Q~6KKܫzhmwnukY{prx̺ob=ѭ]m,;2${{r{y2`e3NN"fWAF "\Džy@x?LJ`JҹW2 dx~l-6UT 2xL:c׭ Ps{4 M_Z3Zۯth% uZ/8o@k4i=@<]TGlU:[6KϮW9:/ z4J'IhYL5AU -9\%46ݐ`/t1}Rmzwϒ R R>Ozo:QU?ڕ\ۺ ᣖ~l[4xl j0U/c&0}$4nLtGn3n) obОtXAUꙩ2@ @M@PejQMgZ){A\[ۭ0rVW+%3=7oE׫#s{!٪]PZ5 xJܜ;Np>[ },>$O[GzSa=SQ‹6'YSQ%sZU9tJ;hv 4a A7uF#K4*=6hռJݹ GE8,c"ѠMAp:;PjD-X6?H"A|X[F|NNgx;d@Pu m٧DUl]gZwf.2N2h~gÖvM չiwsuZ!rwtb B=VIgGbQg}=JxL{?0Zb I E31+ aNޔ: tƜ3ڶ{\kŜ,a$r!;Bь>ۧ&N$k|H ֻA4m@>fwFᎰXn-짧I0LO^0{A'jw3СF~JvКSEKF R=p.5k>K My.\C{I:O'@O7WEVFV7N*%Z7=7p+ ׊]֕ /omKVEkw@]=ZLsvTE_g(\5%"I9Dp1^|_Lo;\zǃ+i6,@gV%8VlmeԬ 82GL_c16]gڛY䇱ZH[lO1vW/{|*d}K7 PX?Y]׍} h:)pMM(QNgk$́A2]RRzPq-c 6/m{(7k䖖H) |bLq:{cGX[讣h(q;ݩj6mOz m !@n:'v*F13̌t%=o )^p#{ŵvyȝau4Yz7Mn @xVCv뢿NV@׹5,A?qx:64|%kfEFτ9m/@ g8/0=}E<Ԩ v&2"i2IKY uڈkVݻbkL+V1 &֭!4nd: sزcs*.?! *ZNOm)&LP }vܳZwJ}N˧`wsNl7kl&ӸȧB,Q.Jl=N#fX%Ќ\4 vTm(+.#qoЊmж24Wvb9HXlU|Ǖ`_஥_;c&~ )rDA}4Ӟ_U\-񏱙v| s'EQ{, Gl/hkr_WFE&j.;+: QlHvV[F.p1MPjXJs-giQmk\u#iQ{V[!yv:{kyAν2W!8ؔY|C)DIT!f݊r񫂝{%Bc8FkL J3VȷԇUZwCm.7;diyusfyN8&i>R̭q˺ PJ:^/Fv L05| MshæᮬgE!K_n t% 4fRVOg/Uxg>c/$S"T5zӕZ@z/%)z -eLa)Pol29}Zўך|| H;kkr{N7(KZuWև0يc>Ӛ$m,k2T0͒X^=yLSlB24Τ![kcpjs$2Wa$pEu]+-Cokf=ọuR>tŧ"-˜W Q+?*h%w eTnD%6Oq-V]ُEl۩-62=UGDxD="Nc &t^l fr_oxpqN Lk3|?SḰO6@i"D`´EoTЎJWXŝa׌)CSxO1 33M 袬Mh,;ƚfҾ1j>f#o(Ӝ)f]6xˉ("fOGcβ(]2l/ꃃhq8{E!X'3%H>Y8(e" msdp!&{HSldP@9Y'esnZh4fZ6g3\>:}1.xT*^aւ$uNIڈ0(eBؕ. =T1o2 e[},wUz P|75b/],0WWTh2_4*5Z :N]"Hy8m>s>l%E|w8{2JAp%?V+'b5 #q8u6mQsf/1ݴT{}^m 0hV 6t.a G(CfvơͣK1VTjtH\PK~=| 'd{x[(r_%.q&i/a'&*2Hxb'Fe<7 6 MM^[^ѭ%0ˮ|j3ik̻Sf۸MwC~l7RWk׉1Ԟ.q/y' AfAa*c^swkXQ.SjwqEOHɂx%xrA,7QNyXKٲ-tN]Qc76rn@5}5sר^Α3H&L' BrS^㸇\ :h SRWcj 56Wli1BpJZdF/kWA>l0%/mW:b {]J|{)הP|ϗYqg;JSJ96^?&"f?_-G׸)5 I#減m;$%ū ĬL19Cո1Н=a6]دqjN fGX[W0;Rf*냣-mLrbT8 UNQ.w-oh6b9>1LpNvvR%Y>uI]:zc$./"$'^ݑ[[J[&*]4$C4|}D6[^So?[ah"D{$^Himz*#5.] D9]˳A0LP09%?, %ބQr+,H R<@I]E%VEuU/ pE<g rvLiJsmGyu*@5Ƹ1]v^P,{6ʶB"WZ jz~BvQ-[Hf2W87~e)O%}S0 o`xbgqm„`x8Ϭptk` 3΂s'3*rqr I2i)UuC/ssti? B<JZ/'{= ng/?pڭ.tEMgˊzl78ھz&?>+U)J|*;]bl씏z)xY:чVDq"yWDrNfLKl2IY*𬛧bD Mb,r#xWoF~_1{D\OrcCmL8/iQ p"eYaKg< ٥ ,ȚƔ KUDC"fV֫dX J?G~8ʲ)&$%1ׅ;)m`jm.<NFTW%E] KrN0LeL75gލBQdN\ 4O(|:Oa7Hn w?vU~O\TJ!r"_ֵo5_QE*Ns ⵊ΂HOvCy*boml:rXa ]U+7" zm79ZMre6W؜4ZZCM􍨐I׀3/aEhP,gXfCmKblߵ7uyAl9s~ҌlP;m/<#oO8_WQd ; NcYcl}Mgt*o8}o҈Q`6YnnA(q7uÀ 4ji3.fӉ_TE[n6 sD96l#EZ=l,qoI:._K583$tEd=y ~3WFO9E#Q:Ģ#޽^wWb4?0n9Mi|֗ϵÖogo3DoPXQÕ7"o7Ϡv1~wkƅX$>%D4 ,\r[ɚzRth0m#y> {ĨT\ļzM]"b):ddwR&Ϧџ81F[_-N[3u(J8Y6/̼YX#4,>70мf֩6o}SC6ٝ+Oژ[=f?y@zK ᦣ`86ܜΆ_ފb 9(1hPZ YG2Ejۍ`D>h<`s0848(|=,xt6EEdKE̡[>&.| _8܉%5L.5%|8@ad)j)%O:A%Rird{nA+q&~̇m'exsx1=koi 'N/)g8Ȝcl+Z>=ix] -$H6w# C(KuGQL(͐{5Aohs\}E?j9F[tܵ(ωm>S >T|U}!ËxQ쐋[IvR|6 7ߘIwlL5 iK5w glQb z**RScd?5T-nvJ{,Bo^ z% V&x§_pthѿG'u?nwsIbC+,y #ncGH^Z۪*kMD۱9SIˆo(7^0gSLq(d0oi Ъ+sEjRaΡq`фGd3o) r_%ĥ!p)5N_znGa@Խ;Q!~̼j\I!P۴I'\U&'ug&w#jY@Z2pğ!|pX$nG5$d'DI-^]3 Ku( IuML14Qbx:G#j17Ed4|DzClGVA\ќ-P 9:f4981ʎHW\)|+M9tۦ;9Pti_ll|zlP25ڲI?B,z+Y`q]-aZQܧ.[Lùb͖ʠvWTA]W\L_He$R"=Q_",tqLB.(2-lGBOAONbz#Ly2TSLk)஝>"~q|%J CQTjQcը8<7>omSd?54陾[[I^P0_WbAT/gv4,DGjrLI'"^G͠xI$jrQ49ݔ$%s;d*lO.#黽m?F# .~ E ^Ьs4qh#nL_Ihʉf6-!W&&#w2TZwJ`]6bIr70D,z&!ש=Φa1;5)Ŏ|̃ X1Yj?_tV Tl͉z5fՐFVOjys=9-29"| ̲+pvgѺvKmGY4\WJَ55Č.ȧdl6=9x.՟ʕ:嚄`Y@u2j\UnvwC,{l|f~I\{ggOY;1}1V*#-iII+u{9q|O˫sJoaV"f$Ԫ5eJA( ޽$ r7^J⇆ىĿBĠPЄgxMx[*`f,'fyك-8%8(55/8,hSt(x[ `f,'fyك-8%8(55/8,hek xksƙ&#nt'K(ՓphSʇ=nsIMJwISY}aw־uo /0 ze)}?7t]O0^@ <"{+^Iܵgl?1mt]cEVAfk]EYk}8 t9\L?+ƱD#縯6WJgn 4&)k>kz'$^~ax~ QtV)t kÞ|Xd 4GEl=sцk-{UaA୮MfK}| :h'%5{~ᛱrI̍clS Q(=&#ħkIEyo wiLNh&{Qeچ3: G( $[ c,p$0$G2ًYCah 3Ooc@)u)ݖ]>,7`iMCI'SrH͆rd(xkiN|n7DisIs*@ ~DGS㤵b[aZʤÛdŦ! :u.w>'&FІPk2c J@/fs .ᬗno&IwQ'n ݾ.ٍ^cdLi|]Z0;x(eڄd챍RbbO%$J2\ۧ,׾WXSn"yv?@GU֢1OȲj\KG6[³σGGEVFh2STO'B=/I7%[DG\dU0p>UH|jqĎ"jXNXR4,f׵dFnkkPjQ?ŖZ)g8Oo>S}9{;r/{hN''*]<".sӟhCՀRmzYvlq02D%ύsMUd,0I:teϋO%~& up@ܔfhURw2 SK;2U,: )|gg7GM,#۫DR4oP'YHtB?@qqbi 42E%vadS43$ēǬbA\&~3w}P9)rNE1e!V"t3>yPX _| VMAt{¥CjO=0TJ aG<`_g;&&&A^}E&wډm9EE(y@Rd %p22ςU*B5ag^noG2G$)%BY8&Q-r+^ڥܚ˚$εJn nR͍P%$[!\U4+/%RfB?ϥ^>.bsmRpV.+w*KʉF+ I1}ZL8G1&>?B{Pȯo:Lhf$sGM-)_1'-# Ow?.rV*#V(|#qEؾB/`6E`4uW~86jhUtuɎ)5 ΚBcQI j*P<ttJjT)<9`3WL(E-ż+s ykÿm ƶ3_M3}R Om板P)nTz}$07h#ݐr-ku 2wS.\V/p+Aje95G,&\*Z~34Uje8 ݊aJh ݍ^6Dg2 ·ȋڌ vw$dnMzagS<@Cʟ] 4_tçbCtiF`}W](s8P m5l5D9=ێ!y.<:/~gMiܒïu/n pGDlv&sop=}> X9ٚCT%c`>w⡿xϪJMMK]>wPa.`.nBDŽWڔ]ϪVy8ចtV`mN> /,ȋ*ͫ@BϕzvۍՐ=k#1KZh/,S%K_.ـT )%a]);y/7JVhl":;PE3:w%:vT9WUetZJ#lA\WKi8:.VUr:e(v&{޷>0Um4WL)LPxW[oF~Wt $$Q[U1ʭӣ00 ث]ZoX, 4t@RӉ"V Vsܼ0{Uz<bVPWJb%?(+d5%*5_Gp5`Z2P$\&I)̬]p13Bp6\n:I4<55i [Ș9^=JAH~a^ԋ2q(r>/@eG|wGO=T6K|KWbzF I쎚hC?z"~4'80uwN`: KSZԸs5۶`Rn='de),نcG.6yqlY3#|(d2KLN<#Z_&784c GyvNTGwo/ov1tU㋘#0q8ªNЏ_P($?L"u;ɅCoNpV8!?; DOS Q @aa 9aslwdo)xe&M&y\[~ƚTٻ0;OC7dhE[+d#@)u1h ;ע9Ql'Y TvZ%t0-®W~޸Ov V3nNJy=αxuK 0yV8CH[T0\i ~S|9@zYODq&g`(hO_]d0~1$KYתN5uϛ.2a2JH!nLⲱ^P˾xs6xM-PHn{mNYBR 0@ss10M\'ɶI37s3Ǵ&m>{ .}t~|mLk  ^{&k2a)B4?.*zt:?"7Na"XG7i|"5e$b޻1Nls#ϓ4mʀF)-Cb۬Krt,bdWcQŭi$Y1 fM8p7a DLHnJ 6 tb .}TĽh({`Mrz7F]NWgSzrČ|n|p=%7ë=2h0x =a7t2 NfbRK(F. }Xw 1~]=NJy0DqCoƋ2WSȿv.|eVC)io"6W0*p7H€JpЀ&o)xmbЎ1޸ C׸ {,rg3F;,Ƒ8>[lȀ "9A گ#wY2QeM(t jU+TLƼ@`MSütȚB P9XS]3*(F#QbZJR'`iu$9iaAOo7O9"ƹLAn"K!ZvbwL^%E bkT"Jc ɘ4 #sdmqAkVrQ̐7Q{}+k2[Vҭz$1$Fc+L [eGHCF\a(b-]ј/6 47զnq#Ұe-U#4T;Ge>`XIbBYqbp xˬJ~iɝhp<Dz&,7\ px7wF|<ގtlqZ\<.|倧7a:C#iavm@jGi20Ùs9l5Ki1"#Hdʹ{bn><`U, ͟EA]+rTҨRU RaFbG~|r` uaX+p#,f_%nS4k˶*n%,V ;j lUT,`KJx2h=KS-/)wq5%+W ]XP},V0D@کZX8vvL@z D84΁zK(|%F8 [睄)c`۱/pAE@[cd-|INofSͿod-pַ(4}Ƙӑ-lvq$EXYpP,о$biROVl.𯿶CV֫tY2LR̿^ `&[rɴCqK&J Ct.6]kcP^MtЖ{= ARjGAƫ6,e==V)ί-.k zAB|GOj B,BkĥUMR=^½n Uo6UaZʢ~}\OcU–htվ*B'zWPyrTyꋩB=eUd$?-㓭 (A!<)jZdGs'_m—Q1="cڶ\Z? &KF=l Ax,%?zBwR_}<:%%)tҡ<{V]v3V+Q$,DidEv%ȳ,FuтLNN@XS]_y#DzxՋc{dHk<&vo +?Ϲ x=A 0Es9B7Y*"Z…HIH&kx2Kwǹ'HIl=cnKiHFeQ{=6) w ;=KXa" %Y&s: ~mR\PD6?獻8^|#<̵ xSNIMKUs WH/N//KMKLO-K-Rq $IVEp5~A ) UE\ʙy9) J@tB PB/I-.-)MeEHxSMo0>_QEȁLqR:uݸarC g&dą}OgW_Z90lb4w}Ь 8WQH$2ki]u~*F~ 9yS[Ff)e%3-Hx8O\\DۤY~˪T~Z >Eq"$L(A|yI(Tj_t.l" &.{lv D? t(.A`\H h-hK4χDlHL$X=L!M\ ᆄzϫ) QU:QXߦKzR t4 A6Bc l.xs jYpMjuiY1j]f&@@¸95E |"1K-?cW( 9QDMGqBѣ+bxݎ8yRLMVZ Ն@4IWIbMY[gN3Hs#8d7CWΞ  Gl!ȝ<*`Ҭ+OuzwY/γ1в4{ P(j nI*@k"q ^q#ߖNV {]QT1xdxQ-Pjcg.,zt>,'~nJ̋f(&O8k!aot~il!Qϰ=pJ6$/B"!,re6 dބxZ=0AW5s? e6&%[7<xYl ĭľ6$i\y VG?)^URպn=j km͚ OOō$^ډ[rik8\eH{QKZ\7E$DLE O-'=> Dx.+a:;g~Q^z^~nUoT[!xuJADD|K<@<8fnwwpGf{]|W17̄ ⫢?_v:"6"ajk]AQgq4!N.}2,߼g0ڞ~y͡YhF*@Y֘ zklu\f2T9?P=WD˝B8EQ,}!.]nZs x9d>xz?_`אO?` #8/ރK9%5-3/U!>.̼ҔT$ ;..x'WwOxWg` ũ8(Rhdřy%pvDFY~f(.RYnFqx=r8*ɑb9SORز[IrR DjHʎ*U,h$׍/ HQv2ٍj&Hh7.iY4/Iq6W/HNibZ&a8 OI+BKCv?r`~a&%'KrBC r/lE8 <OhK_g1$frILAxR{QL`˄DM5^I1O#C9p?&7rI1IYi賂gt2W Ft abAƔ:[/_{7##vNWܥ7 Ea\w>B8#׽ FpHC.:Q3 a!ChQPB% 㔦~H&bJ < C " l8#$HŒQ$qFidzm^8y$?C+?^) /(nQbi?o'kog_pXO)Mp̟]մ?'t]2A8MȼKj^qF%{ջMٔțۮw GG:4#{f[{|cܛ .AqA[*=Ǽ'^i >.x\u7{ s}ɴ^Фl R ? % $(@CO4dC?)ܯ?IJg7b ӇGQgzǽ1;.p57zwz?4:h`X[ n%K@"nwQYo8OހX^[ I k@O;G@$pNz}{ygo#&Dq0-t18?|809ȉVp{0Ń^;t$IpouJl~O{k`ɐ)Ub!Y`AϢ0HAM";``lhu 쉋둟\Op`@PgA!XF/ƟAQ"zI2^guaeDp=]ҥ 9_`VBI67^fӫ \Thh΍HH!~vsA2.״T۸;a _'&=qFZo!80͏g(ZP?Q_-sRKkh ƶn/ xcLLuಛ͐x9 9gMȫ[R97(krg@J\=y ?b'|̛ՂN즉VƄ>Tr}= h;yIHydOWqP EqFu6W(*(8`1I4f B#x7g驆\SM|-q|I'羕'NQG axËί}o xћ +ۂVSZ./" O'OwU֟`&a݂}IѴSXm,U++qW;U؆Lْk V78h$As#i':F9_UH`8:uU7JfR`Nm &cXLز _Mey'*Kc/d@3'@4hE-ӚH}I i5-8)y"ge*guxF XEpL~tU7P N+D؎X ]D}D3Õ&!Nܿ4fp3: _F T:| _D W@wKxM=bz TYy hZ,LFp;m_C"tq aA 3JAzl:IE27pL^j܂c#Nk2F T?kS\ѪW|SZ_&4UJ,0"U= x֨OJ$|;~u7*@[sN ]Nw/<^6ܗszs FC͡a,E|g%nEŇ,$*}X_}`uF9SS &Kdk6 PeD+Pc J XWLw<w:w}]_}A}e gȪ1Wײ^`/D+s"* S\I2|ZmȍNwF45SE d*;ĺ;/P7koYQ (>+Ƿ'8Zϯj`hg27 w+q.N3 ;)O"43:sj\( WUN4 GÜpwkh;2@e -wYAآd3|pӄ]5"VDSʧ=- WZW:dKF {]nU $mW}C:ԧta8Q`*㓙Tl;rwu Hf&+|$.t ve\VKM2h~|(we*Qz6DHt<31roB,"(=l:DbBQ.KR0w67enVΡres@p[4M}aiDI+gji#:ejbR\߸cZl)˶2CgۇG4Wj=oiV {8yV5ZƤJjדdH;,V|L,$k'QUp}v:ϖe:Hg]`Hi߲0̈́= K x+&~Zy!RNƱY@CkqF݁_yYzz=BU`B$-}?=cdl+ 5WnNΗt58yHlK2&5لS'4Xx" * KHl@HA)c_ #*n)RqBX*űAUi ﻺ&>|o8hh]6ΧLd*bp;L톝uЃ68%![ry/p]/4G{Cnj/]\'Ad(NfbvV[)蟱ӑٸCzCSnyHZ0-Nh"gW S𻞱r|e;tj.f~EWkEu3j) tibe|+~fῢ%qZ_l*Q(arHG^@R1E"d 6A36.^2"KUϗ+d3pBS!Zw)K|!XHܼ.|ME^fVx ?C5BeG\d Pa3}c]=)ad%#1irL޿?*պ8b'D!."Wy. ,: cx,]֜cE'&r(QCxԳ6|u}L|;HU˱źbQb͆;k]~o]nhZ[x@.hjl߅y  Qjbh9(Y<3O73-Y2c2Lk{Vn,ao#"00 ^ރP&Pk Jo{y[v - H&זiՇ9`a{+6féK’W *n.QdjS٧̉_(ZlQڻi!IոM_BxzUj*ӈYD{frw3xQf:::Q/C0K#3-:7Vm"# &2U˾N h̍?hJ-X!ъy8C>2dM s{y ( A'x4w\ṂNh^~6F*q~pC.N1 1Ņ󃞢(:Z"BThab;[z>Q\@kF(cuI,5͵e22ɦ7GF0i[[E)SZ5cEE(bK9۫^{U`Vm"xu}%+21_=NAUl#*|3:WP{a:x;햫w=D1M`ޣu<ޕi;5G Ij坏g41sC=[Oo>c*uiax N[8S\\7l{KSO+x"!]f4Jp{&-Tj_ 9Ӓn+APR8MaYu ]Y:4HN*q(b T-Z"|od' CKvrE6}ig8$utF 9 /vש%0GfXmt@spQo`F"%ֽDR D5a{QwYn.bz9no"xq75,w>}a,Ia0K׳Nq#;SqU<y(J y,M`tU\Mi]i7%DV5,/T^w?">;F,p"}sFl-{j1 --]siԧY'_[@&ozD\*U`|JM6Ԥ&6%R_-9=?9Eq-D)[9Q}x|շx fʧ9G=HGa P'ɗth{r'o.;!t^Ȟn]'Z |I\ϡ^Ԃak˚x%fv[bZO t].Ww䇳ȝ!?+?○ХsZܐ[?$ѭЗߓ푀:nlQFg~@`ǁ{{{@% !\R ;'Wz!%6+{\b‡< 74o|I< 5`wdcGI(X 6D+`u72d~!1yߛ4NHoFKh|xJo(6. pqti]&rћ1H ۣI3jp:SBEq/*& av < &s ËH In%ˊݓm7?mL( ƞS"=gM#lz&g?<dzh-zo]o;澷prnozsqgxKl>;{tF-óR`Ur*)0W?dr7E?"Cg:F\lɐLn(lpi;!FOwm 6$ul ;}|ߞA[o?C@/o6g!j5H絗ssڳݺ`h  JwypO"9cfxxuCsٸE'?%&xzwyw4\Mߕٳ 36;kPQzo + ,%Ksa!6=G]شh`Q`ܡoWv@A9dm-E.648hGtE|}Z"&XgEt4:(B<"3?@GuH33a@*zbB _ =g̅Ap؋L~ €S  T^Z€Q, $OSk #`t{-%W G eb_wK~Db5`MTNL<;K> |oAQZvy]S|UGJ=1gP\jl~![9ta7aGX;ܽaYܚ$ݮaNr"\ߣw&;{{0P֦nE A޷=o]PH#;*,{dmdP7 rBb@K!W>>2ǥ/aݷz`'f p¬%`g`Y(?cG%m`pmh-{ɭ!:rֺ{AŮoɠ?:WqB6wL((1Y~D72^jpIGeLOv_5lLuFƂ{2#5BZj^jwu$#4l:8ubD(b؏1~/Kϯ-3oG;ɁO:Em=G=~p Mɫv.}J vwFxR"-ۡ-[y$'#y[g4/lnypUA$W嬂zW{o<49@':D̝4< ?aR,*aĠGU)B +2tSc~.m.t钕L`l\4?S>jxF3!Xtpjhm={KX'6'@qU({d΢/mM>̓9$:WnRP[#'nDو'?Ku32c[@G5]\xusduFxŔ8k*ao}pvF~]wTb481^t>C8cŤw%|`I3Č̫\rtbprgK, z{#^9Y '=l?΋7_x ׃Yp`DdQ)F;AT#I4d%*3P2J27ɐgf|Ŵ-9ܑ5XTcC=AdvGfɃ96_j71đk&s2&vxJY,27!ԥMc9xB nd(Qcy/6{I*]X9۹؛̞;pjkVd4Kn|W{ȫ{8ǘٟ"H)pbɗ}2b+pA)}p a%E/&G]='h2?X_Kn\I`!=W7W &N"YrZ`/OKrf&I vE ƴz٣ {$\ĭ,aߌ6l)`3;=q;Ya͚Bx(0Ƅ5̈+y\,;C _0فxʠ+tI=~gryxaMH6IMz;܏qP x$nH{$> h3h{X%#m1E >~Z/oML'BԆ7#H(3E5{(x JqљiViv91BRgdd#1ZzXWIk|s>Øwr?كy;ޤ׹Axx"{H%5{zظ&[ܺGQj}pT`3o4G6V-ז c_+w9 >!'' ̘y'N݌~-:.BXA.qrZxm: H1Thhz~VX11t95κ'Ĕ^ƜIAgR" PdC5>cJy8?zy2#'=ߚ߿aBrR,,&gSmкq^'顨E(s%k&F7XcULMˬ&,::npL6k 2!!c\hr>6Gr=hVcU~*~v42t̖oŬ{!-iܭv"E(J.Aƫ韠㞁hQiנ+wY]e- jUw~[ b]+^ד_s0J C uFܪa*^|P}zD\oQO7 ۶Ϫk,^ۇ~텢&PpfGdYUNT(s܅{T o`' a L*Зet#e#^`!}ub$?IfҡWW7n)~!g>VV|z՗$;:TړQZHiwfn)HjxrUf3LʖkU ԝ HKe)Y|oЃ{?4lx̂W7sވhr7҈7hҍc؛=GEjҍLV`e/dܪEQ(!,Dj.\ǰ_.ɗ^a3L'9N%!W {̍TsΣ|kd [VofElx2*Yjd0mvzpŏL&@xjvRϛwYTW͕шUz5< g)"d}%d>nR w0,(V>!*WA{m5%ɧmN._;k_ͫ[d; 5fB"O&=\0}6|xTe,X4ިeE kiY6J-mE>2L<-!QQ"!_@,;Xj8f3`3XSx-_;~2OF+ #EG YxRt‘r̞Q52SN<}r)?xe"#O,-3a0{EҖZ+Bo9yeӭ4m$ s$R3JҌr= (Ձ* AZ1[t<|"L'12=.q9z!\?'4!: UfaYrgntTzb@PMObl t71W 3xJxLA!ͥu×_|}OqI,=H-οk,ԧTѮ36 W3|آc߱ZB{aUVKbYWm ~QWh K9Q$ث H'酑/qf*V@Vhˤuh:3(-Ei\$4{ɗ!2B\M\_Ÿ.G&V%ac;9ș<"fLmg=&]ގwtfgU;l#z&H<,hM^1YM17uX%6[a9t/|֤jn]onR/\F>;'ETM4HC4%0 n|<~JYr.S$ UVrh>@CZRH:18B^RVCrl|k)1\K}|'81uxd.fZ^&&/QA2K`ąF'T~] */dk~TKz_ƣ!/#R5GIOv7Sbq S um\(CG+bÅHb|e i%\s>rs$6M.0 l;Ñku_M^%x ESkGA.\֟,,ֹD|)++e֨b" [eRk܈.XyR<.>n}cUj Ŵ{`+KL| t >~3~x`kTGHCA)bfAT%zRYŶ0!gAz鹛9ApoMJ3^es Lh9DJ +VrM2T6fO.P ְlȒ&iƎSݠVYkjkҔ/C-f9a<$2ݪlԣy;k V]ڲӼ({:PeŤ8X͉$ Ga5RZOOe`;lWjnu |i NyD\aZ*MD"WML8F f8,Ҥ$M"E9z)7>5lOYZ3"14BYbheji9Oq`/*8 <0<s{ 35{ύNSf~zᩡ`y`=gb-o!:)s1WY]OЈy.;*B9Tw."(!aJ*cr^R/2זAL/Qm6h4k"3L> ָ;~}5C}^NQO hR3Qe:ME/c.(C'#X`UJre.Zh=ᨲS1XeE-[z끻;|odHzuml72-i·\)!\9X0Bqr^}LztRڏvTl@L 9P12&CTsBy{i/`P^N56Kv(oq\7_n®Ѓ,\(zHB=+|?'cap Z{*t/ b{既䘇sVP˚)#7YOaE7H TzίԸ`?Gn('+Dp22 "1lR[YcBENlr /v&V= 3[; `eFW,N+\F<W}7l XcZQu)F%Ut=Đů.r=cu>$'k?bo‘FBlf{+u*~eđe t⩦! QFք9mPa@ɐ7ln^&TʳGwp3U3㌘+竾Z6m@*PdܓsŀlR/3S@qodFNjrM%Yt1L=^L[;ӓ0Ɖtx~1 &ןa +(D@=`l 6|{9 9`$LFs wK#}U0x,&609>؎CD]DNY1؛Φ=%q{0prVznÍ6Gڗ~oz ׽@LpLdO{Y=&x4hP"/*-ȉ cqOaMj߃l1&/21]iqHqI|%ˊ+$=|$>*ýs@ǵ׎Mr!ߴ볳7gd6iNdYL]WrcOw[0%>o$ h=PѝߑDyzkWmwQ VӠs}  e޳-Ntv p/jD=vqYa'Wlt՞j}];MѸnֽpҧ#M &:P4Fb֌K9B|l4bFڸ7u;^n4&ߞϓc{y7noGoO`P +Pf7FN:n&?I#Zǧۗ}!BCob䶄Uٳ, y00!?6Mb,  @4:ƶ`a*LJbU]HA@EX \Qh?@-b!_nu0 Ȱ Յa-cg+P$` %~:7 *b8 Zr?e g"۞3.=<ȦbX=ϡ0p h!HG\'ʹjm+4|;0C@sv 5\B# LbLP6jMv;&N$ %T*5Z1\PBVGw }o_0/HĺN@'#6aqJoOl\( Տ?S]J 4ij;)Gߵδ Gyt m3;F?$wخc28'@W w`fRONjқxXn7TmX%jbdg+1"$aGiu>zM2kj yr=HZ(,@:Z>M2nD>׆@ޕ(`8К4O=WP`LP_T]n @bAoyz (9A:EE8"4zwxؗzV>d6ǔx" LW8<` "IlY"|C6wNߩ&,~CtU5K&":dAW9JICbS-ĜR°+Vޮ!BUF0 i90)VoBֶ I_U-qbe~Kt~VgPL7N o ,B|Ztvs[]5soP?Ϛהp .Uq tm6j؅;6f.<99I gBGSvbI _ ,:$#Xz""|5h0NPR >`bg+L .rm -WҮ(#|0x @q0/2K3^>Ǹ 6s&9&P&.IW6VP( P\?!i wmo30hPj T.5]n:򨃟ˤưqА0a:| }I"˭,'zNJ-IԒ$R9z |W"E^ODB(o8w!kdс=<"NސcjY9W27٘z=aX/foJ˳T<'P2 $KD%Tu?δ2ȃ=f*CM BC`@;!W m\OBLU1b:w?08SA"ׁĀxmY0"6˂Tgc"Tߦ%I  xڏUރ?8eD <ȋJpH|p럒>>yB^ L "D\0Hy9k.ɽ-TXg/,?C 2۪ R%kV#lV撅auoqbZ0X l(dn1k*gZ&y";U$K|G10*!I7כSRGyd,1" >"F]9'{HFsrEP5PM8[,ءqoX=Ц<'^_{-;$&paU]Hw;x]ν2Oܻn~(v֙"&-`ozKƺ>Qyƽ>Ƚ:=0Sk {؋mxe;>e52|c=Po"_x]V]q3& CdLš8LBVq՟Z8q%]-fyr[D,>ۀaIIuƓٓy9dwL#4W#j=#?dSK }{>3x|ݽO*y0d Pn1 I(#Su`ѧ-&YJ3,+*R&QTt]BrZH\}WJ\wL\l+`Nv+xyݴ6M5]L KqR)o[/]/۝k4I~(& ۜ ,lX[XqҠwCx??OJ((eJndLKmRXLg"~I,8Zn;*! _U=$QWoE_]%& M9% ێA1#a839 ^iCWG?ozja+iK+X+ jO uْ~(j\ZG6!Y?y@wg,3@^BƤBnX,_@)eCp⩗˝x|JGn[* q{.7à ~'r[ӕҁ*)%g#7rDmʗm.㍹]tu\wewBeZvl%ו_y\x?< F,ũřyMYX\J+* `s9g LӮ]'uDO3Ѻ0f7Q-%|"Q-~&79|Rκ%:^Yw3B.'W6n`~9GFw8z`rRL@(/ACrR( Z}@SФ$YS4D560`l"k yseh0EԒ>IbSe &1mQhPe}*F XS^#zҏ}'̫?qqP8tsvb&` M6_e@Q)J5`ڂ;TM&؅f& O!l>7 gtolmY27[['Ѝ[\{$,37 nQ챸2ӟZU4s\ǫ$^>8^i_h*z%S؄U.I7BLl\E\dD kٸ|ǢA 82$Zc8 ?qy 1ڼE,hw0>lkۮ1r,) 0Iu6`|% +QV[@rfәȅLSY||mC $tfy{ѻX}IY[ մ|ʸ9)q[b75(~(hGspD&;+C P\NX>ZcᴲӬۘeɧ;EoGq]w {fPa2JXO 0= z? Jx*c`4X^[7x>%uA}q{55]h07O|lOK,|@ҐsiYeYph4JIv ΀Xk;1W}Y|]".#^.D6 Ɩ#d%6# 6X`??lB2mS1fd\&X6z)ٗۋo]4Lk'Yj)l_6-KK\pG- rd h(o0j7t'},v! ҨxRP7mi'p\@kL5B:QA kZ`I??5hjՠیnOnMnKgНva&kOB_pi5,ՠZ<: tS2~фFJBt[!aU"K#B0>{C7H"0 WJQ|<ާCt!},]':O0Iݴ=P?TCujLnM{G+ -=[NpևЗ}ZYYNoTۜCvMcAe"/ ?;X}c<I]qHîb !kVLJ+Xy0џ,NW-y$ev ; z N-Oc+QcB}PAèLII<9գ)?ZI|"2Û8Nxc`7̳=H3dBega!]41BlL*Mi:t>N2/iȿܰU;~g=C75lzu]G%8ԙA7 Cl_f0K{%;b-ԂP7! ) 5<[l?[O+S/HyPdžbT{uluGmw^EӖV-pt7/ {" Olf0J rP/Ne=SrU(]࢓q5YA!ulkBp[ۼj/+aSshj RN:;B%d[B3o U6 9[6"a#0RyS}ׅ C*'b'EP~X ˡotr/#36àw& ěC9 (fcX0"q]pԇxxu+vxN x=A 0Es!,h-)6 d#y O =fB^aG*r]-8c~i }Ks CH %!!/ ;` u`Hɤj%; .i|f ܩڃX%g~Ġo{hV]~ѱGrUM!J!iF~Jؗ۫ȹ/45L3/ [k*4\rbn5/=t"T37{ B,G9ʚMySKPv!em U9o88J[^3eg%a+gygw)B k-X4Ta/^JUus~t*vz&ΰ~gjk:V `aP .,4c1 [Êz%*GX#1||WZNkׇ1Đ >A\W-zv}"2_zEg|ʤ͟KUS8z 1ǂbhnT pv͂ENL1 VexּAyy>ͅR5h7x}RAJ@H VE#7L+JS0:@Iq@\pG'3mZjM{Gau6O|ۣʎ5E Uدh`1u8wm:?ĵux\ѹDO\sˉ2oԳ}N<׺ai}ֲZGGES;>%D*3Z\̆[ieƊ#W%"RexaKJL"G΅Ҡ|8n2 5B|A$G]ǧL(!Mܣd'5HD )lgBms+#46vɵ!\@rvg|kO bM'Ũ² 4^ fK J3HpC) _OHQz ;b.v>^ӂbG1p)r0'赛H||XZsYtt)wG܊\whEMo5SU4KRP4\RôFͅssdvMWk (%){S\I.>JaӋ"R0uK{XZʈLOqQnLڠ5$}/IxpM~x7h3q5 DJ9rQ<.7eq>H>lw~ >93y695#OȜcZ[~0ɋo}Cvژ9<6RR* 6Dk/J?V[?XYqr=RbV6+E{ Iu17ڦ7dE .P2(36VUuAEK@q^C-R`ۦ%T=mz}ssJptRDx{;wg~Q^z^~ndE&-Oň"4YEUDR/(8 $JA}rw{Jm3:!u'~_DKzq'Nz~{[h`/ic?i:+ lM3pC 4 'M(l#`8~Ibu3̒ 񧿊DbKŋ݆x%){{{[{/vgTk_^@h$C?}v66-GQ^d\l_ɤL[IC8M=9蚒et?σWiǪ L߂^~Jc斻FG¿Maa`N8+wNV[Wt.e) Ʉ3pR?gQ{0C^?[ #J`G uN$!4rQXvG`PwhN,PrƔɆ-Еj̺]~&r2Y'Cd37g̲H H2f%V"m= +k`V7dJ~{0Nfְjԓ 0}S)Raz4Zqa -ԞL MF:U *LԊ P! #Ē7䖡\ OR`@<E<  be.Jbl fZgd]ȗ1w'kY MBEX2s<)aECPg(Ÿ*iX]M1vyd ߵrM9V /ڳ[ήό\Jf8e::>6g'?t?Z%Ӧd=K-(U>'^xaUY&[Up5 V*\[וeg\$[襥H aW Ac*Q LV'ncR'thtP'˞P3tR#}&(.+g֚~TDZ ƫR,+SegqYbh*Lh>ڸ ƷC/LԇCJz'|װ]!p`*K Ƙl;wiB&~tۇ$IPr3@r(jMy۩A2LF b qSAI졓Jr63 tz>9qx:4ƶ݌)wD:Jy%W@1yB~p=50@}cNz@MF\(݆rt26K%2|x^! _c2C@i=cP)l pKi@ n* b?<&4=d9.RI[it}&K,qB W j!톴m ޔ*$ů= 9,OԠ׀]'C2\QT:fFiٷ;Њ+y*n@Jnx}e2hwĄh֞y1l-QVH AC@G}N7?%`4dlwCLG\OVՏMtj|6L*Hbй}#V*#"*6x xtvMӨ@Pi) ߂MS? 7}4(ʩdCWIN1]SAӐ+ɺCrhd Avl R~`] y8+SX,59y,%&Jm!XTE6IL@0\q'w`/a<%.Yg ^$05wsظ&:hSdx-j\^XF*>שn]< U@ҨZhK 1e8}8IB$tBȵD%{=6E h@Qq[!p{h3 r $ra0 J=#?d"bLa*Ȏo@DKB>*0fi4ڬA@@=:^  ̘ٱVA曖H' g0 X/Cӄ5lP &FJ'Yo Օp ؁";VTUY b, 6AY9j V6m]5g$VM$P<6-&iGKnR\3e췢zka%d#U{(~π1 \:>{ 8IZog,9վsmk4<Z4agգQnCkPfz!/6:yki(;8;9{e2@WF˘]6*/`@WY}A $K#{rrߵ /9e$APe-IY5 @ZԿD ɽq`vnt\5g f)GO2?VNY[g,z.>>|0!hkfAU+##R1 bRafQP,b#;KmXS =B>0j&b-}"E"̹Id9,Oz6F|ڒ();pV3-fae a1suǰ`qeC R&oT&Ǧ?t6Hؙf{io] Q{˴";wUhipic'tV9.g!oAZu]U-mmM%BJ8L6/CGk&zC^/7 D Pd9* ?A̹QOۑ ~$s9ǚŨwL isۄ ̷œ, č9dS_ϟN2t6ƕx.f,*^&8 Ax CSKfVZpCoBDު`u;HWeU_S w#Y43V`.iTTYZ=khcŵ5oN/΁Qy2F(_ Ө˲I;6uvxGrrA'7䡉 Sl 8JyDƍQ&.PI*VTI,E!EBDHGK瞰+Ҝgx\v>{WTlKZvW3c":ٽ}v[{ďq7Dl$lSS*4 B̉}s"=,&P:s騔Be̢LH@u+mW)VŠisN!|r_o8Oxz^ׇ/JM\%"2E*9b)h!IUщQ@oǠcI}ʷH 5T;W CdF;d,,P'١~m(PvlRXIO3v6ܻNоfK}Ty?B$B _lB,EoB>{2s{[9>q4fĈRS80d8q<^?/L⽹5'txy؃nT52Tӎqpv_諗`O}/Iy J|@ JTFuL}YnV#X<wtN(obt7"GM'WZ%:;`o.#9[aP<*jiU"n[y˱ߗ 7Y~(;[AOz{,,xFJ#(ȳZ/Z W˩7}y,Ax)cL{> ? [Ɠjգ AsZ\jK~im9-rqb8`T{rqE VDn48k~e{qצi;k`S쯹if;;dW8nЕ017UäǹeTem۫ZnxL+'%QO27S;RVAaz ->1QWXη0*]7>ˋҸ%Ypvݟt܆R3?kQo P6 ۳1M8dͶ=CI:%PU5@"zשZ$Y9V5iځ{4Ϙ tp+$5 (|~+ ^}ۿG/S>oQGe{d Ig.} v-b@dŶzo~6YxcuTSc1kMYr6i  J; 9YYM.<@EX)igP chyΕmΠrzu-W) g3csJsw3JVmo}qv3eVϽA۴_ގScl < 1mR^wm +eښ5ֈbYlT5ј.>@A[GY)^Rw u~MٍڃmYXi~'=ޓj9%gZWRVݗn㥰R P.Ƭ ?8p^,"(~,rC~y/Klj#~_ңlb#/pq;!2+, G, dmH9ZcUE/oc y3Jq^%b "9Zj#| ̜$廱P;_+U^UggS_ '6 ^ fc}5TaGٷ&% ӷQO<ٍm *.XO+n0${eS?{<鶹igu{z6}w5i62IGgG^8>|!wr2@9j]]}K׺ QrA.fq,r >S+A=P}hͽ*EX̆UnaQYoޔ{ԝe伶nbz-]#!P Œ;K??l}ؓ^>TŸ nG}z`A]ho+f~\;tlĻ]awa^Inתn~ d`Լn/&#&ެ/ᢑDQ6"8zAPJU8H?hPbT65/1B 3DŠFdUmժQ]bin-:@ky Cy^ZiYLXд!w˷P@.Qd yx!IaTA맩wӀp7!+P&4͢89$H=װɅ*OANk #-Yq葒`4s왉t/tP Nf쎈GD,zKb`~Bӎz#;'>PUOQ9^A5h>x7cUK{XH;Si&o(SPђk^[GBѰ?q/;^h l\z,_ ]zsr$}(ϽptIQ\rOt ,y'\@nCTdZn^cS.W MY8[8$9n;l.Lzaf|XY掷Qӌb$QM5ψO@Nry>e!yRBO)ZNDM.dTsi#}w^dbîY2] >1]Cɬ'u^iy5nڗ,_l9Cyy~SKTǖޤu¡*z4F-TB"-M"c0V .,+q>Q8"e_xĈp£71US![/1cm$o FBy-V*V/lq:EC)ļg`-]azJH`&gcIՊȪkפs>㼨ˆf]F(kmϳTFK#B1(v ;W^K~v.xk +xuұ̐fk6&+K_l3K'Bi?b$g**:'[iMvFhWCRZ̱Dz(z'*ТFI4k ;\ o:4!VmzOԫ;Qnȴ{_I4 &~3+r5 3$Yg+-Æ56Ƚv9bm6A{v֬ʀpd3Xo ]w[AM *Է`L80'.hXB&B])]tS.{tUC=Zbnd:J]"KD.'hn>mZvc3h괃IC`]f>)h/idv ˍa8ߌ37 ^Yƕ#߳wflX\傥5߀rS%">P=j@.zF v3s}EQ⑌P(m\i*#ktmsٖrjՓv**:38S]r,d˫BuBQNLYfɴiPާ]Smۉ*Ǭb`>9G Iκz& 3)" -%w,eg\T!c[PHL-SW.KZq!=ܛ Jjʕ!Y,ISĹFyu.koJ]1E]JAVl/R ). @y̻GDC/`.\E&O_-ҳ+K9lrElEjyE\vƿiQYٟOwlGFw)iͶ]@{z$SO5H.|D]7xdwq+RcF'J2.y2]xJIJWorA ^;0 É#Ђ}5]]=RŪ:L_z7EJ%_W] |!ġR9Ob߿rѨI2grS=lDGkM]cT0$5H\'?`DoV,xkЪà}= >ȧ9?b\=G(ԛh9\`dOv5b>A R,m9T)a\1;3ƣxۺQ)'T@?h!sHI9gG^ c@@/e (>KhEf ܹʿUJ /"&UGOBIB %J.gKN-Oy`%FV[Z3Bbߚ7t7tw!Qz9^w",sFyNrf{~e$KtFe//ɍQPvBWNH{UƵDfշ,;eVjQك^=ITX`{bJrİJΤ/; ? /{V&ߨ-n3A -c,si10y5u1Y/o bovFI%Sk` pXǑG-O7nwsXփD[wAϣ70ɏ-U[{ { {Bm: x{# Ǚ'VK)MIUPJ/N-*PQAd+nfuX턓s2sJ2K*'ocSRtHm)\0Z#9`#X8AnL`Ӕ&׸˂\0͏LO"FC ۠eKwrKiP\O$ BGx qA^-O }'h+^D2 MEFD/4 aI cd~f 45L硏&UL$}چWE+5f<;Hnǎ6,`Yxh|f6f8%tc@R к0L}B6|A0ւ& (@{I(K׏oߟ SWp:<|g`gSYE\^_]]]}),l ep㱔G c#.7\t:? \װ6MݡxS rGQF]"?!]?=_i͂3eO|Sc716j0;;-b}j#c_k\0E|'7 xNn=99)'t a0wشDvj#1 PݢL4>(%o5=* vYv'Q ёC3{-S8c?zV }KS_Sxؘ؇gyR[o_VߠOq}gh 7HQ?w;M0f~1 %s2+NXm:V=~TεxTuf"ZTLJu_ľ*|fPmV]}p/9a^7:؋ф1"x(/>MQ 3OW =;3YoT NEW޶3&x9lzVo(27'zd[ZT4q4_쾗*29[n `\3>-Gˡ]#xJ$8! pjCK4K-_q[[wIdY~?X;Kx(`f{(+w0\zQڌ ݲU3X˰YcefZ~r*i*?R9/W rʐ?jՊ^v+Z_O-|<9"K B9z׌mk 4ջ p dCl|^^@|roL'>/֦7@UNZhP馹_)zQx)uySŮ[3HnjH% 7daE|m K,$r_V2R .&&>^>eײowY> $  H̰xWksl~]R`clafj 6U xqeS*!5BHws[Hl~s8]e)}j[צI|m/Ҏ]abqdoDw+FY O_V~(>S4 @JWnFs)%t/8(v_Tq'wzmdIMx]J!HeKKѡmS$E+-EŚ4$0^nsZȵl#a|\3jOY} ;$bKz,(pM$4|͒K6|n)uy K-CS6hH' -J,Lx>Iw4{`^eXBMzI?[{[^`6MOKwlp5v't7܍s`c lj*cKBZD| ;A$K#&6P4Mz1ng4H&.?WO5/OL62SRSզz]j CA KqtW&DI8_}$Y'b.OpNmՅnz9gAUE0Pc 8ZdY"{(DJ$!=kS")tk?SM~'%v&yZvkM_i4;3Rh+F-Clcn6:ڑـ0IQ2'6})A#{Nq(ОѤvZM/AZ2g:VnxjP2ޕk?C309EkC@V 9rJ-|m 1Z-aih !Zat-l}8VXc$nczqۖ#߾%$23UPʥyR-LODRyFkakk3k&.|"i6䴀N1,`ۥWgXc"h^d/8 T#8 =+:Uӧl"nl08˕JVD;]UB&tT˭zw5o@7n6Q{I'Z:ḀpgViznt# ;B/D޵U Z >מao4͗Qt8Й*Km lh} ydgJ1+>*Ҵ EXCnȩyqK]Ѻ% mQCK+vSb7HQ-#TCuP*fiu-7u<24OҺH.0.W;дܔ'j!vR7$q3CҜ%]bvRirkjiUH? ={v%*'N,;fkCeD"wӕqf%Fuq㦡"-7rm/ +y/ndϜd$7׎K@w.[lmp.6M*\Xk"iѰ"QaQMmE mgVʮ#1_ 4@5|SH5|fSxNN%o{]=2&]@dJ7Tr>s)))?vK8F0]!g&}UeҮ+*l2ϸ\2*YѰmBGȥXSDsYD`gmv?xy*Ŏ{QRԞ>iO2n}ˣw~aIRox$`v޶5 ֶ.۪e[5؋=l<҈y7sc!rƄY+mqpb ,Mo;ﮬ$Wx}ks8gW J"y$NqNEV8KLͦXDIӤﷻ&AJr々$:T$6\Y8$iPal%4s˽/a5$f=?߯c~/w8F0c4i,~d4KIix̏'/A/=wK^y X2?N/QeI8,`>4o9`vIp{a(p`a ) f/e`%)i9bdZ=\W`ϓh @|veLQA@axbĺ/{: 7^/ CR?}?}*w'ǣ_?gewqٰ0@PC)q~ef]4as& 1pC ~3&քN8FMC<)+V#Ylvup^kwIcO]rjomv1NS$`qOa{vA;[x}ym>һ0_-cIX3]1U5E؏YY~_x9;_<.r8v(r>/ּAY6:Cگx; Zi+rY'Ad_D:ERLt؟`ϓkO r42 a ? 鑀}/Pn|rb}g'X~YL|$.%T2 8JT=}b cJ1p<+%,?Þ dEY%$Uu Ĺ\tTa}dHi68ۿoΖa, 'Q9P&W4Eu''DAO&d}NP胟G8Mdz8co4mvG_HIS/BmYc#q͊C^SUw%1X6 qg̯Y0A,z1cvN Ƒe^M~c;WO` ` ;VQ7$myǧ}>ي8As~A4fxF'N/NN4m%F;₎ [hS~(OyuC(]Pyd+! {3eL5`_=NFFN`.7˴\sί[k~2(mLR5%:<C89L.tP5aWaȧZd%>+!!M7ی%@ ۮ[UU%\uGsAP $0b6ˠtO+E^sT}y`ӳC}C !S`G $BEUQÀY@a2X' n>N1:WN M S 'zo%L+ 0Ƒ60Pɟ*cŞV~z_cP@L(W(V2înZJ̏eP!Xf(dSr@Ki}w^P4 ~d@c`qu#UEtյPhdHسYW>CBm {?cbzRxA0qaB pZnȦku֎hHIZawR,^Q6E) E*7@3&JR%jHr@?x(s;+$CEANY.M oZexo΂/-jٳba(40ĩJ*D5@HNMibjE;r\ŧ=95|^a>k<UfkrBOI_e 7k=^#S7ko3[1_ۮCKbʏD_g ?P,]Zܜ~6>KbXL):쏼ɉxt6l~oUfZDGRVēP) M2'd3A[YG'> pؑ;8dB&ccN }NZ_0JmKUі--vij*LIm$h.%x, HuRcϞ %ş6iT-c28oR&/k34~qe?A;TPPY9ȓs3t_Q4JJ9=C0Q31-h[5A=C#_ʑ)jLsﱌV Mnwe^&$b#p\Ɠ6 w]-FUDc3!MHB 1H>4@Bo @BP]3rjs"lf­fcM-RXAz"cǃaq@LuQD<># O.apj/6$°R=j,ZtʟV!>e{DO1v8C()Pq ϟfϙJ?)nSAԧ\B1C5nq޸!mpslgUZv[򮭖[tg~ɥF^QdO'4\5d5$TÄ&%v DGLx+@+FO<@t6*5W]0f vr;<Ƌ ;YCC4'`,Xmd6¿?qe5+oz3-9{2ZF2ekNI2#pgfhT/Eu)h7! w{~Pq;T)FO:#ﴌe:{{z}a_~|]*/^;O<8`QO::ĿNiDD25^*ע"i/k~QHJ7{d:&(!e ķ)g7T^4&lLFqE jMXZ~e$bOȵ4b7IL9) ?M kAoIp_',/|Lxa:55 S SoDRCH yLU@A0:Vl_X t '? &1L b|U~—YI@)f\Jb0<"V46Y3#L̑Hy;}Ċ fOܓ>ccfE-(ų>@sFs8b]6_7 D:5(㤺ԏ "rmlő9Z?3h)`hI*iMIy&Q:S򪘱bѢF▵En -&j&qt<G@EryBiJTS%/DU꟞<\d[{ܹ{Ҿ*8UpOVTC5j7C$XhelLN6V뷤n!m-Y䆃\ ]RSg7Nq~췡1U{5uDǨA$ @?WD^Q.tm=C%5jB<,Ur Pa CWD73Ww؏A=ݭ fL8VT1fY~?p$}NSp#gĴaX{ݓw Raj--ʚ-P/Iط htj*6ՑS-0#C@ G {Ï ! Wbk[VqZ>f~ul/6+z,۹ Rpq2mӂJc:"N+sN{_#.t ndDŽj u!(KUcOqc(^= W0I8:IjyasX% )![qtNps Uj 5{ ٜqf)0. EVRv|hp|\ paS3`lWP4ę\̭]:VBɹL<$SBrYIOJS :>q3q'uYz  :KTꈴu?oii\ҚOrEx0sw~Ɩ> +b>2xbY(I"$gֆ ;H[FWjP{e,fHN*02p9#Ah-R}YV˃"R&,l1R2Z'՞<yN:z)QpEkz358ly6uh$$a}͞NŁl|͈ 0 IZft#&B[ƘQ-KyBT"_0sئexcQVtfV D߻44:@wTvKJnGGsNk21,#>@ V26TqjQ4j]JqbT8I{ thzng77wŬ0 k1bP,8y= NQ$y &xR\ ]v\ /!w ȟ藹X06ʂXD,D.wH&BwO!QQKg*`\bskA}whڸ̬TmZ7S]5k-ѤS <0/1?TOjGm!de.ڐN#5 rP=)p@J %kBG NV4UvVl8nFT`Oizo"O}2tI<^Q _-rx+`TVSb4))ZƋ!+nEBqq6eI^)+L%(!A>]Glm~ 64 y긦"'椨Nm(Eښ)o.'n3"TMb 1"6~dx σGW[NIveVy$fD>QRvs@NӺ+^J ~':0rB8Ǒ]^_9rvRIbOQt6$R16>5[K<oW(@Hx7M`: (9OU5j51Wl(nM|PZE99+2< S "iPVӢ"d/ >/"g0VV[z';;LF+i#2]~34 :yeeIE 2VVS{s騏?wG}4w*;sĖ!:Тt&3wG1YM25aW܄( mq3j6W'] F7щWp"KXTZ ^_^;yg{k0V6*z\\BchG#TrkIZpRo/L%'[X;#Q#IKc(qmT1xb$rN^5#hIJRshԛ^l3 K&M$k\>723DvT$E$yZ[&їetMS,6jΑ,M-9oס薥:TiET| yS}?6rmA/ˇA0 zZmpׄXF.fs樿(p ^oB7 ppJ[υs2 9_$E}yB4@`;GHm3,Rm^e RGc{.eTܶ H'LxG8@fںp#frywaX/Sx˗!Wlק"MwPh9 6"k[&i|&8aӫF> {ƟdѐARʛރ\6֊F'55]zbgQ5 ؂z'^m_;OR>ȢyRTl_áٔ4QnJjE)` VVE0o/X/%` :TY`"toZx$/YU{0)0YfV?M*MPVaZ:'tAEe;nU0Ksh[G3 dGep,Lr斐e!̼{o Te]Y`FUiҎӣ3 !Jflǂa!YOD(XYQݱ4IGy-Zv*jsjH&UBw RǑe[=7pOsN~qKjYfrDE"e/0bHMv۬vg39&lRͮLnɌix_? = au/f&X a.Y60CrZ k&kvG8Lf\"3/d5 ?3EV!=$>bau`Z~dX'ExK 'o^%8/k4'Q̷Vz4XjE0a5gjI|JjYfrd5`Q`{d%kx{ik wY&k^PK)MIUPJ/N-*5|SqyGYAmF =gi34$jl ?ex}s8_d%lm^4ɝ"+^d%MLhHIݍ$HQgv 4nY& k[7l:쓝t0C,6bEd/|\]dGnm5\NjȻ]'.fIexwցF,wYF˘w򚝻>Zޜ.i|fk|D1vAأ𛽑mFi'ykIZi/>\A$}vuޭf847.g?vpr[堼2+d# > Gُ q8Lxz7 ףބ]]O1cSr@h؞ˎvGxz9~,P8%dyw,ў"% Êӑ,aO6sH.ˎt 7_>ziOvGo=lh r{><៽`5ap-g^}B' ߃}8(WG7Z9zy>!S|e{w^x֛ Ǘ,iDaBP{}*I*OS7 5x9, ퟬ/ٜnx">rlw'+hyC_0?N //?'??.}?MƟIߟ&ӷ+bV^+JΆX픝1'q{;"FV`/nG_olط; kx֣_7:9o*+2ă>t;z 1Sb)Myo]E*appE)IՎ];ˇtuD: +>?@,C +ru -κŜ5EkOhԡ[ݲ;&Ң ZLkXY$SD a3I;zM5 2$uw6>?A e whA!9(H(h}\2p&A$:55*y r_߲up˷Ģa$!VVa?/?1Jm㈥#Du8|^w A:prﰼlǃ y;7N;& Ti%A|9Y7>l j_HNO#k?tk}>jέ^ eaoX^(a{ vY3ۊfx:1h>EԂ=Wnwo-?s6' 8| Axj_O }"(J;m64ĈU{뙝 ~AEftA~', ++`YSt;0r-bk1Za@F/Q7xn{@ KU#RuqjC\$%62k1+dӒڂJ@ц!tN lr=(oi/`35:wX<']j5:wGpP:`9,D( 6sl[vpFXMåR8@8j%,QI. G_q 4^XP, 7WT )HxFicڔX˦"ӝ'rwiSiṗޘE0TK@ay (*۪K? w͚݁WxdoP3nxs-ə#wvP^5ɭ8 cYjqd|XÖ.pYz%|[J? do)惛Gzq,8+"VvM+p>kbQ$ @xAUM`@仦xa$˒Z; ٠E8n$XSAP`z8Xii ?3N7- R)Cрi.l| :EZ:uNOԱa[`y8Ͱ1U4fx9.7&#>[t|hWn l8pZnmގMSE#FL}n{ !2 B{a+{-EIc ʎ@k%˚mfvB S'M [s|cog8Ly)91(}?1hC!j2S|6<3<6<> Fvbxe8~gck#YN%|i+ׂ*JZC%5ʠ2"{:C\;yj,ImUybԉźLנ*XY(9䃮nF/smy @ bD n}T#ylsMslqx)c+y7Y+CC#^1jZ';rM4#HW&eh*[YS^tNy&^&4 ս!!swl.X3g/lǭ8t Z-DM"*m KЬKWvW%475p; ժ3P F玏IjQ*3)-k4vEW//Ϻ;aԽ;ONks2k2'<_˙B>qο#qJ /};Mu"j|(kaOڇg lU/h XH AT!f &Odzl&!5:9!/9.ĎsqHBH~ eDÜ16O&] 7꜁U>z:/vj^1ރZEw< #/‽Z~8܎60UӋchhlحqqѸxxP6}ݲj8Ƶ%?yˬ?l1׏]97n1yvO&#3znEuPRYj^($}m_Œ[k-.h$!ѧ!Vs`1 ΞmUoһ&d82eCG>SÍt"Z<>?ڛ^g֟6:籵ff n7k %#fbllӈ:[ 3"_< MAΣ*@´' {bh/ؘyIwt< E紎o&}ν7^Ds`4qqMCqT9ճHh;㶼VbzlWʈ2HG֊$ؑnf{[kwK <*Q|^,QsʬHX1^l!c&xjgt&**+7uwL@F v<_a _/vkԁ (bI;C(n^KxZ/ؒi4Jo/-] jgTLɗw=:-j"uGL_unuva>e.=W)lFG W4!w̸f:Qۆ;RdB8 Zo}Ad 70̻lzO Dэ.x] V}@[sƸ{4K}sڠX :Ƭ|^)|8ĝ^|Myb mU-Xz{"\ mh /kYW3ӎ"M&_lÎXEjb+}zŚ]3Dr6<MY˵{÷e(MρprG*G= ʃF/z 307J!7TОf͹^o0jb0Ww62*"dpK#qag1&P2J !,ZhR*u-(q1as ,r00^2W%\y'F^ltDo :j¯,\S~p5mWnѴ|]/v#Mts6&Mt7~h;dN 8UJQϼA-Upe'JOINx<[HSv玓iN(ؼ$Iب6MhQz, V,(XK>2deuZ!wn,d*yԑXJ(gyW20Na{UʯJWz͵8YyBdMQdޝڱ3o2#9ѶXCEn6I)MC6kvfϽ<`#z\ca1ۜ^KERW9%"7\Ɩ7MԱ#9ϣq~@ 稷*IPްIФf'tpihւg8z|S%N, "ȇg)9"T3; >E2v/6YC\`Xd⠽ËԴH=!؇;adČ#3YnfƉ60 #I}3_2~}++h0a+& uUeY8n_`o 9ٟ%S VG-}{ppQX+m(=YJğiyvn]b* Pצ|=ђE9Cɫq$v -,S牰v%m*u l!5@%WO.O9bUT*){3(j(k8淺rqoh@{$AmWz6=ɳV`t Z1k-(zXԔJp@7c:xẚ֕L]WYB*Oi/Ol0*yAR}o{Kr~.1Tg %KvڱL6M0#bzVV&Vo9/=ySrj:AzH[v"T?g=>~_~%PC٥^P /t`:0phi0rEH&P6P[k)$ʰיW Im#:r626[=H' ޅ5R豄y*na2L@KOץЍŵ8$8ăL&mM=yvdTq:m~΂#Ű{%b(UNufu\ul_RʰŅ p$GPb TH2d;/" C/rA<;Pb1wB}cLd'.Kr=II!Qķv\N)E/A+]0D㤈TH0 FtGZ5!$קu9D)]rj<Zr<e^Lb_{n~Iգ wlymImUWkVn"P]u64Q WP3˜̩DK9ݒL$r/Ze^ SKҊ ŭ*ߞDͥ0/s5dla/Y4_Oʦy xZS5PAh7+( *|/yt^ZjlѦ]5ޟG+*`˃ApPh~D]҉D V#Ft Ⴂt4Uw?ffEQA ^m"8kW>=]ЎR XR T\Dzsae92ǖ'K3w2.Pv܈RU.AbFώJ|(1&WR zӟ]_ 9}Ipte]5.m X _S0"vw,|Ax$K^MP)iPnu0I<#S쳻#5`G T%(e(! k74U72.;m.p,ϱ3> 6-ē.,y#R"_uwJ8 zA؃4]< `MILc\US_/n^pIQ4&86KmydRw&GIqNMO>蜹#iё1kK,~8'A^ϝDpEn:x\0No |'>4cDW3! >B$`w߱+Ėxr:Nkn|$Ǐ(S*o Avgqp8&+$ %1xx^D Sq>%vK@7bŠfH8+19x'gHJ`\`9oN x:V[C~~{bla(-fNT$&3#CM׉Jؕ b \FZ(޶4;멥BdxU!0ԛg3 /I,[1}i,)dnNl dMY'&q%.)[CQΓezL:2ߡ[8b~OK"Cܛ]ˆ<S!pEiجɌj[ϦXg+t`;)XEb&j^j]vYE7o= *yMvCT3Tx 7Ff<ϟo+CyשckG1?vMw dQ*K<_{б'A, OU";b%zbl&HGbY"8ex9Auv`W$6jCˍJ> \SJdXd-|RY·) +vI갟<-qzd5wvTre'*w$+:ƴB,%jR8T]LNJ,>e]ظU@lGt KЩw$dTft*3xkيJ=.BK pH,v]_[D .!5Sx1ܚ'T#hULy#1' 9u=ό閛_`$r9R? ;BN[;{8%8rKqF?.( lx1_ϞJ3e+T8tX30>㇗uFN &_CiquI%KBq͸OPGY@)KFo ItJA ֻZ'X9˸w+(P1u@#"[T{2á+X+{n*!PJd iV(Ѷ T!6%ͫ/Ԙmϊx:o+})8)TR` |bߕy7oQxT5T8d,:zg{೐bp˺Q;4 )4cg/{}p:^.Ɲ99Q)%,׫޲/U6J&Q}+E4ȴnHjf~U8NV~"COG^:]J"vj'wڜ^ @#f$1,}It"h4\ZU[^ƗC"7RbQ2jѭGzOj_~ bRGvŋN~5w=nmOjǻF/^ouB{X}o;~݅u|3fid0 &MW4 _%Ggw;Q.s+z>-dֺXdE,iu{Sm'8Vn}V[Bl 9bk ^w}ڬ"fM{/J%R{C^[aQ Az ,-]mM}Jjc!>9aa}_3d0ޘ*ޏK eH=VT4|@3k;LȀzn]& k2LA+mz KRnW {6gTiln^lsRp}" ./A뽆eq|9(7 Ө*/NaYWWH"J61F^-%baU-TZMV9Un'ǭلGP\/5\wd(ޣB I-[d9,TB*HNJjWsSܔ/~ ~x{y8+g~Q~z^~nf-Vw )xW]o8}ϯݾGiZruiJ) BRzw%$3>g uj+Y+0\wn`Bx$G1Ka%E$pJJ!IKdLQ` BR,j\x@%rp }ʩ$ E|xb>)z%1Ew<] (&x(C5)>Mɱl$JG.A*{0cbbD$4̒@g k85XCwEg 5-r0DF]p5sob?n4p(80ck5t29CuXT01$-ϱ)F516>vi2y.FHiY}el/K1I )44uD7NٹS*EY&\ dUcdoŞa\;7;̲GH{48v@'Y@k^k.&l _4hnF ڊt̝{'P{~OxUbӚ1)jf`{`GqDFu@hJfy=rv:7&:|4=8).ɾF9;wE^JdXPSI*4t3WcSDZdk\+ coL_pD|K+gab]}΍eyk=dmaͺFIvx],-j]CS>|Syhc9QEaCd}% ߦ3UdPu)|Y,|=>l-H(᧖"l[OϩDĸH<Z0*lq>UEW E O//xYs[$N줝NحLA"hdBw'{߻E w|8p=1w1XtN%,g3X~48R 4fk$$'t z$!ԏaQ( # [eGh|68"ϣ498'B~) - )+FsT~eQ" =Z $1eqG@0|ף Y5tP/R%ODAEU!2E|pkOרb]}/}wh;|M5qx:=CYD L1$܏b;~ к8Dp=m>9?^<i2np3fh4| reUJv/`c? pN&>}:eʸɧv`XSVp3ȧiOP ~ B Mfi<Ņ):gѳˣےZIS1b*>RX):4'܋Z=p%sL?~=h( d%s2xO~E3oP^uÞ`V ?k4 bfJ1*, ch><7 ZT<(NsO2[K7h 92elӄYj6X5J ;^bꐨm8?w}o{l)`hΜ>w-,77@ yDnH?)!c`}6ހX'zEJ0zh(˹Ih-j&lJjbc{5X`"ab%EmOTZ5*S@f#b4ßx<"!/\\]ʭT؜[UDž;Q~šemqL _b9M1=CDHO6 #4,˕$Z. _\硁G(03'׉aq +k6oKl]Dؠ:iɫ < TY<\1|.FL=WYۇ =)4GJJT6"y4dڭDZkכObWۅ|jw2kb)Zgʶbٯ[-HKEDeQ,'x `3#'֧IuޠYd*CWfTVe幽EW"Jl 4-:n$0vtLy\㆛S_\a (f~c[g?WLrŁ+V6妬'.zlrw Kҫi4ՈQݱ'h>Q}šٝe[Iv`*S*ՙPyL_[J,rqTi:KF?J\ecZ !cu]{M&3ǧ#r< /܋j^U* :~-2,b*AWlnR &Y-40eG 2ʵ!N01Bk+B=o^ZVV$"H?BP6bWpˢGlc#;DԽ+QhA:`B4_~}FbRb|: vU^{BB8@&nu/ 7R%9 ȳuߛZu-B'OR 2"rU>^ši/ڡFv`Z+ ۃ@xsencEȉ"jeoH[yֵP"5ɁBoK{~qD|d7EQEA<Ƚ%2sͽAU5  *_F`Ma>RL/?V^N0 ibhΆ䉯c˥ ߐK`b@/oq,C͕m m]Or'C+_jV 1I2] 'c;l84!Pq7b,`=giMwcx2qm"`^l 98F}qd8X*,03#EmPki笊$ӬfCoy$ /,P/A$Nb[`܂;^d2ނ {=,A%6Zo+t&Ke_Ǥy&m׍ls010RK9\]\ݫkm/fWt\dM$xpin$dE84R?+[)IO![B}1NO<(}$r!ղ7koT==0g`Xya/o xm̻ ݧ 4Ʉ:~W"(>(Ѽ&H^nDn\5kA}m @U}g*T XUX&3{TU*"\UO9U$Q2SAUy\;~@UUATY VoUfGS[z$/U`LS?hkU"ii_.Q.;.[mF?q1qL^#jT+ii11ݗy9KKKԢ*MNc c-"0dsy LpH o"1ѳqC<}͟a304VhƼL3 hG7@{}XM$vߛ7vhMzsm{1ƶuCk]Q*=dppp]RG|m+7m ±?o`9G{c k-3338A&0tOr.۸kCm(ǿu r޲9~||Ѹ߽z;`SRXYyX<ՋM@[s56y޺-e·6 scGt4 IENDB`}8xrPNG  IHDRw=bKGDC pHYs B(xtIME !HIDATHǽMh\Uw}`B,D]ή;Ak6E7-FOJQ1.B:şViZH߻3oq$Ɵp{{sy+oNIz0!F;| [sZi!q\ߖX[$N i/r7O=ЯLO떝"_57M(uHGud;ZFZLPdxG"~Υ";nXkSC"꽋 E^1""!έq[DMaafyO,z/Np.c50L%`a rOI;K粒,/QVȚ:o0BF ?H:։㵬Z3h:'3w.KKKmR Ey@+7t#QZCiCAc|Hq>8?OM8p{~]C ?  ̍ʯ9) MZ^A.i2<v?Okh<#( Mly뮗xִwQJACT288#cRljh|t|i'?gTz{4)Ji0DkOǎw`st)t'N|0iL8׷kRwu[OO,.VX[w,`MG@ѣc GNͿ ]VD}ɺm 4}=F[kj>z}tM/keŋ}Uھd6IENDB`hhdxBPNG  IHDR szzbKGDtIME  jVIDATXkpyn+ q"TA.PNUdg:#tQLTL/c[QT*BBj  H0l"Bfwl69y?dO[!7{;<؎"ڵkKwe~fj"H#[nбao~(onO˪G9Py+Wj3y#[>%iWJ(tJ*dt 2p{~\+25!RP[['\B#yCꖵ`pujGbY&x2-J#@~"'1NǕyZB#׳~9\mQ c LL&m#3RO#iz~ y`77GIbս[inh/FCCC\vX,1m;s H=0s Wb~ Ma&Α(-[Kk(@ILʬhEkyH~`aͦfZz3[sE@D*(l{2wJ)M@+I_fEʫH Vox}]:9vf`PJJ$=|zJORUW~ 31@|0wtQ~O'=\?AkG#B:"9E+ V;7Et{ځRJ9t𝷣Riס -/O;;LiaA7>ANJ]::s  8K>̂j\z@٢Ǖ),xTeߤ0-cU"U+ZP\rB߇ |E%066}Hkz栮9 "k/3{]H~`\1>WN% Y eb۹-4x4yW>L 3gey.?}6ue߼|ٛ7L|1UO{Ou[. Ǎ:Bt]GuҿD>_`&C<Řhl2:7Frdt~`Ny#ѱ_@V- Tv4MZ ȴqz`Em[GQ><}=RJu+T/_;P )pj΂/hJ1@b@:%R:W^{+_ZwNʧ ܤt>'qE$ifP3[~L&:? ӊ.Quai˾hkEyeE3 oZVɽL97| 8ffc* p*Ρ|C0/oS&r7P3"먘Mጒ;c|,|^}8,n/?Om1+iS^VtcEIn.?MWx !^zd<^|,Mf З(CIpDpm^F3Td[H-fplh]@狱_7q6^ByT…oeP ٟ a%_/0"Լ}8[I^'' x/ԇ9#,QslՖ%P1*6cdfῚ H1aD#,^FЗ;F>F~3zS$${'@# 5;T :sOB}]VsQV0"v;G8θh&qeK軃ϒSw;$5021Hc?ˠ]{k43 /`܉TDai?hતAxnFy ]wF;UHEI6IorJy$> To>&PZ5{iج@A1qD X?pjA 'R>=ԛh&![/}h"ƪ!/R5qV/9nfû8Lv62*:(t fˢS7¶.JF La&umdej-fHjLoeIMSfCutS-ͶT@l;n/XV":}:5I.C}ՈJQuaʗ#IuQ7P)**0(Vk?Yxs5bqi !N0&). W77ah z&j-NG_*J8It"ѸH/@m}sQxXfq|Y6۰_דW60a#sċh?߁Xua?|HLuox˝"5/8=WLYC|wKI #4cE:$"|-*x8{_Y%qeqvTdž]zԗe |NW,awY^*Nge3}}D,I}}p@+6K΢lc6;;,pd7Iu8׵߾a]winAkߖg5%u\Lp2(]fvTk속Kn;9[78i7aF0r0xN2i&h,R?#XNx#4cP -!4:Au7`TEl{guav7Ok~8<{K;*5&:] VYտFssq;4KbS:<[(+)gydE{{$?qY<8Z2=ԅt<|ItVyx38K&IRk£27ֽݿR~ZmԷRK!՜IR>/\#Js?Ձ8ix 2/b`v=I4i.C6dqݩ{>mNov'}*U飵6 m<?O雨`6o&0Jw"4Z)&_FLPDšB"$Hߍ6P );v~`P9ى YH՞X ^Lqn]&ne2^ILP3 v @ fL@9r*J5me&eFѼ2gZa`yzc eо~)Wp=u`9Ye$N54\n$B60_J IJ0hʞ\`QމPL4LkXM%ё} Q! QQ8#ؖhkf ̀@BE )4F iΕƊחCgZK e++}00L!WWY`$ȑ-2?g@H &]oT˦+!^TRW x5W}9~>'D[{w @P4z;+~bj`8.XBd9ahw@oaAHHAJĸ˖ 5:󑗔 bAyP@ ǦCgy5:ΑhQm~q_0vI!요ʤYb `]< >D>KXEVIFbLlu8$  mv/U3=ǝ~Bkΐ*(d,:#'{Ր{Rb4^ĵ#;3YvR܄[0B:)H,X]F0U cA X?(Ʈw 1rѓ7UegӾin1xPm+^2F4`i(8òo/ lNgn틛Xiwn'I+z:0=Cyb[XW@?x륒^ HŽJ>O7}VK)g;%}RUHx2 iۻm "璉BYo-!8Cةd6'ܴ}?m3 3TO#h >L7R6%kQ;UFODY",86 ˢad-YH_AWxuTMk0W 4f-Pzز[T)]ڐ73oޛѲ1`/S.h3& /0Fj @η8|<4;MqJ-9՘I f4ʔRQ3>:k}!%mam`#耀·`3'u?ǧ(" }ikc?B n[d^U1qCJe#Ey|9[4h[_R1C=NA뻡( J%v6I*dkbSFo^GOh0BrNƒ[e1ahVWڼLCN n wZD}%Z6.{!;0Z{s(3)ש {RSq '_]r,ƚc\baPb7bOIo"b.rps׻"xy#XEY !ъcN='Wb'V[Ԏ`6O&I!3s.xhܿoƄw4,`4a],/Tn"w$n~D7p˅Nx^dzߏɏWpoJ=@uP ee6ondDAmd\k6=8 lN?m?xkUFX+оxWmoHί&RtrDPtD'kx/^{/رMJdvgfgyfv|٦nKi'6ݽp>Ita1 'auC!il4?A9lUܡ/Lwh!*HxtJW}:ȈlHsX\JEEckT=Nǐ4W̧h fAȉhzl1c22WUtTHi"3z-{ \Ty@m{r۝xo4bh-QߎV4^Fc,jG;pWב 띖7|=7yv\8k5@ Rzѝih<+ؠ"%-{&=&V59S[}+\$@~̡ hÇm>a ٸתQIZB3fMt6nšG2JLn-ڊPIMz\[^ b0߂Lwf"fB6[$˵wZY,8Ga'g{Pio$E`UI8QC傏%-9.dy@2 =;0û gZqy˥QnLB01Jvst0:y'1׎3c~#TfZմ=)ՄV4ĶJeu,Z+b=z@m;'{hO0Jj=ǃrT9Q~NY ^ax>ǃLY_v1GULW DBl3Ki*kMԧY53TVLcg`bֲnfA9hyDETspfE';OJhVz^n^^'OQ?1S@)gdbȫ1cFj-UT5,dsKGī/JuhQ8hQCI;^ nQ:m{ƛ*p!_O'P(z:QYr|:}N.|V_g<kO{xi+w N枌c?.=_8ծFճt^ys&< A,7xd"On<ig=Wlc%92*KQJEp<Րg8.TTxsFWrs-Pp3 >M=77!->k{oW+i8&#zс^7.`؇Zm.>pa^Çao+@<-= YCzAk؆oϿu}nyֶ~g̉/ŋ a*` B=YޏAF_9/C|#D !+q3Èy,\.am ,$MO s`)Њka>""{}`Ȃ. -+">w&4׊rسysԽ w(POIX2C.@`x?^_``x#p-{d\Q=0[\2x3$x15sxx?~vw;7bNWb[Po,!r:#ft|Z][ 18W$ =TЬCXĽu[G$F繱Xy7|@ mgǣYűMpkgzhμsj<W;heB!!v.ԭ32h2Ox k@rnn^o4Cb;QYyFcЗVFb 5X )=ޔBXۈrxs"?FR Z)gC4P,#ikTmH<)E^ } ^&ZJVr2U2At񤼺Ejllt8m;Hً,æٕ%PJogj&!B_cM%BQNHb1_`k91zl\=ÿ׷2ߩp)Tv 0v%L2ux5vL|ݲbR!#t>oR[4²|m]k?mDsjlBuOHv9-T{<2#df-K/7iv UVd;!K;TDi~8i&l+xF|qY1bbNR &uJ åL80˃ +>g |.Ɇ5-i֎z +ׅ9i*EhIܓ ҁ;IşqI}F (C? OAB~ɋE_)V=(jfbZF)J0Nۨ&#G71R$s񜂡ˁW HʪPV)iȠq&fJ}.~BZӦ39O?tc4a@Կ~^p2uwV@Iv0l.s_,P}CɕH$["&w/Dmqv9%w̖v!)SS5%F2:tCD SrɃzR#O%lU'Q?)fx*a5ft/u}p "x{*a䛂NiLb\$P89Wc *xmQn0jjV )*>ɵ56 >#Iq~֡![5`[?UC!v~9CSUh Yn`|E99A|>w:yy7Md0UGx}̱ 0=O̜Cq-z )IEĥDx$ݔW4 "( ,Lv]d N.k׸lu[m$k] Gl^:;+&QxUێ6}WL\ +{}}(dQXg x _, E"&g}uop C9s<#ujA؅A,[`8><`1Oi1}zݵfd#G-1hj.֐:B6H ߐ69s$L($ ɯHEF3}lmtm{-(8Lt`(万 (0m-UR:BalU;= i.ק+9jۤE7hl F!1"7\;yFЫpYihMeZx.IITFܣ}'8m<SWxSi `Zm\D@E u՚Pk"K_Yۿe bYHYđ*xdW ]$bi:Wx+'|B!#c ysqt O r`* Ů"su^2y?o\t&q/;mRN˲ ]Zqjhժa[lqAOh X_SEo9OIWOGXo?zd1 :t"uרV;4C[O#c$:3+G=`-0>xUnFxT# W~Ud62x]'A>P_O֙1]U+R읙off9o֠ 4[ X*oh;jЅXq)yJ!3 l*G\*BKD YZr 2P0}̕$(+P<h\C, 0ha!D!gi`>T-CEhjiNE1I x!A3gRXjYj7$m?yBdqPWk&A:KP0eeEO q$"A*,˧1q&* PJj"^QJfl|"gb *Qm9gPY_Q$2I9WDJg6"UNB'QIP6_e1^ތg`hгmX# ۆ 'L`^AB0|~.&ӵ=PY{B#Ӹl+ Ӄ88.L'HKRwgmw }øߛ]˰)gyf74t]7#ge."O{@X\&v@;5ձe{EahC Buu0uI s`[w1-0<˧8hWcuS;c84L߃M#{..g \ǩh6O^~m< ?a&$aP(X̖xK4i?k8yjh,^ 1V_*:B(Ϡsp* lUI,i0 ;7aa9hx}nӢ>>z77Pr9}߾}a.>'m!.c LJ\\p :Yu &Ĵ)sրS\Ao0 iizuwtƶKzJyF1팮oQfHq!;iM4.BM 8i[nGB=k5ZĦ+%~ˀ WCrYs3׫~E*୒,ؤP/U⣲ w|悱ImBˇa~6hne^zZ:Ԃ-k&F2E5;/Wͮ7Ng߆KW/jExVn684:H߼Pd KD7 %&&I%5>^cO;Z*C[""ᄏOeYfB>,JCf ! q4 $l,0vw!YSt:N7*$ ]С'1NFas1O^zp4os@"+޴.ZV| Q2H4Yμ v0YmM-V?W“%pyvpJ--,?=6Barc nʃӜRX,:\lrklleM/'߈$5xaK-R=C>)r8!f.$yDSh}kjskdctC.rMsV-ŐMRCJͤ(͸xHBɝkOyOJd_h5ބ|'Gz\<8QoxBo47>K\uћ7r;9pxݜ DFWף!,p`ڿއh u'0e0PFއ'SAp:{YzЏ#u'7qoF~>\hJQo\Tz:A1QƏP{ɘ!nMqāb4Ho2ŵ7q7#)Kd<EHNH1S'9}`[Ƣ?qԪͫ֏< l縉p<XAcem_xՅs>4_%e:=Xdjl##_P13?}Q^wt:V [Wopx G՗S&r0#נ`ЮZixc~a% [HK{BA2Ryywu8Ǝx ̺/Phhy&_`$M$cRL|)|k^ue.+o3X$Ê+jRH#JÏʽj}5x"r4 =(x+Y*`c7hɮ3uT5G)|ijU@AY(N`k\/dIBq4!X:e{?[^ HiU%2u2V[ͳ`8${鿤L1b\/ n9hQ`o ׻a׹sTtN ;6qI?H'6q3oU+ap]c狠`t L"6zS$r!",g4ICQ14ljtLc'K5XTL`5G;+.5t FX+8 A"9ڜq;o["/&5$;WFQ ~`jNAMzC.:ۥ<.9,ctkl{Jճ;C[:5ǰ Cm( "Ziƍ5 ^)ߎ>Que&]Y~RZu*^K'VSlm|ѼJgPWݲrDD Jvqi|+ kZJ 9q0Wum'֍ZToWnIR΢Z7KU\Hm1aRMrpbN 0͗X(BwO-kpJgfo̧+I[>`]q94ܑ9\ÕKOμD%ҼJއ~*SZ鵆$5pR4JmK?G." :TQ,pT>akgaHQK+b_Ȏ3K/Y D@YսKh+Oj.Г:5.2>S Yj=eї,Jw*0W:A~_yqpR}c9St9k⅂my&# ?xx:wEHD]L?ou (YI ɜA9]mMxUhԢ]4/ul qRTU QcE+ 8PHTYV24YT#(5XUԩd[|0ȱjseBuۺHqRҭH F6yeK[n%'Nr:r(u?7+m"c޳4vqN,Ro%!݅LJb[PFerMe{R9lmw*FUBe6nG!?wW6<ꤨI=D]SgA[d(2!B SLˍ~W %\*+I4Ό5b?9t"UZI]9|.ynB9)!9}ԯb~Yi#%UWERD:uSi~C#r1lhbά̌9h8AO=74]7SB˸|(%pf^jPތ/f R;uZ}h>^إBgþVZܫ gQ_J/j1YQe$%xʟHk!jJ*[ az {uj6"yਗ~]pVF,:JI憺;lc0 a0/I~ bKFb` 43 qGp> /݇r1cp] x4%b?tJ[QwCxw8AHa?d 8JOs%y3oB61WIyH8gi#uaci)%q\qMо'1 ?A3a߃C#{n~ߕ :MRT.Vܧ $i/!Pee 汔7+TKkEvlx1mf\'afeWcZe~\ӺzO }]Z5gj$mUAhTnfFEn%'g4N)}Cˮ;҆teN7HJĢ/ލQ?YeG /7} +L?amI:Wȫ(cEmbL>s#3q ?eN9D xm; @@=!"D"af`3H^ÓH{޻RbZ-MiȎB*KX6,Uߘ𲾪Rω6b,r}رsl&8z=FD~^1J~AYwt"=C# x=MoHvgWvl`̖n㏶i(%LJ[$e`OsCHH%{ cOAEޫe%yl7K="K{^zUw?u66w˝VJkm"dO**)OPC7`>͘'XKߐLyC-|ts/ȇa@s3`(ï cr'r"rs* d8+WmʀabGpVdl#h.=_O<W`$␽Q=@P]ìqrxtnC`SL\051MllK5|]{0ͭ"jR#Pf9 Ҁzgy]Ymcqf\LΐHEXcr$vLJLJK~R1Czx !xƒǞ0[d,&9 `TPrgCX4fh2<쪶 |?R>SYo"UF,U}?R`=T<:/@iR"U odKJ#GJxd%L?ؔ%!砮%^SUbf/!X,;5ȱa,; Um[shMw{#sQ+إm'ނ5GP)HR,QvX0ƺ 30p!nA^^ UӄJc90umzw(6o%)`J|A|FS0>Ci?*ݪG :j,6Rrf>!odU#ޥ#N&%G:I|s1r$aQ$a1HYs̠! r*吗2ٱ j`DTg!Z:{y]MI{DS⻝ׅپ-8+*W'JKصaYHY%8?pC[$6%KSMCH\)U煛;2q^wZEGn]U2-vs{1*XBAfyº<ހl;E= - J H 1ջS؎Acxd`IT 7/q Y6Mp*쪁?p;$oJJч2ڃw#[b{Pg|d3җ}q9q]30EX7BUL`?L2LW}6[6roܟ Q`pѾA9FI),zT&A?=8A@]4J&,>Io7;/[6k5kC:Io~\|[;"GgG@R۹htޱ:6SfὅC2/d0Y8w~!Η> _^yYj+{//twtkv A.paSrgtZbMxeEcvtdphfWSey19&"䘃к(7WHi\km=&]LwJ;8猜 @|*>] ãفbj`cqy{+ToG*C+HHap%*N} o2z<+*.)jwc+0 'a402'zt|KpisܒI@UQAd 8nrqQV8R/;h猧Ä8 pmm)OPjS[2=zkB\뻤͒}#2@ +ם;M#[ *:pCn4b2P<tɼ\ wkO31 V6'O`_.Pa- x_8P_ZT V'D tհR*:7 lCuH\ xbT=0$MZC!jM? O^|ce?Eqbcxx|Ls˄OKG#Q!P6VFpfC[(ȱCڕᩖ:Wc_dY@BuQ/`<}UtF7eOPGͦyp+j:iq6u嫳 +b5&`!7+z^E~rtd81j2Ιad[9$T?ka<=[6 iSG,&z9 9׶e1T* f+e)8C0#aR3E+ʷGe ex^(ʎ)xPv.->lMwZ@dK2bAvz$┘éwc!UϚʪS#jΚ.QX|s> g 9,\/Cyc)uWh3ol)Vljf^VS=E@*:TZVu) zfʝhu?V,eݢ[ צSH`"ݽaU&bE}zi ʹhD"/T^(- 61!PV7edA~ZRUI/¬]U[+B] $~\ h}0Nk:ArU>s_m;~HD q1\Hr@ݡ1W 5X0mXgvjT맩vo4&D3教2xY fa'/7CIfgC8cly)/V 삷 M.뫂 @j!É4'ԑnSmsm6#ֿ=f!d3sjY_^rO_Q[+v]r(oEi9zsfLmNq d_5}A@LuWJo2BG&YdrXfd*6`;Ѣ E& #P`{NOB=abeΜWN>q@¦>ެ8G\oݙ}wѯ:]qG`ťTqHbaKLa*W^Bs-{zEEs-`L.)3lDe)L^ xn\3f{kEC =NƴmZU"߮^n5Q^m -}ž'%OeP$e&SEݙ]eeTx,(:Y%+BU5 ݹx-MN0 @;G)3 @H@H,+MI ==2#Ɉ69L).1, 1de$4gخLdL|کbS0YsfR[qNqo7+ a##.DO DD% C Dҕud܅{^A^ɕh@hn֍"CL]ͱ ?_?d3xVK0W]؛{ .moŚ"zi#);@boٛAa @zePٻ: lK;|g(&DR1VqC]2V2Z}5R^xݠ1Vmi&KeW7%pbkM5\E|HŞ.ܙv0j.A?A,*!_'\ZTɅͷʛñ2[ԙ7 Lq {5pnT@K4h^xf9w,vb+Z._YLׅ8)5Rx*YlC ғ#9xҲ3sr!d&ͫ9 x*QlC қ#90:lx*W|5|lY%k4x(@t扜 $x1n0 EHZE:2 EA] ]HSx#h, D Zc (LLDtX0{1ׁ x ċ D0LX n†GY!'VǏ'lV[Ju c? 3w: XU uTR݀&N%[rŦ pq]ct8-Ӆy%7uHMYr4Qy]l4y-˽?c\2gԴ^RF/U'Z*t2,z.J,e0B%#QѷQ!& 1Јяi>Ul"T9Ut/*Na2@gXV4n?kI~z&}e1{2kNezAY5:Wt|8G~G<|xt*/Ҫh]wGzrk`GR,C!GyFbcW)t{7_tkpqy 3:_s-L\3-QIgG9ɚRd\VQ^??)?|7DͿ^\ \,z?D{{(3j!*r=NsD=˥|o~#9U$DnQQ ng5 7=0椡m騏6 ,d)lNDž{{/6ތ\fE4.ժ ^oLnR͑zLRQn7q+)JSl>rVr<x;,,x&NxH5=Zr]r]Y"fKxqCL2q_hda&ݎ}`Rᄐ7j9;>+JlfXz8=nG5FVOCԢ#Up l1O'nXU*~"lUSLPˢw|[*٥i /w{"&݈MZ]?xȖ7cvxalky/=l޼coptdIh53[g!WE&,;Y`Pbm,tCG-9qJ}saliD,f>ΣZRuF5S35 WxTe^l(3~>f"l[1QVM+1w=zꍆ@of'7pEo(8;~BpXq l}'vR] DF? |QcǰZ"_ G}ljJS vH-JHVg]mٷRIvbtNXN?'F!!G\5Œ%9e!,9f\*탍a)ЈZA* |0"@l;77?ӼvqYã:`adXDcÙ!HT͸H&3`kL{~oğKKb k|U뭽DUU:UY!}=XNpLNRU5BAwxVc`/= CxXյZ^W @K#BPQ sGE-1^DZxz낸gh5g\RlDd {{L;k9yҩԫ?R{lCkrnE_i-j {J> -;[TÇ둹Ee+4FT)2֠eeޘF1:P\OU!bRYVx,XF4~Ytj3i }{I|D?2w0|m|mvs&jelV(6@:D_q٤ õƻ^NHybccPYYNSۧǍ>bO &2YmϚn7\ O"CQ2FsSEwT;ISczB"7X.OO|;fdpwSÈ縥6tż;`)8rw_bu^|:kVZ飶%c|+hs ֻsڊUS@s}1{clR/FMrjFrbKxa?M|@wxXE_%}EځđF‹X !+jyhk|%\G_oݮڣ,FɥLC0oĊh+R|#0[oE0H BtX \6vjbuMZ@k}spE2\ISVW+@3ӶL4{"Iƀ7Qj ɻ%o>`fG 6#/UŠw_4ch8ՁŪj.@Q:LԪ(FY*ג b&;P_!<3+ -WEK܆'셴<߫Ҋ) (c߭ ?^u{^K+8ekWqWA=Yy%c2>)䌇)jOyfk"⩙[LsEaQڑoM(qc/3݉a=w"_ & q84#orA; nϧlP\*&/۟\)Guъon跧X45v19] V Lkl!ct֔r`Ҭ}~I%{8̂H= נs}|j'ڀoFX6=ͣ#6N]IiGVZmr#ϟ#m6nΦo #[(NN\^R$ٺ#~چ#fyHhCgm[ jS#5NbKua_,C#YnԴBֿ xQp=r M'8 AtsfrO|#Jl8R=8,dȂtբ1#2J##ф# "".1aj~nf <-a %8Fn#>vʂmY(c.FpyQ/|<;J\#{Sx TenPf! qH@h}{` ,ߣTP̵gWwُ_@'z* fIL9 yUk Q¿6N]@i9Je_UR˩}P|l"'V0>R"=& 7ip73YMCfr W c@یOZGǰ[)J|K9Ftr㭢+shTRЄԮF̣D.J 3T`B,0Jq10NhYktѩv WZMy_gVX (,-~o[<6~Xч+brʳ7J\O:-AN>ۦ=o ߮2УJsR[Zi[.3H@.ҩM05H-[㼎媒z p7Zc{cR-`Qb7 QTk:&w!KjN8z#HK[dm `o[#.˗Shz mLiӟNʹk !?YIr9>ZqsC_Ǿ֝'3q"ڐI+փLL0 5% mDX+Bk,ZHej2iʒ2*!e5Z cKs%!xv*̱rae> Ϻ""ST \b_YKO1NT AB=>cu%OύdNR8TݵjBg =[qR_L">)֎\#,uDpo'Y#;[@+ȁv!,V{(R9@r(scxERD$ܼLa {w CW>06mLDᛔ*w#"BZL $%~kA*yloWWI&E7ru-Z',f@9QX*뭤6|+B1;' | ۼYIˇo_~ ;"3(MO/fuH6ind`Wj9P(b{DJdI9N(uUC>es9@:56p> "gU.n08I =D냁NQW^{CL )Ք܎AбO%G>O$o6@b<&^yt[?crF<6U ;?C!%G@LRJL=x A d1i9ŧ.l[\'˰$  cAV,{a8u)m5j2zEr2Lez4Yc\Ψ)nNPGMљXcRoa~TpTOUm0 h: j9\{i CH>fdm ҦvOol8l= $DwKߊv*r֤-f@|koJy;ueFއz`|7 w}A os$23S;C[bBN]hnc+ º30O'MՍJHT=`[KapQrLeXFh:F@>hnjz-FwA/B7%35 )Ɉ5n(ŵYE711R|  \m/xNJ;wnWw<jϨsMHA Ю<:1;+';$Y#Hn[@v^cˣaK\obB?{zș ,{`<Ǎ mA|{ o/Fkpʽٞw}pX̉:Rp#[1Y:Ѷc3'su8B cM*T60ЕVCkYo5QcTibg nR'ɣ.3yB b/ec,#SZ@pYcpIzD]&;?AGbQj7'=g]CG4OaR,iJxt7X_тcu!/t<39Ce@qЀxB}6Pd~Z_M'Ӡ3ۿ#S9D%ϧo\Ae=}QX(*ZO0ؖcӮ耻[F 2h.2LI39փK𧑰 ,&ȑEyp o6) VEs4b0/Ǩ,BQBK7[@{f/0 l|gu.!*̮@ $~4_p"X᪴3l!Y_Xѯ4ФLHl:OȠ+ĬM:P*?V>0{G+KlYcy!qu!spZ cLg @g/M[a:)pKe3ɤ31v~xTzE*-j䥁 #Zxj*e;@eMohL#n+"]/, /orr7s68FGqi^iݜ»Qw>R f:`[e 4fvE6UCxW1V&X/B ͝8%/NwcI"R!'4TXl&6 B="L7ΒNfW*S t”CuA=kǤk:+\u/F Sz>&4J+rqTKO+rxٯa(7ɠ"wY@zJ[ @D+FHjpZ0Q+`UlxsY9k&5%m[m~Z Sht%TRrUD95B˧s /oU+b<M8%#N%gIQC1 ?SgYK?~%ǺiuA(RxocuBV? - Hޥ>@nl9<򤦘/Cݒ GWű~FB{X'j+:FJyދjC703v. 8+I"SvpόcQ W"&'ˌvվw=-~jͳ7O uhޡ:_BS[0u=Ռ 0f#Svw/0){OK6̓Y%r}LH$Ҷ`hJ%8_(_v4_s?V\ ϒ =M,F,2R4{ ?cClymX*[T.U-J ,(GbJXB~4rl+ Dc9s۩RڽƼ3-Ƚ45Gw)d# Ў@0sC!]9h'VK50=ƨ9~ ӪeM/K@FWnky wDu/d:ބN LwNe<ݍ%ZP1?)g^9 򦷟w+Ѩg!-⠧CN.TH-?rWpI垺>&I첀 wNgW;Ǣ/~,zFU&D cnћ)=99*.WZe*/RtdpE1"KNÑ&q5%ƒz(˃Վuڳq=E>Q3aWg˰L(g[JdVm\ɗN/oHecrED4-F P4XP 0`kEW_zO]nlꙇi B3Ax>紉%~t ;EQJa'8,5 3AXyI)ir)9 or2Krb7B r7/uzF\y!P?59us+֭myB&dbC5(Yt]SȜfasb=*^4l¤:%ΐ0JJk[@xTBTj̆u >WkV<ѿ{1r,{i2&} 4(D ~\ ,Tl 4i1g#w|ْ|:AR+:rv:<|I pSM3v*Eօ 8d_o(=i3(?ԣ~Jkd>&F-MB"Nݗ6;'tM!'gUB׸m=>w;aa_* &Y(SUsKZt)0t)6~knul||㓩~ Ը9ʭ%s͋ ;#d 6"9z8!x2G8 ?Dw`t~ُĵ4uk޲ӷ;t[(c֠s̎/fak꼛{Qh*1nj^/M*+k&FU7cdLSBA[ë fŊȄ;mEM[aΖ+^v5oNjazx.ڜw]\Sr/9p@dZLdw$^`AGaYKO#BL]zIQnC)+WUȸQt r,wfA.aoRxik5hIuJ?4&m:Ort'n=31v'S-fBQXm';Aϟ"N/a4.[LQbn.cx%rh8ѵ+킂3B(!R N]WԠ=Vf''[)+8 GXsw@I:z "9I-0S[vJ,1q099/&1*mSMU=K )t6N-b hDm\V[@Claܦ͈.AgC9YU.TU˂6FLq[aΞ`0ObG4Cz#YqǠx*@!QJk:lKC7 <#s[3MX}L_A@"惛=>j!*.)zajta %JTHp Z}5y3ff b`5t}P L臚5I`9ɟj$>p֥QZ(ֵ,tXgtW٢;i6Q;Z2DpG<ڀ"uJI_waG3vUBnEx&Fz@˕=mLS˘FVLD}U{9oc'\?*nmRo)Ur( MrۖɁr-3ayeAIdoEY@j]~1ȱyE>:4sgoOp|ƃ)%"覝VFΏ0pR8M)dyEm@]`0/Q/q9*Si٭&em=T"oF/|7w! ՠ}w=` GAu'02BmeWl[f Aԓtj9s`E|Cq3lEDn?<~QHV;h!KUKe9/;qlO'X4ҔB9s9'AyE ^@]))EvECt6xT=P:",An `?}'zcl{\p>g鯞3m ܃rVz'$6lSG3k(ץ+G oah ỞAL61)$'å sVyLg Y1-zhͤ|nG ğ1#>&9B=P'O:GxLq, _:5mL<( o#F# k@OJ͵/=Qk5 "LGQqZmJv(Ra~7>ljEy'zr}&!+]O$`#xi(Xg;f-)yӂp5p^2X(5x1ni!2ְ)V&K'|H_ѹ#w|tל4#'?rpxYqIK&*~@LTCEC nQ4Ԗ/ߝ}zlQ&$<0iЂ0( $fM l .!ZRUqmLO)P<@ [@Q0Q$4Ao=K 8p/\/Ǣ /"s5E=/}OS^eծe!~\Hf~*;)gP N(b5)]dVLLA @+FW\[ʣQeXJ˖r!v"1>5`IvzK#kLFvf1_oq:ZFRm QD#9&(E}(Y)jTPBj^nUg`rXF^5Q'p M =ȡE\0&hOkp#~)_^j*il :ayBdi_ىnW&*FpކϾÜ2$S%^g*cÖoW`vNacU$΂`a$D7 &Er=Ȯ|ָYED?^7ښTTa[n{SH8(gkVy9td|ۜ3I񑁎KUO9'bS j~z*'̜s8K/R:JZaL w tHr6^a`B/+eɜhnW7lzp b+.=g#M 0ïSRrz(Okr@o4%-K^vX[;%SyapOZ@Q%.6ZdRKɩLP<t+o zc<%E7Yۨy91$wK?^"NŠ?3Jg!iR;]t@u5Ĭ -츨7'Gyֻ\c,ZqZ-vxgDph -!l䊙X 0깪贪iXfT,(W-3qV)/˕b64xɅL8藩AJ}%5RKRteAeE[qf/屾hl %ת(2--zS ID"=>7,frǠO40d[3tj9jM4c[ŠX.iXvfzkdn'&˿MAJ>0n Cf4H1;Y!4YNEwq^k}u*e!.~}~`sL@X=z#֛GN%{ϐwd7ZG*zN'ыk%k!Rd70؏e.a#QR 0d> sX&3J9>ɷS;Qr$ySWc>6@j0zFG9Hh@G+cV3%);#I#ҨkW-X;D=}KJf?iTS64+8@^'*nv!LY2gJqNۏ2טӥ5h)㔖~PDڤa쮔m,38QcNt :ᮽ].&&,b9Q*BSKOK?Viy2eWq̃, zn/>#6Xxens"*/d|yq8Izl0jF/d riP pH,o1/+o%&`Mk<8f_B E ѿ_q§ P U3p'L}vP;zEÀ;( sm1 St #;fK5z<2#tj`%BY)ƖHv8 T&#H#73TNX #Rj ArӜP?pry|.h(֓\謍U}{&<(EZI" hr d`D[]Rt;]//bFn9j m&vI/ܵ,Dbn;]TUl Xy(u;g{6>Y0B~CT93&>u&rədut=- &/LģF i .Sz|'l\aʲ r4U+;śTHsn{nZv DS WkcK9zVM+M0z" ]^\p3MD.RЀ wqJ7`IPvOVHZ*Gx1R'}dNc%+P!պNO0iZ] Dns,Td^ FҸ18](6_Pd\x%xm+K3hk\fͱQ[* 橷JX|+ilҢ,ZmG ZME ;K'H-.j/DJy ³ԥESӌg1gFGÓwo^Ƨ?A5a }ŧ7/>9d 9vMáLp JFL5sO&}NM׏:iqL4f:͢\OwQyoj#iЋ0c|2A`,~a1Ùo\ܕ&6Ǵpҹѫ 2){8:zxZɛ~0@b̻a$@l(z);Ȼ;H~FRrJ7\5c0/j&<=FxbVHAg N4l%+,'\0@u;n"]ޑ~m[VWW,<T6tmG%ޗazA1tS;U}goPfzgof|^C-Zb/FG#`?5%kZ'5::X.q+ CƷ5]Ăy6jl K0^$jyv8Eep?͢.*P>lFsB[8|>Y8X aL@mNtT}iz۬U,jΤ('aT\ EO IaB Ze^^j]:#8- ypl @CZp ʌB @yuG֦%HPdMi<%@z в~? O!)[ g5.Z~2d`i&1*z4Idg/Dw ,FQ'e' ko0pьBQa1_hë8tʦ@2C̜=܇NN<"^!U8\~|8U'~[QoFcBvR|DX#дn2=*fX7#}r׶8mcȰQo-|AJjhQX֪b@5?&Qi~цݘt~qe$F'_nt1rJ }i%03Il Hɢg< ug KQ%Kұ'Xv4GtNh\bu #x:?SL=@f< /a=^K4f$H$ {Rџ(83yh^/Gq`z&%}9v߲s^Y[egX,ftTNPY9GP}&t3<{`a>.A> QQ\fܟ|SMxsl;v/r˚`J8a63caQ=\ >Y:lm=+"[s88Na8p۠uwKɉ^G[d뿣3rࣟ4({695@[E`Q,Wk|xW| fX-D>˓F9R'R^-u܀l|MXmF) -Cbwˍ8s0E˾+?dFn"k0Dd܈>< u:<%@?G|x:[lu )K"iHorErg_z%H"i+rг;cάffE1qvm:Mڢ@65 }4¢?n(P_Mڟ:AA\ܙٙ]syswjɊ.1u^5ޔ5 )M'l?NpOoL`0NtQ$[Zu,i95ɰ&Ȋ*,l;A2:YȪa{\FeM W0ACQ=$E2_x <9)3 /+AXSi2FՌG3Z)_i?7En7U_ocݿ)ޑ X7FDž\U߶53+'"_l5E>3c\ejNYE6L#`h9]a#@h^Wj>OJNHdQ ~*~`@j.x|sI C8P/r'c "T"ϣ 37'A?/a Yͽ݌B.*VT]$vU/4V/i9C%YNWeHYVj#)I\EVCDЀ`oH"gTH蚬ʙ\Ɓ)d-^"XAyt2A?zLW#∱`ٛALiUEYvGO_~]qʕ(/3e^a2G풤lܲd%E`kMDI]$!")f++ Kzk9kʊ'h(VҪɮ$U#zNek%q(W}M9#I|% vVÊO<)9f$|NGdPQL ^e 7&:!^Q @ymT=hH3~ENh@ٽJ.eK_+e M6ƘFs`1WbP %Fyا?4sG۝" 'èȨeCYR> uRxTpO!HJ]&$(O2#Qpi U}p&FVd4a RAZ]z~ש%] u lml[0}v[\x$s>^@Z!rK'zI.EK隢xU`ø BRQ.wpQEܖX-.but%%M6XdᕜhA$~L~01 ɶq`)uwhZuM}sK4.9E;u glUB/'1+dĒdeXx|- y{ 2x(,AB_ْP]B KY5IJ Ejrt",[СKtp,\k\3tYHҪE=F N(4 2C߫k !B݋Bh~ @AR !KD w|`!DbC$[VqBtץKe+fX Z4XF֨}(VNHq ZtBkPG 7ҚotD2; %b>ChzĎFÕ+drp4R Fsw9^Md[UDrkNUDvcjuEi_X(Gg_a>a%sS`xazg8͵ڜLu1tzGcMC?%&Zࡤx!f9~%gx$Dة=9h~| tzϋT%;,f,ϟ/^=`5 8w/ Y}K4\OkZ]Fœ/CaB8bStia8K]H1X# ؈/M5UriY5&Wi#WFoeqebXQ=ZOö,ܧ@_ƞa V-%1<哐^}4:omO'6_Xn|8L'`*1#ܒ 7}DUiG M.b @!á!@,ùI0ȃ5EDQu #w:Lٜ d=XR;i)Ӟ:{W\+cb3[lI@ѵ;8S1AbgXI:;63avLj`<`>릌.Xiq0ɹ آWts4U\]D Whf 5+IKld!$dxmKq%[Of seȷO".nZ2XҔ|ƺ6sEbnwz.5x;,] wvބ jɏ+*n}0 67ӑ!a%5DN)%|*k KloM˟/8b@=7)_pdujO:TRԢl3B$MJ*+.BټH ]풮ef+u<.v;Vt0 ZJUEzFcIzފu$Hf58t'c#8Y<Ɋ`` o'}{ib?ٳ+& =4[ʞ%[T =;KhC[;}u\˫6m0$;>O%g1K@bǧlST|1(ZFjۡ^FvWqeź]r62BzjqFI;|_`}ďֺ@sg:zrAA%\fphNƋ_ڼ>ԑ{JȖ-.XY?4-aDL%VOB?WҐh!1FZ%uaz`-h>];]j]9(,7bu`pQmEjk>_ݾ6\ W6G50, v)%>.UVGQ\?[jŕE-jT@-~墣aٴHS̙bɺ}q_Y(ٴmr}sj&MVJTmru8Ge[ :χa( YBGV.(ag\s+d_2(Vxuo/! QTC(zptGBU[GMrx |~u8kbepctULyޚBR`Vd W Fnb8@+ sQ|N~4"#T8J 4 R塻bD_(BEhY~f ֣e'34 _~O yS1[ZNS@V}ioށڲPrWm$ª5yٿ.?W-<߾4 E(xսyw77|k>Y4-Y$3$!awEy~F$soΌ,݅VU(ToS].EQeVHy2)t.#]ԥ#YԲ_}=_j2G_&ϟ>}Bj$C=ށgNJU&wTæ)ƲLL*$S@X\fb"pm6cngЄ(fВHl'HNtOc4qw9/n x"fR NnB_<엒Xf<}>xuӯO_>}j|NΛjٮ'eL9-`X` h%5DjY%Jw:l E2kXB=NJ E>TJrǣ?k- _T_j`xn(Cgp*2,Vr&2o{53WHNa%q״@6:~VGZDL 5[U2;^9 Le6O^TAfV&2SIkø`l ;_on_o^76;Ƹңɨ.$<{mha-eUfj0dRC/&: &7 ކy nyf"ST}(ob\բH]'Z>_\UJcRj*؍c69t>p{yoФjI60Ѐm8 Z]*TZѼpXm۽㋠R׆ -? {27_ y6ϟh?OpN/ȧtESK37[ @re-'1!(EF|tXV3↍s]i)Y݃=AuZ}{Ζ}|pwjIu?! O?޶-gzj/x=ї?uOdQVpdƚAUF~a'2ĥAx@U`G ;ɱ6Y??AK'<9QGh/^s#u0@v]" 6;\ J*Ghx85i#>8uNpg4iZ3g@BҌ,Hs" _X}Toő]-]~˰emH}fo1H5"jiɲ\.TG9(]>q/I׏_X[0`p #$/eƙg (ζgC is5C@{{z;Ƭ>83äpquc/ڣL15׻'ytg_T= Ŀ6(\잸#gOmAd ¦g[= ,H`kR=Lɳp^ VaS= wU9p^۲ HJprҾ2,u{[¶}-Zwb>8hpn{im<}/<#&^܆{ P%pn9ƖYk4v'n#GC xo#D;zNFl{/ 6}6BjSF~:Zd(Gx.~^:c5Ur^θbҒL kع!4OTOijgKw~0ï;Vu{C;H!3q_\{[jgfRO,Jߑ;q4s-o_ oyxw|Mf(ɧ\*i5_}]R7[A_ju)jdzV] -ySANzv N<~DZ>uM܍]\)Jbkz'澻=s {[;ýL^$A>4LUmqƿ^Jj4[$F2h}'6Rz+.[i0`1Uxӕ/? Wռ/[?EKfǎW0I1Jv놟[ѵ8kΙ6Gy쏛<_ϭ~OޝD.؊ɷ>H>In&n3]ĜZQNFdlc)e;WkUV!' 1# ^NK+JΆO{38HhDur8R-\*K/:ab(&Gs&SD_ b'QSV\4 `9ct}{Exø d-~])~|Jog5q d&\r35b< h/i,_4w:n;]хLm?U.h]/4&Tf/o+^|8}Qv>[AZ~V^w7l7 n4q[֋,e072Lw['Hr֬ _<6MwmiB4Taz_mcwo`$ܢF῝kkݚ{m[^c Gs#b>I&2~^ qjb 1_4R޴~?_$Ex():_LD'== c4 >̜$_L4CwaMcĻ#~{ t7ҿ&(S3nu-=i==~4Ę`#=3_߀d`f-3F֦"ExmNO=OCj"kU!Y%k@򀄏`q2J҆"!荺kA+t+9B$^$U2j]c죽2pL&-n&ߪ/uoԼ;:*rduK<eK^?W Q#vXQX*GWdx{\MzS̚i&7C<.\ʞ\,jٮעt |s,iL8au"׏?0VʋUF1 LhV59zWkcX7N^2Wǥ<,F}@_*哾GBYf=)nmGy7.1/R\."PR<̜ۥ-O?'^ySV**hI$x+\7JG9gpf xJh,Y5 8 Hr@v 5 k= ">3'?F ~wh?yhv9irδ|[Nwiq_E•@I'䦧 @9q)40/ iMkF2Dv b;-ΙgjnG[v؎SHx5w}ċWOZ ~BǑUw1` -f?oI.`z+97m*[u^궝5d\f[w1kCXi K$uLCsƄzNCd޶¸{ȶh0Ѕy41n%MOyʚȍ1|4Ϳ7[/(=CL^Ko)%6~ruS"aN +=-%}=IlO5GeOސo"jǢDnfSCeŖZP'[Pz班tAGlei2 1ؿv^}"lQ9`J]-[7$oOId/WƷ[>M07cn'W*R7bݬ fD$u%q?;9 Z@SCQ6EnL;'K-1eG;:;w'_8J?MMwj7-ݨZ '9`_G-Agz71/JcLS^B!t1mwq3oIo 7D2A3< oO_%|, tF' 8GsyΦF:n^5uCy/HNK ʺo`B[ëf۶my; |M8粬Е*oY9AH4GÁ'rXTW)cÉc+uވ6}f ]@xG,4#K/݉8ַO|{\Tbc_cMN*A8Τ̖L0Ft;5:y6Gۙ~~MxO|? "QI`r ;\ݷ{5ix`+pC S3Bp̧|9Àƹ5X{Wm`f OTԻo[61y7ocVTA3UhO)&)|n#DTˠJLjAEl1)~0"EqXm 2c:yN8{۲O_vFtaiSelB.j1j@_T7m v}*ÅF;ۋp!ϼӓ)Y"adXdǝ$WS=[wRxoY/k*R g8zrBm0qǞyA:9^65@%i'xkLgNg"rV$]K݂͟H. "8S9`KJ@m_F%5?Ogu,<\43C^np[qZd,M ^aJ肆}댬:u)S9p, e.af*2:k4IU(McӳκZx"g-JEzq.8s &f2;$Lc l(: p2'&g| R?fR cCkoM[7.̤ 5y3Kg #C{Kx`|OSHK-Csmf1V#CM쭍n-H5ZZj01fTC!Iŵ" ~uweR3,zک5:U$ڟ5wLfs[Tm; {)Xė>;mHW @[T @ 0:_ lH?9#‘̨=-ju88B ~Q=i ,bKf2 [w9cb%:]{}Zǜh-hxx?n%ܮF,HF)}b S&ɔ5kjHL陊Ks Uƶ,(ʓk Qͭ!;x[ؾG>G0& 3 ]Ȋ.x݄GtL/c7dœޢoBWyBH4B8H-<0HggYL7S92n mXvXs^5څs?# A;E ]ccKNWgbp3YsLY`Of#3fj!-~v;Ⲱ% V]lu C~lyflest23RAU)V*De0b$x:Q@ҙc&91?$5"ݨƕ $WywmᕷWk")bޣb CX/N3I^ʾ ,tƌҾg̤N o_6|*Y *v:^lTedBh9Y  ƸP{Z1)lB*`2T<޷V LU׫q>7n"N K'I Zbiu]FCy:g7bpxha%/͵k$\7ḆL23G(TE@h8QzLD6#:2uz,b؛oN3 AL Ҥio[Sw!R=dX_^ JGۣ5}(R.{b7W528_/1mZx"9A`t&np;IJu"pAeP-JWX7H h'Sq#bXxY)eF@`'SPr>5 ?0Gy[E{'id)K=8iƇˆY.ťW\4iN@!,vq} P QF$(#]ԥ;C0D,}NP{"=dSSXeVC'Cwoxyy__Y?iornhwe)餖U[G"D"9$g`k`yNcfiƈLK1ӥ(UF)a,'M)ws8+m}m`:Ie*ot`j}Uy/.!E͞Mab@-HRIc.@Y>!Awbי.vq:JɅ]` r=ޘijʇaHD"XC VhPQ%'ҿLI410~v tFs,)h&017;9M>\¾XtOT+.˒wsH ]"f_hK*fA0I^+/<y֔*3 =:+{7MR5N*!qLt!ҧQ5l:Cج JƞD Ȁ6ڻx][zdvu{maI^LdHYc*㈗aP ]d,@/~:4e{ɕ% xj" LQ; v9 _=CGo(>ljW0eŏGR,Q0t vzYDtJ]2?ZWE?Y^VXHI֥f5bL-9e\EwFT$|λ-z)>t%A7@:H( @읺EK.|;Q|O%@ YS FoC#p-A  tWL:{f{O$u{גgf%4p } B@F. X֛gķԅij`Q'ãUdJ{&#oyo%,2b"`{ bwUBOip;މ\m33mR"+ShJxt8K[ |ZFr$ e^!jXxM7l,++ SAUa )R}vuz GJ`)NDB#0MiCOn+Av3>/}f,5!w9G>D?F $摣ASc y #2 1fP q}HT I /:_59>05n[-nھSb,c@("(BCzdהbʯ_fA]4ƴ0EHKo6ū_@&ΕCPPXna}cnF ͜Ko dWQ$uU!zrϸGf2e5ٍ#R^S/zZ?fnpD%&ei[y " A3Xs9Rj X[zO;,,r2_YOy)%)X'YQĵK:Tt8. S1,bd! aӮjs 4ޢl+BܙkRisQz3Wi AoɋL OJ*8>O3$ ڏgup$O'JetzO>s ;ϛ-\6/;"/uOChdy>aryMɫ`U [҇é`^,6RŨ[]2 t!Y_ CS?'W+U!/~du/$BNSQZ479pa-pV>dBIGK:ĵh=]YU 'y=~Cܧ~9 ⏼gD7gA'ИMfp@-gQ5b@Rv-B8A3{ҁ ()Yhؓ}z4k(H#n`E췱]Hj#aT#SqijPcG7l#;>L tA-]DXᮓ@g9b(?`DSL}%ydȁОix֛` C>5Cդlq|v}Uޝ7%o31|#nPhDM&:6Dj?QxTҕ<'aID` 21tSz>ᜍYD8"p,0e"x8 ,U{'unցƭfN!'& Z,6m\kvRI,DWI,O2׵zm.4nx'_7qj̒eus#[)θc=trbOM?`;9OuߺDuD֧gyL֧G=HkRh~k^o6/@6t"#7آ /W$M1B}7$8i,|߱vwIЩiь#BKO$ gEqmcd\sA? #\9v0NɦOхe 3jaT&M 3?geSkWq{$z"TLIK | ^0xx_&I %ȋ3X1>F#˅NKNrA tbXX`mS !Q/.Ȃ/K/yKf/&ެ8F wOwϐ VXTB^'Dycӂ5"Bb۾w(r usYSF-(Ej1(ߕp;)}&^AjF\JAy1`iSe8OvXNVU\.=3&cȼE3y1pJEM>DR6̎ڝ S"@c":,xY9ãE<5^zIfH! k'`I(R k}0R>=+ f}/Q%0!›OBU<+f+%[Pph@ . ZQ>F"Z;C$p@w`ugn~;[ '.HR\ꢡ@%ڏJ.+ d]G.┪Qt tቾ %u*[م9VDWO+|f!4yg/ GpFyp0gl4~=Hȿm4WRkt}ɐ 3:HI-\#^޽ GY&MGΧqO&_"ctkD8tkPs-/F Ѩ! 98 )]%.7@jr 6a0w{glJٵjaKbVS*5zA<Ƽ X;ƑPVV]Hc[9rLhV<#010m7".g6m!ȲtAR9Rg[ %73BNXsτtHP'.Q!zŗ -IX놪` tBsqսgT&{ uBo*T7(MnT.giLmLYw- JZ /#rQ2Jgf}HEK5p _c62anelk`b pҍ8r M BMY’k`!;KAVBL׀$1Eq">`r6]9L/[1BD߼+z-{cz¨oqt%z4[#CL L/  b}RP fH)7%i/Rs]ՠpNY _F -F 8Bb&H7^pnLÁam* ;.8))mEG>83u!`T;Rb^ztQ2=C}%Y!' t)H1KyjՊp{/ kޙ+9vʛ[!se۶rcŐzm 7s\^i >T|-d23&-2Yt -qҒ%N*p'Qld@ɭ ,֬*G+%!ݚ}7b$gٮZ6Vg0{2N$#Ybjo2S2SfԊBe$ tU4LfgL?&wcJR]5CqC5*uQD 6=;@NG6AAV/dy)px-SB=E*,q0)fZ7,)J 61 M;h}pdoOT;!pK ,^/>~f)x@w ^`0[{Ю22eݫQ5:=zC" Rͨk*/H6םop~Ͷ+V1xOPYoU4pË׍r$c3 xr:mGL| TSmcT0/si* )˵/]A~})OMb=6dcgfŤ5]a"^śN\:c=.\;/#>BC|n>-(mݨy!, kp' I̅׺`dK<8@SPRgyu)vɞ"J ފYԖ E#bpԉ"a%˜MSN%W!aF#P5D}ﴧ+ctOj2vWhޡ}6787i9|;^r-rfU?l(^7Cc}{B^Zl:*{Y\FTDp{8wiV_z1$:}># ~6MbI$]3+ 3j#2EKA/E pN.Ѧ竜N1BgqhJ+YWiu σǥu/YINsDu#hO qEgqi+h k@(!pIL.\9h{(OU=ra\P\4 bdQ5aw{,]z-l HRI<3I Ӌu( FZ꫅N-f%6AnZ>%&P"ץr? 9clv_G.ڽM>}g>嫡c)BzRl&:ﺵ$j@oﮗW7F4ٱ.PJ]*S0p0kalw^z40a:5y+0wV ֶ;{XK$H鷷x5Wd5U/Z|F?Y}vZhY)覊.aTdzόxEspHi$? }jݭиjh]KUDM7x蟩_" IL^͙.@6ͶCH9]iՃM5T^Pkʺ;ANz`A?LȠM&Fk+{pT#=^0fT%5aH }7\#/cW/B{N@ Q>\DzWIGKBN@a2g a--\r~@~~`R4(үJG$Ƀ9L- !QSIvCA\b1X+=|8 JĻKRD`><M-h,=̆ +ê'B,ÌË0#ƃGZMDWTo|V "lAR̩E`.9+ͅ6sy.L^L ".b&ic (,Ӏ ]b,`^q[;=Om:d &pcLUQ'ڱ ]|r?&641\y527Om2Q&\^PVݙ6 [~1"6vnc4 [ihV>iP7 SdH2j'E_] j9Y\1&~0*߳-XIn=/EsvϭKްQ5UMf6'JLe58ňT-wr]-30mcUhQ-Ih= *!v`x䴧>zuF5aXiǽE]ܧ0DEh^\2d-ώw-b7{+m8$ld`T*5*H"*C\#GÛp[ '`1G#ps"9=M1EԪmzUh+ rxO΀CEV鎎RL&F\u 1"M .w KFd9h nB:C_h{`TH.ѩm$nd']hG MBzh332׺h1Sd 'Ha֠(9pr!#\.< G a-i>pbk }G-ڎtIzE0 ޷ PF3^)oX)IK"ZfJX/^/,C( =F.i5Kbr鎪+Xʮ,ͧ[;ElD=P1A%*ݠu6%Gh$ }n_JmyxP5".BXnGb? OT hmppf|tnǺߪ9aG Cĝ{܀eŞr6\xF!-Ǯ(xP C |׌Lt&1d J&ZD`ZJq4JU═70V!it|ys7 }=y QÃ" #@`G6C~؃sj WFA(M5~)\{:xDGFǥ dF?8?E iGtXDuE|@& ڬ7$`sX kD=tET;E8UzҴKn?fӵt Qtc:h"Li=| #d3A7JRRy?2f _Ifb`HC:G]w/)3 Ʌ#4ӓʤG)@<#dlkѼNi9kG541'C*mR ndyBI:5An%(ٔ)3̌~7n*}_V @{p{nX~sa̰\<Ƽ8U ɤ1P!\l}U 랄Ʈ[5DOB9T)\2B A-;B$:<cXnr9 i$K4C&Ob=QZ&Hy@Sz ,` ܧ} 曕 3n, ܍Ve:07 !)Fre>ZD_U\Q:Eh;?=[+FrmIeMQ[XxHh PpcpTZo_uU/qH* T9jr)sZ"4435epvRSPGW!&?Nr=DfaZ}=Nq&VjoHwg 6T=ՎM$@b6f`KirAoxUkY3U7p0E0kݡ (;%'۴N4Z{iW𛐜} %l7iPO,!.gtD--'q 1kGljIּhfT`Ԡ]x76&N N=]RlxCʄxqa뫾ZҐd=| (Ō d~oSg.D"Y #K-ҕ|1FYT^L;}•ҕZ!dYtW4ִ3x2) a3=;c qbDJTG PeɮpF,4 t&2.voƸ͍t#\J Βeaj5Cx5REjǨs%ٮ5[HJL0{ԩuB_d\D#$=N[mYwN|qݙT+!c/D{P`a up ,AxI3QPUEJfZpػLŶ+bJ&qȴue s9ِ5ZR l[X!uz!3*%1ɄjVQ)];x?näۘ<9o8Is!ջtO駏OɍA*>r/o~5KzNTekͷx p\@* adEb%" .sQ~hpbC.wær$h0a޹)jqn;E!I,i.0 FEh&^V?a4bඊ= DD^`'sl6 HQ14e2AܭFփ+Phz N7Lʛ; qwZR2̴; %7nEO=Ѽ&2jv`Vd6d;>Hbt!U?1G ô9o2>I."3X2ߛ{gMPL.7 hhL% úEM2c)y8FrAF;:ƫ GI 47Oe1sa!0k-(Vm-&9ՉRh+B vCeCM3fxHf!LaAl cl' #6V!OXaR0[t޳({3d7yL|a06iJ5)dÞc%g^5&g¹v'FO{}xoTLkDA-k'x7*<>x‰,n"ߢ1oBp1)ʐ0ŊHRQz;+JQDa0ˋ0RGr6Aْs\Ϝ7ɕ7x9 #B5u ]a 8f6f>'*O ltҖSt6y$]w_$Ŏo ÑyrOaUWק/` 0){>!{Fe`KR"|o(-^~ z=-Isp]: Vs7ƛ 2] x3S)s /P1&6+#^y-][R52) 9~B?o% ;VzIn{uFv,p<{T>eVU5%rۃK?^W/t,Ϝү2݅޴H)%l6đMkun)pA.]SVnL~jq.h  4ӹ(dSx`f98hL!9~poL)6Em߇G!FOCdMB^I:G's,khL w-|cU~1lM%2!xCG3^+π4:0*m+$O=˯ CH6SBL`υ<.a߁A*pM9ArZ@,*ub;{&, Zx}m^2)U@Ӂ'1ɯ41*T`d2XgiBg=n9E`.gtW˅ 1AvD/fyL!z~ץV&&RrGgvͰs=o8Wr7<ק=䮍 @95pqW^๶-r+a*t1yswG:t$Y:krXFFn85Ľp>p^vC_72pjտOzh\{-? boѨ[wilTwuݥ=KiF۹SH{,7VmyQ ]魟Nc,ޢp&m-oLg5yg"T%sw“8U&Iu`5Kd)b[}ذ^.\سw񰘤ŴDr*lS<ۧdYPp0Na\prԶY SVN =î_svs& "at/>:75K8x!*8qnQLs;-&\kHpxk,byϿB4{7ou39>}8 MptkkFǂ%ŭ< NLH5YaJ?ǂ3c0\Q;<:5T[V6R-o>Qac8 VBo^}/в,x:kTT׹3 y2 s)0Q R"G31&7j|K2* jWW4Tk)z7]6Ļ>g90콿{]zdl1u۬vk\gm\ghom[LmfXOW6mho[IVѥť^n[L/mLBkˮǚjՠ6[;&Sg9LYW/k{Y4r:qUp[-{S r tg'Y1dފMI\55I*%*lX)@բ^緊7nnkou?m4kmVsmuκî{Ӭ$mdYש+2j1!k|4lIl9G}<š$MfXkc 1_'DıqEU כ@^-d7RY)to|#^M,mOZ!dAtSsx<Z|&U>R<6Z.>:0_ypY&^!Q.FkFA9= ~B9`YJc9Y+5H>[²ԙC;!K2J%o(>mҡ+c gk(BPlWO'$88}PTK`N} /g71khzY$[|ߊGpp߷<-_!ttC_yfm%. s9w>3o._}D*E&z ȇPWa ?=5ׂXbn5ʠxd\ uUvhPbi!bU5̭-ԑf]+BY׫cx'lc> UB:?ȺN"Dm"b[ ~4N9f7֯-.*3 0XƟluS)I s]W֢e+ \^V/peX$ؿIm[_vРP޸. |MzPvpr x)/#Q%I6m&bϿ\Q'y4oSB*xY l@SoscGWs ՓFif91*ħ]k8 5^%S%%zx azXMw\ OE?ٶ3ѾLm :8/ 2)E8=BI&!, X_drXԒa.'*a{\ _($핬W++a*Hmm k͘(LLoU-܌1|,ļ5˓|@ *Z+tmJrZ+O450~lV DT k鉴Ֆ6¶ uc{ڤ ::8l[qs=>q] 890:DUx-:a}!o5ҮHoH֋gZ/E!E|ŷq"(ؽ~EE.E=g˄{ӒQ=XDW;6 )!PK82ӪF1[rž I):1OwO#;_L H7_gPi^nAcE+(̖m9kȼSۥf?cg؎Hs@ #.:Rprw~:ܻ[2h'{dȑֻXg/#G3= A|'G"!#h{F_PGtB{j@HM ah1?%'w V'Dܩ=nh|q iPQ$}M..3DMy 鎦{~T;飺P&E 8qУN+`}Oz>)HՈQw+f GNOW<ȎX{1:֗ M1sItwzub=m߅,La9b(-D,K*0o>lBmcʼPIr#ObXc_ )^KHg? bN+[8݂DOʃ:LR.ÉTTщx]@+ȿFN%o'rA^u(K-YP2 ]-5aw)oHF!]R" 4'<Ⲓ^M{/CX+q6fBoq jX1}?2@C,;"F\K8(XD!>@9|=^f=d]4;oat8} {|6GGqAΡp+v.I%sQ UsyB7=JAr/d͊<8 Y8vd!_|m&BM] T2wDc-uW Xq;Q81-?X' xmqA3/)l1Jnt_EQs%j4Jґ H#Zmߛ Y1QX L M]Vrp;@_K9"'^B_~IXoL{(L2p WmhXX^|E+0iSGEI5lmm{isU*Td5] }Su$JO"6yu.gKbɟPLZ?n(- 8b:C;5DX 8lN\p"JFNà#U7'JE^~"W?1J pV7YM 8!FyGOZw~yֳĬ/_/3Ms~(z 0L$NNḆIb֥>4%֠-E!"&3?00V8rYs03{ (s>DͳtbaOm<3k 5ѣ6SCDƦ` "*{hڞ z6(9s\D$"*'/椘lښmdvE p.%u]`q릠,'MJJ;q1Ǖ6pޏ 8ED撒N}* uj;32Tz&8-י' JMeJ_fiU0 Ҩ񞧘M(/j(:rr)D;O*+ZJ#vTOe@;z*!( 2÷"'<ɹTCƺ"#,Og̚"j/4"_a,(M ڔS/iљ)"GgB1IJ0ɗ&RJJ Ňz`o6k(Jk0,I@[^R'lhJR0VRC) N%TTx} tՕ)l˶`[IdIZ˲ҖbH@Z]twUUJHC&!5Y',!$ d!ˇ!dB 6 Yd0L}Kիm簨z}waw^T G2[7A#j Knl{#nՎ)CFcJ-5<.tG YgF3_4T#H_SUхǫn8/Hf)I5$/'g^7) p짩`,]VVq+XP:W5^[U-Jq<´b$ц-hj<9nxD1>sMBsDV@`'`dn 73NdoS|?&C) %4|w?SVai0veYmC_[=}]~:n$ JR\2w`#ў]G |k)1ғ*>$iˏn06a"4P/{o$m!9z!85/ n[nFÿgҰmo[Fp#Ak+ƱtӼ\/uk(#"<N[\Sjfݷr"E`bH,_L~y_40Ҹ.1m|K+#["Nnd iuZ0Z8JGgjѺQn0W&Z@f(&r̸4IlXi2]b 2N+ PҁW,-T}lLuo<6xQIe(r4*x-ؼ}3z:8br/E.G=s|'Q3 8{I JX LmE7P+@} M'¸[D4%)9i 27ieZL)jJ415`oEL!VG sgctb`̀,tpi0l1|l(eLz(L)SL&˵ r='Rh`(AC\]=ԕM^kr_ ;if8۞15\>nfoI_iQ Zgs+) tˏPR>qX={G^Y*B'1?) O_ӝeKCNf,,n0xq#b@g <q5;f) kʔJFd1;2R1|BhIvfFB\+z|fX:R ̾ơ_+PC62η,Þ='KE:0z,t0Yo8qP;3&^\ /t0SF6;Cvű!S2(bj)k Dq kT ÊR7X&ӳڃQL$fSVI,8oUj'uf4o&D"_-dr}/QpΑ\FeCɭRvΘN,t9ڔ2O%dcts: =2דMY,ǡbZ$aRA qD |" D\WO:X`b: 0#\@;L*&9"X@S.>2cZ2x-Ϥլ6%Y̨SS Lħ*b4#f T~wtZam ʈf9aS53S;+ iP&+x:1}kTY^,sǒ4Ц _AnSTRqd̡b>"T=>!DV XD؅Ac>5]Q*кXuiؑȣʰ^ L8'zrdǪ. k֡;WPHGc5*gp8ժ lWWNX& S[WN ŇN~I(J;Wuh8V:R˦$:uP$޸$z"_oZݏT'm< @O׺SŦGàea)t]#k3'wL ϤRC %(M ,'Gc0E'^{xH"P I&F xn`MgaWZK%F@T:JXp"t'^FAYc{4 ^Uڋ(t@}4"l. t3 X2ajrPhEqXM6/߇%I,Oˆ' W1+>l7dHQPGqiL6Vb}ηS~]M%a "G%_ҁ >:G\ I.Ě!J/uNr%\'a9ZPƨɘfXNL+T?TRANP4x W5#XF̺=3a6Y1>ojw+Bdzk=‰;nZi T#Zo=コHzw-AQp+Оq%Q~/{ }c#'u3ɖH uFP %p 𞉦i#̢^`L p˜upwBe]v>#UZ֐ `ĭzVD/1h?vmyw1Ua|MS6jn+,W:ɱ 8 9ISEZBPGۻ݉ta8oWRiuc4:?z2*Z M7o?~] XilUGB=g8=zt /$ާƺcpB`^8KEt-1w'uG4X= x{E'+oFĨ0?%| dz[7H~ F~:'ЪZvk;tX>8;Ut 6)GDi0 _rcceznl:y< JؼK27lhԔKе7/qZƁ.f!@&CGLD"2CEޡwܴ}3&P75TQ.AЁޱb+OyF,1Ma)둋l`Tr!x.-ok)γ(532zTǪEXʗDIYRA/aEXv |hۛVF(:]vs qBT=Ӟ0g<^Ws}Mpk/o\/bY'wh^1G {F=ŦUߩΊ93di FKzUN w>@P]{*ps,` ZKEQ HWCWh;ݸ2sn'}v{!*:/5k 2\Ƀqm&!!2vsBH:4@3Kak gq ї޻{_1b:׏Ǵʤ([*f4ۿ|-RHVpi:$іTHz^4)NG_4"zun ẑ:,NT_Bjgg42Dcb7="ThXU0P*W#[T {+^*Ok<[hכT9l"@嘆6=%qI$E L-_+z#bgL'RfR1Y7,~!q`#_5WaB nޑT'p9BoXȬL&ȁLȨ(&fY)REt uٍ֞و&:5'l}{3Z&RuR'M_ağL 3}*>Ph?́a~CzF ]~w~X4=i) UݶyOѧ"ƜZ9J`,d'l@{tjFf, dxT˜˜.M)(^0>{"9r脧 <@Ӟ?@r)$TUti1RNEWTT.6g@nSWT<MH!|,Ԕ5tbsø+_Ne GX8ɁE>M_WFMɰHe6Cӕ܇vƒV;`NϤ̠a0`<x l9b0, Ii[M ,B&S6fx)~6 f1Jʔ5w odA7`@#$ʀg`5-4;SԌ2c\N1$@-J(0Qxd|!<;q{)KKXH`* "2],tԮ09|N,4<<Þq#DZXuqs M$FUG((T<‡/g3cLR ˝n+PΙp@eI\Q(zFsuV5:woUőoto{uZ9AP2f4MUE_{B  MuRTvڞqGoCCXu75qEr4"|:%1-ER>BE;kftFM1.;4FQfUZ5`%:E]wŬD E'98a(M}"PÒ(-⋍?LH³(A<#h(:Qٮ\-}r+" 1D_0QvF:'#859*6Edu__ [>ɼ,ZBE4MÄ՞qU-hrO\W$"+7-ǩ#8R>$ A<]HO.K@ |&hw k)7DomPuh~-Q<ۤ3M zCMZF+V冞ztl3BO(tf t۟i?"e{#LAīeO*uKHZ4:eG.U灶3QS[ =O< ,yz wt `hݵPQh}.iȘP2t$Yb;NQ WR| F&"4 ên ,'gK皖E' %w}s> :=]\Z@Ǯxb6+MJMhX<E([a!r~2caR ¦n9YA\Xdw,;$OҘ 7b`qeVc E 63Loog~RMtM]Ŏ2x4OX u:/V嚠SUNhôpl)Cc u NP2s3K -呆1<Ҷ:fA\A9?te/Uydfp' dXcS  $0?EiWD@gLǐfLZ ĸs*ܮ .R$j<8 )T2$x4 .l"Dl7 و?$Ntm '- ĺG\DeEjX>=v. /ͷ ]=աS7Je8+`?&>鐮A1~L/Xzu!9r/zm3Ľq}+-ݶ2N4(ɻJ !p1L"!D],!,F0Urh+Gx"W|MxB _ ,p/8*y~4:։GWLtQ$b0;}*>#a.Ї!Dc c5<${_%Δran`3ӌ똢 ݓ1 ~\2LEV]ZCՀ5a-yc!Cm{"uNUJ@9Vv+Dǫ_m^D]~ (cB4x|_>.W=gmo]HUa QPk*ƣ.;yL0 L y?T{i%W|@3^8AfzMhD@oª i9x 6dx"߲̌ {lj6xn8"*ɯxr%5S0[7kv n_ stkPL6ma|:ffx7~#X`A|76E#gJO->U~Kv/A,V(>e,L`p sٷBJZq==v"cJV}k  2tͷ*.02Y XR,q }[L: K&՗X"EƉG#;iX`f>ӄ;ˈm?vCЏpűϖj^~*gז?*^TBlzl@;ߴx%2>HY1sJ>F©D6heSV(E-?YrAkfv9t1T=-vfQ@  ߲khD>ʬ~R*w6/ cR ^*~úsw[GeS9=Chw0r=hݏS iQtŏeo&)@V76L $K3Ҿ?:&âEGhoLژDIs)U̇JguOTzPf=_;ȁfWC>]zO7;k Hg< /ffg7x@~VrjmD"zS?k\+Y_w~ֺ_y8Dt (DUhUC,Ri tuR,KFߡe^D W7҉\- )őS""Ƭ[_WQ> y,dōXKŸ 77JI E[M:RA/O&T'u7όuEВB`JV\,զ<| ?j^NB&l<"u%elJxP+рk$y*OYCJK+eX$7;j)z HLM':>Ayuoq}B uV߰s>bzsm*:{;F(,rgZ ըE>'7/鶥dA͛*iFѽ\?/bx^_SEWHE{d%+Q o'9^b)͝,ηv|,u/Yx ,F> y幣,^LO-7G)4 N.|QJsHuXjg£~bCZU 5SkGx.2t %cjl¤R4= !8O6x/p]]S~D/)PeZj_i\I/@l,R?)=J`% + Glcƒo$5xoqB 6L|u볹tb?UT~g cnp<5j4HB9+I $x>)I"I8P<\$%! ԆsI FCK/R,IƒJ>|!"'[BZERݒ(Uha($yfU @|!)r@ޱƕY&NpGHenaŬ%Ī-9w^PߵPZRgYr"]h(e.x2>7$Ģ3bde{"? y\iIo{4]}"iK7̓[iHjX2}YY"5=ŅUA!o)8VIA 61VI1NKh^/ӥRmgK#rat*C~I$蚜q<jĔOb?cIjisH}6*|O~Ҋgz"Eǂu+`2pBþ3F!D݊4}X-9=p T5c߸F}9 ^dG,UB׾s SǂxhPf/Iێ#kN=Y@d% o4ǻ%t1r/OG'ek?Q.q.?rcRY#H(dƆOOx3OjȢm[he/z[d*r4 EŠ?])s~_D[vLt}eތa7VMcBh6Y>P&*%lӂB)W "G?qD .CrF5kw4 O BP@SyUmDWūmwR$+X$ NHTQA_m*b9' uQjYS$d\ȏ@ ( zBkhig} |w/` >Z0^|`"_\.h[@I{Qȷij(6y_,΄87]3[S*z=w]P3ɾKv 8r!Vai!'̿*QKl8T8#:㕇h^ZB{28`njք ߔ[1`R:BR`bi~iwHMKZ6m-R&pc!ӛYn&X{uP9Vis(@2ůnL!*%jyn+=aVt;{+W-ZYʨjMǿq/ˏr؝Ykۤ轳Ax}M:l`l[ۤ66j8ʃxv{bDd`=O Kųf5i:C6 ŀnGLM 'Z8Q;Z)?S']bwy@ tPG$h QיI- C^i6^ !dH5D0aֿAqA q]ȾA)y3T|΢̄B}Җ+rDrJ&ULab*U7ۅNCJOwKKx,]/wČRsƚwK+W\K=$>iFtZ_$Nr{t~/d\C{_J Ib VdEˆ=4 ;טMH"H5.l4]ف/kуOJ5K9S;1$u?D~ѱ|x} \UMxpYdA .KK*)i`-rECro&%D LC3h~3忬+[i){w\1}<ٟ眻}0F[x}l2yCE%* Sc UY[)'$K '/(O.5yza"` gNX1o…λ%i~=erʊu,m_M*۰lӽk1 Rt}SSJR7[7IL'gf9ғҳd//yfoLW8;JJ7(XX_gLZ[^ygqUwm# &+-|ҝ6@T೩Ty;vho<DCC0ȁ '.|R*vtt7].Ռ>u:];]Կoo @Q?NýN0x4:^:ƴ_ykmm#o>>K}%2ix @ݮ$Ǻghzu T)G{M#'A 򑑉=1AS}pv:F%{92 =g$@jѻ^sKU_;RYf 4۵8ɦ[hjeDxD~=T:=v]ڋ6jg,JFD-Y^B ALƆ᳓xyQaݮKLv~{E%.<;{k]PTi=|/h5<!UCA@o8 \ gߥ%t V)p-ߞeUҔ/0a)]FC;RtϞsB P H1ݮ*褻qPgޡ~bE4hfxzxժKW/ !Bxut&H8׺Py=9Q`vj"Ӧ/ZC 8'pxZU8dFYbs*hMD KI RDjzI",d'ڼcrjjpd?# 06'l8 & 6r\7vUM U%R U2O/eX^ M6N-uZ+HϹ & xSܙ߳q{forMCzP0!CH" ֬+*M)<eH>.b3- 6C04OoM1L> tx_g&Ogm^j3c@D UK{1((d/mxp جsb "fN 3iH\闢בfQ@ C܄^~Q=o Fl gY%{a!NL%Elq tCC졙|x3 .̼ ޸aigfm`;z ωE{5R;<3#ԗ_gs5/47L9F7=o0];kд F ^!p-1g o Zf( +7; BRuSbNX[Ў6^p(! wc!E=]u Ϝ6:kD4n|Js"N'H8`#}q1`MLI9ot $.W,]UTpڽ!uh_a[880'׏ K3G&EYEڽt&4iK7oWHJqԬ5,%1}OqߢΔwC;82ɩVDqT# ֫Dst!~*Ö27 +rF+WIN)RÛph], Z-K1I:!+7UsJl1wn\BQmraLqT)*w?@4/ON bti-Gq`)r@ǁU~K+?aG Vp0guHB8ἴ4@Y ЇF6գF]Pb֐%!VB3oVt f.zAı=ؗ[&":TD#5=sk©ĴR%¶0z=ީYAZS4Hk1 erTi6}9"7dQ',44>>qX(2.]-ۦn,.][RJ1Du;3;h8L^¾,,ekR,R@xZʒBt\e:>,ZSV^:&ݑAeѓxEC-9<w7#{G2tІe!lÎLpj{W- -\^~%,gJ9Pa;exw%J]̜L4!ZFL3Wc}+;cG).<Ff% \or"b69 D^ Ts ^c!m^͍KT<5e!e8mz'3 YkhU\,Tz0oUD ^,H.&U^~.tc{0aYtT6j{WB ^^ĸs"M4rDf](,STV`z$ܨsYt~ӎ) qGTې\3fwF-;cܽP mЇcL=KH'%)[}i =7*SO@ޥ)FWOD*:#w!.ϼnX92<P#qQVH 3e)Bhg(tN˺2l11߿gRO|9S>H}.:=K#' OL fpd Fh$ y}kh +|P#QԴa~m~p;`zs=$HQ xcS̆@Q3Rs~; <]@f"dZ`26wY/Ǥ Ge~4: vƎLw}>Tu֦Nw+`A u _HGF8vE_-ovGʃނs$'*%Y;ʭEz)T\BR:x\In=-M[Ο d'V){^PS9zS]v5P%/Pqpe]ƛ4w~SP0h;NfNu"&.:LQLj)$ |)w1;q\K`wpHk7NoәUq94םt: !D6Uӌ u|Sۦ8HE)௯{9N,ym ;Pva.żZhEk+lP\a눃 ꣹>uT4uRjeVpQt`K4)}2=L~uʦg`Ӌחt@3ˆ²UwO}G qo=i d`hc,"a -G ,96:U 2 mO '6Lvú zx8R)]%}>dNJJʤʗQ[J@n{cbrR#?$јH}q5ˮ(?,Ul  p>h.n qV;' ڞW Sf3*d\r&tDILG\цVYab2^`KnZ$Ӥ¶ BcAQ:6jRs)A)bGZz/Z $g׏Ƣ4pP:m-@эDoFW6`uc,.U*dJhoQEbRcVYvb%x@0婐\vlB %{D@S.& C0BSݮXQS =^?IBhC+kDOZ`-/lR"ccA`ձBؙK=Ok]3znO8?ˍM%V-coRyΉf$$7vGӱh#7u@j=wΟC-z՝z%ƇWS-ϪnV;m͚kh# n#p DrW5ܾZ3ce?ƅX)mah !b@r-0K̝-v +O \9ԡ? mv^t1^-.#Dw[_A5jOQŧGsdoOqLbVy3.t/]lQ3۱˺㳭"[R8+Skd͠pg5c3!/'w:EWm{7?M@_z)Gh_\p̠4E()v.&O* %ZJ=t˦dVoB`թ=X!is v$'0s+`Ofo.#uD|V¶溯Zm?irGHDڴ8K+TKuo}Vqrf0(-rHmтNC,PM?2GZtۧt-ȇ3QA=:CZL\A>9A%ʳB&I %} ğrAʟotr%V#]ZGZМ?DwzBaߨz7aIAs$Imԫr߽ovEzwPv_L| Iyɱ1Y~|bA`li>d2^32"yhJY'RE'$axvpy.ѡ.zT|dei=j55\y*jPWh[4pէ=W {mo!#hy^ #[Q6ps^}+>٫o{ c6&E6.oyng_ ^}7\]KY^W dDWvSk#R杸]<-";Qn${7l :#0Ip(W:qV79Q7 .;Da{qvO0}N0o06Ȕ|a-ǓC=0P;8D.|&4& 8Lxn^a62am"407 q#tn ͳaO!|4KAMk~]7l_cP=}_32z= -%gQ"g >ۘ_n{:sV].ilq9gvXiuQlϧ$9n>͝Vפa.n/_Y- z7VsWjYk: \ʷ/3N\RK呁R0xޠ!&.X*x|+M.MwG,̋ǰ-zfM\ndab]jMe)VPvw5Pk$YVOT>(Ey"R$R0:dT8*Zn]RXRYl(mAR|Pk(_b2u֗.xitYf p5P(ѽ6'صk z8,i )<.ҟie+ȭ2ty>eMTP /JI5НNͻz+`hWIҜ KW-X-شRSGUIpY5I(IZ7sLˆH.`'uPwKA=;T撪[K7S#++$|v:qa(-j'i79:]ԴVnPWFx_V䪶P}aZӐ!*%29 Y;0].9Z+KKL%xw!G9P&K!`ÆrJb͝8sɏܢM@F9"+`)M"3$X#VguWLij§+Iݘ1smC.2А5)톘z2JK q2DԦ\͔zmw☧HY!5ʒzQ!r*zM4+x]n1ÈaN+9R9KV+!"kG+މ_hgjp)[ܵkmR*Hξe?c|N!rۯ3NʿvwW16WhlʼqRqRj5f'TRƣ5U ^RYD7^ U4^ .߫&scf*=mCc)md3+w63,W DlJE4*'-C G|s4c*VXNJr4]ERahqDI9'q7+B s[Rsaֽg&`&}πchGEGznꀪ${TWB%9P,Ԅ HYobeBΗR-Z!h38ᕯ%_wP B'Jѱ͜X`^WTn( Mi:=\T*@0cl^{m&sx7?QB_צlg$AP"3)ce AٱIR[3uqνE[Ewܳ/=v함YD nK7t!4;݂K"S^gWDr+m`&Ҳ4|fGMuN3lh.zM|n+:)/ 닊6!b9ᨥ=n-o,-ْ_T~eIJF2ѽ{]PJ^dn#Ŷu5[ [JE)7vW6,Hy)cA3,́M\lԧ E ?틒`ilM{~_-^_Zu f/Kabj:Qi m1/Ma#ZMWN}mY  9 $})fpqY:Ť@_[>ϭqu\]^qq+@SBi7QS/Bt/3HQõf'_ B->6lu9,yz' 51PP &&fτPBC4V 0!toʀvԵCla7߾+iǥg 6Cq dF=N *%>zTdm8x$h[|/ S%,y&Aܶ6K6mLC{mU|,ܛT6-^,5-^[A}JvXI^bE9p8G(Kcָx󒩗nҶf喵y V ٪]K,6sEܑǵ7O;hdja^| uku))YZ9?+GE })7elWjCQC|~b,NI&lX ޴ 4͋೦#wt(m]WIk>k͕*DW54[S>|Д?mI*)?ݻJ*'{ UvbwQ$:gWh@ 8}J~s1\ar0C^~wISd`&2Jء3vZp<對kh=!8~$ݣe!$|~t;7g3"&.̷=^ʳa@qW C9k-b/Н鐺Y^! "u.7'C, .+.O'0(fZ01T :8ӔKDy, 2xY-}qsG㹬 ӈu8y,o> |ljtPFqE-XBphlKGݾ.t3^TnqmA?$5%1xnRGW" 3k\~#|Qr$/}"vd熓@@{"6nq$%mAIg8# Pbf1 Ueb*4!\J3t+=_Pp;+X$M OkgQ#D^R͢ ug-kk?ɚ$м0xzdeT +N[n٤1/rIC&5L rHU4r)!h|nj9>!0Ss8:^J4@LG㩵j}%-6x^/+}v!2T|g87h8^^;EsY3>Ҡ># g8*jX|fSglN!OP$[PW߱{w&~D89'yz *~r+ LT~&߾f^o}6ikq-v8%3lBWDoa܀!?Fbn0Y~-װ5TW(̂w@l_E[Mnh $775~};zDYҗ8}e&S[rLŅzDzEw|䁂mk0h|צǓP Bmj9l8hʽ\^`aD:x0{ g7 '́C ~<({{Kjū3p:d|4{kЃt;<'"keߖ۶s)ȴϿNW*apk3,I}딌?%=']Z{BMCK+< 41 N!3|-T_{rN/^QaD&˘gȁjT=eEl;ĵ43h#6Ei ~? w stzZeY)Y-G^$LmXi D#y3&i- ATKN-9S9֧5eขq kx4A~ 8/_iTdPX>x}zANБv)'7bL X8ԠL2{}N_25քQ4\Hx_Gp֐H֨Л2Dn j7:Xh=':ۡ-z-_oֺ DW dkFrmiN(J^xf{B DsQcn$-0" i"B+ dJ=#'+u'{A>I&x{Dd,pt/3S#"qV}Vw\gq5T< Ry]q=NXuQ߈k~rް6%0+&p.ax=[uy~-ഀ?Z1"<C8rBpѧvx@muUCpQL\2\Ͼ4g_{ul1ܙ_P:euLQ/8EēN3ois^_ ث`Kc-?p bSWKKxF$;nѡ|?Zo^⼢!։b?agq>%FCIFUCR^sؿS Hj:Gi"}̣|#dX|}dAd$`y:#QhXHu`kTiZV͌YAYNl/$Ce["~6 I.o5 2 dCdx;kpTy# 6o!Ћծ-#@`HSTڽ{{7E(f-!Ŏ,``Lb6̴aO3Gt=1ч۸|>vWz8 }{u>]yTnj#&(,5FhE۶ڤJPQA2,TߤEtR$[7 ɮG b&8SJkMq1jFQ=.Ez u$ #5400CeWԤR|pEHJS1 Xk;᠔Ḩ NDdL0!xzn_!o )U"KL/UaINs1"o*.iƪ%Gմb`$tfrF;~ugɘCM4Rd [0|@f$ 0)L l1̀7'Џw{ \o2%F"KH`V$3 Q3Y$.$RAzkbCJ-IJJuLO @Ψr6#?"@cB BP]S YL6a 8@PL"H"OpR`nj8Ү^ E( HpkHc4&,c*Iӌ Rf~0*C N: timG$IL>cZR(+%iEtBU%Gqfe!EN2FYH]3 d+ .K)CMG)!ʔWe"F8߬) 7Լ)j7Tp2#*ySs}9jiDu\eRAh+6͜Kb3Kb`A=ŲgAN:4nݤY3Wx'&F!ppP(l̨1IԜ/2וQ/SHVN?yH12IB8KS)Al(dĂ_4Ykv4)Q"?uD3engTdVxQB˜V *QR`^2ȵ0 U 6; ։?zxE1B<͆mR+hKu͵QVk B.*hQQnp/[kv[#Ս ~A*[̡wzj2 N(֔|LYA bHOeTZE->"D1^DM5=^xI?kk-k _u#hGvvO hH?y>VCH[ޖj]QMݭŎbk#|5v|`^/Tu+j6[hwvUo؇m~0}f:HJN% 9%; ÅpG{(? ?Fӟ?uj;ҕABuNBA{f1| Z+>uMWzv/0dT5mO{Uz=+]_EOw5׺')(<,#=>O f`QVy}O*̹͈ 45)1>EXpϟWY y5sETvVW41&j"6 qv3@B%-Gd @/!†%?8|ϥm.ڷ+X"1\VItDr@ ,*Nq"jTw^f vz}45 I@1jc]/sbg{Xgd%ȃ\͉l A*./j ݴI Ae2.{f'HJnc1䙵%t~A;M& U[dl'4W0x3/m_>-L\tj/L<:_ٟt4h"\1MSXVq׿Y&],cIǿ5,s. FwL:4k?3w-xXPaoZ퇧|--˫ :_~ϿHS5B6`Vm],wpl lX.Tffq!I.dʔ%6%WV4!3l85ݨ * L6ʳ.GE o|[`S5sjJ[14*r7!71ʷ18A/Z]cy՚+|&ێ,Z4V`狙h.2~pѮxm&3ȥkN-߉b-oGj)nx1/\ :㻷5l W{K\o'_Yh|a/V+A=c]<R5RX##Y.;ehOV#_t)\OGڱxyddO=+mn!v{s »0wWu%hRHC<[8eyiS@,G壽xqo-^;Iwql:M-oN{ K#P0f=u3h{Bo H ~F?]pW2g |nFnleZ˒Ud}C AzkaǛ~EXHE4*X3E()B(P+)6>?OJgE?''k/E]eJӦl F6R@^DҲqS\džLG3Z9SLdj_p>P^ŜHJ)Fޜxn$ RJ3e۲n;[=wyQϓy~o 7c1 !!⢆ŝݫ؏l\uOxek(1)RNbP Tix2y}EW5=!X؄^*%Kbtq+ ,%NIyµ0NL?hf-HF$a( AfYA::%?z<qs-ߙhbEjpZ5j X4NIG(]8df2_!/'3{j$ݘ]}*3Okx͝:uAwsG$yF4| s ˎpoǮӗӿ,Jwbpe+lzr|xWFk`f-N!ra.bu_|,(tp}=HnKo7fO9$b-4#W޺>}> 7}!ó)6;w8O<<}5eg왳syz ˧AאzЏ-#NWteb1~f=ff^y2m30[ϓLzgg%߽[/kqv||绷=߹/֯\zѰͬe^8fnEP 4i7> :^;~|;[?0z_w~{-> ť @ya*{Xαo>u0$埭&i''k( c!+lgWP'\m˜ę(_E1H@$a؝w)v{o< oww!9ylg/G?r>R}=d۴2?z|vWxJu'K^e d U!_dx-!ٽ3w @!n[=S[(9ׯ}El3^p#d2yN27Y/w"+L<]D=}y!~]B0Ԏ=c)F񾡃~Dl'1lήy%/V$M?IpՇxG|> Іc~*G}#OZ m*>匔lxIV6"8^eYVH\/p9k`E(wŞ#M0  u D~ Dg +#<m"Vk7K M#9SKv/8J_R*n-=hvE-|M {ֹڔAw] `Q ;Ǻtu+s,rYR dzk7~{;|NBi $Dp?"qD Zpss]\tr*yP62?w_0ASqƷm7{j]F54\] y!\\18v޵gY)B~Gw<*5;L#׭]sZ7=$fl T$.E?a%b&#a(E=!z냋HQr`t0h?SWa[h! SDg(e!Kk evѠz Ožb[ 8H%~9][l  ˣAh M ZJo|5!FQv9!{‚?}BS%D G!6z;f}! NKF#8ŒaHA !GzEjME [ȯ{H\;7ۂ[dl]]6+˗2򙓛5(?|P&q^,73y4ȶxHD"Y [Ι۹-7. ¿-Tʝ:G "ۍa?ЮK|` ȣ 嘰K-if_p7H4NERQ6++Cm̰ˣ s"b g)$=IɘX {[8ie;9vR/Ldg*tsӗ#~#$&"<(7Y~(IGvC@a',0¥tMVCf0疸Uyאe\ 7Jo0٥D{Ae ֏B"%Ia' ܳjPaZ`s޽YҪtt^slz~ xZ˿Ksh[CP|Շԓ>\> YIirE\s$J:MGKrꏤZ^P6Gɟ}->K>h]Vt:&\]f'=Nj{0r5VHJF=HufKNrySYlv+uC*#hπl7%h+am6”R72+!Ti eUcԃVY6sObA7N] 7!%bf(SzΌO#d'e0Uhp-cl+UwF>M"x@{J>6/M!"id4\)Z+њ3L4FB0`ZיuwB{c#m33"0N3-lQ)Zdr>'b'P"!`DKqfԄJAReCJ|ҁa>9('B%AsHK] S]±Е|*HhZ}UQgNbSݽ G&DF-< l#Hc4V.]RɊC4fJ߁$?Br9xo+B+jr/n{RKwC}[nm#I &!=isK >|$:1J.9vo]#G+Y#p|PXK<}o>xC?`xA]XM%ŽIe&¨i_*ʲe(Sr<˨Pm!29ޕʃt\2Q0T&M_g9DZRR+'M%kƄs tprk``.l;^` +qlȬ%r=Pz6# F3Ht91Gwpfx3gyt ="\Rw s>-ahD#xzt)H: //#'쩸v>D.|eӕm1qȓ~h9J6CyhNʋqd&7pVjk9>SZ^j/75ap8Uώ7ۧ/ r(DKJވ`>Q:22`uEZ `%n #ݒ3AݧeY1=uew@9C\ I GnʓkavzM(skʞc fv(ݏ%v?zU3LEdDz>0]j'3:УVt¯)&*?J3vGTlFYۀy 9I'a3Á9-Q {*-0aTd7п^vj_,:MΧ/Vqb4lp,b݉Ϊ= Z]ie쐋oʂ. abiYd*a2 >xڿ/|y\❯KOc78Ɇ-p cbUU@6pzck'#=U-B9StZ(bW,ɢ?XP5?GAK1 rscNS$"ro|GplN;B86Pkd#{w8Orne:A@a\ :vfYJ7R?Z5vH]$f+("`M.\eR` =p2}r0@K˻|nɒ Ľ7gO60ZTqVE> 4(f/omCPDAL@S] ΅'7A>C`*HɺݜۨG3Hobu\aU}F=~KY:Pi0:8۸~1G`X&V !}Vk>v1aoA0IGOpDpaҏ:ՠ_"P3,g*po/V1D)`|!A1T+Q]s6q\fNa\I˼d˥y. k+ɕi5eR͖z~)w=lF=aTc롛g߬@ XRQgCy"$_Β\觬,l1}72ݛ|Pcv&}Eub\6v7z-QEMUgVjЍxq ,:?E}|?Z]hae/&V(J_~]ǯ7>raqk!5V*P]T1:͋¸z4V/仉L1FVK=8 sw0!QoL͈ɋrM {=&Wps[f8ӕԳpH E PMa=)E7YI,ts\b\zZqb{gPWSr+\5&z@d~WuW{' BDr}ac7EU_P~~ xqLـo6TROC.*0EP< _:2dR-LǂeODρbp}Ml ܒ#U?b81](6¹!讀;+5q)\r{J"i(R1umܯT!ʲ`k.(.l^Y#_UKmweeh~̭ Vh- /ۈBHIū|Z6Y D`$ Uki2⛰\Q/DޗnJG;LUGvDU!ͬS=AhD5qS&ͪ ݦ a2y[D6mrP+hE`axa:'{:'_$SMOLUJ?,.O?+LtT^\+DM Cc:dYͰF[ӕ$ M)T\K蒷e'FR[SJE}Pfw=l D1N۽Bn|[!jgدqZ1Cσ %wÀR&I[ b6 2o8/2J|SBve=X,JrEF(Z%Gc$ᔦ?*d Ou7xD1&Kt@}Td=26u/8哶8ƨF0fA RngNLJaJg|Q<'!yT8ZMUF:sNU%A8% }y̳ ls5;6//(XT"P ]7:i=7ZYN 1U_5$;ᅥVܥ{H./*RjlLo>e۹OJə2)Keٜ5)Utqj^91vDHXyx$+eFP32>FUxmg,R 2nqyWxmptIըϏ/:9aHPϜZJoص:uLоX3?5 R:P䈡A 0/ - :n.&izɧԢXnDE!hF/?4TwNu_e; ፨/H vjKV*0Nn!B 4krFk] X=H"ȥ?=c;Ad  D/\b]qKndv ᷤrU0(TQhZ֨Mt.TdH f4A"{^5䞛6oЌr9W9r8? kڳ0 t~ "X IqnlHI~t4 $U96rLK ^(h#\I6IO 4u)W2qFyNk)9{:#NV ZTGG2|%Xx\Rd Xa[s~fj-s )J(e_yuɷO$O5Wx1]Ԗ+]My~ tG0Dbf3V!x`okcIUU}T1LJ~`d k}@{:G4۴-AK~\o?BfpXNH4pS'dрXX/j/s#.2n0J̘IMl`֨/Ac4 &"xpy"4VeFNeP2B'2͚[ r9ZQwd|ʯT\y9qYOANeLzkUQVi"ѣDHkh/JXH}dG qʊ_K?E]?tϥYodNITX=zQb% =t>Hd^C˨5,O)׳hQ QS*vG$ΰs5<tvtĹtT, MppW a5 0R@iԂpto$'L[bC\bW#ѕR^-qev%B|pRRO@F'V9S#n4)/*)ˏ D9A-!xyJ>/b%۴d{.+5 *&4ΞZZLDvWyM,")|Oi릀ے!'D|,e ҂Kr@I_(RR fN4WJ7͡ OTL{}gQl`e辘8|qS~Q-(GA4OW)M}'lBaH34Ȳz\$)>9W5$Y1u;()V<9Y'G%wZ3cJ 4ZF7þ 7_3_6C<['RA'},4[#X&-*3[b1بr p>h >$-AZz9Y!<%$ECc!~3 UDeP9&52} ѮD/(I Z:AlI\A$jKݢ'{VQ_oY jN'JK)lH(zvw{&@?|Lo ߾+2eXτ 5n:[B6|=p?a?pA̴*oG+Ә r!%[)_#~dLYYK偅0(|sW @I'5?O* .a?D9F׮dC@ZLV6JWGB׏Qie͂sR"!{-P_LFS0zжkUMyR!^+*K>iaRWq5W䃢;F}Kӓ:TW6Ϥa(gڗ,OB]Wix A݅i0(Wdkhn[@S㲮Ŭ!tBS#DQz񋻒/CV3J)6W9O j`tXJrմU/Cs1".VFkk%ۅnvJ?"=kk@9(P~5aIx38@I#m{*a%e45SgMȃ@m@UM)'zlQlu 'ɮ:`sG?p`vvsZN5K?F9^:5z,o[-d(W2-\ȟ塠$7߈M;#jȮeiAka9sᔲ9 ؤ]1oYx=NOpK4rZYOl9@mJ߭5x^E܂x,evB1KҼ3ee5Ra( e`u5Í`)ƄN6OFK?!aI~t޿d.STLw*roŊIc}&/yO[cꞵ åEP bi➀[3C1p)q嵹-;z.Tm*>Q.>! wVĿ]>vpc3=|ގ#~qE$# U! >2˘C>cQ&Ayy(+'HWXb܍rh0>ed-L3JBF~"Qg}bUiedR<;ĻU Ai>_},ثhEԪ15`)(w췇rz^5rT%[n$) r|-m!(tI8" M)OD>IcI&S?PhcAT<tܖΕ/V?Kd嘀<2ťۍ/ۥkk _>ܪZϓqmETboP`pXY>YNG@b]IZlb_wѐČ[-d˧ۧ1`a=zj*!h$$?y37CPϞwp2sRU$=kKC'h%~mՃyKL x X A |aׯ{箿uY"2={NA2LPuWR?ݒi",)QZ6K/úQ,}l܋0~)7,zJCgN.|-'?㏾KSjw4lҟ  MGӯgC2wΆA'ҲOl 9v |K;4(ocOmHgN()`/&n$ @ڽ&{)fj܈NJCh@'“+, MsAsmR1`+90lр]P'N/ 1>Wy3+V_H1zJ uw wQOg˴[LkÞ ES\>noGS8OFw* Ix U?'o3޽S5ÑC'9_Ň{23cݹ){*u('RGQi6qʭZ8g:&hԁd:}JBf?\tu؋7AmLO^8E f̛ A10ja/d9J\WLccqϻq뜹Kq0ޑ&SԼ?- jT.$TNNjm5~.0 *bUZncߙhOkޘ˵hPMn񠏩~GOMܨt! I2Q4YK Ƕq>rP7`1AGL=\A[f}U:uI:"kdOlƽ6Kt7 4r}%ovі&p=ski?zM<{9_5KM6!'q ~avmݕuu7xfYa\{4k~怄?ɞG> gDzf_|XTA =Փ"N7paa1,{;m |?jK_7~`g|]oV5ob, V ` ΢PbGAwE!Jn 1q^OeۊSd6STWy+?GmSaxOX]dZKܕLn tKmhűd:y*{[ఋJW#cG 6LSq1芅ҙ.UP?9eض{ܛFx͹ {b %-f`BB^G%(yTv:֬AIb0t9ЩZ_剟uڝB~,m.6͢8V߲[^5L0̜hEyZ߯nR ҟNiդͫIo0%q V5L4䴬V:_PY.?| WDueS#Bs{9쳗+ HC~M}&0-= pXTwchsRoi:2mB9EXJ(#KH:W+My0W-?W:9ԅHE7'ɉZ֪zqKۼPr!&!NWARZzAmNTE%]^@q6l#Q˙ztw/Й/4YXbҵU"A`nr{ab޵?#բ/T#2EM|# Ԙ=fXkJ$3D*ܒCu;eۂ;P7WpAJrAE[A==~XZsGS߼y|FsELV ƹ+}aģՠJCuwz/[o,BY HHCT)$RE#XvzqO6-J' 4⺾N1ra_3_T̋C},;t}\ua [Cż7%1zj !\l$A @ϸxA~b&Uuf'<^KnD)?W8 I\!J>v0Dp3-뜰]GZTxRtV9ht!3ޢc,wO/(]5Ks\tWiDyP3!oM$I(Qe\Y@U07ou)|^#v^:3_sv5GR9 #e]tTmSO5h]%&b˧*o?uW|qgtyn΁+[-s$ԪH.lsWL9ٔǡؒJBk;0_`%Tpv. {웣|ZcӊqUMF !bV*԰ѝMh U$dTq- ,_.-/:xى9TѦuVƂ1&x-8k_x*[|0)?)䁴m:3Pn:٘m! F$08Q'\Uz*ϕj!:/ 85v־RO1ǵN հ0k$CbK֠d묧=vL7n7[cFyPnxbfz cPmiT:--ns`˥g7>Oei5rΝx_R P dԾ=-ܓx*)`VɌFCL}ÔgMF3g1x>L&ԭԞ!{nk~5re1olGA1 reoVWѝ9=z6tQZ#TRIW pn tDU%}说W)z Mh3FEŒDnoB‡Ùѷ! aWt`Ng" -Q|!#p}g[> +<{Y9ԧڂ+S7iFe\TV ]GEw1`,8HI%2g}bǨ8WyLͤ|"{N'(R"ᇺ5C1l' ҨPB?J}2(!t4)^ޙD(?(% 9p&_;Z=uvVa9txxa ?UG㟵_'k2!{2ڇBAˌSS*EH*{A0Gxub 5[*f? it:K3V_z]\rUlY]FvA*k X?s~}p6)-!)ϫ;J/y2(͹P d}QںMȘg{<H~!HV/[vۡAFA&A t#uQ]$a4ʹ*Fa'F+ٵZo8_Fo켎}l\}OWIIX8Bj38S%b(rx qn_rDs?E߈안_hxbw{ ZJ>^lH; Í؍њfӵ4N&ĶndpȂaἸcPHY<1`YnM{Et.a@\WKvڏ<EgXQŜ<,WCk 4AK_o5dKd{&-,"[)&[)Ԃ$&e5Dk'Bj8Q S fTJiki4 1,Z+i6p덄?O}vb:#OPRB`1ww[nQ?hЄ0^mZэoRF+ʒ$fobxZS,zI8C5+*XtK}I"}4:lX6&MUM a{^#a(Ba ʃrJ ׽}]s \KZ8»n"9![#aW,+]w^|5Pd2JV"%X4}Nym@/ʫ`@5n%?Gqygl$z{}X5 IHAZ7 -٪ns1g7#dNdNcŮ^033}\&/x]&#}joN]59ԍ]ǟp+}n$?{'Xȷt.8vi?MΤGK^*r?EU]{[|-ޯ3\Q `\[w/Lmya|P}oFj%e i!6pXfKmuЄgD.@^$ycs.2-`דzkOHoSMtN t{v<#>t;B :JIL;8sss:ۂ 2mN eVg×XV #ٸ;=O"xChB҂nd !2% 7!$j6Ŝ7`vVg§f~F痞ǿ3obn$m:IvHgk[;(8B 'ae*,33ܘ;'=Xu-\˷ 'rn,62IJzӤ[rF+b\J$A@ղ [5fR8{^ʌMU%CL<~CW?M_076WZ#x#PM"4cTVՏMaH8:ځgX8:P+D5+,9q85$[ BHjb1_`#*wHiR60sAPLќ#Q 6OMbCcJ?2; /CCia!`W2{+MVW94<] !Mnl~;-~U}a7. oaQr,RN\jFG^XlGƒWԋF/xbKٔ L= O}1Eo Ep͉c*?M~$)Bu%#Vy: p zmT㶥 B;DiHpJ *X#l̬2o ]SnuT9\y`aZYn0)uio{YYR=d*y t\*%^$ + D`iomi ϡUԕY)tFiomu 4Ym%viMe6#-=dmֳ&Q[W*W`GD-pY)b z۵gTYB:9t;O뽵%S/?v|'+:y؆af2d8%D4RXl?(f:IuN277 P=:D< xs0SauOC9αwp[_.D˺, NouN /CT`%Ip;]Mҋ;3W8)*2S"f4|Psb"Aw[R3흆0Vj$hH7Fx#_Ҏg9{UZ(vwt(nrڸBf_k, ;#Z~WЏ`j+D}cEJ])N?myYIV݆EHb<~KgQ8a(Q LLf^UzvFpc0qMl߳|U~tLrSoYOʹ%oQjQ '2|9fl2= aɊm)q ovnɻ!GfZ$N89$,ɩWbޅJ5؏'ZUS#(Tm'Bʳ*n{䥲 U٩ɭVK&nv.9Cx%謯X*jkm}b7YbSaN6c:>:~{Zr 8!r' q&imyhPȟWt9 ɐB#wa{"4&"0;K\~[OLmرZn-f f觥ꁹ_e!)]7 iIc~0ÜvQejN;47Of BJ]KomaS IPlF7s,}t0sjN3QV?P,~~qIssl6=fOP8 ެTB؏HX$.-WD t tQ Fkp NdG-K>Js7٘p<]?6 :`d2{qQt7Qf';xUml!Ȝ?nGۿwXig|Zz% (tk{qli/B`8/lo婩㍖sJo;m@ՊzoSԺAjeС(X MPR)) v?UZɖd=#n,{E?a\$6DeVm%ZVPɯDE-)W&|l5iƫkv=@Av׾,)Y'|%s$,aIasdMF+rGjGY1JĝӋ }D7C >, ˄0/m-Że?_hd8"XMb< (E75^yB,SB{:K%ˆ5sx*!w(?H?3<+#L* Zأ\\VHfD[НbEяx vͥGC=tR5AoAY!ԵO~Yb\W+@)̀nUSX) 0F4S:(fW\m!%AVQrj-43ru3/1)S<&%2l)T DDȨ~č\$ Ixx#i,j>iһ(?DO'1ŏ`p3ZXܷ Vdsʜs=&hI>dmi#2qduo- 7%geP[qKm=rw#a%iS =Q>"L  Y-/҉&zqdR v~y\]T_{%Kx)7ׂ(>IF QAJDSÀJ.{:xW^cbA&کLNJyfQT 9WjGC|EQVh@]ǎrW~3R]5`VYv쒕ⓗH;OjQY[@Iܺ/պ69]T^kȴ)\Z?ȏ*[&/ASf[Yp0gNQ-KXdunvn [%yv;ѻp IM5U\ٹ>bCOQ}6Y |)_;HFgkZ釁)QL(ƤRgnfn<14*wiSv <)w=kmr!F?Fzߦ)/)z0]>A/{Wˀ^{'+NբzihU\Ѱ'"쬷BKG0d2p>!آeדQ˗@]9orƓ-\4\vODQL!a ܜTkQU)> )6o'VUYj2.zxny <6p6S+ܐ+YqSHpkjogՍ/%Ò~#J_9(y3g -NrK7_h"f3Jg}3[bhJS Gנ%.zTnEڟL-*m}Jab4y+> ?iooJ\{Qh@KrG݃~9T![PTWQ*=laA"Gi/0aщBY\YQ@_s%C)k6O𲱣(|B'yPd_DGRqlQKjz'$q^LKswV_5cḧH2H:كYUjkUV#eS=B 3S(Ŧ48hJe"4Q;UtNJrVѬFɎd`+ҲDᛝt"Sbɫ^4d&BLsb~AMaeġ`:FNTdu2| SDbIQ%.%VU0N(O趌u;o GRA9CE؞YC5x 8v_586\KI[xqL5e3(еw|E22TI&b߽z!JKxWP?!KA^8Eǯ4d,S#E%;p؏Jz.̈́6SيjjSLNrpv~;cV+I@#:iɮ"i,4AHp4N L7:m*5%JZ1[S&8D]1$pymq8XnR{?zU%=º"@%iYk[UÔ4{0.nOQv [RH#&VL63PX^НuꍾޱQPΜtr>1_ۖ6l~*p|6ca+Qukgoٵ)Z=}00x}=[n@7xGWMptڅS,w]$,ڧ. WzIQŖWN>ZB[-CG׍"32fJwGnSa LafҮtwD)[\t8y_@(~h^Zޕ]K%4ULEqWU`=@쮃iA{ M#d(wSyB/O$B(0,>R~8-OeL^ܕB55CNhYG7z!6_qEOlG&;VZCJ!nCdRSWSY%U[ûlxNFv&V^Lshj" Vs Fиh,~,]ƀCަwϝ̋`'V-9|틎m'փvH ʡkb̙ L]JTlR[Շ=['Қ(sMI ?W!Nal4ԷF b/]D͵qO!y"P*L&FA eba?> =W[#A}2^d]A^F7םKàjD E@⯧"3*ӏ۲etq[>0KqRVJ"'|d(㭼kOYӅwW[ wMpJkn(q2pilo^w%2D~]7z IzJ݁:͠h(tWo៷}r·13W"CٚiqH,c ғVD{t53##Ǣ'/Gh?eGƆk(K˿% At]㻲ݖY XJDo0)q*rwW&8&!~/7Eߗ^ `EJeU nVI_zVw[D$bLr&ʕwqMax 4~bP"`e\X7K LjS\v3hFkfq`jT3 _n%g!*FW txy~J7h&^(nu6qzǾh.HC`_NE7~ƕS ҃K |ƛXk}h\^_{El5E{̍cdpQ. yٝn;ҟ+xW7C|x^sLָ;K_Dy]7iق3ʹrDX9 [BV !z}(kTv?Mj,1֏Ce;MxvZjͻ~vY9m@uCob@ݾ-|56?~4N&FQyزcDqN}5J͈P:"d rOp|J Uڸ&}7BNcF )ݮEF)_naކl+T)w>*q oQ]S$ss;(@X+x*Q +U"=]&(֯.9INnM7a8SB? $\58*\&/:C^ݓ*B9֚~o'-79%HH9[CK[%=&r]z"*]AV¼&\uJ>|$ƶk #Fa埥UJ"|Lct*nKQ6?ua|_x8CK[Qz4eAjM**rwn,!̚봊"řKjDrTb +@b|JM( 6Fl&Yœ9!R?CPZ6ꛭ(N r^0?;pU@#Y 2UE8lWu{MLu[-b.9g3J*7"KWƖ* 4#+-*9(橲٧1K ,G  GH(U@2T 1kJ d$~5~MV^3]njhffδ_mr%vmL̐3fȩ}vOjח/ ٺ`omVľ4ؼW 7JZ+j |ƬĥDw-)'M\Jt%?tr`5~Cޒ'YSk:7-~vM0c}rr_`L⤜hgrDTr?Cvݛd?:' O .fgdL`\Bn|HHNI!lٍ M[3q& >rd_2REøؓ,݌nF(זl č4t.ߕCΘ Gzx&&V9^ tO B nߟ/&.'.Ƀ2Ywr@wpęd+eKF`ey#<[n%H>?[05a'4 /{Ձ/5>3 $:q:PJ3㟍*`[K|UB-xIg6GqתxLƻ 7MWĿGk #HQh2i2N2,+ #EI29>fQ AVTo+Ǟo8F~4]u~'\QwZeKv|ohDm8|08;A3wK)4dy'݂GeucW&m_>߾۔YYOU3LMe: &[: wf/fOǿG[3ge7g;0׏_ G6?Sx?8N;{fiwْ=x |UKܽrtZ|Q7~jJۆV+~{ֆ  2M xl|\t|n]Q؜i_M&=4+{@|pxֽy؞F {:{` 8w2>lW6 S_<:tV)Dа.`z/e\d'Ib,V'0 ~kp$}0J\d%ۓ{L VũHhfl xV^gV 聞9 1FBMy? M;-X= rγ8dq13)?vY *L lD9ILO g=xۖpnr}?&xg2ٟ8܇eQxCU8z>1X$GTi)_3B2DrK\Z,N:X^W##' 0ѓȆâc%Y;dT 2^1̓`Ô (mk |yYQS8Ɩ"|AgVd,{lu+ؠPW#bpd .W&Mtջ <G+o 2^EƝ=LE~zݫ/Ύ {|Ivw @ >8^NhLN{R1&<2rH*2k|rT5/EC0qVf_7wcE^R'>1Y!Q O+˼Oc!&:&ֽL:ͨ~˝7+[mc¸cMKlf큢P}}6[-gT~tS5lT8^Ó+fEPd0rguL޷ҡn>hz3yVZ0@M3LܼEm}_ytuD2T Ug,<{h4St^l;i(Lkh>Zv]~ 3FӨcr#KNj2/Pv+LX`+_wbLN7dx8^HCl0ȰPƗ4+ʙiSPf%q(~]'l3l˩h 84-E亖;wė~7G qͿ{8>5T/?1:Ȅ~ ?ZZ}f1!?~jn?X!sߡHzJBWFPHAC x&guʅ+ݜ )TJ'<bJ_$(S9U j*,?Ș=%j)TjnljM`BH>[|S3io9A\Q"Gh)9©Uc3$n]ba 6:p }ȀHD $ nጳvّ# -i*)ɖx׉IzaU\w h}ǂ_ ځ!qs8o>Swߎ1xү>9X-񎮓E{Wn:}?ޤp֐6l6vk5/Si G7u?|f|1/ gx2~7:,>bߗ!?7V|k0'o[ׂ߁_!:6|h"AMǿ;Cf<|ܼ73hCNԁXh?&| [l9CH|_⣜/[^,A1 ?~L~|e}4jPLژR>?џbj ܉7uva;jSTAhab@Wp)|06߂̴7U8ĊG;5,.'0a ʹ7F7Yq`(56q_D0FjiVdG8x& #!ϛ/9;wp؆NUɝ &JkN}M0067F`U|L1Pli1U(Y\vɥ o3ʘ lg\0p*.xv̏3(8B(vk͝~9$$+ign"p)hģ2`BA}Um:h5*GI8ʋV(:mK7q7~ 8>cs}!I` vsWҌn\!{?x93Cš_37Cˮ~KU|%I0QRY _$9I zr eh:qudb|kY/Ǖ5>9O?QJOM6dR$~zs~Mh*ħP0=%#+'TeڵE(J.r\ns=j:-$d j hcƹ)\⤂ʧk+@U$J=oeASY 7n 5˸@ ,`?y xzssiF> VOz׋=a @̴^`8 ZRA(}zi8d +[I'^GPMYū^ ɫt\֋]6񪳈ȆbT"HQd1t+?ZqFxO:J՜ʺ:jo*Ti*jsx.(w='x lbȵɕwצl2 d`] W:1+T~^WoD)DҿgDC.3&;ъ*3ci䱉PX)]Y7<.JAӡz] {h40#4<ė]2.I8IO#61̆OEEsu "@$ DkpeGm(kKкn7 xT-dè%UW ]<>*q*h@D\ k]oTjf>]lT+] P.h^iWQZn 7JSuyWj`m_2(:=#XR\}AB28n5&z8^ ZiVYI)pUjC{sRF}~3g|L7IY Ν)+M4z/ӕz:ɷQ'\% YհxnY,tZ0>=_\JteMoJ|s]kcZSJDMkjhpc%\ u|K)[M`vDtPJ^b:?EuMkR9 8fiBL +omJ`UJە:Lr#TB֖!=#furSȿ!Xt)sX0,BE>@|QKxH:dC?Tj׆pO_+6J%0zaBߪejFi`pEm2x4gSƑ9\GTsn2эܿ]{Vu=i'?$H]+mh)_!5!I:tzHS+!%t&)//3!^IEl_y #؂L (96S+4DܕjlfeRị<ȃY1YmpQNaLAHPMJ\ a04Fa~rG@mYfsZ=܋ØqXI(+Y;ߴ/4+xn`\&y+N;ɷ~HЍijsIh0n_F ~r*ZK] (Pt~T_t`﹊$ Cs,aa*#|CL4|nO-IH;.X[#qXDC63^*{z Z×nuJz;J0DSLGXZݣڢfd8[U?AvrPRBQĜRYW1!r,>gQ0Ȱ<# =>Ԕy+Uge^!IIfQ0{h`8eBj(G J/}s8)(Ej=ڴ\!Aj|.mApBpEqPHrSU1ɑıR`hRItĝ8EA\tdV\.C]rs oAO~X賣HU离G)Y#.>>Fhh40{Ѥ篭 1hО8'PkwB #Kz Fh,S2P[w'0%>n O*KFѳHOb-Dbn^%&mT1IN'.Ovĸ@p  SUVѾ.-AG_%S:2jǂ1s0ls%jf94VHdn B&o$ehi-.$xUL$ESzth]`p"iI-n? W&ּjեWTqѮB2>,E2^;_D @~F{""þ`lfJ@<:h1gtw9U"$xu]Kq<^XtrǓn|P#bQc} [<SRe ,KD_Jw+qi`B~22.bѥpkWڴu(sl,'> ތs|29_E.37L%o7Ъ@gq&Mًm261Rl 2qb'-p̃xbiW&Vm0T¡խ4eZ^j!WBjw2$4/91OWz@5pO"Q5D'FŤ ;=Xc B_:),>8k鵥q!Ak>\5=Uq|K./L+vd̓qr,#1uOxj]įZUrjTK#UրNm/85th/ӓǿ`*~m МlN>%nhDF2ffĀnGV̇k-;L ;y8qJImBew#EM72޻2x*IY.%3 4 ˤ7#0'9Ԝy[z}Ls8T /Iv;]q3$*¯)g%.s֯'M'Đmq'Dz6fm2& lTW@͖P!\,N~h dVy<], {d(2S#+µs%њHzͭēb[ɄCDCkIy+)/)B[ I>ⱍdh+,rTXǰ v Hn#Cpj D]>Z6I_z(f>+q`ߪ/muu`Ƴ8,Y-:l+<ڈ6VI_&FإGD\s73.1:t_a~oTwﶌ>TBi Qael^a,[Sbz<]w{s5+r+@E}5c'Lc87+u4`J4E52r WݵxPKĒQRL܄;t!dZ©+#-2s\Hkte>90l>`N9ژҡ{ C$3:<:i&؃S_; S{lbHj0t TOWz<ؼ%(/YyGFhz(uS YBJ1<[\ 38h,A,U(G4tR:.U/ӟ7F$5Y 2 I4AIgd?x@ZEeqhr<^;KW^7p6 `6Ew0DC|6m=UQv'7qLZ@|&rz%P:{1q,cnK&+fAё(Lo jc)0?, ɭʠ{]&풃l[%2] ү}/9<3z1R\*u͉J!RsIY>aR&Jz yO1 ؓd,} ;?yr,Z0H58*eDs؄Nx__#uo<ә+5X8) hp'؉öGQiȚ4F r13Kl |<9v=2Ѯ=RDŽZ/pzukł\n/d)^E c}I>I2y7b~:LZe/NkQ*eP KJQߔԚU6>EǾoFK^г?ln+PTepJ ;CBnLOX9/ oqbYa(fe-" d WhÉ:[u=>Nn]]KWs &hؕ!Qo`(m'CGNA~LpYy9k\)[eŋY2HJa6 ˣ\L;϶iWbUPđBy#JqWJ: eW=ثd6~+chS}Ǹrms4*k=bT΄D:z&mwE6Qu鸶-{5E_ 7HNk68swǬd9 7H)ܪu3q/jYln:yK@n oDdq$g9XAŠ`Tv-!9Ҏh w)>ǥ@Q( ]It%J$)ܸO s(71mz;d͐@HB#vs(?^yJߝ?`soГ*Jq# F_jqX?% ax!iP}?#)H-ΟaMkILk5Gūg&4 C%cK$gՔ򲾌S~IOM5gZ b˸9XM*1]$Zf`H(U.q;3y[0\= f3Rcn5Z*OtN|`m,4r1/z)vZk6ÿ!JSa&7NrePK¡(&?]g}Hh>nh^0ܨߑ)zxU/ E|XrG&g(keߓql<ir1~{湛"f0 ;Zq_"VÑ:Z2? ?.dTHߒJE.d%f2ÆFL[b^\O0-g 屚’~))e=5C;@1.l 6:d,傢ÉKоg /}D,`dѳI &$ԃ0B!=D\'?1TL:)T޿*G'SD`FOA%uN?;Mf#+ӌUE?W>sRCL}fIq2 L[#yj\Bp>~1ʳ ]Kg_+5/MCYNZ9%qtZNxń8y`ܨH9tXݕT U0Oh㢯7){˥YNP}2Iʣ_ ,@tq_ZKёQtE+Rf<(wD6 #pN)KOװZoHw3>~dυ~dpD%`&uGiO/JrN>(m`8 c\$'23ʓtaUR5Cٚ03Em?,YMe5 <C2آQ%3dtT34T$߹S;쓡|_05 JYUx^JIiJo/g Aw OI;[Z3\}8PD|man:LT*+kI P5m܏#Y&?4#1Og#?)J9D\i0NOCFGUJB.+NC$)7*B%:ZZ[7ZP\Iݑ5<$u4yWvI!Tᕢ֍V2Xiβz[ ڎ#"wEw u.M[I) ؇k44|] `(L6;_ ޔ/KŒn<}iه^6d頫'Hroiسʆc'J& d#C0n@J 1~ Y9?Qm`i~YNݡm)uvS|B$qaG"fK= ( ;7ռ@5 'ҡ{K^vщ˅RMMЫܓiJ/Lr]Q2Ȣ/E,/*ƤQȑb VCHzkvbK zO?,6z=v-H!An;て06q9Q*-|vIa7?ݮ}}brco` X0IsǴiU/RFBPN[a`EC9wTLL3GN}@a u"aM+XtV/zj2"ސp W~al5v'-JçA?kًh7JMGLfJx5UC{=x*9l~U jW.MWIڹù*fU9 ZOӂJl@{IQ٘\tx!tm>*U0 }- \TS+)H-vK#.i-0׭29Q$Wl8RQy1+K]vWqh~n&A #>f "dE$Azf,ȣ?)=@\,㝝fK31 nZH\WWϠs̔Y:# Xsѷ\!*] ӭ̟Έ첋6Qקt}=`xLȹ(H1]OLuYF7#b-Cɶԃ(:Ҟ#eTSR;B1dWԲU5Ri4x:hw_C\ u}BM;G^"-Z3x`Kټv( 0;rTKg$k2L(ϰvm5٥ gpVlev \ؔ6H"Ҝ G Ok#C>7 :u.+t[-M~.Ce0_TlFcyő{{H$j `mAXK^ %J3L G>!^zO=*1dT6X.gmzL2VBL RRfuʋZT8q2gqij#z\SmBMK Vn}B*\mȘ->!ݙcAꕋ&J<*.zݢԈ L(e.g66+{}JՃ/pO@}B̔|tsinl) ^ރP_G R^Fi&L C#Wgt:u6?\J$_6W -&*$H#pKTp(*1,GV.w[Xp FhQXT˛[PMCK-7B@9*,Խ($}xp+qCw1esU38 ΫI1tiIJ ~a z/l\8Kr NU/ktD'\#bB)b`?R+Wѱ Xn.WkDfa%\+Qץ PPyWt(PV\vNw2vViK:jy9=I[#p1Y(6ˍhSa~܎l<͜)iM(p=PU%DUM+nOeh6X7o>+ ő:А16Xؚ4#$`6#͵5]6ȼ4 =c |ݼ-P}@6`c@jsvwKbZΦ$NVaC-@}ٺ;[@-` +f0t.imH>MN\u+6G4Oni8p330(CfC#E ]nljHK(=:>i3-t!fl/^FNv.;N ILL4C)K K8*ЎFΌ.fBcbeD.4j-tii.4Y5\ >6Y34"3?C%pAXP=\\s54OAoKV5MM yc EaTnM\ј)hhu̫:/_Os5p/hn%7]DCL\| ML~flj VV3;o`sQ-ch. mj#}wlLD LmSs<^`+CYg |peHN'`o j2*wG2j)AG_[C 3 NZvA7HuNfW/P)[u{6Dtw4R;){Zyg8iD}HYܣpQsħ6YrJ He4:Ƹ`v;D[Bwy̵.!Q9G$J+r2:4m flqdKE": `.eF=-=tkh^(oGu6CGp 鑘2(LH K w*x~oUB_s/9H*G94~T'3荩m!\) !1]t@pl|aEmKwbC(/=LKe ).P];@pdkjo?%< ?z6x} xUŵ76H H " yG@D@!!|` A;aHAI U[mmVoG53{s@k4${֬Yk͚5k֬y Bc#//+/*,wVQVz4g׮-eć/)n/gnQ{ޖe%%; K3JvI'feM?*2y;=-3ok]]V^̡:ZKi{2ּ9իy4[&k'BHe+;Gʙ315kzVV~i\H܊Š8e3ETZpp UW.e;)W\VV\RT\^gWEƖjPwP<(ݣ|ȱ3]%{ Kfg̈́VBg[ wfR0}>@;z[}K%r&Dk:Z>r/I:|iڏ%syZwƸ㶕o)J/)+.۳;?N:jmͲY߬j-xΩuj]GL>Ƶ>oG&|MK;qDUU=[2@{zպ@N$jF(o}&()[]zBt,i7-kMiO+i!Ôag80:<%LzP])kWݲݧriZfNY.;ROupB)0z-dx,ڽlߡ -xm TzI ivm Qf `AC[bBӮT *gqdUR5?.U)ʃŊgbҐlKg!VevtC[=K:֔R w7tVSU6o1'oAi` IʟF;-o6+$F}{|s"o+O /uaYnzSIdx?e٭w#]0D$n`SdXޣDm-M VGED"kEwS QGLL"ϥ$C뭥Blu3#c#Ԫzb q] V#bE:Ȑi!g+_FFD/j"x{lZnSO?ľ%4^>GLj'hA jT} wBWy[վFK`'ɸuz<x4bP475hxOԓ9R/V2;(;2\E,z.bi95aퟪQ=8i(uqJT>L@ "YLkebhW׏HHZj50C`4O--kOԓ̬H+'+ U̜0Wy*:M_VJr%kL$@DFS01J˰3xk{*-%t4#bov/ #^Hi!31- 6i>ZY>9ekM}]di\$4 ̆ٮ]rΌYw1jht4(R|6 ӫV[(zpfr4Fmldzj ^LeC%Z4&Fq@ABrVZbFɯ,YbA}wIk`NQ/8?ǰ&!3>9 LFSQt(RBq;UI;[ 5O>hԕ6/}' ޟ73U'S0P#G!v3T='XQ']C5.(\C*$8Tk0/PnI (zNY73ʿ%Tl(_Z|X$>@λoItK胓GקdQO7SKW$2cUy(2D}6a}%[-S8eQʎ]y*`X'yCkK򭑯+V2۬vVjs]IJ*mRW= Phz8DYH6C )FV,7!koٔ 平&D_! 1%TZFʄ[W֪ELT .%Vf=I|*Y=eu t*N_eVS`uSrR`΋kiPS}z@Pv]t>NAȓI’ ,hx/5Al"n.+WkY_hmTJYQ a X 9n[? n\N=+,\(DZ8=wLxk~#|^~t~}U_l=DG->Cq,]2:$Ye1m.Gtwm$"t9&4T,ؽm7W\qfF&pdpGg ?}QxK:[3U;+_n WL+ =Sa}sAmhPi SЪ1XHEX@LP)0xު~ zd5鴥B1+AȥN ViXoyʏ>Q -3}\HlxNVpNqBB@H(~c5DŽwByʸ[nT6HM0 ytJF83=w{zW^;G!Va\qqS jPQ.ڲ;.dgEqr9n~M9!J^b([d~(!v٤dgt4davNtkJ#By6)Y6%7Bܲ!!7gQ.4(?E~YZUs5I9]%^dF_9$@]0!Tt@6 ~SWfOK'@0-G`29]?;AhK)ٯCƯwf;t[f C#uQ-Ȧ;xYQ<7Kucv>2?ݠZjQ#xesnſq;HuZ֔IHfj`) bGdž{}jisPp+nZ} ȀklxK4ކ^bg=J >s|+|2@}ܣI֎6kňL  䭚ndn\Y>ݩz=Ċ┟5ѩlC}U},]^sw,Ͽ#6eKZH4pv0KzhoVQ ^6ά'c1:bMm Zu0mGhZpU(u zYEvZmqջ!w4wKVCIh4{'X}mᥜ$ok/2aZȄmd=95=px^|ڕ|baZK]2QHp7 FB)շBYU?5_σN"w ?JSwX"+z竫VC`Dsm#H܃8Aň0eZH~*8QqL26s_b,t21NlKH%$t|b, 2ƚ߄U |,YUQlo.n+b-R)gOָld#At VF[Atw6x盃>K tSF]<w~VC}[|ARZtlkSEk(ToYȁz_h{Zu-u,Dmi_oo/fΓ1~ rFTlMɝM0y4O`_^gRYAct#o\Z*{NՃob:Gv4]R.U׃z:N77Neހ$ߛʢ|hڂ^f;޿5Cu&и ĥ"0iBIķC"Jjjm|_t0sR/Qgi^ث`9D BH}7@jul8Pmtٜʃu =F eR N뒐?J&&߆N%f&s߬"TA֍r! @hY \|Grƙ^<ѫ5W?KV\Rԙ|kb,A NQ)q羪~sŹ:W}\i4C.kK_]n-kh, ĶfVO%QL3E@  nř;Jw.+ػMu/CDMeJo讗 W.03;[*ii놇$%T@3[/a [_CcڳfZ)뻂1>yȕ򉩓L|p[Zl=IPboIL/-۽}Gi1o/+/=&\)MC]8"D@HVVRRvzɎIg9 >Hios#MXgt1&@f*krZW}xMSn4b8q^ug"y]}#SӝUn@]3S;7X4,LUqyᾊ-%fuԐ` wfu}Ď_j*$X+wHg8oj!*X?`e߿>_[LtuA%SQxnm!E6`;س(ˏ۶VfF2~ I;~ڛցSj5,rJF,*Iw!M9= d~ jh ~Xg}RK.Ac^> (p*B^+!QȺT>rzgڏ>gjZYRMn&Ig7[,h〄1Ks5';2Ce:M.laJ}ZfתdXSEkPQor 3Ccsq~1C "_WXiqT1MŤA`4p(W%HxP$dh{ufFq5 -"&ą04g|a(jXjpjz 2Z\4EVHxc8 #X4T7\5R煣#cotUBf}X2aOT2)'%V$ϻQdm wDYh|:':]N!@o4"}'M@j`8`nE }Xެ L8,z:&} eL4Nݙh{@o%C50c,qYw].]ض\&k+#/S'dE$?GIK$;mx%%9$.6MN0fѪI~ &D4b;SXj ΅S; THHYӈi(>2gY0x5MG#B;XXe#3 53P!j@1c&g䕙sm0XP>uJ_^>5, tf80o gg~B(9E di`-3 ֚ڙ ? 5i5k\4.n53'x<E=zLc'v g|]uVGif.@c .C :ðWvXFP~Bz9=va-!%"9@: Z2"} mZ9/}27?[h4f,sabZ֤!v‬,SQ{*6{%EDBt&hڌ[N("$ŧhehdg-Cqh~r_"V2;ǃMKzyQ E7$+PnWAKA -g%K釁hL zbqk H<YDS4Y՗בɗ~^Eõl"A0JP28log:ydmi# b 3uqL n UUpmha 膏GX)ߎ@F*&kp;ZLD&ykk= pgEf; 6x|n!w6Ctb(~#Z3DPqhA{\FDz[goۍ?[;Q vJ/lZ^goG)ap[;aEmGc mg%|^7YW ]dl/+@ɡzQm3>满 Mcw CeθKk/ 4^ lFㄖ\Rq5?G& pc.wG sRh#0~)`VJv21f,{vi{LGx_QQe(aB {6a%]]0;+Pl5+YaO>tmڍƏ]9l7J񅲓|dvJ.Yi0;SGi#D'Zxqnl/JnoBoC!V{[ 0N0JwBV?0;m7PJ?T>Br@" mDGT侨1=QERḦ́(1ބA Qr6U skpʍ c7xI :8z̈́OQ8z`X{dg oGoN׉;5]()m@CuxQ~6|řM~ Πnl`3|oDĊEr ⷁʟ݅X~7l/^aNNNޖ!;Ig0KG_PӬ{F]v N"]Y.Tjj{ r~_SC5e-mg0?F]BXm fyTr:a` &5GH=e_Yt$!õ#0FNEKnȷKH.!}h?Ůb߇]ϲ dR3 (Pe?M#t:{EN acڷ0ʼkҐB_6" =3j-5<)O7 I81ȠVS,qdžN(DѦzv*dΚD.~D4c":k45\5e4.a򏗬OvXUz>ע|X Gp+hG9$2o&1QL ; 7ؒ(U+Z:|Ň ~%$zGɺhJvuة$0pX mxF(7šU+DqJ?>mP4*Rf.o)ztx"1~hYv0*~ )igrG7}?Dlҁo1Zu,\Ǭ?DG2Yp[@J]!NXF܋?BMD 4zL=n2n1ړJue$'K_ 4>P<=1so9(بwa_Gu+ }]ԢTo~ŗXB\&gУx뿣P693 "ct/9ʌ l :׿C&a@#ӽ6uM 4c?= :+-u1x :)8'h~?Q|D:4pm9B `}4;͚/KuJ^L1=AFs 7/C\"XnB3غ1=ǒd7|`}opO0TpAj;Iexoʢ8 Lv(W;>g|:%P]kdj~kWïښDPw6sYEq9z1 %#Z3RF.E<9لIH1 Ur. VZЁ; Ygu[ꓼBWBk|Q@)y( ǹAuB9˶c}~<,Π?3XDJ:sM63uB( xΏX'@Ds~([Z:(s376§fK_?h KYW g\:)25^7pܢ{v}j3y1+**v7) _Eh#ƞ,P,{/ӋV#dOԐb?EwtK~?\}o-dd|hY@+ ݟ>tp/C0P5ݜhB+gꂄhz$A*V_N|߿BuEWtvu*x ]~/1x-J~$c$)jXQe{J |m>}͌L-gOn_*=_l7?AKǿ#y-ad!,gŨ2T w J֫:gYLԓ}p#~ev [-Paҕ+X¥jeHp%0<y#}m6֍>HvdȉRXXt{,.^-$vf0}jh?U96t(_vQɦ=ǸwW#.;y@(Q{ }44jW#X9t[԰/WqLԫCr@LȌcf^1XO]4v=mc VݸOM؆KHxapԜ|{ypn-iz1rl7 ]8DvɏDY,·k5pxчDбq`<;Z x$$Qz Ԝ}#n6/&RP u;p,X<_0DK$g"qRBթz?DKpJݖ=_K̹VKNCB7gip,Gҥ]a|0@H՚X2ʐ0G)ٷZs/!S!%z(CrSt8S* awf+ZcK8+K=Brl,i{ P'̖& uS񟲥 s4=Jm'9 /.zMfX6y\}diV{ ϑ Yr4;Z,Vdj-4,J O O\ I!4{ɻӤ%=fHG(>C7X)M 3ruޙ)X4{4%s̩n[+c2jtx<vh\"zz) (ˏ[vQ޼%̼DJǣIs3~(^y҂T@Q ެ8𤵮̗σ)_]/^_U)'n B5';ʐfH=Qc{*WHVdYM疁FEҤH ~tBWr|t.҇QTϺ M=_B~\]ECt2ɓV-: 7J3DpXN&M b2ExMoV7WJSX^<1r2tչÑVK6^ wiOvpEj)Imx-LΓC;e VշHS"猫ǷHQ>EZrr)=!/:JF8|> k)'ZAHH.X榲a_tǛJ15@%umzF}p{Rvc@wYQ46J7b)vMc#)/~y2)@h3g2avVz}2Gj׹KwIqF_`>"m[o[xÂBv^m gAw[!сo+f/OJBj'E!9,!~R^c siܟK\H#r%qG;{ɋ4ӫ @#2wl SQt4>n# n%(_WHqAj71WRPܐa&(xݽ xUյ8mIe$!YPQP$7-ɽk=0ZPrZmBBBBZ[;8׹juk3!)V^{^{MW}vX0 #Z"냉p4Ekh$W"P,3][m %Zق b%ZMjPTAۛbam˾X4łDpY,6=h .)BXz}poA[u_SC0j ,mUڣg6zmU0kncկ [BAÜ1N Z0tAq<|ᜊ٥sj2~yُ#.m ֆ pio s|_56>|فsbŋ˴35keeRT[^?Q(_WS颲RY/ڬv+ ˧2fYX=ujլ Vkj[IM[a덑*!c+ G.J^++A4@?4 F[QhcERr+'I۴SY"-yNA7̈~h> HQ|z`^'kFё@ L ~IX'߉")-if-`cyˬcq/m N`S+]೘L7VWq2FƟ\'w r'k]#B;Bh?/ia2iڤo,.>H?VpbM,$Ƹøf );>  >餽njB+/V]T2)1e%DkB1$)sٷ12(e 1 ɣbzt^,=%S'bq}繤8cAFtXSp޹rrÝH{t`c >$rA8n9)o ~Ya0)x-jaOB1 2yBC"MA#QN8,cEJ- -D^S"C#mnΨ\B;ů !AV#2lFpCsp-ˇh@|zkv@4G$&1mm=|yu m @G86 6Q15g}D@bGFj<QXj=RJ6\f\y#t@`cH?p ;5$r/~`vHxr& 0{k"ERD^ʷ E<##7;}KQ'7=lé. B̩S\G<`K=P=WEzXn TF\ >Na6;X<56LܔUz3`a4ơ9FǬpv ta`k@B#-,ZW>(AYTcdsv0%30/2Gi˹̿0 gPf%9Tn 7,I3mvי*Xz\Ɵ FA>w.<@ᴵџRrw=a{tIKJJ S/o3UN`eEz(=am $!8X;zV(g3ju롙uA6d֋&Cm@WZ64m8^` ?v@WrU԰Tqs&;iVR/S h h1gFE㤪̓:g՜ѦX8R+ C< 7ⴸJx|Xa vJM'NdK1rI)^pnJY!K[JaBID80.7xy>J,h]C6R\!N-4:4c*No!yv)Cླw^N]^zfOnEw&7G=ftΟ`ZnAsjTb:W^688[V\w d(UiȠ|:ymNmGFMA8A&xqW!n]BAӍ(h iJLCq)U\3RWbILyr ՗~L)AU8,H@vd`(b3Sq­;sl!h&. %f"tS 1fI.&l.azߐo*J{5۴6 rx)V6UA[›e\94^V̋O 5-jR |xB_S49Cnt d$=Q,f-RC,\ʼnEi6Z:),-J-0EKk'дum ,f7nܿ%;x=lDwl4ftHO+4vTaژ 9!p=^@u(n'?j;TsIK4NH 004rkl0s5kGNCmZy~Z`..ydݨz!0}[2 3h?-(8ettS[&R&`۵K^1}o12';;YWbzu<8On)f/huqe?GxKo+-L;ïcE9<]Q]3*:ǵBEFO8;+;-M I;>c4ZP 0X0ͪ~@%Mڙ7Fm4gޑVo-dzij?'N8we5vρ[-G0i݁OYJ 9RWbXC|J>&sƤ2KZdvRVuCdQ {4ݭ^=@Ќo'laUKIY3OSi26w lwӘ_ĸɁ{X :׋ ^9^_pDu>)i5)oe.ZY\xy8nDcōp>U Cr5hxХ1" 7m;l.:ǂhAdiM@KsPm.;52Ħ,=I,%Khn3)m&4`|pedq/i'ط'`.1Ҹ3R %oa$&hso,Î< "Ac{>4P@N#9L[,ƱFsv{KXBlUUr_<λK&z%3.`LE)S^mOK1:esuQͷjH1t#g,5pZ:wY_PP<#f)',!I[e=D\~9rm@Jm,b)*2^\~p=f遟5' QiD?b( \Dt$A-L.b;Q2x3ez!AN@f!dl.Ǽ \ f=)a3`^Gc:Π͑Сoݔ;}!ٹ+(@q lD/bnN[g?uq~\ ҘMRyUp"sc8XZMy&p5֣\` *c";@0ƈ{2N`vfa fܗL'@]{#[C,zY*k{чsA-6e'}@,B/XpK1V}[Ӷ $2(<4=3xt ("Fo(0F)JE\cuCBUDI /ttEDCbGeI/{ȱή 8ࠝH#XD;iRˍHw*i[2wV"mJ!WjCE-7DuNw&! .c^>;O*;Ƕ6kEa1isA<^N\dlw?Gy8@䃵 CJ=b,UwoeG~`;Q< Uu%Jh+q}?݊YJ"` GOLY*M Y'N $h5cG!ul*!+oF62bʫwx}:{Vc 챺EOvH3J6>RO;ch]qۮ]ظ% seĜgukXswKY׿&8˨l $d57aJ5R\?c2J/Z=}*B*X𥘜gb;rw Lp[@8VٽJEEi0 `>ml7>k{ ?Oz~(Il+jjr!9i]e;G޸CRO>vgjS3^d RcgYC9Yю&^Rcb̋?|;m9cya.v,N r%t5{NR CY;KzDAu2oUM r+!BF@bogɲ. "/Jѩ;~g8 rcGZFScirW=;kڤ=71/yg/uV꾡^AaE[e%w,% |)^ ь]+g1n9 $xje[<%n}gڅ+%,PP  FR?:7u$RWLJl[=ʘ 8='o䇼5bQ=s:N#=z_[FqWryVZdW;t8`wX]tShanmї1EóR"{Ϻ0?3Aݽ= /^XV7a_Z߰n\ű^h;&=/ZUHǬ^^Y}[Fd'2sK!i,^?JƌsB;O=/E+HKmC뤾LP w$W GnƔ/Λ}MȁH:hc/zU~^y1/n?%, 4lԊxx(1'sDmyOx$Whq~F{kG@-|k'6}yֳп@K_Xq qŸ3GD=2?=~[Fʄ|\;IC%cۭAx쪧&-Y :o&Wƻo]m^l;s/pcכO^X\*8]?A+oYʈcp\ś-tT豋 J>1UH*R[h5v~gؠ9f߾1x)9je2z%1ܿ3n:Ar/\NK?2D5=8S !ewbW56g=v8H|r"r2W}p߱g#7/#631J =WQK8ί12%eDsМq7c:C(IۏPn.Ɋ Uc"sي[w䲞QV࣌7ǜ78ISlK_p8)7&}g)^yEblO~Gj=fG2i|2GY!h2^3Ӱo=:޽ 2v4Qo몴8ص[YJw43 _9rVr1v5C{xԶ%J[ϨT9,٤2";iRcAB)So. -Zj36j3Z@_=0UcLdͬs_wnڿQnqd[}hewj~oSt)?{2`O&~8ߥ^_P s$07UdlK*ha)'?f|g)+ع wζH) S's-e]Yf]OWIup`bШ~2(,N`1/B ħϥJ!䀊w/ì\16$w})J w/?_Nj`: 9Ƹhο<Ɔ&>HJyڼ\_]W[ȷSu<=~`5|sX}0#_DŽh"0W3EM;e (q#C1“{$'wh3 Γ=R8ǖF &&[e8Hf=yN[Oծ<};l!ݵ&[xmm˳i3=m|p\tˌpv\%׳L,[ Qs9ȍdXT#ǣ#B"흲wkO'sdYqIPrkgVËlb<ږg5to &U7=^tV?)(A!7{^8u/SDzY7:O(Kg߱MS(zPcuteK +`^9) V~QjIite女u?L >tڪ^Q&ýbH~9ڨb mS5b38[}kl~f8v g7df,SosʁϾ'F]G_"s*5O2ŜDOegnY&xLxcM.);-l\2۷w>4̜TX2IAG>3iQR3Hm k@ p+D&<2)f>cN~-xf gE6!] {DDx,cfٗ#'c9d'3ݲI9Uc"Iy>رڰ~0;>Et(^.=ǜ_@n16B۹egz.̓aޙsqa\a˺;ȕSdyPY, 80ɇgΐ stQ+ͿTwI1q3Q>,4|j6 ѳnEdq_ƘMEpU F݌'~u"\a>}7ܼ1ͥV1wylRxټ2cL sL a[A7z|:@&ۆ1uV) m>h~I7 J_B:,h9`H22ҼL*";K1HIRaPeIȄɩqRlà9 ض.R}}rodk|)"9dzYs@uesT?C_BT -QeA)bJ1 =h~q.8{|O-3c̉HMXze8eXɴeAetվ鑨ke+A2P)6  YUG RPy U/$%`7VP.n #ב@};4pEdN/ S&<(q 5Tetv/!轝\mi  Jq\J`T"^2ܻT\48w5,'ZtiJs MoW9>5\=+IMi1r]"U/V9Udi%&vsL)qr d]`9%B7YJj.,D+yDz}^{.NT!OQZϡQ[9j sB#E7|p!:)]|1GR?dy L%qfFۋ6Nq,<ܵTd&o 8y:-;|F2#d~w=YeX3ܯ_4C @%${  D)|,gۥ!*wj֒=BZdxxCM"d#/AхI<5#طBsF͟QRLG4S[iMp6:?]%ly=y,Hҫ.5^@u9lJ+6ci|t%:2RL93s8.iV敛d/UM'o%Ϥ\|BrL e콋Yl͓*/'M_*)vBf\vXyz[&z:<:YCf~55_UA v-q JnصH} A(ǜ&.:~'5_OחnRVs6oSM aRsᢒ]K$zb@!c7a}A.ya.نBv?B}n]O& 'rμ(2qٿs$sNAn1d{n~FyN2ټvY w$ͧwu[Ubfe"\,wmK%a/>%wս{+ovrm'pit\s7ɛ g+J^6tci>\n.twa7$p5Y?XoHLDtQF,z㮯|] uՄ 3H,n %ޢVze%W]iZ2EoVC $Ad >}G0`pZSPllt"2kóg-`V (b^ڢc$h#2>H=- MR D;#qsNVIYWg~T̽8N r3SJ?L?ѽ:ɍ1je+J8OzZ: Lu?aʼ0F,넃^x| }J{I+AOISn.Qu9L΍as@U E:9߬;J>\B1ۣ>`? B@mnh?DByهɌ 9e7cg{lQ(OddiXCˇZ I%2݆-[ĦȺ %1*؅UGmFN_p۸U-,2dU)+G~5$ʸNK<+|S']M#Enj!,&%şx~'.wc2vYO;N׹~9e̷%Wc >b뤠^t]Q:6Gf,bO']漵p*s:0檣8?RKMQΦ6:MUolkU*.7#Հ=dNi@,KeO#lF_^{ uuJur+W}9[r.Em6%֣>ĩz&[~fC 7#v/yT8sgɣRY+Mti^9]Ϩm &3lH>b>y ac:KubG3m'Tjyfj۫&sdyg)9l~K(q· a}ԏ9Jh7h'Sj>OQǻ1umC,CاvNRdAe`_2JBeyլw:ȜB8uTL5hSUepcgɂԣt9IΓOq>7Բ!k:u!@8\l"- 'H`z&bͿv n^`)m6#eٚgϑpnsH*OH~$an[]nJTEm[Y?t[*h3!y/+S`?(`v`b4 GZߺW8D$᫔Ɵ'KB X]1Ez\oΫ':Γ[S M/8t %kiה4*ntX1}(sD $CVR-lS1tG@idY2 ShR F-e/;/d=%) )^vbHL w͡m>Aݚx0 K|6Š+-8K6oSv^gM[Kt#S'uSGB_$'n%Y󬨥ؑxor? Y[[/;'M-SSEs}օp$kh4%ZS< E`u51`Z?Ux.|S\nD+6NQȁ5WD1 *EKN ǵ`6T͚2pMv-h}H в6CFϱe\8Udžs@'9p)]dA[(n ֪H*Fj|i;G;0.L ged 0}VI' %-Pn8}MBkvjD(KJy6R Vud jVrkrƭ6:2`L|O(QC wՇh3.dnrn€EI|N"(yVd "blV4p(+>T{aTsAoUiBz*?k'Gg"Giw40˘ĻEu/7G )Dk`"xG({乽nIЬ1 G(N*%p0,p<1*cc ͞}B{ƅ6ӥe#>^~hzīBMt#'ҚwC~jS=7zY@afvViD9"M 8QTׂ AX TDc!zȅváV#~w5Ty[ͮhښC`H8DsR :B{Y{BƘ߁p-!nHIA:aCiq:L^C N jUu om&5Ӆ-m?вp&\X{<ѵ CI?kJ~ =VbDLV+(( -H[,KBi%ė8-"BJ P.*=ާDJ?AbDˇ)ĉnC)rYEwLV/MQLs?BND8ИWr,:U!p F`ulfazFBUhl[pA," E/OGvqU (Nkdj6Sx]OzRb]4bmu tIuP#?pv2ɦ(.t%c87/U5Q6wţMThV\7z+O1MV:)XD`2.b%'7/~L^e;4cBQ< ;avʊ}e ӿkI=4$YP,Ho_3]#3AypEhZ.w>v0ۮ,om]A#|jJ$ԠrQӖx7\FݰW3N\3 c`ӑznɬc4zI2 iF)' rܐg ~ _B Nςc{_>_'7jyΆitv(hϋYw}tsd8f 8^[JydppI`M!)k|v: "ǘ$]r=shd$9*.ݓyYbeD}`#X=PYa>  %*Oǘ)5W =~) ;##ƍko'U>O^v\>%=2b".5KFf7| U-dccl;}@4Qw.̗ؓFtS m[1˲ <_ )#K§wBrwfW W_%'w W:URb7(8aU2; ֒]VNK?{3?v(HwPKoL3~d2_&*\ac $f({L82욱"%>ƨ_v9II;Pqӄ;RU'FYB@PYa2Vu[U" Ek{v \{ͮV{A1\@:z7!l>DuѦz0D=#znAlMұ'y:Ե:SDZ<gۉ;#65bE"=Ԓy-2/Z}Lbզ59'5܅`~3D +6*O,?Ber)Wg¥ݮYv#ٞ;L! = VQjÑ*La4J 7VՇӨYiY5Cy}FYEwRX9;CFUj|??9n7=#5Қ}0;6upYdpE@7HVLgU[X&ذ/y/ x?6n'!rlb.*v{g_S? {cT>ƲuZk ~I$3nqUmSNS7r[0yL;*ߩGS0bk)8S"hktak5z WBq aoԷ'sEDHJ$ Zw|!^ǂ:[=4لG >u߮ ;(!a~y<)ZSϬC݉hzt z@ E`G_qnE {=fOE#ۄ6D~{F7eVap}8f X?s t]`M~!D^Sb/g9U!RRّj%~ WQ!W ~M;]{}03++[{vC-'IDj><4jocP/SJꢱDU7dMqKFw+{o/;?h{͓7`RVTY!O}3'tw)STE&UL  D% Մb=5GEnrN;^sWb?,U'ƦSIJB]`D{ڏuX"-O6,jX"h)^~1vC4Xƅ|IwPyEW[.ZɑFﲽv_}KS,Ld,ƇZ7{b?e]~cxj`yG[Ep-V;D2N^bqF#~!G>+rqIi1w]فs0`VƋKݽ i{ FIO2΋@`" p:`m8:rgKX8:)C}`q(WUTR 7X(Tmhh`>"ߒ2haH~^$A,3JT\ҋ 1G9}|̅#|rړV `hd|=a]:[guq5\V/!]M÷ 7n˼P+ 冠8:*,Wd`9rɲ74Vǧ1 S|5X\r{|H\TQ\|C5y}<>|E3I֕j/~C4wم%][_ c[JX԰k~Kc<\UHqek23kT^_ϚޗJ4cjvq$c"tbji;"%B(5fŵ:Wu^!^iB,Ba*#q`@GRg=q WHj:؄3{1e(v?B8C`e)x 򄧑Z1X΋X9&h<y0ާ\ r T$X>O^a <7l\sWEmp1XN'3/@Cߝ^ai;x4cSğ[^A GD-hH{CǶH0Nr<Ƶ̒ILYi=tk#$6^w||Uy*Az=ɒ./(*0";!\592 $x} xՑZ`[cYuѺ=Y%۲-dhiZrkfsI W^%#@H8aÝslB/,HAb l ^H!nguWU^UzG9uG,YS/'br\R?T4U7es[I+bdv\N-!'Tɸ2Jj(!qj2)Ec8Dd"Ĕb,&,FIYMȢeӪbdX>%-=NˆɃFv d ơIwm64yL %JNktDJJ1E3hbZ uu4=B5sXwgDjH2*;t&8T8& JM&z{5 {HĺWpvs ڏi*Y7-+* 7e1RR<]N+v'πggúܢ ,}TZsհViPEOj"&S˩e7h GDJcRȡtp{uXNt oO/i|uedcMle"DBr{[9vINit9oFjbH ۥiб6CF\t۪-$1Eb51HQQI؜('`}T<*'0p䗁Bm4V^JoGZ,!4#dapRFu'r)[\9y\$1"14pP**&Ozo.=QQ,xU8y\հ)YVJ\kJd<&pD Dͥܓ7k m&ܑK rUZ\9 -E(r[үho0!>`%Y"ž]VN.֙YsO:LM%pJXlEdXz; 'EBr %&L^,TgHAM {D gO%Zf[L </n:md-waXF*]5 8d\shv06?Liݴ~\ڼ+8xLgftuA9%o +OʭP+e{b2E"E>q\†RQ$J9z(5pq D /G-=p;% ;D;fY'``N(<*C ̓[GWL0hmv+6'X͞M[LL"1=FY/֖oяz<&]ĕJ $3̨:՜Sg}Ϊ;*k Yȣ)Do4h;s{-{ms"z"kh_UVh>YEqhT3\_$*57htѾFxj^r^[lvWB-hA^ll+Œإg⡷Q硋oCK.,^CFw;=zܱgpSG6![ML*`3q h%p_ou_8\p. )G / 81 Ÿ/$E3}Fč#7\ܬq0>!?rGuQ89.jB:Q )E*7yj*\FMa|6UQ 69-]҄a.0ӂA݆C/_m$JWi'n,Bs'ҷhxwGߡue7]ş?ϣor6%AKoϬj3*@[en8̥ FVVeV>K y_m\[jt{osgtG:xN? .gaKkj3}vG0EHdRQ!c?Mzr->Jw<׭R >4J.w_NLXh Sr@;K^JvJ1%9hΠ)@!-NE 1gǐ9'6x.&CR A9Oi%5`ADy1rH"IUl#eGKqxJ`¦`Yqrr>]}<<Oq0{u|IHTRp~F'ڪZ!&iӑXG<LUG'ӟ\X0_H'mL45cZA@^@1`(PG$>7@y9졺8(<npc :iEQ>)nuT2^`$#nÛdՂ<[Ix7`)Rv&$}zA]ι%6cj^Rל\ӦNhE|iZzb v*MS]ZY=M5dFEPo.(_9Lu+߷F\XZ)n9uyw&3aOم%J1Vڗl/\3zf6J_S]w@3ʫJp͘vxk Wm[Jz/5Rc@VA51%.:y|/[L+c6-fqG>RO{i<\)K%w:Bz!|p0<)PHoMeAWPNC[9'SO+V$kb.E`&mIYۂz{kK6J JQK?TW1=sMF~0l> ĮV؈$Pz7a.3 bvlQKTnHQyR8jc#i@$4tQᨆ3QJn~ϸc%;nxH[􊕐oJ~_B_'vCrP ga+A:А4 <}K̿≏*|6'Dx!Ng V |EJT){$Ga2"*Ru~ĩzKuR6FJrnzݩ :\U {⧣^k0͚ Y:E;E1-JGd!;~ ·f7/PV#kX2,/.xpi@eϭV[e wkw_(x"('Qc{Wž,}%G[x}vP9M)r8!1/JSϝ/ ſpӣy>qJi rz_'ft@7{@)]I/E(;}&EGާx*l S],ՐkBgONM &#e }gOv{ Cz)Gy&@>Utj-T>]zcy"Z|ܲ0W/_w=_':| n8|jJLxf W\How6R<]Oc?zٟd(ϝw+Jzt歕n[BJUMo,`Cy &[E$n+%/բ g+*m@[8%|v-P3F*r{BjF ۞"Y "3߽{xW`2PEf"IS탛*X^1{m)7OתŠ6s5f>جxG\.Aܾt~IJa?@aٽx"C#(_#B԰d5AaB >%IV kPM(4p!ls͇}*ia?]NVR|:L,$%~wW&R0'I\>H-{}>h^kueIJlu`r/Mhbm*>b]#tF':8 fX<Gb')aNYGGD$Ջ4n{E~ͼƄ+ )#_ )pRc=`ؾzE"g£^ȾE* IjXge;d7Kt7dC./ʀ]M6 Q{*2qni|l-X[Vqyꩵ$l*v3vq1G! D!-$Gn,\BFLRuddzeɥK6j<-cw4 ,,_/W[_xR%1  K܄ K J1iRѕĎ|Qp*k +C.((f-ofGȦ]1 %ijb1-\xR6G.`*,ʮ2,:ӻ XC;Dp?%YZfP3hٶͤOD`L:JG(ed ?zHSM ;'7˅ص]:@X~AʆRy$@?@Oo~Io+ ZjeRV.GB졙Ct0 Y\i3S5(ِXJ0 ii@Y6[q՚Xwzr&9s➉Ή"n]*NC h5FNUe.3bŮLfCgp&C$Q3x]8w,5j4I.YtT ҢB| Ļ$ir-$iNC&K)!RP7}YRXH?h+@.kl0?arCїc>ٝE"H$?H,@$ 5>r^Nj;JJ}q=@^}c-d} WBy.z?H1Xp[A?wChge\ Y̺A& + Kix~5G%MCzKHGDkE3~s(G`&rt*KwKIE3 AƥdC`XAZY19n|͗5Ǡ F{㽗Vaf7]Nưzq>;e_O7\AB9^H~4/3cr[#++ .|Wh`XeQ饹a[VF^Eft rq2k-vo_M#(ZY]䐥m@? )r]Ic@s ,`iױS7*,_jSS=zFXg6DjG?EWJθzN''%>|04PI~Mq-/nySę,K19z&Os*6<|U4@OǑea-)q@ᑱsؐ 883+:39GV$.`_T>뾅x@SATxW1I e6G=L9~ͤXxôbuhꃌ~ *]3&P>vyhy+(޳.{~|iL,qZ~x;9c爸R&[? c)G*Ȟ^vX9\Nypq1åPMQ&p&bҤmlvSa =Z2ѲFP;P9ڀ{W rzg '~w)&0' vʩUaVʌu |E(rni H*% tr5K8xw<5'2qÁ/]C,)X;TG"|\?J$7OבOR?h|p@hwGg,VDgX>2!gs:[QIc1ҶBP y}Q YZ@p# PZBhy.3K⩈"4&+HqVa|'Pgxf " fjhe7kɅj b@* Ѥx~Qx4fz:B kkVՉ/]4 *{~.sz|KҢ-R7 n$Ι q\ .Tòlx%n,l/TS[T9MJߘ퓺'db]\ANQC#z;9 wXocdP]ans1ƍPbaqS*hr@Zi|kYem%MHQ!}yzd>Q.Z̳ϜJix]NjPh`4tKj[yWgI!iGfY#G_m&`h]r d4ϖ]0 z8qu+P)l<²+_(fw;/;فv>ّ>+A;)+J%]]x/~k>u/O~{֯B%s\0n~ &z为lITCo֒}P~{/tڠ6JIJˌaf.?}ľrF{QJvls?Օ98AڧArg]Ca8 ۿEn_ɓ0X=IB9$k 1rK){rٻj ~ +, 1.f׿N!aWR\Ъ~ӘY'6(ܘh6.ΊZE k'{Lp;Nda;wH0챯6vW[j RA!|J *Ģx,#~r=~Tco`~}/ ѡk_kt(7(wdu [Tq+Lޣ# ~:/D~>, *^J_ƑU#u#\%ѯyt.$~2 M;4p\o藯;- VE;0llq)L7,EBxdAҫ=N RkVOAװA%4.tC'ydqVurܽdq}`Nqd;w1y5B/{[9`N\ eX6/ZOgo.ԏy~&|џ wY.'<}z];Ɉ$m8~k6lU-F/27j=7XS ޼ Q.+ȏ4MLAاr~{/!)&)W&A`|a|+ \$,6~_`\ IiL1*N} 8O(B<[3O.G2CRۜ=64qy֜,:"~`vlF 4=K/z~ҤydCO +A̘+cQJg6^?;jܫva41O}>o^.\TbI.;L ӷ~#zHR!dF2uOo6KTSa<TtimHkUfΜVvI`Ba BIoM9RࡣR`&Lp _&YA-~J$d]b%E6'z,xo߯yip{^Mtp3ģu`o|z~D'n>]H6gsɁ̨8W@# b08Q!#R0N;ʉyNh|?S0S| ,A,<4iN208Foֹ }TJՂ5N*Q^[ܬ_HEɃ$<5yġ."iN4~wqθۺC$r6Ty<7k{!K#! >^$vHZ=z*_Р_ q9 $A|-gV>< }kGy쁦؉WH](?o_ɶep+Ou'nNSʊb oAp\^]p\7F -'I㖓l6⫤Lku u! HBLŰ;ĉTR<," kR2)Ǐw#Ի>_ʶ4 }uiv8P- h午G [9ݳbwPM{wK&GcTDgR0F]6ZzB8~s}XK_"PJg]malvRs[T&RDkymBBB"5 n"AΏsY!e=Тt+tj"b V R \E~_%WC_<:|70! B OVƞjR[L ]WtewQ" 4m"3(G)SG7XO衊c? #.4T V1="a] M]oz~:1ay(̃52N L `7H}sdy͚~LB@c?YU?O!fbLs{/L 3؇r~I5sm!EJYDڋ~]G]˞~< B0Moy&Aj􈟚HB=0\;WbI6b0JLƛTKzgmָq٣B?stBX*bHÃJx^H +дdɛuS0ϵ[ s/5+zڢMA[*{Nj,f]*+rF7}B}т >q_:QSQAz^Ӭ>J fAi3mGy)!K5[` $ڰ)/:t: v;L"s.{GC ` ^{b,$ R!Z_I tDUL)-&;؟B~TASJ11UA,&Ks l:*2L\-O 5K„:g|MŢq9< H`%L-:&㸞!`HmGbxxP\0|!qea;[I e,'ӐgL&2,z+O (3Vf$CóV~kkݷw(o.?3weWn8!ZiL*4mBcǠS$o]GkVa}aG?Eh*(_g3-Bm"?wа췴! Al}-BPao^A.Z~{,Ξ68n֏dYFJl+[MQc% Y2@􍇡nA:jП-&~Ŀg?\3CcKgJvAb6C$AJZvxQl3قWV?0w,KrĥIDf ťe5k^`a6]}f0U7g ={953Q# sDH6VpT^ Kn)~[9Ƅh]ߓCY |+y iqM:xսےF >_^nQ3U_[")$U*vF"31иTUamdzh[1c~q ,롲2ww;ˋ2 Ya{$fq[9/0[$yϒty=?vvN >৸IY$Y88CEޫ"gay{07s 2xsl(ys/em˗o/.o/^ogϟ}qq49>=Yyx[L N=/|ޣGOγ?_l Yz~$+^@[_eԛE'}ElǙ?qwö? fIP0\mzŗ7I|{^~H_'}TۺdOXJXKO -9I󮗟뗯_%!O1.)<[4ba{ϟ o/:>Ly";bn}dgǽ{c{zh 0߅Y`+lnɟ_2) ^4ɽt,[ b?`_~<`ɔϯ$cb|w!Yeax[?%oR < 9f=9_EYX6p/+cfc P~ *ym &Vn[<=C 3 =s<)5f_~X0h, ߳!@c^V!w!ʈ9L.H"X09y<Ƃ`1r\R5φ hŀLplBe얌ևȤDph]yEː/R72ն7H)1$^("M>VsIQ O$QT3> @g zi,Nj`-2+{7a1N.HSO"q`<Hro&e(Y|QJ+)gs/+i">-Hj! &#ZoW'T 7I *_P/~ĝ\ƕ q! yI]h_"-TT2ߋ_+iZ'N/e`'PPH(s8Ɉ<,5$s$'! RR+-q1YE> Ǽ݂TvϽW<aQl^ r[r[+Gf`$U'9|-] ;<ػ. b} q-x1O,"ABbqcF75 <9vJ2E5E%ã@h67x _I(/]ҟR@~ X @Bk%1s4&>OIt l~*]x6y8^6Ix\TY6\3Cf_Ne'2ѕ%B(Zz&7g+5?%B>3T!KZ9GH|bf*Qe"K2]A(q8diA.r;=24avhN}Ӗ|Ȑ@\ x A J-ci(%eBٻ="t`T\(C9gϲ+QB# 4W(YIq2"5eF '$J@YPb$g^JJ8-U, gpnl0]V5e>GnJo9` F-B k4rskE&2Q]!~U9S*e|#nGMFSB 5׍kY_\428hHWEh,_O.`l| ' > t_qsksWa:xpL`1J1[(\ 8 -\좭8)i(Q,Sx2m民-Nɢ[,\ !;S$؀#DwlJ'hRcltZGak'cmjW=pخ0:R 6γXV&jm. >(/.xWU^[^?kh^HU{}(zvБ:z_Ozu!t'X`7T[ bM |$`"(#am&+"j{`RdXhbd_!FG#C S K bd-Fzm/9t.qQ@~Ha2nyrZp?/t e%ˌ^Q8őqj )&QJ؋p2 D/hquEA<0q( FD(3rb8Svz]y I>:buR,m1'wnfx;[bϰ<}ao N +h _Rz| J<^|k K:"`cz8rJ o<9\Xc:.%ꇕG&6.BqéGޛ"Ph [$9{0h {\">60/ h"񐠨n2Ԯ`i@`|x_>m5/>9z]_'@%DB\!]: $Q[yITG=H,D1 ӇB; ( /5p~k `k~xb䖔eq,`S B$x#;#?Mv,nW%p[HD9MM+ݝ޲6%1ҁ-߉__V`KXJAf+E#?lf5qQD)# d<(1g_K h|/WEh4R+T?P1mhCW^D1"l|ˢCʋ} ~&b SAm**C'+Vн7 "EA iax/Ƌb|D` 2ZJ*l!D$ w1BxwÐ#OCv +rD*zez \a1opg\clAhoᙰl+MЧ-B;vŨ^+$Xnx#x[Ί:gV)n+z:5N(Mmo(D]%ktH! V#X4TXF`u!)(ȹ_#'b<  \wRAYtܸA"+Dfak4TMԷTŮt2H "uuh0Lqll/ 0ק֏Im M koѵZ>ēU VTNKFе/ĥ4Vw1~Kz`2(3ПF`Y*0N6b82;sBQ!Ҹl|#\C "6`cS Y l#ǵaL]wEwYDϘBLjl(OD -= 8x3)KdݏkU9;y&9lYqð nPu>f\V(BH^79g~L ,Yv #mì g45g6252"kFW.Ԅs,ͤ?8'T &YIn|!c$ڈ֢"%~{u@-ʂ67dOJRMF+ Z6d<3.UtS)C+U Me"6sK +/TO{I'LT{5-O> =׹!j`K2Gu6WaQS-vƥr@xU%{)ۍdR|b0qtX]ehI=A1"!>'AYu /`AEiL6dKO\ǝbtw6.GX9uށ,RuI@r K:)--> ݆bt\YOfؾ"}@]Jcϧ&K0>c^֋,䋴XnY((a"r+G<'ggE>^fU P(U.))iɪ(UЈ{9IXכ5ETu. 3p:eZ cCWY  #al`Vu?k ƞ\@"lFa`ֺ_^ LڼZ0iF!1ZW x;e Z,c^`dɳP܊eb^=U=fگ{;tZV\F]  Zl\ iLke''X:;NRd|eD' wozd#$c(}Ŷ8[{h鼷& .l7ż4ND5qVD`Nie- 'qU*8(< :FUsuu8Uqk}Ed4bkTk -ġpԤ;GaNָS,!hbTJQxbB)㱧 a4 vRĔBRogeJcklP͜Q}I?~.}wBvN͘Fzվif'^"eҮ8rqTVՁ5cj|U/sNKmTFE~'s0}\u^K-_E:r đssVnϯhdآ_}˩e(TMp'>,x%ѢbJ"~ N5\_ NCn% *C&x]${ɯN-})=¹%w]S ?J|1dNECU@c} ےH`51i=4"R9 riIk=:i}5 (D2*+4*=:Ot} Q!_AꕲLxa3'IJ%]Qb%,л楈Hʬ^ ."1 )~[dly3(qJ%rNG`BئI,T4|ҠRI]sfIRE>U@.JXXXՌj"ˠW|OMn Ge kzKL-v\7il j6:$uO W X/D>ONZߣZf dMȿBw+]Cֳ/@$y_ GڼYǟx|F&ĽA[tQX+68nU)F 1hEhܢHf[/j*:)Kch=T-.XUBJXI_t\v4&q8pӬTK5Y |`?~ +MVO0J||晨.e)fg񻉩SDŽTvN™nxRc8Qey:`meMVEw g΅ʷ1@Q-} RÂЦ ݇4UE s<- ?gc2FW`6*NӬ`PG$lDߨ06N^^nW͟=}J-<ۈ^#N("l!SF8 9kf[-"L*_ƔPL!\eG-+CF.s{ue[]ZeeTxB(s9cD'`ryr V!,ˌ*IYo>D|?3ݬ ]邬r\'y{S6W74&RPe^YMTϔϽy!D#G %xEG-⍩1娊cԽ0}QS\ KZ[m=T"cqI < + =M[i"EIr% (:NQ sŗ&0)!\懷b@g(DWޜċ!)Sq!K+oP`tdd8~6rJ;5SXT m':n-J9wgR\V؄"$+[`xS[cHEHFn1"ѝX}kqND\)M1*Wb71(.r|,1Oͧe(QT); E =扡[Vb _2e; EaJI`|+3[/u 9,U݁] Xae6Pڤ%D0֙oPwY]V Я)֔>LKM^N PQi 328O$K. pqHOzOu(k :X*[exMZ Yf#`<ڋX{EH8Քѩ}fLqcڐkٺwwj"CZJ"xmHi,^{&ЉZڂ~!}Aƅva6Do ԓJ67~ȓ]4- r,nBl/_={.3/`ۈ;'kK&لh;O]JW,EHSdmoQHpl2Q1S䩒/mOG4R49< @д| jb`Tε Lk9Bgy=2瘨Wa%/#cN8ˁ)[ F,eʈ-sNl6 XxẲBCxIm Oi|ָ+ԁ#ѸnTOYΫ KhSXX"'Zˮ+3IIy4Sɽ~'`xqh&eJg0&!nQ|"Cɣp6/[t, -!!oL(2é>3db{2"oeQ{',Q_f[D'Er=$M藛biRԞ"XJ8{0A\4d2~.X QiϷon)jdH{/Ho~ NwtsO!({xwG1klZR!dF14qޞՈ,1X,/2KRHϨ0ﶰW̤"")ڼ|G J 3b,1hqu p{Ó,`uDzp`cbMoKv>&7:TUC-@设` &cTX@vx_Rʜ{(,X3!j#c[dL+vZΈ(N4f+t a#cؓqqo,(?̲k/R+yJ^ksvU5&dR1tdv C;b.)N=-]ʪ۫'u^ ̑Z}'dktdV|}0+X"b#'fU@X &` iT)0e )]'x@ 0a0 ;A=دgޔH\Z_sL</ ߡ,)j%taV;oBI{i,/L[e3r6k"w_p&zTxo1"ƘC{"PVjCD4C{B4&8V^}vw[ZؙO0ŠLntg,?^cAD*C^mb` ,*l-Xf`OOwE'Tkred##7ac+nk>SɘmL6Lᵁ<9]c\\ܻ,o,R_eN2g~/wwA;iyOw]WG,bN LFqbjFlr,̓B#қR|lk6r/ް|E9`k@<; /8^?r> @aՉ(‚D;yw2&?TY.H[,!zZfY ѷﳴQ]PwsN'ٓC@Ȼ-AbWx~7 ]Zg[U">2mcV sBz&e |7*lN?ˏMwM{7 ceqGb{?.\ZRD .  EO"R.#V8E RwCEU]ZPN:Ҙj=VtsEo$2Hb_$Xn`VsrJZgaA댥;+)6H9E 0/g% :-\qy,LɰS0tamdD2U=8)oXQz7*2T۠BEUT΄(W ̎zE;]kŁxZ7ըM_vX L-DЕˤ?Mn{J+F`()=C#/-L Btյ&r0|I5[5T^8?SOϬ`S禍=p,+Ќkn\!oѧ?du<*IzBWtG}*G&⹨V}jHַp7u!,ɘ8.ߞxuvۋBVcʘ,RfF|;M`C"[4v[ g=o rY{wdOץ5|jY2O*^Yţy:( Wyvs̶ fTUwlOηKkaxNp⽑WKq;ݫGu=lȿzޅr?lOHR$&`c3}Rҁ;<3(R)?,-y.]+j#׃lLAoP.KoS9>iG>?c{WHfR bP6[KH%=︎6:>:vy 0n{iWbg(j U-xdt%*\W1Er +RoJ+ϨSql* 1|0o9i.ַ&$Gm9PI0W1xJ?==uԣz6ڿz7,%17 vS8R]P%x IHKx&2I~j }_[kaNKZמk$ccaL(40N9&C$1@#)L.1 E8RbH4s3=QO`1>U@}CN=:zRTz462ۿ26+txԷ1nHm|A0|Q8"Vb+SoÉZ,ۤ|>"Ρw[(Wxv`-TTLW١>bsqCVi]ԹsnA%>{u>z+XQ^ZxׂYJG­Q^ X>}2p`0VՊ&G$#r3g[}LEt_ޑ KvmN)ѬZ*5ᗌ桻9 ! tl|8 #m]rQ?[Z\CIγ۱~X}&7Y<@o*9s= @XQx059f:ntmg255=<ݯ漏Y\yaޛWI6ė,A 0v.Y32?᎖zu*& 5|Qyo"U)V!d`šB >:wV=a?+3t47e!xZߴY S6HAt KMd3d%Z&@zͷa}{?pvn{趷76̢GcG 9<:\u|j)s!-xÙa~:|lA?"ӮlG\ ?icA[(y\b5D+5R'q)X']^9^U{"+81?= _Uq8{YnLWɜZ ST2Q8H)VB(Afyb^ ɯH*^mtEGTD|NV6''odve r&wҁ|xJޜuΠFjF UNT,bwާ2xWISs?? _UU(X`c̱ovǩJ}'Cm~;qPсBucb:[t'!"xAl~jڌh$*ro(Er VPCM\mgG;{3v%]L|[[0U ^'ι8^IZAF`\84}ɦ7}(vsbYV(6C u|ΓhMዻw x>Ot eOYa 05 Xٯ8 <4[,d1FGoBP"0Dv/51rǠ2Bw?OP8zt4@<~y_wx x8ؔ, gw eº)ϨoR*-LW,Щbzj.o}nK#doe}"u(EA}\j:=w\[v6$vxut6kWXHb:r}aE7ai`e=O:MԎɎ^o/ܻE]}k֦vG3؛Tqډ)dӾkY0:ٷ伕e6>`=y GgS@ $$1{ZqPr3:7{}6)\ xuYأDȉ^gj6:gԦnS3I N^@E[B2'Qe1FSs+j8/NM*82 ؼrj@TZ)>=Hcݺ%{ a'Ӫж2Tt֎VjVcC6:{uV0X; !pgu8vU[1et2bt&:m±Hc$Re<0u=*8Tb&u 3؀0øSk%Mf;r:7 ܻq Hc/$Ƚuv ʾR,Q, |VPY0(HcQpXS8!g2[]jK_K&-ÈTW+3t+hTt&Drek;id 5Dq +$ s q yХB.BCl7p 6caK `s>ĀV΂Yse0Q/^\ml+Yǡr[)_ TqqKlIa4;r͒7l-=ɔh2f<ae(S9YkQr|8>dd.#̆aP9E~o耶ocSq}7Vɿ<ޙ>~YE|35o敶GE =bA6FY묎uf[Q+נxe&v[kA}<vp? ZrR;j =][@AtAwjMaX$ԧ%a̢ L)'$[Q]Yދ_Etq1z 7qY/ ^+jJmﷆ}'zs8+ KAl4cl?Vk>kN<|ٟ5C3]C.APEI Hne|Uw;lWCvj2C_ B?ܯ'qtmݺ+y2^ˇZw9X]-P_uP.%zaʆi2#,ސVVRYQ0s. t у,ikkbhud/̚WmK-CPu\80Hp>kȬɡhTψn_{ѮہJJ/.AT \X9p#ֳD`&@%k@szOkIk <%XS Xgvw&bx'&mDD^saì(r&erFX+cB:YpIKnHs\&rF5.~|ۏ> N[<`$.0jNkvȰ ZˈI9N сsI(t5đ#9:9x YUx"Pg+D\6PVkQC-s<~s09zAMk[t݇`F1$@Pf*n:reآm{cYbBs~P3oTszh'"4MduION@5[#-J]1F31OۈYue}"uyssNd{> ] ùW#n'"qt/4krym˛vIJiE(ã!޽[e/-_TPsKrOn $eӵR, nj5 dHk.҂TA]LL=^wFQN8sU Q5 蒐5$| 2%"mK%`o X &1HXf Dj9[\xۗ}lS5gj {-]|w 0&5 )=EĒ3Kٿt l1&Q >d{4Fm" j+Oωᖯ@x= |(WjarвO%Vp1I5:ʅ\LۘcʥhseyNӌ C''$&ĕΌ1[}M Fğ69[cрEB=o\ÿJY1.^Q/%%3*Nֽr q+!(kHn_^0yMn@ө7Y]. A=rAL*` 復&ƶuZ*=#Lہw,$ ǘx1vpz*BAi+(TY[W4R_wQRoȥMpv0 H z06O\*?/T%glrm1o2eT` ?1!kUa/ I $tjog;>ciQ)B"E^0,f#8X-lw5w,Xamw`Y8)M5*2-޶3Z b-t<ћ&N8Ow٬bYmaMPe|8=EwZ- A(X<+Յߕ 2~"=^3i_(z㳤B W X (m{LsY!. .h/I, B 4"vZZ#|#2 rC|Dt?әdJ"VߖKRcxRahK({̌STFU\ {^Fɬni-DGoǬ !DecYzG /} 1+]x+er~>-!ThU%<2]UŕDɏ1'š*#p_zД7}?qԷU?\aPEKҍ؍)}@$dƚ׎C`B@X"~#1Rަ~(73^ =}~5ҭO:949cjL'I<'aKoY!>6C!.NB3BI#,gP=FwT)A1/ ܣή`1")ܙU'b`،tꠍ}[%Q{b9g{ *Jt+2:"t󄛬i'p8ǰ^kcYb8#ڪ-xfZH|&M;'R$G-C@ؖP?)v}%RX+r4o%0 Eՠ6<Dħ'Ԋ^*"B0"%KP4 @W%ᘗFy !J*JdHk}D*] obz~r;vBOu\[)¦@zcLsSݪػXx2 09jm7#U{㌳38sֱ8s+㠤_]41YHѹfkS\> *`j(CTշt>;m7I q^pmVpڨFċx]L7=j/tD:au-LW)5[BJuS/~O#4Pv?lnQ47,Tb G}~t &"x̲rl>AT>`4K1\?Z*k##ےC^1]Z 1<-aܸ;ySRd|U?"$͗RԘBX 9TX*S5y].US4ApW2i` tS j8$GH$"BX:V)px+FƮlz[1QKB#td](|xu "AE>7 1l.mF C>LEJaX@y.UHVoa)y_Tkm|y7T,^SýTto)(oba 4X)K'>7Op'sTlA ;`="ufZ}+G25,%<<<;C,)Bȩ2uNyfuɣmDS0hFItƳsjT4QG[>zV4V^,n[fbqOT#'컚zEfn#ѫsX6[x|S  qۍ4&|B4D%lS,~Qs+ RVtdY8O]3,w,Ʈ F/*?sM{ɻV޵wXs΅ǻD޵`;)R. {91eWˡlL1窹سk:k>kܿ;&NK~9Uxb3ɺUDZ|Da &x}ys9)rk֒rꪑ|5>m.nmd$DL&Ȫ2G!<zZK]5I;飌~w+I9xC8®8wكG;=[Eppavǣ{ۗn"k`#> ?O`m]l,`ZX yXʆ:}[<ǰXNKH#6wP_LTlݳosY<-zQH58E[QV.5ve+~o9bsmlO\2sM.' Bԇ<fgZK3:夀%`mfcdLYQg@^YK_lޮgUZH,gl$ G~6z:VJdZJ`g{Yv)΀8RtÛHx8xN׸?o2eƢ@3>HZ69nׇ{U j~ۻdF^ҟ멄3-+Y(v-4ý(Zw'o-Eպk+9ڲʮVk؍Ũ~H HJr+ciಮȾ]vbl X^ʒ}+&{OSm)Z@o&hj-D<-d!2YNReay.ZV ]C`AOUNFv/=|Zfbpuou[=˶-|S:/fj)@4tj$Zg=K~;l 0ѷQGH\E#eN#OsdDI8^;jk *Z\˽,]$t}}\{{rc6ow~ c8o:O6~waT[oxN:NuF:JB{8ZLz쾜+=@=oKZva }In5avɌDL⥬8+ ==1K,r&kh`% ]&OܴN-+*'{WSՌJfh/U:ڲ$K4Rz]zیf D! ot8#Ynphm Rbp#k+Ҭ/Ut |p?cIaTHMd=np&$:o`$cSPtEߝ⟼9>6=We ϧkU~>jgN`qɰ;Gޕ'"R}Hj$4޳+Xf ' SxU|QMG]ne }T@ z*y^AJ|9Vo/6 ыAw.ZJВ猖 IeL BKL!Z>PU0 78- Jδ3ǍRҬlJkP'ʉ&R [kǞnda01hv_Vjw +DKe t OQ n Fڅ9o#_բ]^ =&㺲x=s};pERx,qTuƝ^-<]k5W נ/%+FF j =ٽ\ÈP/Mۈqf@>G}bAצ]DՓfO,e6:=ǘfs5޿7t|95rB.øu?w*){ؕZý_ܯd}j?mwk#GJNBP>|!G{W Kp+8>Fйi.1j{UQy\{/ypw/xxA.tgZ1GW0\ Tk *|Uh^M@\q㼏^i~sӻ ݍu}[M6cty?,Gn>9by*5 -`,Qu )yahxyt!c[wTf/1i=9~r-y#ƎWFY|o1돲!2F`Yjz +qFfg^տNmI^Lkcwg_58$)#{# n\}>fGfu93NPPtՌۆ>b-;i+yjq~. 7\5M핮'rBK11Sݒ8Bm ,~8^ @F.q)K,J!v)wB Z2 C@نX kRuET:+}tȩۙsyCnÞA=Z}s|.$]g?^5$x-F.|& T y <"jvo }kÜ52heBNޱq'_=rd"8{nJA4.ǰhpx-:?ϮgcM|lW3EF Q n ^H.;U+ej;org2?b+=Wt<7rj͉k2 ]mƶg}z~У}'b?w.&Z鏝Lp@>@v"'@_KH{*&ኲM6lec|S;]?nܬqH+ W 4ejnjL+ʔD37NgRJ ̦ܾYLEt[U 4|v(}F.gFa \Ug@57WlJ)/rsypbH\s2~OތT#TF6pxb7pGGEj94ُS Jx5Ffb,ԘD`nXgnX \pAdfGplqA+onNn]>n o(mǃ~V(}%=%[)Hxߪ ^ 0xg蛐cj#6ZlĂاeu`_gm&xES R0fhŖY^]ą[^+ "wx]i)o&w g[g8@m,d!68-D} ЂCV%Ktk}tN~œAV~1A{Pfx XBS{6 邑tYioxڻ4M]ń,FKbt旫wgpu:di"q!$5OY(%$FAdO(el#,g cZu.5ecԅ캯`c]S1\M*" gZ2QPLd٤덺f ^Js/['rFW.(;QS&ߴz~_K/|gՓ~icLlHWTs Zpݩ͊=9VuJ0rXS)jlA՛JJcY~C>f'Qlǁ@џ; 8g`չ\.J 2Λ;MFyAsmIo3REAgmO7D|>,Z#2igh2A=|WZ}0>qſshX(-`?Dؕ1 ~ߥw"OsnDdQ [mǒH$ʛ5& #A,N)4NQ86a4ja"8Z+ % V2v,b7p øh @@'Od|Ox #D~B5Nh@KQTPc ]7DŽ;fg  8_Uݰ\LxaF\ _E;Q"IAsNrkpSQL3xХYty ȋm_uhbhɢ!|wiFv xYm% IZLklv˜ Q\+t [ܭ_W*kWkb%G}%5vp#{/U7E}g 2 1n:qiJ8dm y127mC<ϲ妓 {0v߹SDZ>On%9̆ ?.i8e'mO}խ:!v!qLb*<#B ~إ|$0-a$m;u-u~mKԑQp (9jrʯKXj/P8G1GL&:m$3Dnd7h$b>٥j\ΞĻ1;ݏNCixb~mÿ̺0P*C2-w43o_}+AW<8ۆq6.뀄nK8 ],[-TOQK5W$1'{.Fz:0{dZʪFkFx$VBdQ>DӅF` t~ :\o;M!Em6D]tEt^`lɂow?4)c"N'1j?U?E~ϧ4_ =EU38V)BFʄpm%_z"t&2=|L?vPvYu54#o£LLb:hVI~fuu@?sX2j~w3a7G1#y9ՠl_2{C7,&Gh޾t_/L:o˦[XC LRrDC,BGI|A.w ,<&UFFQA bd(i:n3T؃ ٫90N45R70ugC s$Mf,H ).>nY'&L__ɱK@KEHl?jhӑΒ:.FL--7`j L Ti2aȓ^ǘHh,j]?Н: :bII` abQ;9&خ+5A+f"[^ hl1+$swPAk,\ySv7 K &OJޱ:U**ŝ?AW:;L̜Զm#7n McVoHmye)5l6ӱJD.fQgYsgAw w^]I6b.C&/ݽޜ4p{A\9,J~xLI\$t1%prTnLltA!cΧ88*uj]`KYS% }8+[M -o 3s[;-5:c8v[Uz:ɂLz/^^aC3 #t/_uشBZGRİvU:?5yqZIюg:S9`F rGKŪAS,E;![K`6% cUDٸ2$~7?Gi-1cI)U.>9Xذ0gW~!;9q' #ؙ[ð#7(~~1]=V$CwSq)\`vN:dKW>)v5d{A&lݜZ*_>A F~uE IJ:yV\98>``L'jy#[ )8e10z)Z!h3a$SIX|-59~s~~8;&˦ 2$5:on;*" _hr5̻Y)ZGS`s!&8H[o3@#ѠEáwP">Dd?tǪgHK60 Ɉgk`yLNLde/x@D-{<ܧʤeât@*DvQ3}^J+Y ϜvN;vT-ƮZ9~"jXaǓ9%&Vtۯ(8)CwLЂq]-vz!,IKTs9,0ў𪹄г$fM]BVesf7W"zK)#5#j #/a:bV˽ȢVA1o sfIqFdat"8AH V,Ac)mC%XYЌX:_M`HV^0.LN99?YaDA#P++TX ?sCj䟍Ps/p89%7ҤuDZ2xS ׅ a=yLMM:wT^ӮI#0V&N)-|:m%*L:M!+xOŔhLDVmǺl*]d"6Bt$Pѩw91+A?1/N[3OB!F\#VjZhV뎤PlԼwI{I!4^!c]ME謑u>a/X-"#|-ďߧ8 9㙨 Q}]x!T[eBv𤋮N#i}߉ Lp4^ O5"/!>K"&҆S8}KFͅ,&4n嶣ǺUZ=3L+42`x@#<՘rTΚn.DX&-3S%d'~KEP߹w7ߐƌ(Tqu6RdVb…#2و(x`|ޡ o*+6m"fwG%yR Z?洒YKBvkB @E:Hwcr0u,`Nhƌ#`pXc$ ^JÐd' >4L3<j/X'BʦR-,!:̦$t/c.Q;p8 ?)Ce ko $R&Rڱ|Rhx>R!ȮyM߀Y@,3 癜ĬQA=Ռh{,òf\~W**\ӯsjZ>~"G=njAh%[>H|U:ގYAK4nuN{OKAmk8TLiD>O^OX$bQ䱪B2&g]Z&ScFk44k[$d:_]RʫѲOY+  h g "r98cJhk,BoiPsM c%0^BTQ#Mt%AвƏ|tX6gq QZaa3#јnS5' "%ЧWt@vSڛq! #Cbx'[Y!(RѼOx1_QUxXF\APct]ň/+5PqTb.%<.gŘ11p2xLbZ;_hLAīniq) M8 spq`& -f?Zg/Ǜ"D+le= <ҿ½?.^#cs{>^nWǐEY.1ѫ@نo"nuEO֚ " ҂kV77S< ܄HrȓC^dibRr8~ 9uhLV<79`0N4SqϑT#&Y-5yc~Bs,2pUX9Ji7V[seI]SMuMʀ=RTk"Et<GM9@A:iOA*9څ=vV3IV"7ba|F\$45q}ԥ*لKlIX7%B;Bt9ȎfUA\5ji)'Cî`-->iwq9Usz ;̯fkmn LBKo%iA hѼJb!ǀs_Cb 3]BFe2\DR ѳВa[xnaE0Z²*#;=BQӤHE6w/tWz"~ |<^ ďRX%NjفmjH*jwy-ck kr]~&@* haG( &_GWo?~x|?HCB#'_S%B8$xĪ{ 9@:;x˃ZSsyş<@ᨑ3reW218\)"5/g|X«㌹ h6F*6Nɻ7-td.-\GӾ.rtgבBUfA9wǹ&14Іxg 1 \~g~:o"6^qۖ\-oR\pՊ 2j[5E Yȁ r1Syrg1ah7$ ')7BtmtctjZ,Q;_6G3C!S䆓,3=`d6>΋Z/ B^ AR&u;\F&0P"XL%KFKm,¹۝#&&HF[$n=76%Բ jmi/ gw6{I_aI2}.#Y9A"B}.I?2N"A4]ܜd7AS]'nE}+s,0H2sx~RST,!ŏ[mJA|҅BӝpjT]H#XVR8dv:eLɴ5Y76q>[vzN/`ߛSLιIl,&h+m?jC%J3']JTNYQNZXd1biFiz t FZ* 5qgoz8|dͯcUv+a9Rݱ_“hDDbsl5f ɷ$VޥwT $ -",׫=ae^b#Va~mx2viO[o&Ͷj+ T"-:ݘQLg o:kG ID]>Ga󋑫u,RF5QGT=/[l$g^"rcV~{7\$dϰ!LtdzJ/d4xa,~ZI7_';>_OoW,aQ4/gmO/_k7Q͸A .@c;ch䰻c x4\cMd" fA9U 9~.=vJ~w4sw Ӛ!S<Ġ/XC upB>GN\My1r) [mï6= ?XG;EX9qwv D#I Hd/ZDBAsr[1;|歃 |ǀOvx*Lhh=εDzF]f΃E.tUJ.U?@ѠI]S>vk?llz@ds1 XOb@.c&CW13xw-`6U 89 +9^S 9Yz÷J ʄvZù&iV"Yܔ^; uCgjmo]. 2D&YsPs< Adi M-,o,}ے$`jJt SQLuGϑ+-툮;Q`v 5"0y"kgKS>心9&S/iGA t-6Ň2K1q!E2+BtXrN?UD`1't0=Bka, "DPi,LJMz;;[+w `%eKB팀RM9 / !a=qoutH{6+qw<؆wd:q%>fs5׌B~i)YCEp:UrH8O s8]nWrT2ls~ X@z&e0XF??n$;k$`鏔 =}$a^bҫq c>t t ]B-=qVSo'L |! bwԸ҃g^@^]ȱ_$ ځ WA s8Ewv/r1iC!gp=+D@(n&1!#wB80h$mPj B9F}iq8#g8TS/3'p_Xn bpsAQA׌Wɜbҳתc\v qq546n< c^ɉ| fpN;&^8^5%sLGCR)fKƵ>=.b+"c(MbY:p,_2iīԽ bB6:(](:ˆ)v}P l{Qu+.D6ff{:0~PK LܰF>GI U~j84=Waȍcalq'\jC #e=0l0,o_qk}dLEkķ Z`!0ծOĈJL~-IMOc*r̹$7,^${+v!Jw_S، Gds( @'P:vyJ5^^dD5YH'GB`XgJ_hU ;;oBDLu"c)ytu1Xᦼk  ?-Y]7H_1<8ƥؖ8%#1h3ߒ/]qvQcI;4܅⟣{bl;m,mMS~ lh?VkmøBԳ,GVU̔~ĕ(т""xG \vtg,A2 Ř­Z:5[4;t 2 7{U3sbO(g7ϱ2qCGn+A X,)g =el}Mi> i ǘ(vIC#8=l!EYؒAʫ8a 9RZ0zPp3)pek,ĂyL+7S DM%$ՆYk BITaW#S/~#ɔi@* brDڀ- ӟMk Oy-q}&z(m]cMzg۱D  +FǥYcrZ, Θ#Ą m. > FfUqn e%"e;Kbf8ΛeViWK@%YQM̼KuW<=w\d`1(.]Ake] `9tc׹6-^e'@ۺV/1k44͐ؾF΁W /hD̚Fdx*V5Bװk:C4ay٪m|-saߎs6ձZ5vzj{m^-4bLE! KD'WX5'E#~Kb=N+2 KR@3CsS)(<ݱ}蘇{u*,0Q5ϰ 573*0WrSQEOavX6~ek/ %݄=lKlu5ڣz7QmAIg6ޏt׼UOEpLEqEEu(Wh]DQ YB@}OW z TEUkt J'@(N-A;V#:MDVIf~ lǞ2՛pCc`k8lrIDѪ;z@4=B6@ pi|*uL"> hc{e#{hMi*M13ʅ]P y(6R[eÍ9ϦCTCVDwihh6ٶ-܂>rDl+H]t~^Fh/h"w1?6= (і `dawB<׽Q錌q"U@E*ٗ=.z9fL%I;]ʐW}P(!)?}ڪ\?G>x)[<E u(:.!B"}XT9ճa?naTq#2;X۵4 # ^ sT>(!dDRdBi(03^ԢZv("\7ܙ9ү&Gd|p9w\w3ؖG0fZ%(ӹ͜W!= [ n\ gWi03`lB19Pm U)Ns}(,==kі1q oAmS*iO[4-^* ==(^v+sMC"cLx!Cw0) .;ޒlrU8OJ_EFQF{mY3GiЯl0˭ S~}7E3|_Wg.d`qeA`Nh\0JH1r3:!pLk>X*U\rtjLN*z|O $+sڐ)jR',cUZ&8H)}@#{%u⫏C|w =1kLMCM}N#7"w¢ .?ƎsFЄvfc+i@:jyE `|E;Q=%tKreR .^X٤rts*"+6!yX}P\PWI*+ AkH#AhL' ! 8s0?Z|ET7T.qrm͂Av6kw]}oV"]}&M$xіhVrC:kfPy+a[j/8KS-;4Ipe0o<֒f5Zd1!^XhJT- p>.ж Ƌ1|ٕ%Q9hU =5keDv(՘1QUKj8#>)[mtH1C1|ԸsY:Ƃ V[ 7X㑭-\ >\1h#mDIFǩF6)z=Wz~  `e% J  ])*$eh5n$"D|L^@@VE |y3_],hrR5)1I`šZު&aLbw̵]h"hΣ]^e,D2zCU05.HwH&> !9ZP(^~d( `n+'hwأLd0Cw 8rK=t;EDbү UXA2qivڛF/SUcLD# Fh:w7[!m݅ ]|z&-r₞I[fgRTٶ+ca!@!N̉ 6$D\ Cq--" ّ$]L2qCn6#\3ej?vo9N7ȎE'm~9|i{M/q"`Զ*_\@{уg'P [hd/( gor{"AG7)&4>n\O6| kr"L {KeO܂'P wr܀党0 ccϝ|Wq7ɕWn~cwDm({b%~t/xJ@KHE=<J0ٵ1Rx<ҊCn֕ hMn/WBQ/IV\FY,inq9y0_j(MpF+;$$@c9gt;t]_v1yf/6z:V"E897:݆5-ʀpn;w؁d/ xl$w!&\܅݇8*=U*~[?s 5L rQ6E .3_RY64o. YS\)Bt^avl,,: 7+9j+ڄ^6WMa}b1&VKKv I2EEjLԂVJI`p2L:܄(v ^kDI[Xt?~ %i ZI֎I5@Zˈ$:pt.%Lw ۺ-S[!p}1۵ݗ.Z|"&{Wwv/~5GvV㖖9$z/7m6'x} p\ŵh]eK^dYղu5h-%ˎ-opG3.3sG XDBCp  09rad;-aI ^2Rvӧ~4'H2*fkknSr4(7{nE=O,l.6;T}j?! j_T^S#7.]YZ;aA .׆^d멕k=u0؞GwppP^>%ju=J:#܌{{/WIud?Ұ s7.mZh^Â=˾QD]aEh0t+㴾uvy@ˣԜQhv*ë*q22AFW},(p{5oMEq{rc݂Ɲ&֐ %dC;G~գ#QP~a?}ÚEc=1#qGVT"ʐ_є%aMQ֬5pTҭ=rlO<Fn^i9XS*<# O<,'i=~7*:'7.-/ij\>=:Ync CR" $e#JVvy(wF1E"ކqW C0|4/',h:<@5%=4 #V[=pdoɡ =A4$vѬ0E^D[ "{~{NK6-]NĀV1,7;:knnWSe8%MZʺjՌr u!-zpӲSv+yS`0yce>iX!.$xBi I,Wd`&#Qu⋅#0㥦S,E(* ZC^_y,{,!WwUWDjĉSG(j؃(/8$(N*Jn5iĠ4ͫi Q%J[/K׭?y$0QK0 zba٧UT^d pAچcn@EiDzJCơ*7/%gVW/7@6h0+(FH0U ࡊql*eE&,CBSٽ$w(rwϔ[Qھ Li=f{W <Q`[(ev=^?!?F f}ӻ~~L]^=j x@$7"r HAC?7;ހ jFr+<*Bl ̀[KgY7%,/7VRnrx- )t'? iK .黛?X@tX#B=,cE5^^+ !H-i['Bӷ& ۪(ٚ7Ⱥm?Mq{9xdQnxޫœ} ԑ;Kk`۬.u"'5_НZ:Yc/N.F]{ҡ OyR˭-ɲ1.> @# SX2`Tb5((>4U )FHk⌖i֤f-QKM 0mjGBE6p|eP|x㪟utΏMZ-%egQ68lq$quZ3A΃qٝbcMل>wVxt`H@5(V#j R= j/lTC #{݋&ƪi׋b's!ecOVX~n<9(k?3-@j!oJf\cכ7 (7^ۤF_`jGk;D~d2G>0oV~74k>\32k/?aپ:)z_[-C @ 'w,/EZ@fQyd/Z:45o"ژ% QI 7ηYSŁ/wL9I%3λ؛ nG!crn ´IXNT}v^;3iAĢN|FBeb!u.nV.jc~\H.4x㬺M Y=ϣ IpYMERfJOp*I"`+o<*y?&`-o Nc1~dGMZތGuJknZZU30 Ć&7x#U0[W*зFqmQrR>6=ګ3XeW:)~ixHTfF"dž-JS@~DigϾpY4+Oo+p XJΊDbp>pբW"-SdM.r:\%/*\aJ6_rAe(WavQ, .9wPFF⋃c,+< l†r/m4_̂C([M2:1'Y,NTVL|g4d=rw*T_jxz?}!'!7@ L"`O|wqժzASQ2[^루PJ»bcU=+ed-vٹ62askԋE6\V1]$99LסJ@Etjkz#5t̑.BAVO /wH^כ<NjQ2xGnPB1˗W]Y߫EgYR Iqe7bTT|7\7uai>jXebu"\ ˁI)Y{$Ȥ2pjyqQEP^CjJi=7+Bf_1f20F(œ5|K42g`Ƞ\:Tũ6ˠ+퓷o[DK ]SNhvTս~ C*p#` w^)OBxOy_1FXکT(Pb2SfXgwϳy| r;.Y,]vʍlQ#?, v%.)Ԑ{)W͜TahU@]q|h '6+vU:'GGl> IQ*b->Xx}Je"9Weg=>"? gP'crxWE@$ɪ;HIocBzGDڤRе8!%vzр1;Jj B aX@w,YyN W|5mbN )*.y>m)=13GK aB)6n7×`lJDZsS֣P;ZDrmt"JoW |lldR [cIqRT;!\!n)?Mu@:eFu>Z5Y`F,l8UMdg V/0/LDM/n5s@,;ÑJ!ÍwSɹ4e1`uSѮk(H^+4>L6z]S%-՟IRQly"ϔ]Ԏ0(ܡ~r yH2`:031 Y3 a̷{F )`%7JRν^pJ oo"Of2ӣ􋰀&U:b0_n MCwW! Ey<){3hY$҃REq`˃́4ʡ,&{XX O<`yA @l/_4nZ%iy1ܤpOΫ2٧"䥇U}#7&IWVZT ]+iaVEQ\\ >-z=K_Wg:8- 0{rOOKDwi2ǒ%wl5cy=%\S`q?XblܲXMMN'[E o=]V~vZ#J#e)FIsEYĎZL \D6m|#;b_`žQ$cs]zt\.Q,-kDS_/]]+LinvN腰73- '?RZhXsehG,]k"PeJ`F/&e4f U׫+ד_M>OseǪZ3XI$bbpŵ|6+I_xy1s'hI h 슳Aӏ X~HL@)M чvi^>8?G`BJ?Ѻ՜b UQv@TVW(,4`EOfz>Iɚӭ=Yj%vxRk7e[95YXf%gfU/P1~~lgg?_Jx~ZΘ^0E%i ^J.J^gSC2:"*V2r]m7`~,mQnOW54oT2K}my0$Q>ZS'8~^C٣ZT^_1ǘ6:f}Wu)yYk|IW7J3bP X0 "mմ.9 h(Sށ7+rӔ&,<;Vz\57;eJmҶtֺUF޲HN (/ų5jJ Yy3hmx;Ͻj1R~_WjB@='Jnq6'K\ry,#y] Pޮ*bMղ$vE/n*iǶz:c4.7y:6y"޺`1 ֕O'6v`utDC1a!zR75yˠ?D乏g cQLldm6ʌ G1/Q& Xb:M(,:mк&5g8BS62{d0U(йKg~"1jXhC3> !.*ߪMOc&$l[-ij޲emm7w=` ׈D)RQ)RT][۴DTiSQSȫI6#kJB:̑2o)+[.$9Ӥ- )U^ VA*T4_MاKI?&wrZbp:`\FwO䉨@STRw3OHms%hk(%'[*nhb4[gņ(h3٢mA'ZHע4 Փ[ab )ۖҗE͚_!*Mlks`|%GK\a^Āģ9"rf3+)5ՈW=Rnl37wM<`"0k)14[.L^%[JSf G5#RuĪ9Ru8%1=M^ȎVײ}.#gSPT-e. 57=tcY:cG2X'Ai8/̓OjZyR2d/FV+N :9'3ޥD)}\{N&DXn>kZQ35\4(#ox7M" dlB朤HD,k 喖Uk\$kFs{o]:Ȫ {X[R5r[͎װu&{kFZ8{=rs9Tj/ۊ9 T'fggvQ'rRF@ddn^l=}1\:d`v}şrno7B'rV)1q8691+eD5JزJl4c*>W6l30BpNTR0}H(rE-$Pȥ'M59@y81Z=ܷ}nPalpYSŌydeb`*mXgoY Tw,l.(x߼ '-|$ppl?ֵvRHia^”}9^% K"O|G7mډ h l|s5$j/ySQEaˁB$>( gE&Q`ŷVo)k\Վuѕ Q+`նa E9Me 7KcY8V!ܲ G*VM:x||<1"JE%66Gzv6!m=0<)d%HtBVN(2̝`-B +@bZg"m#j=侃{V<1Ѥ-e#6Ķ{% 9ć! XBJWql!PO^yۯdj+eȝ݊&גczȱU23yЬTV2t=Oz|½Lr@[2ۿE1-*yIظ.8#'A;bEsQ۬>0tmvgC S|_p7HxVܯR紬(9z4Uckd'NY}c̳v(N0U6P7]r/;wJy)Cty" w"_-̬x"[昐G Co65Hh'weUL Jh1>D61ftrGXu7O?)E0V=g\|r먐)}%?pƽO|zmU,-'Xý7m%޿7t qGy)/j!S M'(iQPg]W|cц0tBH[m;fܬw'L"\!%@ʋEA~X ,l"3!P^oxzC6r|LhvVTkN2ײ XGO ^5rR/x.eutu{܎ [ , }lk3EODZɭ-KQH+hvcu`Ѿ( R iI6ְv%Z--nO&;ɿ';DBˣq2Y>RLUl9w{BR?2 ʢ͒t+~[ .X'דKw!H`@!ͻ[5%eB5`Rv# $Jq5xބ{pm#ӻr6%.ʼY,%dbvv.e 5\4qDg7*1Yz e .H?_-bctibwTc<ɎB_N81ǫoa% }\@͂L^.|MjH\Yᝢa@7E g2Ƕ6՚]Խ?c~<Ή|.Cֹf(Ena$^c(ߑy]/I, c:Y1@S@K5iQ߸,^7tu u;ZYYܚw]~ߘ|ΆiQY1eA;F*L%TP>>omжzQMpB0&aExv%I(Ax~Z+n7r}@=PEFⶼzŨBp`rfNpQH 9ЋD_QWwUoV%lphk+ў &]$M}9Fi(B aiћȅ770Y3>r-V;4ɷto 3 ol+)ՅհrOOk5.I116دêƒbZtvb9 ̶ (tm^lPbF9mZHnldp 9T,y[ȡo Br8oCn÷{gԢ㌌1.i-3;NV[28RV=4d tDmqG?ߒ6b?&%\@|xnMc%×13PCu'97qݻt5! %5ve (G`j:fV(Я6tp:2[q{{; n51kVBlEV 2'2%L{n ۂaK),Xy\ p*XAF`y]}aJZ)Lt>lƑNP! (u":7TwNCuGۄ",$uaAVTbVN0)ٶFlh -\ѭ5:mb%KfFwQ^*'OWSO\^G^Ѯ&qri]{$[MDbe] Az@K . 1XAeGaNy[[3Lg۪|KT)LJ޷2PyQ#?L=5# VgOWA]7nB*,6`Lto(yh̒EdU&Z1lonwUܚ[u\1~/mvDMX=; op=T肄c1m'bV:S]y=瘗%򺛋e3Nr\MccYq!; ^ RD\(}&{,!]jv-ߟ.J4E/4T0T!_&Wa0>rǧ:8u?thw+ۻ+IZ9JZPmEd6ešO75O 7Q7,F~6 ǯ`Z)B(D|*}DBE\6Qցj%}c*(f% 3[Uvo3|+œ*scXeI31-tP鈬/jpYnј͜Ot YtY87Ӕ Es*ŵ`>r4~akKIøA5tމ!Iه}xa!@(K7~lTD'ŋD%ZGhLg(W8e+SBq X/;v' 7S}S@ ok֞3*S i䙿s#%4y×,L@'sc*DԵef]-vdE AtgҔfk4E$9Vь`[f,YVf߰~aߔOO{N{` Ù Mc5J32e/i&Qg)9jQ+YFtTX6Ș=dPK.sdn#C=u#5o$X7 eiJ[IuR2}.p#?? hoaA8N݀LYq/hM1UгU epy>=܌2xwbkv.-KZ#R7 x٦+r&ZW=xþ=*+4⑯l7t:hGw;)9Zose=#Hb }۾\GAM%$] TAK_b:7vp,>oti~6ˇVojo€~TJ ֽFe$o]֓{" [F)^jSF,Bxl{ Z*K#K#ɽW9cg?~8c -b1RpInJ-͗9!5Z 3Pd:ࢷ(׻ux,,@*"x c^bI~侼X0̄_#!Zvx+/Ż xyoqyoT;%lȎ*ե>\#Mz郏lf²$GiNsmI9&;}3jfE6kݥH'?~!-b} tćᐲ,Xڪ|:JZ{b]@>`Quf~i~~Ӝ6獏{=ڙkqEi%dn6a|՗v;66 ̎{)]8MrEiʕl)!a 'l!ÆC԰d2\Xk=K_3KET[ƝkkNeoRV* :i[`ͳGGop'2I9XJḃ] SqE=kz"Fə*+>n*?B m2&K/ԫ)Om(J^<}}`h n_xP~\a̕<'kDDOX> )=ZN]ORGU=e~h lmME-?^gj; k[坮[坮[坮I{] "6a*wC Q_;z: Z͊%6 zloQLK:8*( JC[b'@ JcK=- i4S%Kj{pSh0fU!‡Ңeޛ.I xPRٚ\׾)rysdK'I$Znʃ+>S;0f4K_qQ3҅4-M0ب<&H`8;d%.*/;D~8A QTiO3/. ,fx(#j.y*D)we: vR4ϔG~_Ob'L[3E|zbʚ̃< CL3*>0Y@ `PRf_ma|/s%[hm%OkL9Kwf'%ѧe@̼Fo4[>p%ү*(^ ȗܭtP4Uraeԩeѣ rbF ԝ}L1?sMK[o5ޮs SkLą cl4;Hݥ:j%/2 c#mdw_~# 0 }c Z ^--.P^B Bu0pi&x쾉0zZ]4k誧QE~hp4[4‚nvap!cfLڤ3|W@a᳣*_9ir UHɚI?]_(\Sg鬩.mJ_oOI {SC^4CoG6>U 9ݕΛ)?u-E;7Td0K=[YXI?Nˢ:2s5EmOoRN>ݳ"̒J+ZjhI6i29͜z]5 uXoun- =JSL7X<+{ 2: ?sULgj@Tϴ5=p{"$I晁U4yaK8C4 ?)Y!,|qhpf';R_,+#BN# -ڝ?:Sx_= g.\S[\%&t?Pk$l ``1OtiȤLLqŐ4  SN]dT']U:.w2*djR&ۮyƋn _XehPE%kL b|w5Lj=hL\X~H\F[>r7&,PDN$́ ,W_~rz5Xj X UyeaT$c$|}p EfLWe?}4cS7`*af|{yfv$S,J*takk-i`t$CjR8wٸQ7 an-.dU}FjA6mw QVErG]qjo 9nW ʠY72`Ǿdç?W8s#k'cy1=L{MH d<,_O:W*޾s뚚:΂Ѱyf=:{5/i].+blqXWϳX[TPon`f̎vZlOH-{N' j{1r({,[R;7pTdͧEI]|FX7eH4¸f\7d&nu>Ǜ.Q*ߎXu5u ©wE_ĤT ]񌟡 `=d@KOݛ9P4:|jex\-4L I ?s=鮴P5>Ƚ3ӳMM%+wYM%¿PRLBT٩RW]Fm66FEaPTUgAesrGc6$DYSlBƞ,is(.e] ˲ W+yđJX? h\'pwmA,.bm+?4p}e}^ﴔr#M_^v?ZT Y8-䲥D*&nGmg];'>3-%Rb ϴr;>:O>siiAA;%b$BUxPݣ2 *g*bJbܦO8KQED3 i9Ь?˪^қi3PÿPнʐUeP~p%ڜURW{]f&AinfXQȴȡT#Zr J.N߼Ir) x!X9l1Ke9 mYS,^]M|V2rYBO\\қNO%mJ3EYyk\?k\-\#HqU΋L[ť^%DXM):SBK耧Ow94"-ITm4 08b&Z\ƿƣiĵ=HW8 [ΤA 6T$4F홦+W82ohFZ!#0{193'%>##g{EAP!|I'@YVp=_s[;J˓I-E'9M1%j<\ۺr-ştpJn+0۬kYou% VU~n {>2^A; ֌PvJ*qbS7l/].t7wbKsx.~GΧ2:Mq.[|ܻ<3eR[A{kt^ WWIG7X*VYpnvs}_JyO^1S 9p_5f\Fu1s#\wβګ7)-D"hxkoG E\z%͐eM_#Kr֒e YRl V/d6n4C V$wW%7N#2U,==IVV9'N8S^^G!F t7鞇Q+:F(]o?){nqLwq<{5F?E^D.}?A~oO_RCY1J%'$y ,xqG{=/~{/?$kݍ ZN_NQ(薇V-l) 7w!=1/0B܉1SFq?@?`?\;w;yI[^~m~?JaczxL]g.g迳ԍN W NUP,_Y{aJdJ{OɆCdSswNMprfo(Nod䡻eO_6סtx} an &َ^3͙Kw0 :!qWcL|Ksӳ3hf_",Y|i/-̱gozI:}(\{Fm\FW8d# 㛏]Fnܺ6`àJAy?CݾӻN/8v#r6.5?e2Bx\Fbg 󋙋?Gv_SS܌6䧗Q~K~{lD ֐Ұ\t6n΃Asyy]=@=| pO%{|@&=×-B?9Ba"X'9Np3;"?Qws:(&[.(K#Cm6Ȫ }KBR+KLj,J@痔4 @vroHJ}R^߆%oPko7ϼIZҔ( 58W4ф?"69QGOD6 PS&MiЊ,ƿGcv#ʔAMH^u2i ?6V(ؾp } 5 ^>ސbܣ>8"[.Ky Ω[=b:Kc:.3+[A7q+K=dmnoi6& yvU.>m kUU < -; *9MW*=y;CueA8 ]J#OSLp"E C,RPW8d%0]P(N rG[VGT*U%O +OM).[&.U"[x۱Ov+C\TVS-kf+_ !99^,jłBTACJAõr!tłB5AeAåJAC~+5r (dC g]=ET)osYPʌaB KDABdgP+Z/}UECHT]dL |SͣNtD$K5R֦Qt#^0bzb1̭DbUxI.g]HГ+Lz0K~  xfeEAbk{}gL'}.doG^- c ,vfd1\Ac|?ѳNx)T6 xJ~1l/D[ Vd5s,Ԧ;:+4SɊ|a<h1E|HeyBCV9si͏j|Cm)t}-+PoP涟`i 3)*z绎/G>5xrq(KdfTTy`^5CC{4ő)W}^#1S;`=?Fv/S:KD_qP*d)?kt2:Vq'X(bɻF}nAtܽsSF$$*l'T0W)=~%Gz2"xYOvR~2L$3tIp q7s^ )siєU󘼡V<6)pߊ}Apm㿰#+YrpY?RhۚX"i+ 4d ZEkM_ީ3NIo &hu֡oZH |J;F遦h?+C 5[\p˷"6ZJ/Amh%v,\}'@UDP8NįȕTzژQx7h XPw5Z?y̤F7#aJ{wbw#;K:KNitl/PW69/TW P`^K$C.|Oo hկ,Zr uNЙ Ն1Kحa(vK K7vvN#яԬ!0>6V^e4:6]ac6i%e`ċn㯼fRSCJ:Dlڌ_qQ*cTy¹y?O0d-`1xL{7p9De\c/_5rpFfWɕiy;KbbB#A{K 'q ^^ :U )m3h\fpD \(S'wċ+" 6|G{.Q3''˵nR2.N^oRKFWlzR%Ƌq!x,f5i}$[g0| BDŽGU?drx))'g [޵3Ta_CxQ" xfc⸔1hd|Mcˣ лcrLXP'Փ$3nrKn+䦟?\; z`?%ȏDkY2~PPظ*ͬ%M'%oĮ~MpE(` =eAz'Ⱥ')/ބ> +ݾ7/YAdѠ:UqTLbd ]t=5^JF;U X 8a @Ӧ $KU2Xt$,w/ҺgtȧG:B_)s˽iD߂64>ud]3@4D'/0=S⮿C !.c` ^ۉƿ+".۹Z\)IJfۣlepeY,\XE+#[}luupL𥦮hۋCjS!:&gtC+ h )¢b9E  6ךSqzZFhzf| Rj8:zi3mjsR%#4m#ڦ[.֩sByhuŵund$J>u@wN}%m`.ْt` \ѯ Cca<2Rx\ރl ՉӛVs!r%:;.0݄Gmm3b|Zj 3(_F9A*1[Q tސyS^SnW%gvT;=*iY( OVnkΩਬ=@>jxq ,=k#wEZ~vu[k8^v݌h,iƒJ{f ?+G^+&l;4AbL!3⒵?B*U"8rDU2z8Z.*Uk t iz{&Ns{jDhѐv˧k7z~%#FnB!: Jǡ!Z+i -b{^3>ŮcCV=ְ#(]IU ;"- ;Cby1Kaƾr]ak\zZ|=Cm?Rݬp4OԮ rM6!7U9dj>ٞ=ZyIǚEeYiqGm|k)kY};4s?ǁ~PivkǥBh` hM3 Y­LOq8R٪КgmO{c8w'6cOe N&O7=\c#Z[A?Y5؊<g5kh@ |H+'+V q!*lhw-wkxьQ}s/7bl)  v3f+~hCpH۞qޡ{dWThY,%ȹ^fŀi⿯t(A&~0@7k!b+J6j\w~}xo]Sw0YϥM[WϜ ж%1&xx4aNMث>&E}zPJΦգ\) QE[7j#%1zc&[$n@7h梩ݣ:9)SLI ,gbhRxȃ$rЕon|ZUrCṙy8i'i'J_K4z"mһ0s%'·, ޱK;e)#,-Ux `6M khBoDk0ԃ0[7=QBѬc#6V޾G!X!d01A^Eg^v i&==V9։ںM&s`a]WRrLQ~*:9âw{~x%KG3mG٣m?%B5}\g\J`ڪM{mH }>4ģLH!dȖ,#'qsBVEtbA,0j2qśh9E$j`rWx4yp譑 ־ڹ>y1 0םW{壇JLIlRڜG.?Ql'?@I3HjZPϥzĤN;.n-?QaٲwKj"F*LsHMVv׆C:itђd, 17[ {R쀰3 6yrHsa>vYJsDGد?KV\x=Knp^X-բApR:=Q- ǂ9IBh^~n݆tDGu)(.~X5Љk[o/Aj0 eY1EB3DҶcSH]Ģk,6 $hH2<5S0ɗCA'tz̺9/ir FlL.D%sō śZ+a=QfJ3=4ű <3,5x&\C<t0ρLن@I1E'(~?W..^'eߺ-~_Sӎ|\)Q+*"FnaOGT`x˨)ޡ(>oycR"*[K=T2p$N59E韎N* Cjl{=;W ~3g .B6]_Ɇ^r-0ͳ4L쑯[(_˔%n{ ]4d=;ađ&Mf)QGP[v0/q4<ɠ(._ A#ŭ5D+nŝKA@r-pށžZk2z kgv\k#M+ɦ"^3s@xl+Il+'=ΫO9|\':)+bҧxǤ<ҝݜU*:D_7DwAu? 9qatTTgowKi' `߸voP=wS䷡)k; 4 +?YwƦ<~^ʼn>8E gKCC*73 (yTzGw `MR^0.r/m=6i KCjߵX Y;6WB٧yϊr_e_:YIqb'#W6C(ODg Oڻ+_D_ ;DmmUgQ!a 3C ٥eq׼T̕dsHan| X da0[h3%>ƘEM ZL bic@!χH^Hk0S/L^qDnA2@/C/%HxYjq?:XAh9JiOIӚy(גf'98Rya'5:S /%̲{VXI(h<;ak2U#uD]eDus 'fN4;U`;deh(^SaĐԑ1ysJ 0sRu/ x*F Y]+lCUr 9>z{Ho,3M^F46]@[Mr@L(Z;l >< n Q#4j !i#Z!>p^SwbѤo '=xƘ|9i%O&+Bzpih;qyz)[kkOmUҾ6K0#]w9Zvb@/qIg0 dFȗ$7)h.\ـux)e= ^v7]|()A!e 3HZ4OBTl9,;Oɜ*#e2R.{. nja>|q`cDNwN((?H/{ JUP鮞0s@ 8%-6ָV; 11Abp R) qĈAP($DC))9QBݾ)‹ 6b!/ ? l!V0@}> Acɤta;Ƞmާ2aռ TI)zaciҕ(7CEwA*{ c{=p(2*U0O,iݛl{܉mVfؽE㇂e[C2&A) G A3NW*M]rC #3TxtQ{HJB0 J:X@zxBVx zv)^Fc3gK"24*]2f`q9!&3welOJ24NbZQ%}Jΐ1+?3Nd4 JN(ӆٔPB.w4!F̡\)q.l^~;JߋFgT~EbzP轧s$I{@@ɥ9-|zw0 mlumk~"N0bȀu9<50? GeZ^eA⨜9?|MjeZPr 2iĐZ@fʽ;^y'wV/(?QT{b`4 C.GoIz>-J}[UBZCb uaZKl%|IdEo#Qrk%0D.tp-ØSMϹ"z6#58HdGEֻF^7@";3P]z<$_ɭ0ݢh811xY==#hްN@{I7@&X1e.z=S$)0"VuP2y*x.-TIim#\[cz1}4K& kXGFK4 )? f^'!K`lL<*)`[KOZC=k.?k,PѬixHEN^Criu܌5Z`'{/wNA~G2#4#c|߉ڕ84yPynVdz/-<]D%?x"O%<`4mUB_Fʣdٿ"OUi!˷I'Fb} o Hd͂E_Yʍv4zɀ| "!CXg2!=>2c{8&i`rFC4(RuZG}Ź0}0̄2=1gj=A;5p\^iz FUY& f @%xmuOC8 `ӗUk|؋fRІB_h\sÌw{a&c7 pXr{ʖS`?z:MfV>mͺÖI3_D2h^q0ۣsK.zC*))  RޯLQ?ֺncriow\@4KEqF2 ϔeЃp@z($afav`ʋ.:a5wFW/34K=#͹[~7}Op+K'j~Խ->cx;f>NĆAd֑Hj;&Ky 5Im SaAZS9yO cBH8: gl7&$oo>ekrC~9eY4aࣜrh.yg|Vռh}6Z"[,P"D xFJݷZfM@ma"~xCQ؅@]M"6)6۹ p i2}'{|cGNU(R9#b^.B+͈aI34Wt/%:0 ۏܗ6ќG| SN -wPg٘-L{;8qg=SL M:!t:9j`GD4ks&86﯁)(ЄJ ZGpx1:U*P}v^3*)~#xI#/b18ǟy[fX{<;D+ٔMvɿ# =Ұ+^#','ϓ*.D+N*cɅ"Tl26}֍Y.P{`"TfM-AJHCZTU971DYm_3T%NYiKHI2ˁ /VL0ƞFeͳ(p;OsMls4|e|լɠ<~ ]Z2^rq?T⳪Ѭly'U!4.GaaJˡӴH!T0~3r\^w+F 4)_$?̥D, (? 7C\~/ŝ~aAnz=PyZ|`})E@A\oHKgBY?X]K\$H'Mn{Cީʸs7#ߞfO: 1N8g:D*pR}v9OdI9KJz6?yŐX͊֝D5Zqg36jzZ;*5bbB ltEwhł,4BSpЀs젎:,7-Z@քIΕlz/o* P:tk<Ns7=9eh4l E-Q0Hͩ^x2YXPT"*" ͡y0fBsrD;ڹ16LPl1q +beɴU1WJ\mSODϳcmI]b Z(lUa%&dAzU8+vnz9䶧ްLoॳJO..8%hrKUO䚼:|BN eqrAV)ꗜlpRj>Z<DIœx;yh6T}]Qm\ iM']D>?Trrd,dU_&=컢]zx `4%Yuj_ubG]>Un o/``ߤ]eQ=D+/(Ĭg`U@xA9SQDL=?([8SUouZhjEuy99w.-yk߮r5r׼&d/&%; "Y۫6ȟl̏hSv'0>iĽgAN=[Q@YL ̩l|.4"p)c+u)pI~}튍 ^' d3-W,_Dk~;\ƞf%6G29sz  KSh0JBllTֿ5Tw?X BnKij#V,Ri-@?5f}rlnc`Z p+[R֢TZ5`V!)ov #='H k %e nGL^s (DQ2[نՔ;?˳[\!c9Q <#^;'@@,ހ/Sya[mтmSrZ;7a!T<[F}bO_N!75}*Kj̷=?Tkqϐ:ǹ\K KEfJ1C븐+dX.2fML=1{ݐJ6Zi* I1;|V&W`wg*qu!hձxB@ς|V'9#'ƿK\p winum@'ƱK˅olo<ԗV6Vu?DbĶڕl6 m5 f^a"it0e@V0͵` xz}/hl0Gc}tRXKZ Ss Nqe8> f㥥@\Zk5 ͳ}󒙹kcm"Q@se(SOSr7@sqAֶmȒs{nC=7 RJG`dǾm؄Ћ^P-'mSP^S Z]q^q1=Gbfc*`0$E Pljaڜiw;y09*uiJVPeA lЄ& NM_mƮ$BS^a$PvJSf{>yTBY>j>[={fOw$ lӱhnd~D;gN&8,g)Lkh@݁م%uwVwPo6y)M 2 ft')(P"VMKVjUKmYgF# <1vWi$n3ݐt,-sDӠPx 5 ],,qx] '4&"A(RZYs @Mh۳X{(=wt`zu2W6xgukG*S';;z`cVhiLydkDxW6#Dΐ H~` $dHRؿ$xb qIpŸQb@g6f:AKŵZ9zlqq{!XĮV9wAI1l@zsagWj!%< Xmy4XMBRh ^䂺JrSB\ MHr*Rs }tI*n4YO#vM׹GK3Fq-/O},"S;2B!Dd;*$"jݬHzbt {/8QRs? UDGa\3]N̑QrDz p2QA`ApmAl ~uS7*eo@t,rS|{d\ŽƉ};76iCȲn8]-e%ΊxIg,P#Flb B)'Tm:&C=(vawOܸit%7,'O2)xݾbԋpB!&|3O*;|J}"UbOHخCs#7X70tcustD|0xy|iA^4kcK5VbEa-fp fcgd@yU1hѦ?}Tة'E yNFế`Ux-D$p_: ;i2\4+rDAy B\lr껎&j`LӱDԑh$Hyu:uaz1YLRpo=F9꾭(7gC2l?Sn\3&)@ΙqdH^)<#t͹y I 9}Uu K>:7Riٗ̿\.zuځg)_z?:یjI*_W U1ZM%?DNb B^l]n`H)c.}o@vܼ5ý=[Nz`PI¬c8ꂡDU]WS8ÙL"?1,) qWΚZCF3DpAO/ڧv- *1ޡɡ+jRf+h( X>}4)tf,'UTf8*%yѨ`.׵(zaN k;Q&8a;ԓ^I??F0AH PR-}-J0_$asA{:871퓌f,xh#P"B.z%E`ӤQ?ٞގv4cm5=9 Y:VsjbN/݉w>Ypv1H1Tw|uVE}nnS&i:SDXyr#6"Nc)~f8HA9H]]dAKNv|m-8{bƘ]vw, +mK9p9_-;c:ݢ]%{omU6c jfӢL 06"Iz3L-Eˢhjԝ9Pk,I𱴁2~Aom{xٓ3ǣOQ|i%5tIK[æ[7cG:ͺ`;U*ϫB :/M"FZc\;eGWOi- |< n5>VQBYYkjL]rrdwss!RAP+K<@c*V|~h,t_娎JnDH,\j> N޹{t[Ӓ _L@ 8h 48zDi}u#Eq9t ҊKkm'j ~74@9=Η#A\" '}F<-ٜ/W*SVQ[rH8CK^v~Gsxn{1nryZ0Vjk1Q_F篩*#R`>Өh@q5pa([!(; 5zQ;zy뉡l6s%:rk]_nJw{~_kM#Cv+/"SyCxG'#S2 [񅒑嬠ـD/j|wU}:tIgFsrɽx[8;*ZU_T$Y IZTvcԱqc[$|M(A~|*!aX(_Xbpe=ʉaԋ諰]/Q,3 iǸ}bs_JNr5fCv -L$⮑| Ab!kL_:sqy#k\$Nsƿhb0UE'fAODj0oE /֫ZC(], L"i8XC",8ca̧í(<` X:g'?UY=C,cqTOv,S7VQةj="G5%<6&!F3*_;b޶vTCb1ʘMpgcYŎ"H܍&XaWT5&쒓0@Z/Y O >Qi8KShFҒ5m? 2:b^rd -اN),Q96CKxjiNeWܥb#ervb`RWmQ"³h -+6 (Fihz+h߱Y=8QcLg ZP'Mj= tWN6QCV|aR70P \xٹE%9| C>dlPBQ`\Z.装4> ~ZGힻ$yu|\ȓ݆IZ5Kyp%0TҺ<#I-V6nT˻7f=E {~>OJ6‡nK|#ˉcֆFcni)wWB(Ko~'ƄPm✰GtN?fjQNc^ !؄қcCE;|p 1`jDE6߫'l4)%cPK'R,y#@ AA藢1F3ws_Mcl :Z:KBWBٴy% Լju=c=k̇ğN&X|ɘ` sGgC>G $l)Iq%YwW }J_Sw=9vp;Hf-%"!xɁ0ˆ ,B߆ђd#}sЙQgmA䢀fn㡝KQ;  8E3ysԣ-Y4с*iqp"˥QԐF+H:DncPvt`(vr6 pʖE|/< =͂^ΰ!,ϩB }{K_ͨfɄ5xsG0Yx|_[1aPw|SH1ᒰ7ž p#6Ⱦ h+Ml=괁zvw-RIpv9z|Ԟ:͡4LUr\SOR@x4 .s*);!Ea7+ zVZd ACˆqXej30*B9A0:k?dq4݌ F~?2g> a6l/Xlhƻ߻ONWK\O_2޸"fbIfBqRjN%{4G5&΍o%aԳMCs4p@g/chJ#@\ ,uWXaNuT+l߱~;e>yƞ$ kC ?4ۨP?o,wv07pjbi3O+|SG,?odza8HUQMMbN~mqf+u1ZbxyN1/ 9ؐ"҄+caE>$+#a2Kc%d?E;Ku m"l4 :%z6HPvQtsބf?:уƀVǩ`bF&Ktsq`=ixcY@'+p)}-JL]Kj٩n~*L*YX{Fk ssX_3}j|YUF;w,jz:9ScT`VU/8JRIXO9|\ ]Aw6̩)U_;tp,Rҭף$n\.^͟n=mCH'瓏\cWx[OE;mN UWcn3?mnS=tLКgѺh lm#Ħ?M,:bHz܄go?}' "?|*q =XFFWܲ%I0@StX{T0I;Ԕr]}fӗt33J"0a=l 9ne>}Cϫ %de*I!9j(-}ŝZΟ(½jaVJMNdjB:;lX*|uOZLU~sf|/rO#mą=U< h\GusrzO9'hڧ͎\%Q kJ) Ωl@[nѰm<D(d1'?Et݃f/P>Hݯ;C,/ɏ#sʷl(dD46UόP@s )3;Q_Aم @$flop`zg[&HdHJ X}X /}wc͙,%o܊B?5Ƿj3%e=YK ; 1G{sS"[|pBCo^wCIP= >WkڷR /KY. mEv3GBm fS4A-NgddQ["@"8tĴۈi#yHwP {1(GӦ6"Sd'L 4I\?9/ дN)^jԣ :>5݅VG>w{1M*Ր7G\abΎ+=mVZrwX2:D$CrB^mi)56}ݕw%TMd|\>R^-3(0 g5|V 8+O5PHh}ѯ*D۬d?|f0Ѱpp[0byp+ N0pņJ%GPOjT|'nW bG`_Y҅JV6a^rFfq7F?@RI2*34e%['Ũn[8ʶyCˇj/ڨ]vi|ZbB֑o *edK*JSI`)X^oGSӭ:!BI-bpCT A2`ey"}ԅUg8kG)^N{?^Տա҉׫ Fb8/W40<<"K4~L4(BfCЈ|grErnH 7B^JU$I'*`yϤ3~?^C3X.cd ,UPQz)&`n>cl/ (r׵} en>;<-j* YO 0ߵRT׷nk71߻3f?-Z$hNH4xɧ!MU};elrH[ R|"𯪷lADAIcl  L}gHk_T E*>&A /"`" zYYd?3Kay`+J R'_Ҽ{`P0#dB^2p.XOw]_d 0 Glyz* "W2[\498ۘzu`͋Ҫ%3Pi,쌗D16B݇y0&<^ h"2 PRGM$ڎeĚB/X'QX7."^mJRssdY?5E@_^|}vF@ö8f)mLe`rTRE$ xLHĵ6~NCti@JFN%G~ ʦqRU|E79i3jEM5+ [lp[\k.jl@>.:QǨb)lp`QE59 fQl!k/N$_Vl>Ъ͢L#}BD__H{-BGZ`b+&;6Xî'@) Qn߁܁!o=z$z_,,x.K0-]F'h!_z~^MTw3_Oŝ5S'ݔW/LѓF]l<`uj>{|'MKNj|;kI8%i*㶀Z#@}{;J;jsb |͙ oݱA@#"ѴT)-317Z!+|oH00ɟNkKnt(=i~7͈%1 @UgֽoНlMi:FBrٌ]`r4ow=Ax(F1zVIvu3!ڋ'IJ榴,˟i [Xy|<}L>{@Ԩ+ VZϨӐMG_|3|UqE>.(n. 38?gn%:$)L5trwuy<(]5z\8?ʼn?j[o+687p*pbN.ܿny>eFȮC_ʡjƊt;GfEfm}_;}XQ8 ُf]jJ{cKw!\5rdJnZ{º֛8"Z70q):z\n2֌%By@K+ر?8-z71k#;d,۾ZV\*q8vL`Pd #XӇB'fŧcBPvGO9[tt;vhF+<F_`h^%HMluK&~:+*5z,%] ^}/E뵊 k0&QBJ"lPu, /i0[׼41۶/E~-#sR7Q%ӊeX:f@65 kr<!Q&eܶDlmߛrÍs)Z@};Tm'i=I3!~orZ&WAwlF)T':&u)6|.ćT΄mأl>{mH/f{M!6!4pWό N3+[19@{&7Ys;SzXV[GY` *EM ^6mT%^wSs3]&S":a劏}B"@ˌQQŞj,6!Bvg^ыŊc@d ojD4/#׾@>8|W>@!.̈́ @@RF* nJxIbԣKF%UDԈ>%[n`GKyA5fӈNnfc!i ߦґ}:81W\~bjt"MT.m'2_y \NIxݏ ϟ[*'y [IeCKMxfo ]Q _c TOt2) i|ͫoc:-c?ۏ>0+:B)lsr =_>-{cDLKz"~?x$]6HYnI@X//K~/Sy:3kjƎTxa/be\e\W< ͇j:7cf`8Ba{S>3W)b-KvaO+ aCu#t̻G]Mtew+GWT2:FKcg*C*a.r!VX = l"  3L?[ e1WK(g #z;u+pj|5^eb@rCZ|ބ$2i ]4p/cdr;$ߙVTz>'@!Ֆ't|m$9FAAЂPݤ^.*&X(gjAAqV=EqCm"Sw.chc"U 9Bu!OB5ەQ7.h3XvANsM,/ y'FB6U鏬, *B4!?m9&dy_DLu7I‡BS6!Ig,ii)[Ƭ<:I!rYn.x0Lwh/kf>Q,~O~,젞c#bkMRbAǓ+@Qw8?$_7sr%(48DkԆQQ!68U R2ңCiH̀f{|WPaйiDH"~֒( W9>Mq=C{mvPP_龛U^IdI%_k]Ap3Shg*fɏ4˽O'C%ڎͷ©aá)pEg҅Zi(VPƱkp1?8r7YcǚDsqc[]EciClC١%?J<ƨ$t[뀇;.DžM;[M}<F# $iKS ѮsE4ִ =ik"fp ٖWyGa@@p=7¾:Mt#nMLeKDP$$۩k&q4^zP]K!'a$`Qg693MY{ʝ|y$f: VԷpbzCyM0/K7ݒt qbi1a@ĸ -ۘǓ!(β)Dp?34!+'pm9E|)*oՍl#@!?e bҁl_^'[2.ޟ n!yU#7N|:ɩUD}qYԜhw*41vYv}"Y΀ =3S.3 j8x*֖&DMˋsz8.bV -p1(_|^7\ݱ+B.@vLr">ʍrl. ]S a<*HOxl4.z}|A0 .j&TdQ^>8[S`jnЕ0"9!xrYI/J;sX +Vā`k3$!&h.aYӁĄ\ d^'&94 *6ӉX<ϧg*|Пr*[I̤76;OȎ|7&Уy$29GG T \ 6.+a[{9Wik2(lIdH]b0#31Y4m^a00.-m|ttnêˠrޯq.syƅ0MaEc/t`83gF+q IӲ=dXt2h=z_b< SXU/T<*Ke^T~TڌxQ=Vtw&=d~\{J0ա@ΝW bfB쇓N)#(aߜxl'ΤWk+¸NGԱGo7Q+8WYNt .&/yPG Q,A)fO]I/Jb +R-/ v2܋mYA;Y?rVBk$O xXSg\ILD MyqN nMHMrQ. mTX|ۋ ttn^vX*q wILC=Vw"Y?+3z ~ZyTVm:% l&[LDsGhe~KwԙȆ?Ty0z|$q8&kf>ȵao[:svSwe w[V+&l`:#2딸2)z-Nn'/] Y]+֣?izXOUF~y/]=sNeoٳ'۹C]W0C]dz;8n"4gu, 3p&}zB2:G@ZvU~VT4A9T#b RYyըfg<[\&NEu }1NOV}*/xX+I_Vн듼Ĺh؃]d.ˣQ] :=& r t=@g E q;8&5h!5[9 ?;~bZ2d4nϽ5/f:u>hZp{K~^l'B`^g4}ٴ;W} S6@I2,d1:OBSR>q$ԕA4FNgH؋[(߱j7jEa/P:W 1ZYnr8A| &Ze"$[ͻg7? ,V8 l>8~i-^)}ZM)=EtNӾe޳K,:{lk_Rlx兛K:cLgu𒧰JS d$4)tq X@GDLG|!eΈ2kyriko墨V|uRj{Uj [Qx$[_LSʴpbm }h+i-AVxbTRd,I~Gtatc#W"44pLS ZUJR[i!3YPFb|PYP{e3 dU]v86K k2 j\I163R[z' ]@%!CCªS" XXh~h:xy]۟E(f 'ѐ-=[*Sd@ˆ5@}1ĕ{m-Yö(s[ C^@ Ov/JOQObRGYqOtT;$`\јO pH0er7CNKqًfDR3f [h\4+A{Câ:g8$>5&ע8m/p󖀁NĄd 9ubL h6ЫɫJ#=1{r49lD2H 6 Dłiq4*$\*xt)[;ٜ!`OaG ?l%,&r JL$ҵ%y wB=ʡimξQ9@LaϷJ0m+@c"YޛM)J_ E; _ΐO8/)ѐ&$Dʘ67C7/&q5C5t6utPN2.]uv~vgsIY_[E>uXM'#믺o|O&;el ]տŸxnY˖c 5C2,l!yQ+r dgszډ ƁHa7{"^zMGX5OxZ`Q `,,<;g j"anOrzZ"^q >c<VK<.2De J-ӛ2D.89z-B1QK5xΟ0e`M y3ԬNK-v?4<;Oq/t36Ky\*6@ "c] 3|V#x T0yg,}}V&P,[ҎE)N m0ǦWD#ϝ|E&-HF|,Ϙh4ψpJݤP_?K֕Xw;xEՇiix兹4 Ua]\X`+g7KK<, 'flGo%Ҹ.ホ[˝vv_N* *`+\= 8%Sl7m{5Hc ΋>Vl@zcHw*}ѩ45LțA1>7cﬗVI|G C exnZZ`Yk( usubZ;4HW<^@e,2sfY|Rgq 8o6%5{cl|ͱdU{]CzEFUagf9oHm2v1~E'w (re Z3Ε붺i's$&ysD>69 ϓRjàpjkehlr1W#*I[D|N aV 3%vMD4Sy1scW_CP]tbU8Xccݎ pA[)-dϔqiN5&u1(I8GH9-U#0Ln9N(N>ᙼյ+ TkR«o^{|+QZ-tmT kgmRrOlL_27e Wo0?:sq7"3Y{f&$:k,%ZmZurƐ¸h?gAma΁GϏGh5Wr(S}FGUl/r?ㅵը˧9z4c(rpC E'R^C(l0!oJoD&Ph R1y^2-鰃-g .-@7*0<9J}dQK Z2Ss5\ bYFN="*9,NTEy]h3Y)ڕÏ$ x}y|ŵgօ kXnBHnnB ! @H0 ބZf#Hk__}X[oΙw]B%;s̙3g9sΙn`2ߒݥe{+|SwV)+9s_Eʒ陾@`?!7ʷڱEg+*-oKAE*} +X˪{|SKn9cG>웓UfW,, 씫f^RT1hGI;쨞VR^8+9!YP[{C ϗ[ח\3zynV ?+g"| L6KEUeEq⣿tͰiˊ*_\s ʳe! 3K**JʊK*+B`%J }ۋ?\s88aoفʢi9ir|ci99>-b@_S_rjNw=k`rX)8憬ŕ|rVVl @c2${wTgM7)2:}F ׆k.n-Xb<go\XK;ъjaM`hP>J0է%p=.Ӈs:Cj} ceh dhY.N֛D@pCH`̾\d2LQ}pU)] FOq A~fC}q;݄h2l* +M)&i$xa$1"b0T(+ۺzwNXvެ^zVsq p6kF;-O=GHjd;1W }߅ vYZUx'd_:b>#5+YR)PZ^-a_ç3~C'IM[Hu+9l`+f׃by C{nԗ0{mPFPa\@ﻞ$F 5zKwlw:m3cHߜT2pu''yS((!p1ZG8&Zj=.jxjMOs5z)hP !0^ź5#))M{@2հF9llܳh!\*6!Tor|@b`"\;1qh%'SIs$ϴٹRx_E9czcz~~Lo[%yJ9D. "h&ߴtXnkqVku* y(ijANכr3-}k ua-? dгGlju(r\MLq?\M087 _[_ #zfC/ gP4X ,v yÓ8* ݛI+:#x!ٟM:ΜL]9'ee h}\Z8&6ug>eFzə/8)%;ՠdjLţY TAH%DiEw ^{&NEE]6 6qŨqtǡ |^zÁ \(#.όvNB3qqh0-25 .*s 3E# fYdz2ͽ)SG1S2exDp?,"xah-m?oJէ*DՄ[8EQѐkQ(FeNs6}Ix B)藅 -Jý m Vf#3Q݄a@aݒYAPe%׆2"?J:m L?[`SL s|f pζN }e/N^2*XU}Wف*{_UIUu/ EzV4p.Pl! ~чGʜzUKAwGД-RHh6JUmYB(\35p_y;AT :^>Y!VrdiԂƨ<eN*;T6$Kog,P֔>S⬑r99w&Nk@LeQգ3-H} DNէNGL7OvJKg\VYro,]5yi70򳌫TQRqՐջbCnQSyea$&Mӗz}@dD☺,bU ˈF/&t0N2QfS.ܠ"N"cE.>Qti :*viSsBå(.4pPסFԞ9he@(Z)>s;]?n@ŏbZ:tgLթ}jkk8P:(Ib;Oh`<Μu槞﫟ې4c؞S,k{/n_n<p\o&Z]MrJd<<>m[ F2IȌ96f%W` ^P]Z|mz8 tjn=tLS% 8"xn1A6.ڶz҃E'v՗ 6>z-( ?i/}eȚr̾pֹ21Qju{,ve/q5 q/Fᦘ廜IhAY ;-Z3S3Lcbܖf ~iMI~?&Q0 hdl/~ *X;򱃨lLdWhZ27/L]SEL<+-p*߹]{(9/4hʙB1o`: ><-Q..Y`<Ϻ# v$A7fn]x >b/\ij}HuQy]HdО{v`ML >pcۛxS)6緭µ%hfD;!&5CoL#Ϫ^l- ) ץLp3( j;LxIGAϫ/ i8EqB"5]"qMqnVvud+H1Ih[<<# <g3: 76X0 m~~ z퉩x%Npi;Kx5s+Q|㧰]v "F WG╓M eAS뫲ƃBL ˦{OU 8lg0 3ЄEm<-xpr,M0A?q`;,q&+/IO&̽n{8oJ`10T|¥,IS[ J7b'ܘu80Oܕ59zC=r JpsݹK<GWiL]f VB`/ TpI90`'!(҅b7Ю5xd@.1R>Mahע .$G"@TdJ D}?Zw@WeWݑoԎN5z.ZpʺA\V+w T!+uՃ,]ȳu%IR V'%Gd/oCfMgm/Ay 50N\_=r,a$C;{ (?B=/ۛ#~r|c >12M\a q<~95x0(*?Y*ww+'¬I)uy} &1P5ɏNN`*d  S!N'B,{TocPo6B;t"LW ,_'ۛg{-D D D~M=c^ qcƇ]hPXc lAM9 O'.h X{tL8r0/aG=bt+%ڧOTNyhj}<2qF<$odN \F Xc}tNH^|,5gH.vx9ᤉ ,\(?r>9'?aQ[)Lm͇m\bc`''{ -0mOfb̳u줧ODDQ0>3$gY6Iv9}Tt〯帣 OxgO2x1= M7nE/DE/ći#fahWo޶2 UzЃۊ,,Eሏb\v3z g z7D@t^zx*̺>p.̯`3_Z%RĔd5*\I"zVȝHS۱D?)z[{D"W- X cG[!J{FBzuK7# U߷)=YogܤzN(_:;RGQI&xr zFmSſHH֣!n*y=#\pK\Ƴ稊 5 HWf/L[-]L\ gg\^}ӝ*.Q7G;ww8ORzm3:<*!x iWCAnȺ7uup~.\rM3!>$K_G6_߬9+f/Z&ˊP78fDzXwHIF>4P>põ+&G-0- .:N\{Q˜ҭ$f gl\xhy+×Ƕ#1Jjƛ}dX&׵s9wOw)xoSS?u"jrK5ӷ`28gYVHPiB(}5@lxWi&x/7-ԅ5A3ˈ_Ac"tU1lּٝqaZ^#/-qk^1>cv!@-r:.kKNIpyQ E|;JYg!2.v};xGuiEyց}Kˊ7'\퍜K6d;|F<< 0}R'eTɱ ;h~[yAd˜ yƊ(8d.fC:awo`mXa8h((h#dnu&6X~R0!`gx / "]}0 ֙ؗqY(Ba8s:$64p_e57 Ię+.̼s1y;&aD9 CYyhA% VSTz7b0%|5HX[R1pҭlb!$Wd 8y pQu l\R*&?̐z eG𚓛|x֕ޙGź61)ɥ t2CB6.ɰLlu{eH~}?J}wzprYxHԼ.,cza EÍ a b xs@tǷz/:yR:S?䴎|i)c [kGd%xm/}AxX~ f~{p׋" 5gDuA$3()2%$K:ڵ W g -iCFw;oEc=36ֶ!삍'l E,a <ܹ K#qŤ_RS"@m/\bowP (Fy݈CԁWŶ"DG-,MTeh5UkFuتnl^g|F`-5M$:&~N̆ DETQ!R \!=d1PJ4·ӛ" ߱2[Pp 4ՠ IVi!mffRAlz8M4g YtGIpRi9+qJ&X!V~@oEO~mq!)\=2x"[0*_sW\rG?2 GUh6&RYāy9O _6gĠelGQD?t7e|V(UZ22lɣr TsPc=5g"YgL;|+xMm7@u WSVxjEl2.sTڹDrcֆrOv!H\=NW?*4,e%?zOKJw CYfi fR?\'MB9;"| =\6vRB*\fQw2gQXl, wL&Sk1hϺ crd(Z<ҡnYYA*+ݹ99#h;:nmDYx1y9RŷbIș'٨,Ywyq?@d9..tE6qilJ(>o2m^O讪EeK]$J5QKEePzʕ%ۋx!,^E tHt/I'}x&%at 5* p\3?\ <4[@ҒB*aV-9y_$liH=醲*R85GP> ^TAYwhRhFn(Y ghhBH̛8xiPҕUo5g 븏tTYM(j-EFk`bҳl]$`kl;m:WЬOFW#O.y_7W@a3_-W<"g0GrM0!袴R68C@}d:}lEA;. '{x5.eP%Pi1qKIӏGQ:z_ ? z[ѯnxǎ![Z=<=eJJߴLYMڜL&z*y'l#}4rn~Db)E\:5R&>.n4 Cv@}Լ[R^ڴ,#ZGNWf[P[iO4cd 2+I o.0 "A"Lr 6Żj5<{ tx?T73WWkg<񠁋Wm)N$ҊydmGg3ZU Bq[)ܤ@Lgw|4^I->c2h4t>ӗZE ɑR7>i!y~UFj7;mA$c, C'T77\Wb>x0h7t($ѕIo2g8veBwS{84 DǺ_Kmɢ]JRUJl6_7+A -K^[q`E;}+T_䳢hud@;чjqubIVA.V0o{yF 0&%qKXI;Udd|K6}`6R|MxɡݢHMA]MQk?YMFeV1Jlg=f!߻uiD 71]~Ng% kɨDcd)yIL9m5vDu$V'){-du(cLA+ֳ쿅$:P|O1Hlȕ\t{qeytin"a/2_O֜ˎfy@94sYd"^|롭}&a8F:#V())S$ȫ+?xa3m&2sqy#xM@1{j3YbZV_xtXHW*TW,.[1bW.9U!imd a ~fV5d`Al{:sV2.KIvx!WFPJ 62zpz>lJ@Y^~t;XnM=n kd\XO3LeQfmr2nIޘLgXSzW<xҽL8_L>RGbzSSBf.-Zpś]!DD~lBA s22f(B!L†Ż+tsed rw9B/Vpz4aȧHir4Ω cMce@ ASGRZd}Uv,vtl5JÉ;#͍-G^ܝn@,D8EN-D6 oUw+βa;wX!RDpf ^#EKi˳^Foυ*fY9{D&\*=dB Gd6mƪ>8/CN4,;EQ,dYTIA #)" J5_|0Hƥ{ek.k&%B^"4 =v`,ĭhkh2Pok <&cJ>,8aq O׭K#cٱ*HgFMߪ#<ǯ5Gǭ3Q=)fw S׉- DqnITI돏nQ7Օ7N1іX'SkL gb:*O֓(:%$I}yI2cNSdHn#EEdi1Z˵ $e:ZH0oE $3˳W ,pNx56Og\Nɨ3Pg\# #hy1UȸI1((ϡ5XMg]NI,# Cf̡$#1WHx>*=L<{Ev#k/xGxP5'أdl]݈:54G8Iqy{DTBԤ舉IMw)4Q0<?%,^;ORRU'Hژ\d|[8DQO/`B2?G邒 <"{F?E` GEg}HzZe0/Ӥ] Z: `(}U>YS29!9vt)p3+4w'^Ŋ^AeCɒ\ԼQ&k EdH4mnX612c֍utL3=X N "@t'mv-94>X̾ϑѕf _c8~Ef>d~̚-bkѡuчn׍>W`ڄNTzGE-o}sdk ƾJ Ktg!i7ΐ4K bxg^ #`o|lOu ]ϯwxQKۓcT"XY[]P̬dJ`2+_†jMzə'\!dV# Vi\ .,E893a'9P옠(,S? V9>MT~D=&}^K|_5Iruzkos4O#w )'"LYS`U{yϱ yQ"'[ͼc } msRn,Pfonλ߳哾_6 ֢Ls(НY[ an> m]5 syQygFˤ`_ѯw^XF5HIz2ϵ!t/ɞ/z㝧Ky?Ȼ1Y^Wuˊ G)Ms[s:d"kgծ--h`I?"B:=i<`D*cF[rϥ?~dD (}>3AuHrWޛyF30kEoߑ ֐-mGf}*~ 5 XKD>Y9ECC(@=ɢ~) }1w,όud9; R/qy ԰#&=1=!MX?!ģ!1f0Y}ʇ,6&cbI,1aKyZ|#28fp =6 8.ž72Ӂd^~ۨȸ)^1֐N!1H!UEe{oܚ/Ԭݥ5if^ӦOHfs9xSaiCtDs"`nn4]?5Ζ_f%dڥdeK"ݟ%_úUM=:)+Jz FhQ&?9~XM&w.Ҧ ->{l1UX-T|Ur5&뼀<[U_+GEQuSrb;`xEAdvb;\t 8M[4#dcS)ENRpByY(׋WָwkEA`=^[͞`[Gz3@";Eh e%;Cm8m & 0Yr+gh3ix-:NsA?^[y8@y:)5hL GZ3XW7+2VH|ʇOxɛoXN7wutӮUYt_BiwZyGp(ޘ?luN3Z?&)? J͡o4Fj2ߚ.xu)RQUyhĻj0n[+XTQ҈wm9;~2G8.VCoZzh6sg 4^_6 \LQ3i,aҔ[fy?m I>.Wf 2sKy+rZȨ#x}qR-[6hCa,(ƶ&4nFWRˇ# %J4g|HAYHruQlguFq8ro Z2g퓷⵳}ZL:Z5{I^λڪ \DFv-kЖKc(5l΅X1 O8-\' ^1a@q1_"H\ ݥ]X'>$gfrP A뻵-c<([ >r&xHKL@Շ "VWNx}y|ŕ|H/l>ZeKf$!ْ/-_ݣikGtXsB@@ Hef Ir&r|{UuOH6Yv[]]ի}_5zI5R~'ʖΓ7Z'!T{#{4u<d֎°f.(]&7,olX~_WVCNTx^7Ac.^ߢf,@g(G-.m\Fn m1|M$!| {&Z5J&Q ʲ6}}LjEAVbDCԡ[תGۍmuV48*CwSV21=gO:N'S2zM-A[j48-ԢMia47ObF88ЯjFjǩiz0q@p5S>bb;4n+dhsjHsX39xڄ\u8Wb=OѬnt9QW} c@\j+OLڬF,(4ɨر+mj4QUO!=v鶌x|%$&Fa:D)4b"8Õp|4{{/ڕSgNhI$KBT)9uI-ڡ H֔5b4˥O6~&e_t-0!}LD-@tFEEk*TO +8jh6;Op~ OͮB*G3C SX )$V_YCE'!Snxǥvv6D?Z9!5gL ,8ܼTuuL˄VhP ~'Bc˻5)ih DcY`)޴!B9-'lzvCzZ2.Lkd^$H}J*?cP~yΗ@@&ƭx#t=儦dh +RXn|ށlGmY&%T` I"+攚0锼s[G+Zu_x]δ?9?l'3LZTʧ `8'o[@xjB1+nk^(/]j| WVE@$= Ͱ|~sٌi8r#P*q~wJG'R;&hJ+-zl6 83@;Pϛߍ$1x2i隟]ΉXyEO3AS)"/N8&i ?Mbhh}p~)\ MɎeCh[㚨"7ޞͱBD?EEcLJ ] C,k~1٩U&lBIS2vum&6# A:x4o LDݗKKVϮؘ7S()%ɡkjO|^QB[ދH-]uع% z-13"evuu߰HQPV >iuA,p ZC>:mj b8sVP8IǝB5}> p8٧ri X@&mDat%we[[谷Jњr'*ɬ%okpYGsQRGmH 6Y@0D3ncgV@e/Z|VL=2c_d7.WſX_? ܫlCx rV{Sx7oYJ4'6tcU| SeKm}n4|v(@ϤRaqR]/_ p@{]вGoyǒyC7-[e+ ,mANV;G=@|X]+g̵C#2ĒNo@W-! z_`y%oG"fHJ"ηz(#3-n gHKٝۧovo,W#G x&u[W ttл*罋 {,| Q_XO׆7%q ous"i=oD~ՠ@x5Q! bͧG>vljn2O>"6=AAݾIA:A"34\IXi䋫o&/e4G视;  cKFVASG0$/ @e/΅6GlhQER1KЬ.,Eјv&=K.gFvc]9+Q]9s t *.<h+ LCkv h :-r1T}+6c|k| (/̉8pDfqC@\}Đ0HDtfQJefo֒15H>}Kb{xj(S]8'w& DĐR5,Y(>_/] BnȂrJC0ɎĈq =sdOOf坰:hhKtXi!@]~ش|Q&2>4U :\?ԇWUWWGþuDPYqƈy "/W9OfC H dFy kGľ߼Vj?- @%e+'N2 [K7&%L/xaWqit/\3Cb܆:SfXvڳ0;Ù ڷyuSrv|Vt\:á"eAUj#UV,. ]X5x#e(X!{7m6AzƋ݈e=>#) zEZ>Z5U%DJ`8/.žFg6u/]V@0b tO/M=,Łs^$_(7ɏ}yHsľ7mN+o?f =_Z><;<ٸി0*6˙{&ɀR7赁Od?1"cΓqt7sMU'2rP&zACYD[TqrK)jP <ifZڋd-[uCO|1XmPfaW_t`$4G~n_d{<gcs{͘ KMLCےNm"Q=1\1.ZБh E (A}l;]sW?uwp{WZ<tF3yr ?2E54gsj)y3:LN3pcF'`O<~vWb,6Lw8Y`7Dd\]8 ~5kx!PA8DƀSp;WpLOZ!\y70KXinT1!N '$ȆP׿oi#&ϥb~3J| `6`mrN̆Yx[t0JIL*&o &ݵ˾ٜ~[<$ݴ@%ME5 dɾŠOxc]:f߸T0 RW)+-5Fc^DdѿR(p? Ylt aX< fhGy1 0saw˃90.WBnSIM ]ߍ yaW67g+pDJHqY?nyA?vJ# wG&Ha977Ÿ?ܫm6:k3IkamԌUHk܂[,B7J>ɋVֺy֑`I'QϹ~MtuS)0T 4ɬ`$[DlXg,ug_nV,"tGɴ/L)_ ~x wETWnNz@43dyd@V_˾4`ŴTo,g=@:NI9{L;olpC,)PFQSyίGcO˃2Ѭ٣$.oC(ޛ/ uiGd(j7# nL##Y'%> /wgO|1e]&栒y1: y Ū$^iN,FS)ȹo4bwEC;+a'hX37ඎ2-H7`cN)s98Ǔ\䯹*yRk[@pnBPP/(zm勝`PhVk˰i^+զ\䔪BZHp՛:l.PӸ:댯0X ksI2?v P6l[$?KURTVxʁzoa0䶩\^LDP›*e 6aHOưr`}8HG4(L%/C(>F#G- ;?:ƱQMC1ZU T٢)72x^:mz/;R6@7lY\a֡c)z0`cmD5v':Џ댣\;8ǏJ%΃s8 ES+ma(1ki A vD@=ml-֊q5CYBE% +sa+n~+MVpJWdGtOQjzl>MFFt~MVQ_+gL3>KOsXhTwr2p{|{+gdfv[R P:3آvY|w;5|JgFZ+6`g{81(wf} 24șǽER<ʆ%}8[dMqFl7 hZA}"F/̒iwγ2[ܿ8UShA*U#L?W:mT)c:/U˺&Exy[ܙ,\=݄WyoXNo@lhKk>2Q)l*mmKFC+lsJi3XN.탨{0`ebY"'%Rҟa7{ujزwwKA!W:ae@oր@/=#.!0.,ACkt/f]#Z2QS,|wgelex^ r% ۳͘.@tM9$0-8+on7ۛ6"rRE s~f׵|9cO* '%v=Ghnp^\®^_A9ZNZ- u9ۗYc/c'"}Y{/n+q+xOY@51),Q6 W= fz}2wy =h8nYX`:>J&i=ݜ[jcCK1,~oa*yGסFwC (?"0Tsn^͜m,.K/:ײ7DôeyMl7t9'Y5wd7)`CT&g X\ nwGP2l(8]Ѐibq x1< \S$V:'tv\#s˕CĹ&_lneӝ[YҼ ؋c)qyqнobӻҧ7YAN&y- JKhx3~LKnf9N9(ʸ<^ csŭ?cVg,?MR;zNV696%pb1MYf;7ݻ^1?ۄ#fZ6}{:J ΜN6#qdthF:5c?oc :2j7Jvt[k6YD(П&^=Vyi;W:.V1\(|lvjA|_Φڗ>RӮaA6}W:v6gҾ cJ;oC[eaFdn'L!Wx.[\ l~4Oa#Nzn6* `%fǰ#p.IUDېUDqL*}o%s`/8e gs;teĝ0lŽ0Cjqs+x<Ӗk8XL0U"2u^Sľ5}ПO`a.l{0m BX)y/P^LZ~G[}LG:Ơϋ+njS☔i<0T! lO ӞLlWr:\;rd&^gaӜ玳?ds#*EҒu6^!0ao̟O"l:Qh>оÖ(2;:\e/jdW# L*{{/C8g{Mh&$֣Q-Fa9YSO/FCR8[=0{MuVbGkK!`HdkGmГz*fh<lVJ# 6Nԅlt^l7ٖUkci(ZPSƺau-wcG^:6:W~_ *I &lG=&_6صc)L-({,ailxO9Ϛl*=D}U5F,-k|f)}\\|b-7a?k|(x6S$oy=Zf4 FxC%}>z\*A[Y|LUJEOk}/xagi/{&3mt }̴5ꆣ;ƓshM|Y{MS87<}-qa؂t,?݅PdzuO`OsTr_.SFVz#ұ@+q~,7a;n`KRmjndm0(zF^:`}#l:mvO.yGe'][nf 'zonU ͛>{oQtmrK/U]wi^xdSM8N` M'XaYjL- "q] | 0Cop~z7[4oQ̏a XmpచâXBq)Ξ֐/I웿ApOy ީn( d-8}UUp+IP]t˜9b7mnM*(:l`0VO[aQSNb3VM԰t3 `̃[<.?Jp^ u~uC9pZ ̞DP(w=jĞHHgC}Rs%xt\K<~ة2=fU0Es,Z䃏2; cQpAj?ϚgW^hNӓco~QX\]qSES2vQl-/k1j $ĵ~ѣANiyE"C{n88.:Ɓŗ7"oNq iSʝ`1:2ໞ`[C9t.N"11< @汙~^DH{, s!cUSᄷ %/o)nnB|m9_4{\#gXSÚ}ϏQahd%)BCY~3C~ϳ솊LBʡ;]wcX8l BN–P`%&) s {p 2Fh_kE:Pt&vqZ]#<E-ҽȐo>my؅ε`O!+8Ndߧ"%Ui@3&T#˩ۙO,.|?~e-x9kfIM*;;gΞo;9] %^b>Prrt6nx(`+Ѓdﲛ8y.͡偷 noY(F1 PCLι oW؍o=Q%*yJ7q#lKpkE\1kD\LWGr)iZLw\_~e$֟b2XZ|vjU^K;hLÿ36:o[UMǤF$#li8Z/(EUx%n%pq:|ZoQ뒪gD}KV8{E>x M>~^'!{ 2=$cXsכl"C5MҜcw$|"b~J\c"ȳսDe(IP\Щ9*x~ϦfSK4ə6;6SҎ`g'[F0K Gp GhPiY۬f.h}&DyUfÃ}k7%.ƹN'~m`{T;1LpRIWj8'wsZ'peUYۧFK:*y[% TAT&&tL_X|jR8\ey;n)U邿׳)}c@7uƵ%RcB}߼>`9ByB֝H6-Cn)(alQޞ_-A96NZ_̀`}54N ӄί&HhB*d sx(]=~>jR,oAο]$> Buyk4o-t ʚKu+znG.acX2SJƌ` A(IWN6;Gg6 57C:3{`$'DLhptxWaENopC?S'oΒ=%Fa;͞#횕YO5`>Seh0{s<ҴV!.Q16vY3RDv]м,p^OJB9շ@$К'If]|i[)mhxCU[TB. ACjM3%{5LJL'5KѽD })FO` ]|pϗ:.A:CkF/#+U( PFw9>*"R=X.0xfiNib ` VJWv"n#7]P v7TK tK +9ůs zNSIJ.jݛ6 x1oKKҰ}[넄a3ZK뤇t](n.ׇQ&H]TR|츊ud3-/w6HGX*ئ@ޢ.D(^tՂLz^E9ࢧ{e~ g3^>EQn{jvANg7.-/rcVH\$|X+&K){c+nO N0~P^%=q1y1#L`ÍҙUVPVpCp3|tUEU8]Z'?c?O>(89@Eeζ5wyhVB#Rx9mkc(p|}>Nf%P:~CMR?Pis!:O-v׊f]8K/ȹy0+K?\ w\h96Hwl@C/~gr[Cw=Bmܸ$;tWmqӒ>NrW *vVFf6J>;x Mt`.H,0FnP[mAF+LagxۆCt^o y`xF9ۤ/G7h:jPW7<,CN W^^Oԯ!'۔".&J+%CpvjL0xnFa&[]C,5_>0I"niz1.R`p@ӈd 9\=4y3ߥ$srF;;z; Mh!bRW\GS/xJ>iڔ]qBcԱHԪ1KޡvkTW<'RLȀ> u9=w,U ?RX[Ĥqt*G\qi{Pk3(4-뜒f/$hM4y/!MBnMZ<(T9w~8nSI+S$~>un DB_%#f4NS 9-#4o?KלW\<3y)ik?^~>0{<AWM48/IXZZRu;[ Oσ”}kh)Dx/x$#,Zowx&t S] 2%0fR͖O>q6`pE+e--tmҏp羯pp;K>MR#`~iz72r$ܢM0ԶU\0B4犣E9KiƕIz@b\I fM Ŷ]1i߷5INM~ r"~s /D!iΚb_4IADT"q_Q_BHcv1: ;̽6+Uѓey; :8.]nN&ʠ,ޘ,Nj}O8_s4"}ntmچ?)xs[|~i;#Daz:}]yKK/`xJ8rw]\%,sq>sԲZ&>5}G_ J/jk-;IE?/_P,Fg҂I ;IAiAZ9Fwn_]caU7n񔜮c妆gk]6ı9翽EΏHއwth;1vz*;o ⻦ўi}Xara9MҌvAj>*ݧg#-YNgt;34ف+{ҳ|D$"|'ks24i6QS_ChK0C[cJ@󴆍x"K(!9%mW'٫Fekr2$*rm3r-<+?o{vFnTܠ m/Ԁ,firsz&Is Ɔ K6C7'$|Y!a!![==PMvn&py6fNLId+5Ѐ妳d\xUnwPOp +r ]Gڳ$d17z E Eܧ oΓK CTv֠/6Lu}𒡰PxPԄ_}7<|wy:VlmvVOC~g6uo`njNzz6Ơ/4tV]ڜLnm~VOc5/ +cb=4{ :CA: CQpuCDAznTA_c(@ Zx[xᦱCx +x$j0Ca-~ cB_􆢓6 #s&v8pob_6Up_ Q|k*0Hgu$uXܔjnZW0q;=k~x R+~69q߭tuN zQ`, =SxQtC=+=o65}-é—Pox ՉFX^sYE n8؇V1P78q'{l ԛqpgm2KC/' ~މ;캂{uRNl"ɲ* SY`]QDm.9ުpxXEi4L9}PTKH6Pzƙ9lBDзjӈQY vssrB׉jCb$u2y9L@m^XŖ,M'fBUCsXZR:єyyl653#uosVܼӢx 5j4Vvʾ# S  h%̧&6#_tW5x5MqtSW'~j "2 NbnP--?ւ ZV[\H _ph(qɉ9ys2XiFn|ReM!3sw( sgKg-\1VSqlj l5; oČ <e2<0g:J4|-#%F䋐̠aX:h/B2|62=RGX!s85Eƥ3'0BjSOgؗ>s0+'nϢ9>„ȇ>OaܗId=rwF rY/h5v7k*":7,EȧQk#q.$)>ҙ|ޔiJ7w'h/fl.τfbsY,MdeicC>GI)«7 lQDD䆞!q4;3y{Yϓ[(]XHǺe=`MGgٰ6eH2$ܙ[;LtXnsEB"o.A͈> ]$_d%GMǭ[(睹x%kZ<g+S EĪHP+n%8C6/%Qf8}U ߽IH FqK'&*!Q3@/%E>:EI b_mRTȾ^&z1bNj- ign~*HRkѬ<m˚/@Z#ڍ 5%\Ze1lTPY\Q3imXj*IKۇ3Ȥk3Hӆrׅ48+YcmbhLЍY!FQa'bGJ3wlvWek'r*ja)֮5 UęA{~dWZOT Az(_Gؾ"noD^78sY :UbUOj8E A*зvp)VKq#93@n4]XLPo!_r^MF+ W<3݊W5$cO$rߧ:hGHLTfc:w%|0M4#s~к|:RSv+)K 9%C#YIܯfY"Qv8,ڐ)jdiYcȰ6EͯbLCgX Ȍ.'V%rw# ޶e5^5ly=:PxNCO|L~ 2YavVBkÁ#Wr͎ 4]>h\xIt#ecGyn4t*k155tHH<#ppΟg (ށZBF?7(ߛ0gF6"Ɏ7suaRS:P𼡰|t`N* ю6ɓBA7w$f풅}zGsBxgד%$4qLFЉ@cgnZ*l)t' rdM%wҙ?0sONTU 7;.qfj.pr-@{ƙZYM259ME?Wh .*RIGTuq E!`Aхxz!?GDq*c3\S>lac QڊC?_tJI.0Zj+49Tc|%=Su@xGhG$? Jo*<`7CҤ |eum9qZ"}x5"ؤucDOU-A9Lɥ:|sNHr!PU1;q]\Ǘkj':2ބ^>TWj >rzaMhkfP*]u ?@}|EY)<2j^e}A j۠q[x2`ӹyJdU DWՎ P q(idtc=r̮ wȒIȚX#y@G\v &ɋ$?V+~t%s]+<.mh[XyeCƪRk{W:f!K0:%Nr"?ư;Ҹ= \U9k #D>8EӴ$yyDfI؎!ח+I GmvĈs S{9_=A\mJd[յ^kҩ#T%M.Bu4?7=0/#+=p6'p63#u?+]tVȭ=n@,MA1Ӈx[m8_Ihu \5'ˑ_QXGhǪ8Wy|,cC}w" M׵zq }#.X+QFvZH7ݸ;FM*4ga'7s/:Zut%놊@$A7b>x0S@oxg&! ~29T*S)/Ѽ 6:fM,az`jl"=w_ԉm+&sN>6&w(\ PXGјtZNiDB 1IĮOc+=KINLM_ԬA2rn+K;Wʴ9X]c2(,Γ{D<$VIxSopإ0YJx9woCd_F+Y~ҍb6&vU4KS8ԾG|\jayS:iJ=O K ar_I.!pK*ϖ✵|4L5NlICCXTmvv:I v*K3#3'VX,`UJ쉜 wdPvP wpzۿXE\Ws~Ͻ$x*8%e*jl+M 2IVo_8V5BV[t0}I;0 3Yrp/τxWmQrJ3iZDH(>d:{W\ϝopވI2?=;/szW ˭ -)# 7*!#' eKᎱk_ .c,m9 R92r8yt"y+ &cE$Ԓ39Xn;ܣ l3DJE24[!T r &FP rz=[8q9LJWB8ImPކàtqaa|c y|s E:jyHw{`,~ebcꮢYw:%&aVbmc~+| ~IC"mi,KmBz*Oң{%nk,@ƒJ/3'-j {Q珷o2=-Galh;ߨD+ɋš. dVX;u}ŸUvBuuDDn &KmIvYfZɊ2$rQ nΗ#ȝG3m~Hg!AIc͟?O?1M4iXKWRIc4 X"l1%FW'o2Ʈ.,R.~Sѝ}8n*bNhW,mvF6'7虬L05hu$c13.Z kQYnqyNgZ)-v'FJnzlyPcGn}{x?2fxQ\z^FP,®^R'E/8ů¹_C9=9Wp)_|S3Sz5ZRkA&&Zq:omMӦ%G 5۵(x`6oOFnڥJGMڜݬ1)fN 1A"S̞D;o5kMdzvw݄ZGlwp_pMSw֙zIc^qs%w ~tDZս!uvhj2I՟Ss[H9~^2ba b>EB/wx;dk-|h]q(}ǿ3UOI7$nC+#X/%:0TƉǪ'F8|9~t9FYiYOUbP33y ј*2Dhl^27m-[dvŤY4_6'ɀ ׭X>cKp0 VsNi$4h>s.FٹFgeh234e>Au$wڠxJ|@MRJ*aVG}__*Xu)f$[fQc?,8`4ly g QC86G8`U-YǂD6❭N 6X l :8=Jx۲>>ay6VlT=P˙z ^~s"}.EmKηɟ;N( }$)$1+N\rz(0{"4FE䗤)X0#`$ME(c \܄nR&|=&;L ,K-A0 M/0V$^\o?oT}?Ȑ1ڐ:- p><L%spGqN4๭iWòxT* 'UyHOY0G44Ms!V;CU6dNRMt},d<_yV&mphZE߱yO7(`/>c-BY3s; |}`8<JiFF/&rD0\h}5ɥ=_A:QKKޗ|\IQܗa;r|@벭d ~`_ d`K<x5`^ ok^UGJ #CJ;8,kWDw ~)-Ay]q#ZvhZ0,Ln#0#<#Ep. G'B@yk"p4B~n"^"$҅kKlQ{90HaEkp`0h tLT19 Jf|f=c`͏.1J _oQ(y.nGj<0uYSE?: ?M H0\{glfГ]m*hĿM碁u`E%P.~2B.c@>Xk}0ZWwSFXؼl)a"ܻˁ YzaP<(N~y*6%8/+#W^ 6) ).t@q=hz\I15-0)%_ܽU_I  z8$DJ[YZ12jmڊeTOj2Zȓ'?mo~{jl6?7=t^Unƾ#$ˠB#y2 4:tFw[rm;X j buc-1+`\ 0b=]?7x-?f^ut"DKү Wh@p ~+k' ?(_w"wS\Ҋasxu)9n&>o j"V-&YBx" ِ>s4cl> vWTOi8 )ۍߐ p)HJc$L ;p['@e/|3{H/ G)WKy7$B{,vtL,ޏZK ?)DP<<gk )uLW+b /]ACWJ BOk%qQJUݖ'v=$ '!]i'"2_phd՝BC4(-jʺ?nR$$Ԃ@% odb7 jRNپJYћUi ? bPn>:f8B`ʓr֟%m( s+P A~LEؽ6"Jj7Y6a4|ڂ}xPݻAir@,S"==7I*ml6Գ H_4ߤ=\!$5gV륜R%g* G,3Uؔu듢a3ڱyNkB3뻰Q2lV'>|1psh< ۈ u>3|##pGlYIZdEbm;'ڰH"A^XL7er2+}FƐݟouH? V+wmC7S} KUA6UԷj/mS_A]0ca?D]CZߥ4u,w`#Aj)BTvgj?s_< Т+"$&?[4ZǠ=pߡ`AmN q . Y9X 2RYR(ͯvɯ +8C^M-@E(l;_"5zmYs[aj,H{&Zk+_ 뼃ybׯ#hD!p/#0)V~AkOP.!KUm۱ƽbxt"9 ,CkwůIqBE6R, ivDŽ(dee# |О-#9]Y Ͼ&MX`2Wv r/fDX|j'"v F?ނʆ-)}|)W[:OKߣ MtSOcq:[sqcG}BH7> 7s*#-d\hJ RЧxbggXs( l,z; *D\jJ‡|C~K\ٞΞSg23t =&#;R0)@zN􂅣l| Nv93ΤI^F?A4AN֚4y.b~?ݠ;'Gz2coVBg'?o@$/$_*~M" ~3 ?Sn'{DةZ=n<  Ē6H IH;H"5Kf׀Nv|m,ռE#|>3fI[N펨U1#Ad('!f9j$ 1DT#ea6 q2t%M3YC[QR5̻J#kS]H{3+l,:Ya$ 6 q<8ڎR^0z jsElvXG[\u9kjIPn4^վXS9=*dR ~ /3^*-[DLQWX4yRL*6Vֻ29XP% ('c_p SaܤjS'[3Ak sg8B/}ݙR+ۆk0,Ϋ@CI̛SԆ4K3|} &iә *h]¿T ҈ŋ+ f%}5q¯Yf$=w db ]~ċFãi@TK_$̓^&_ܷF:_"?1J^2ofUVyY3H +"Dy= 5/XQ1rAL{!\+D }eD%P3T0P(T!4~r9dAF$N2OR @ɇ_\]Șa2D=#9szP)b&+g-NZ g҇v(Rm ̽0K[۶_fkw;C)'1Msڟ8cEɔ̼f]f5'_kXA;5si mm[Nr1H0 p:fy݃آ03wȮ,fcL"?ľyjQ2Ni< *ob­^-/3n DLlff<ȕI`y {z׷ǘd-t` 3xQr4 ]K=mav: K2bԽl+XP/g31p,^;Ǒ83-}\mǙ0Q"{mgVze&|#4GO\+x;0!HSGakTLR`Wu4diL ,Å(&#@|1^7L NFobFÂ]L&%n,ǟf $޻08TeJd0n}7jRYu };='O0 a^ѕCi;ȡ<# ɛJ̙ȡ!v.<BCo&AV[!N6,ºxoK9TМ2k79$ۼ~0įcF>i)RP>8JaYWFBs՗ê\f+yUAw\6>=h 0)&y Z*7#ix>ǑMH)v MEp3L2=eUL3/FZ__5)Ə'ݹ$KU"bsEsv'gg L?LslYtN&@8,gkNYsR? _ø9^TgoC (dkN Yi,%o`(=񊒦:v՗0SmP۞s *%_q].APyEL<˭ J1aj13Ǫ!P _GTfakz?? WDozozfc/܂jfR\񢇻0)ZJ(~Llayq·*RáGPHmg 0IHQUY*V1ǘ$l"ge`Q&r}ZO+E4I="aC@1'ARd']@R纀X.chD7NħmSJ?WI ̇/0UxF\oY;ܒJJxj)FgH4v; [Lp`2fI8=IJVHvM l-}r͟R9fv3fp}+̴yDzbxCi~=<24~xSٲ1zȚ O&ފ#TV2e(c#f}:UxU %7Vd# s]ci%Χ8&Z%+CT(sUx2 sxQ; Ũr9TE*=/k}2}cy,~ۣ "upifDk}?9A[/ }IE/1a:R,RP6U'@_P8I'͂,u\YS`", Dl!#NTO'GEֿW~7!xQ {x 5f p$W.Կ*{śU/fy56O*HGb/ o3o1Bh瓋_PM@̢GZ:sx;6hʑ-MOSV!Cv+7Lg"|]fz9`~+:3 6%.c}b~Rd/̧n#G+uch|ySO*B:_f#yM^%u*ybķ %f2\vѝK}rq;/U;Yׁw#1IJ-m\|{EsdNf&NP@ja Ew:ͭ a ׁ +{:cG ˰u']`K5 +17s_ǬhLV۱(7VLhz=wd;c^I{w%R51YP*_˂haX{&WNW$c %5uÙ3sV~՟"]䪱J66ٚtOg:n,/xLQD2%_g"B邡W 9H8C}G˽Hnĵ@d{.$rF$購$ QqH F5dIPˬt՚:iqHN>H>*S-[lUֵ\J9 Y0dy,m~v#3q>Cȥ&B*Hض~ˆFu%_LCxʣQO},!]E)-!xH%\Fb>_JLӳϿ ̴ѱkEG&,)E'<.gۥzj/<7]6U;H$_Jg}Iz/V&_YG !3k?!A!,%R꼣 1{;CTX?*՚/d,eMo|\bo7Y4$~ yYXP>/psߘN"|oL2,"b{zx]k,+l]jf]E~̋#c?$IGPB>э(Y^,ǎMj{ -tL|a:J򤍈hA֐JOLv+P!ܧ#O?K'R<—Ly_,@UpY҆9bqM!" )ߢPƑH,\],u#ފG!ɦ:دMA_m Ld~)?q5!s_Q/ViR.CCYdxrd0ZaB8grc< C{//嚜Z%8OQ-m3*1a/_ ҊPnr99\GhJ'7QXW'85ɔl {M(4'N]/D =(Z4Bt+ضr.l77 Y}ҁp=I #ܐbQnΒa:O\gU'JRSzRgU\nEB‹Uy ]C7 3XhdXw`"啞pA:Ĥg3LbG!;؉Pvf#}0J]Y3])e]#汝[M2:evNW=kvrT]8bo%ؿu~ l~j 6I=F ?t#u.+)خz-1U7esG͊[:W5i ${Jx+ۘYeh_v[7>sp(ӇQ=!{b0̟Z!anv4upŢĤVxE|ͥCPyDԕwكΈmhraG~TJ}e㧚bUaڿ\0bRB}LTV(~`NˉۡB:Qe.dw'L9P~W}~S'5KM!MtMsqt)ܘH!N( dvd M#PbDBK +z-wK X\h)A̩w39hUyALgdG`vLkV5kR@P.tUڒNS+oQ۸NN!ܙ>|]tjDW'l_c=DA]WR"Ba1B%4bzLgld,r\‚굉omȗ!Y ~NajzcWB~@,)F+>H G D'=u&d{~#xւNK\"F >zՑ)|.0L t1OnܧY0Ԡm<ǽ9UwQ $rUś-K7M0~fc=׎$݄uн ~ݹdgWY7QO܂&vQƜ!<ۃ}t?E$F=, "iG^qS|(!јRt$ELI'Na$^NCuv 蒜H}4gI{nF{@}Bq0r 3A7ỳ6[>tȲ<\P'D}hMvI4 .7 MM{4m1s Jݎ4@|*{3!Q1\hi4m&|D˜P&'fIcT!1 Ūnw(G*`(EaŦQ SodJk$DjdqԔmK,q?Cj/*~ ŏ'&g|+;Zp/ů 7Z IQfxxX,`Q_!Q|6P_d W=};>w{"r u؆󰭃Z{5nw`=I_K<_Y'#i?v oa84vOr7.00<=ƒiuǮ F9OʪH?h* :bdFPN c%`ĻA4uGdK>g*.1Dʅ!Kg$i!| Bڸ* XN_:1jT9oTXWJ*k//>V.HrC[sKj؎SyV$p֏yVy`N +_XaELv}QgR4ÅPѝqarS$TثAcYc0*쏞u0c-+ɓuL&xh}ɒewı$` bOȋS3VF.Bg, hMU9*}6;qS yG8Jc/u)%WR=sdcFcsuR ]ξS&&fٴiE*ʮvztsSrbĎ)~8"܊I7&9#<6=?nՉ>o+(ntm`II~\WB~~4QS΄2;˯!u 㖿8~08f%d0;®>w~[2A;"C°QsOғ&P dLLCZ@}UvCުuQ}u53=7gdX z?lvב!F>=Îh^a?zɺ`䦺D>yR2Q濘;yU.~!Z9P~AS&ŝ[&5e v !no"p;#=HIO4 6z/D#XRyH#u{wBkM/#K+hB1awwu8ecsok9RRC[?M#Db~_" &!^C_Jh4Kxt ѵ`EOX@=is뫳" e;IzeН `0w`o~FN4F,g#rȓz |AR9qS2SZ*mM"(e`FxF+.e + Y/XQI)=yUWĕ6/OFd1f."-(S/~JyY1Ρ3&Ozt17[3rbTmFbsW#g)52:;5T^/ǖin#] xe2+Ŭ(}X(5{Kׯ2mV8;]1r#=1ƯUhȀ@ɭwX62[l~4 ÍЃawo_z" H\RU+g!0t{NGQt3I<{+^T!g}JxgoP]WfV]S.S.QǢ8v(w'IZFUn"w(A5^X-*ax-ʥ5dyT$$UژXe煎"쾡aTMsىOpUCzwlIv{{XA<-E_'>J$N1'4zT9Ǔk[ b} l1E}W o#LoEfQpb~>3?au\s:@q6|˻gg*d5*azD[qUY#LSGV*&-DڤOTƐ:"ԷHkm*^NW,hyn+踬)@4x\n-&hf[`/[]qrɋ\.Gǣr;L.y>R'DHONzKyvFyso`yQ/l0+f*fm .Y* CCC~F5-:]nEѧד$;=z4w%`t w@jKi቟6^3$+6FUad1L+"4_& sՇ7و/;'%AQvc\bC{%UsGE"_L& @ )TvQaGLMn vz"LoA;s-y6 ͷ;oȦ 0xgAjZ}R,K%YD3D0LUfrJC \L=Isv|ý0a6+ ,s_Q\0g7pt$H0gy|c ȎTpT,1qd"ס[yA&dKqb ,w2[:+SP?7qBbwL9+ƇBG–H.Z>P؝f2DRif)NjhXm]! ꔭ Zgpz5eJHE |a69E:?fc,x޺ aL ֒O4u;֙z<%;㭽21<]Q9,O#qumrsޕeo]muC{k8!Wxyo pyY!FVnmzrRZ2<\<F]BhJt1)>gF-TŻJHQt3{wRDxEU')^E.W׿"PHŮƭH![54rS\50.^rl6p- kj2Mc 0k#ix9˧G Q}S+B4OpnK6OEAauٵu ]t=cc]&Mx@Sl&G4 1 W]R< ?,#OUŽ 3[4wݛ]SlA hM?Ş3PX C8Br~@%NFUK$Is/8r"Ɋ_& +9O-@p!;:*^* 15݄>FΑf!)S+։ڜk}+k,Ę6yJL~/#x1>݂XQ$؜׶Jp&e/\do 2[MҘ)qoFV/{8ocb1,PҌ$_F tJ++d}D&5C yrhHxZ"MٜjGo,VM7=TGw55T>LV;0bAnagНܓjO0#[mN2p D(50 Ұ[&vd@vMLk*2VD cʙ%= F)IYCQSYLRyvG0K?D O u=3ٺZpD m۵`E #5~,k- v.ݰr)P-xuk!xfF&,V?T->4dث W Qhlv `lN)'%@C4Z:~1W,ef" (OMo6mT:{Rl:tpCnVS :g+\2_1\CҌv +;Kx0#6։`1GC,"`[yF|Cma]MA;H/AT~$̲]M<DUQnsL:na-)=Քf;25@G ep,1,tL[l ivb%I"\-W&m]l:Udy6:yz SiTDQƣC.rw3TGhcp/)'yH۾DcS4dnq(i@w ccUKD1l8d1-&(w6XUcߢoI_&{d0]T^9YW`N|*M^; :#^_B rRZlqq>Rӯ%m ]Lh(bJ:=yysh{hPSQALc.<3N1eՁ+xFѿJNjPϤڎs&e%u1wQ0 |hq|v]JUJ RVT2?=>] 71 >t=a'i'Hh% 3IF)4ON0^-5"-҄"dJ߆PυFQp?ʆp6[*k&JMkwػξp \Ƥ&3 \+ef*hSGT{\?X;;D"0HL><#ޞe̟)NZ~&8iQ/fۜV)pLZĈJ}6+;&-5T3Cd|ƂOK= 7z c|SrG wْ^1Oq},FduW} jeلW? - yE " so9o sµӍ RLR"cH݃s*\l )2ǵH.bq7j.۞tcԁ3& t毊=L8:dw{YY]dQR\]fd+{A8,$;qtV1<{lWL9+X(;?JCxeo1Mju~F@q"RzMa|C Ѽ=3U_[dTk&n[1iV`bc |iʝh@\qףLꟕLIG=K+Kx*6- FOC&Q`2@n,0~̸8SȻB%xc(x&Fn?^alLhU$+@e Xa Wx''BͱY[nϏU{kl0~HM>^dDiUF2k{Jn+|mL^mLkKո!v[Wci\3 a4[˃[cXuJG7i|koIwڪUuI|8nIp'),(BhV0SU[]C 2J[2!̀5P|(51XT^Bdv.9,*3aP0,c7DM./@yp:gz7)?"2. 曍MF1Zc*>}4y0@Ӌc݌A`]Vjm=.RvPŰVdhyz HfLxqgjjyx4 /o4FPkW2ۈQ(Iizo@vh7;;վ(c~myHZW&z{18"/2n?BFr豤;P_poUz.ܕ{=4|GvJG;& ]r13=], ޱŸ{`Vo1 [/g$?n5qԃ@ui!UӃ52D6HNp8I vcڛ^ݻkLk-7%#6gl7OCL ̦]LYHVdK鋝L3sݠ@~X9[p C/`@2` ƄܽJG̒{ɺ&1԰sD{ϨHXedŢ2z;g@8һL뚐}+tWHųpL#%4vym.8ϼk.|X׊v)pCF8>/BxZ1yUZHLc1-(âO ]h$'v¹GQJs5YۈH`&LN>"j~w%WGs{٥DF6=J^Ƹ񰑾:Ɉ bey:1򓇍##W4;5o3Xu V1/tQpM,OșMFvQ,~[үrL+}@5N. 0c1cv3^l;Lh=aBҫ?L&$}1aB=ZBcT–'~pd jhddAw!#4OK"gbSF^ETI)cjAT>yΜ6g'a֟1.-S>D|D-ܩ{INj,RvU+fG$a}Ճ`uNxrیbNEHdrIX"JMAcG8jN^wfXYFY)Y'IN;Q&K^*c M$;SΦ炱ug\[EX킠LpaTW78Tɯ0 7 ־b ?-:jm,d~5DE=bbLZ@DIݏѿ~(?_6~!s֡(#}u"}FUT#Go=5<#\9bE#Yy0YކMN$Vӵq[Y%BTίS?o͗x`w(GݦAm1 q僞#}FxQ7gALq'bc it%•m2@ȚF? 3F$ax_)ao,Urg;Ɲp?@QvO1n˳ju\K~"Otz0>~Q%s7G~VhsW_Z[qrAOWk{56{埍GW3Os:OZ?㨥 n]+:C?6ӊ@=220wԲĕ+k.+-3cIN9eu`roG*,GeLQpd98 *e}'Iᚷ g2z6W[f4{u/ `N4 Hj4./3/*;3\K̯jM-N{u}N65ȚTDF0q1 g2[q/b3Swpÿp/>mrTRAw2OOvkKsA @h2G "56pOP5 Ӟv0O"8FfqxWkJwZ8f ̿8`JmUp~;#(wcRr&yz1 xeNEwLO:SܣK(4N%'j8 Ɣ )__!o7O}_A#-#23v?y 9*eÆ%*;QQCG:BOEHRd:?6:#ADX'ո|8$xP>l: 7 Dand]˜1ׁG\ޣd"u+k₣̘:%$ |=-G0Zԅ rn6ض.xg/.l2t\W 4HE9=ġ;p X6&EL?&l!ۀ'EúRU|7r,.1/ W4ffxEDk: Ht*r׿E}Ft}@bRFGo{$cO Bp|`]pxg T`IV*BL@Ի7ETh6 N:r@  pW{3K KDHjH ZK`MIp$PKWLd_;pEff[V(_3)恌3d:Ŷ`>6Q䭅$3i*I0 Ӓ6BFA{yWw\p|^ޖS$7n 性VУj>XDf}^9ypS.1= <0NQRB ÷H%%NB..jY]Twu"lQr >¦qBPrOFHP% ,@EcmHw΍W,䗢Z⨐"95EIY0u'*ck P?O;kD}`SNd =D(V18^<{?z#C%ȇ^&exH>Pk ,7L_L4Fh 1x)x܁8i(1(Sjѭ ȲLnO䴣Y>-0f̀;fy:#^~}*Dسx9igw瀢Y:4i5B=dm ~8@ =8;K_FcJח+% w)Z. m)~lBmϸi?Sc~h^.ս.NGJ( ;Όn @1hY7KiH5ⱅ`sjx!X'USj ȯ0<4ê 8~kx(, -JۃMx0O,1B$e4 `llq<T ߖʌ/'j^`ٍ] 6`RthcY`zπ/.y%r/k8`(*/,ZқMŘ"]F͎ڕVP\,+}3OW<~BO* @L^vXW 8J# dj0!:$& Ӳ j,( ׀" J:2aYNG?UgHFd'}vYZ LLߠ"?,9^R+t\Xmj]~aA: @߼ *cWl0UKa};A ܺ𝷃鹼 WH+q8Bì ` '!i&P.0D;AdK^)(8 ;AiN,}--'6[XHY\xC%]ƒd ur7R fY`ȡ5v7JߨoÆ5;@(x ^9JB@p冱U`Hο8K ƝQ#V{cXJ*neK:42k:\8`7[v"&sT73*x w1ɞ"–ju##?b$|:r5 7LT7y&‡pFj>Zpn{:5ԀGE0vܙ~ A6׽`f]5In =|, Cؤ%xb:[AH=S_ی4jMBUc./1>gX  퐠hs͐da_s~E#-{]jlHsOmW{#i3}ȒRݷ'_98du]_"[VfzcJS389-%-|ޑKk{d QEE"V;1 -IiRU?#VElU+W ~s]J]iH̟/փQ #XQ0w͝ueصY\&vA؛ kEE/ޠ$ʺ Q3lτ_8ކ8kW%Op:6XZtK8WyTgE2yNdn&^ L{P:񑙱"Xdm$s=eÓn)Gvy5H.,;(t :aIeF%ɫnTjO^.z[vg4tfzlEtiF1ޛ[TjkᗾF1$YlZd꯷*6,z.nM[̰WۤgKIȰZbI1eEK%Y?a~Hv]1##lAv`F2E CMIKOl/[D\T4:犖{J.}KMsr 92'K;d~|rp[Ǽ6J_#d.예 b92 Lo?F΀PD$~N&nfbr}ieiA.yОv= ǔ܅dyq=>INqG]B+YZ2L݊+GLP :pD+V2D[噕tciUb84s̍$Ô+BwqyU؊d-ӌ Yd𖸭*ޗ΁O{zX.dF[lFW{|ksOpg^ am\ԦJދX;ҕRZ&f1YAK# d]4΋1/?tطlys>IPYFUY/!~Av7 W\u_ dG0-6;_aa7Ʀ+cgePS]ŲFEWdq,pIQLK D?Pd`mNgbޓ֊K¥~I=OZ7SЏ hUYR~Z2xDw% reC0C׿EK4g`%%&z)wN l`Ɩr|]@z.EoBf]5pbcB6Peq*kLYw$ҥ0{4'$_A,Kbmwei -8ȴls4_SvQHnOcjh'C\A"J I2kFQ=W͸k5op?QADLVe )B6,|S  oH 2ŋ$r"urxy[xAj.dbе0 M0$rOzedJxP1׿ L/@pǷ ^Ѡ#79B$Xn@ 0S^$rff{*LBص yҩ 6~EH\d9,?{ $OLǕӦ%mӾ& V=ia;`(03f#awAR<]F>*C[ )Y׈1 6{`U䊸>&0j}A/oĂ0Pdգ87lb~ Y y,|)5Z=v-Q~Q5eגG١*z?yǐ›|<WS ;;w'yQ˳ &˫'9Aeb7)ḬgE'õ,^Qb$Áh},O:%iB5n3 y|k)#w~[\5RitLf4,Łڣ!ZLNI8!3Qz#0{hG/U\ޜ)r*nch~ Rl$o5/;~ r誸x`J 9^C O2 .G܁H{{wUݎ5U.{zr4hTk-6<22;Q~ nT 07\PRDřx2uϑܱ^ >c?p 5#1S%V~T$&$СC1?ٛD56]BbbF_\^Kuqm /@N2S?iIwUQUTe]O$w9˷M>Κ<ә$Gp9EF2\*PGkKv~S]ˬnkc՛u;Z^rձ7Ia.f!C;e1ri QEe|[QV3oST {@HQ9'@>QǾ|vDHܸ&Q'[ T?ihDLlS',`$۟?[R2"dI_9V%pX' i@KDEH&jU871u]싪Tg )CawEP<܋/!-92~}a*A:,-8HF`œE\Ak"$?d=+w]6O,\`=/qeFYV_ӭ4faAZOKnU)AsH+Ψu[1NbRJp﩮?Ցe\_{v~TVmUýu {\ f4bo˾X]Dd"̺:v#g$]f3Ap'o0-9'T :*6ljpbp!/?rX_vg0˧48H7 ]Zn+rK~3+0k$FOL˃Ms?J:lvd:SܱP?!$G#>;=9pן$$}~d H>w BHRnDϛɤNG(TpU,kH5 U&#uNҬkY ' LU]k QfEmUMN* | NcŦgp4 IΥUf!ɹ rH ?eU`d§EӁeyŵѯL˿xY)0dbAIj }ʶ\B 0RfHKNPPŵj̃+kw7qTXLKaw;z 0mZD]4wuգB((Fݺv9c2TO.>2괨fK6w삋gfIHLtoL_!0sXcU|c`4ŭC/^qH: :W2r*-1H i+"ԋ X HtO3D2y yBၱKpX'wo Qh*yg4Z_ kaT`ѕw[sp`)fyvR%* elh28bEKZﳂ'nRJ^s89c 1ǘv⪱HWPH #)%-z}#Z|'ZCA#D9k:7Cy.׆uaZ"8F ű|r&& c+[c>]|Qqșoj",&6r24ؙ>.AAe&ܴS/Ƹ 麣9YׄR RbcTޔ8eXE^$nx/#)c b>#0~ wZ;kN 0]P!R=NcDN ~VUUxxZ`|'2~pPo5g2d`$Et حӨ4ڢ<*.i6X* Og&&KNMH 4Ah {L͆s_rE9Y sɩοY6s gVn d07^M \Db\%RrkSxȯ _)UsfM{j*﩮o2$(!%I4ۜ T%l^w_ypoݎLxg3N& Og*;yCw`;E\Ou%_ Ko) ˉѹt+j$IsXFeRug8 "SjNTVę8nRxa  {9Wi_U{WբݍKWUv}Ά{+W­w助)OQ0p{mWiL6Bw;s9ayOH%I -M$Ќ&2jCS⮤L>%j9"Ki䱎VWXKL'bF`raqrOf)(L|*\Q9/(̯G\lhG\G 9puxq F=]@a\ɖ;. d% %$a$?!Euͮ ~vnThf wLΆVB%ma݁( Ŭ`L >% gkޮg63r=y'ߙ#M, &]aY8:7QV;Qt?^L@Ƭ@Qis1јn&#GB$QM5M$HC(3nE ~wRw!p\y9RB.<071I}̎-K3CQs&U" !onJvqo?w/h+lP(1xzExivJCerGh(U&Y><0/\nXq% ErQb*ޠf[D#xxB8Eْa5`P7ߗ, LA )ȫDČܙESX0w+n*ô;4R|_~,Z(z\Z󖺚{Lj_WcHz{VN2y12-м~C*ofΜY]_[;}I[n50:eMui/Q&yTYu HkE$kn'藥YhЕU1 AM7*>l bXxy}z5S[CFP3bv̱ӫږ镵tψvK3֞&.uz0e#H_:7>2g Iu3jw k5! {5jp9 EGL3Gϕ|A k!EUJ_L5h@GR$81|A͐6(]ӹ/jzGIrD )>%Qt>v$Q*(!?yj~I |$ˤlzW=K,Z=P (FЭH}A-:.G9n 5, uI£O.RS L*6>A_H,f 16&ӊTڕ1֐܊*KVnQuNh6˯K2U>lM֤U^7w{{kBC}0a2E FJ/RW|aPA4&Ӿ `k>/`H@K΍_LgWFtMXhUP1[Lr 4#u"T9O<,g2վ(" GUz50C@1~HB$nH O +$`@61|vW4aʌ>L!(tZQC+cy3ѝqSܲivy B'IC\{n‡rtʧCEŕçv@ )I~aHFp&rb Зg. CsWvk^Q҃؊z&С_y&(X0+QT-U5X0]vJR(9ÂE0ZHQm(WWOՃaR6ŭ cUi]>`Qm*ޜD FӁ5+=2V*!)~^b{&k8DC,Bpˆln2`ZĕAs LvڗyW`7:U_tOۓD7?#D ,?LIl*/IrrjN\W49Bż FWޙL]TݟDqw}Ll=pg-YYY5:7q;;}6}~uR>$ӋV)R q܄q$tN_V*lť) m Ί\o%ӓ.Y^UY\q44ޕ}kVAH!aMWe-x4cV$qyR˪% 9s) ӣۯh7vLBԃ5i>`nEKaC@Iny Gt@ 1Wդf Cqx64 ;7  l4eӘ2EW!YT$%/tA DXZ\4^@L;.m]Pǝcqò.f}oRg@5o?I5& Ŕ}ˉw68 +]EN{+CJ!ZBaMdJ0cY3#F SaO>n\ YE:C}vAzU ܀J[(/䑗sA3:1"*gMΟ=ܒS甖$&zsI';nԲGt)lB_:^zn8B~RءCI":GNOuߠC~E D9z:z9I6(Cd Z#J88}!S!a8}ق'X."G$8yJKƑ,$̩$=D__WQpj^8![(MfМ*`|ۅ*9: +$IܕLE=؍\ď{#$"Ƥ+"/mER$wz3F- :qє*B4uAPӼSH&אsBOEJN2#LCΩߣ )> '+~k_NS6:(`}r]@ၷ|˓@u5 r7Z}6 ޥ;J d6#f醦xL7@c|yḦR@_&%L"@ᯋߎF<@x<RaN+X > A 9i98H[XH:TZ όEM 1ROV9qd˰QQn]p<ǬU[zFcRD>4|8AT۾'CҲx) !nx3ipmdu5 -gB)~ca_:y|'A)wIq^UOLeY @@X{٬ "5ٷzUD/wUU~,8R\<-nKU9\}6N{DeFMQy$y|7-V[QR$ff kMޖ?z+bѐ^?fy} yf t׊uU & ʲn-neCW7L;2?lvH#,J?*49{tCJIAď -rGuu+5&nSl~,M a.vi-d!)y$$y#Ƽ6s7L庆!(' 5-;` ܷ&/4 t :CoɜXDwՕtYuT;}y6hS8}}M;v+*UXp=%"]q@/˩Fzj=OuS7Ǒ0Y\}S\5gP-dOhaUM OӔ>[S7.zi̓ЁG[Ba ?mX 4__α8>l-s.f}4 ߵOݱ}4rk.Aү2GTatƣzZ{D~/}eY(ۋ' ^ɾV\u%ㇵSB2<-BSc]<{hmF}P\A)s Y.֤~lRuyx2ԡr~}k[xl/$[6-$R 9~;;m,6'A#:[ Fr%C(6G8Vh'GƧW{e}$w?E3ఱA!fI!$q[7ExׇRg+Zw܄OPAezs*MJz`@H[ Y:bg0=5y}•VWΎC;œYW5y 1-2N 0{e+M"0AlT!US~'to.\.ޠ3 h櫍OА=dJ4 I*xQ"s,KZ(bn+q-*Nԁ-i??!/(:zoԄ XG3{1Xvco$#0n(&*k }]zj96bc_;ҾwӹϺgʋZEx;D E GÝE`.igk;7 =Ck4paU ['f#G;XJ=F[N[Ŝ rI=4sep3wn#q|{`{!H}! p?CZn㌣y꫌EnZ,̞v^YY@a5=@ՠ74Fk5.i/U3l]^hlN[8]n ~Fc΂َU0`si;`Qy6b'K?g͝V*,1<& E%I,=f#, 5 [=ӎ Fݢ~:OP7+uhoYE/g̀Wƀ&X{A!)-<'+lG2[Co<ߴ ֩jğR/]܄ݟ[ GwgLF&ҔOrOIq\u3M} |:JOøO(l`c.J]aIgc$1Ms t_+FTxOR]4J\胿NQU+u? YM-"ֱIvc"]YqjhA.bл?RV9"G_Y* x}Z/x!Ө\=sW~+_?WzLĎgb{ =y).?O y+L şY)`D?W͈Qiv듖6|ũp1fȿ}Qh' ?2vC(Vc`scZ*ydb>6um+2K!,y,`M#wdÙ(^{x82lykg3Ȝd0ڌL"ٴL2oecS"T"kN 0oePKe=N`Y$0ڧBr"X63& Gvx9'u!&͝cV _H_G\䒼aAъ?4Y؞ zZ+~KJFX.# #g9$Vh+0{ Y5/†呶vEzW{C ޘݰP>hYź"jFd4s=1([hdGpyaDBI&*$װW*A$^H.X-vԱ-U{4/2$ہ{ h+dQ^, ;5 {TD&'a8 Izv`h;KC7YJ1!OI>dj&oXgz5PG 3bi3l6_F W;{L\=en;}9{4e9fI(d@u 2\dcn"HaH! &&ʂ! dRY54MN,@`Yoc?/'FuX`s*ȔѠ6ؑ * ڦL%e)fJ&fRI*RD (WCk|q6[HpPa5ijR3!6_CjR_CDL#S: d&LXM߮%mM_GΊ{HCyOtxTOb)>*2= yԤY]N7tGdXT:q&4Tf:X0kDd{s{|69Գ94ƈp7!)?,f;g|psE\K-}ZBV;,UFolhf=u8=*Pik~|ȸQ"jh-ny`imnΘ HISbu"s.e&>=JƖ%3u15>op|R049*b':Dj¸6 :-Eaɀby6R\GblcӽvNRh v2RČvVX"S u\'&x3+YB5ֳ;ɶF򷆚7lt1֊ˈCq"{a!ц͘ɧ7lz ."%ё[O7(2N_L& ߕ섹5ײ%<:RJ_P=Pd&*2+n0Xi`[1\JroNC}ZϮ]Frcg5\ &3=I&Gkxc].U]Nw !f *P.2֡ o7 Ui&V Y0 Ri @7 |JaMž Cٓ-;n[ssaU0АC_*v?\HU@H!kxP1^R׀(dNŕE߲ I#,y FhOuL=gC^ F22h)O yV6ٹ*.Ωe 7pj-ټe( 4E+w\5C!iD(BXdlaHTRwKOs%M}cs8c|@y5" W2"Q5|ǰFӖ ʠ]nKq˹a'R`oϷ&{H`bQ&L}='a&>A,?דJ6w0=/_oOL3l +'鴫o&^Udmn2{C4WQ굸sL/_"zXoִ9v![M,  b+) i.Vr/GUnkLXy6;;V.m2UeٺHߠ@IX,š1r |5Yb<ȍ!ɜ7 eA^ۅ1=~q'&#jػ*LAOd%$s*[O<5P#Co0zP!S"U}BŕZ<2sH ib"!"6xr&g#M9b2FyQi#Xn>NtreK+>UrYYY9CB|qm`/6ȥ9K͒',Ï1-c hĺDsGZL#n0;Xk؇;lt$-v6!V[xf&BAFDgYUuC7rcEbɋ.L7B]s%B%v~.Rl[?,=.\Ya}PVۼ2 =(p1wk_C&9FfGg^N۸sZnd>Cأ%}X~LUԭ 5 gY|\=ꯆu"V"VVZE%^Ջ `22MO=1}, ?!rvс[/󼪊_ZsW_fR(­?ճ͖X:m}ĦxD-U@~,!myqc>,sP&)GX|x|QX/Ht*aS쳃dkҴJ}τ~\1-^Y^s/_񱖦8Œ¼#G6{1C+bID˼T{'hףge]@_N+bQYLBuKsU;v2bA  sP69h4] ȏjv=,kVwgLܟJXms~LvV-H%ee"^0B0hHXĈ(-q<_adz^~Txůc-y![rYZ'e,$)QKSϏ~J !Ω+mbȮи YskMKfU3d&Fo0O<IucAR1Z],n'ȥIݐF4$>Ah9>]oWD1oAA&gd ;$9qyP3z,/Yg"m!F? I3ĒI6vHxH6y6wp11O1쉟 =  5v7. /Dx4Y {/?u_JiҐd7G&{S[*v3aՊ0 ,YOaE#?zY2#o(=4ib+~E&DT!:gr/iY 8-w/O }@+/9jk dXC.)FԲE0'DE!'dn^v&VvDjӖ+%rŰ%أ/z 4_GMJ&X`#|F_/t|z Գ7^!3{̊{r #U4g(T]ZX;"i{ςwȢjC1!G^~ǫa_C/OV#vW`D/͜&0ZаDn;Nf ~߼m?nsOEf8`̣`x} \ǵo< J$D/ q_,f3T"0( f^.Iڗ钆.}im6i9s.ӗ{g6gfΜ3sf{#cnzwaDC΄c 3OwdyAMGdW4.^80'&&6*faDÎ&֥eKHNK4lL n۲}| |Dasf!n )+%=x":11:uoFftc"DZ'1dKLM2%i ӎ&-S?sB+>GgJH5LL5;H:7!̓# iQғhWv؝D4Ġf"#$&GmL{,19%S0^ғ䟲sf-%sbg,y!5+xsBzFΣ ) iG-q_rt|yſ@]diTj`^ ˧'mFEMymJimZݬW +6?[\-|t+]Dɜ$5-5Ccl08STPeӎMܝ#GsjXL|LuJ]l)s4Gk1לtjpRki,|ӣMM9JvPLxPZsLL9utN+U˕;JA{wD) 6u6[6v>Zxo(J)irirVb+/ѰaGJdؚT @i))%fHgf)Ui@KUr2;+Lr&?%koؓYNpHU TMgo`ye S]} {RA/gR'L'&a5:DUciQgHQGp%T5pjaybqN[Lr?{z]#1Wd|mVc߯ JGQS &߹srF4> D !h.M`e*)+VʋLgU`S3@EkMeGQ2kmjn7v)  lD_n?0Z[ 큁n4ѩ^9T'V[+{V`2^6A*SuKykEseBTS3)2Ard P"kjo4WH#},x9ij,fTebD\؆ߗy=-TX\M*eUIH0LPFǒ >/ N4}OϘ=G 5A~]/Iq/y-@B,d#|tfJA)̷4CAT.Ak4/!p\q3m;  դ6Wjɼ! Mnz zLpCS]UUuPѠb7A;GރrW`m8k$tϚtjP}$byW 8Hr/c=!$k)f{q:/|o}IAzEWz^1z *מWc7,/@TmQz7d8i8L8Gﰏ2g?W?=VNwS nUxU( A4zjΛ^/習fg`1Ѓhw*@큄To]d+j =oU q%hyW0_:#-sRToD%Z#-Zܮ>Tp Řc {.,GW(&[\1įvf6YowN.Ƭ]4GRI%У⑁[z/.6j Y84|%h/\TnW֮ٸ`oi/ʝ/soF!=hrBʋS M _~!8R"Z3tw|G^l<+Ek ƒ[ϝBV0ZP*VƆ81[+'ԟ%rfYaKǪgz|,Z"$LCZdh4tV*ද׎wV[UZ7VY*iljv*~%{,ot֒Z cO  *HR\P ,M9ՃHRD%zE ^I\8 Mk6J{ӚGCy[ Q+!89})ZJa0 NOpu/6 ApsLx>F,c&] 0*o=6h\?OZ?xRxM \Bo>وd :#Os&z0x2vR ޔU}Xyێ"ΝAJ^2XHqO՗Tu I\#>(7[*P6 ca ))a%aGJ'o`ama-@ cRX5.D79Z]hom;NΐRe@{@p)ڲ÷;hSb ^u'djIpwX D%4sRp <\ߢF E1U9]䖑Ram>D^+@62?U8t@4JE6q4D%ysѵ+Z'V>3z2"JͤJ#m/ Oۑ>#̰~{ Q@ ` Fz?oZZOAF8یJw9cy ˘NS࿑\Z( yVU ખ[e4ie5BW Y oep41*1fc;is qPG0 A +i^S9*L PkYaͽ kuTp|À;9*>p7yhňOn{)_HEJ^!|wgN%9-CJ5}q -pssû)|[F4UU+âE4u\e-9DTj?qU.^>k:i:;\"R zoMhm2u#M-W ܑYK~Ts\]b**C;>jV< G/K@X)7:tЌsm`$#̏. hdiD ^ ܑ@Wi\yz"{Bw.m_>N.EOx?I([O NJ)%HůF !?4o˥;X[i0Z] =TկN󰞯}mAKrxkS/2ߌ+k*.J5`'Z*$%:juُGmĨds"ړs,!=$LZڠ eQtGΩe*2#7.x@W8[%㸫pÂDq9Aݚuڐbpo&0x F!\GB5Pe J&VX:Y&-"݅GeHa"Vl//ԋCmrv  =HLv|U7zhODW!S! oeR bkLGT7QnX Y7O 8_HB\cl*kTʫԃޞ+1g9q*"z\{)s'Udii zMA- P2쁃^ ?#h.P+?1Ah5J VsF/PLgrMt#wϽ:ϻDDYF}?Ɗ$np?\(-aGtuh<]Ex*6dyܿ)­ܡ;](mgT[Ԝ4\Ѱj\2dmqJJ(Qݏ 4jE_6V.֚rڡl{{4Dӵ3}EE8=16Ua{csWEgW*W@l560[gW !a-bx-+ x*6@nK0q|i譅 1q&=!wa`/,Q{p1T}[с,dv(V^14EQ"(}],ro -ޫ*\twk qjĽr[߸JaFnDl:@:vxfvNKj˦Q}K]lbMT#ڕB%dl#`M[5LYinSgSIhHY&5yBSN;ۢlxH i=_mK$|BzFmr~>ܶܩQwxԷz݁"`fs?f, Ml,Ltt\SOC;_K*_`*8OnUc~R0 r#HuS%|èƒCI ?ܭd!^Jjg悙,LA LuW0u$}G )0#{ߌ TT~)SJ ];acهR3ҎG?nFiCˬU8 nL\j;6(:eAc%sZkultkU16ZU! ni=Y>)NI3 +ri+J`,XZPξlPk[LDfm'\d>5-〚!&H`c[M;d@ n8Tgĭ aCq+FL%1NIIJIUd3|ޜ׆iKb:@I9"AK b޿;3O~g?*[f9l2߾t`7.?(lZ3e\3o$*tlk M$6h‰ )*ԏ~9ZSGI{P!0T:+7h@\hVͫ3qbZ P=P 4 f_3v4c4\W!3Ul{{)sć ;$,ykY"Z(.'6$RP9M Xhg&h37W!Ke:]C壧Gg >8#DG(#wΛ+ꑁݛgj<  *ͅM]EJR8O{]H jaf]ΪsE H=_bo$yQz?ir7]itҖgVJ'pA>On; <,ʹüf{!mo="^6=, @؜O@0ѝmDռ>E&n݇VIlcإ4.Uype'If'(f̂݀WX8vС\e k,O}ÝSX9HazܥU`N-˲T:,`&2"]0[ Oګ# 1 \FGGXC~6e~T*(EP靈'kdqb}&tr+)E;:ɕ lDXs^c!Z[)g3|5':NNHJ=~_e>[63o+VLOUҾ^R*RB"nfX拸,x$d|tDv>r+wnؿij\S [Nna]1fQ4ְs%`,w0/MP4V" # Rm\F%.Y%r FE^ӿj{WffJHk'gtz6 ľb<>|-`kԶ izHl"xS L Ǿ^E^ V,ϻ7YDy&)<C{iA]}hoH %!ʷYdoji466_nVh#x%4 [=>]⍊TGPDX)_=6{Ə2%W-x/O6|Z)iV dxIVƕL{*,|F7Pס۵, k"4A?dUc5{WHxUs{T*P%'l x Pk@,[Vr'1H4;]Qpf d%4m'ݑ~K޿`]3~ֻo Iϱن@&?+4WdWtcE.܀7*:CŇSmr=#,x"JòUoTJV9:7u^t=bb+JBcCP ˏ[>, Wn_#ꑾN̏Wo aGVPAl;Uǿ=+&nlTzK~˾ڗf->~NJ:"Mw >7pY}"_= Psuf`2_OI};-7n1}?%&1`Fa+5tkHJM;\?R P2|h[N"p=z]p_.2lݱ@7@c3lspw݁V'FO>/ 8(S+O![56늕Z'VFsa>Ioa!Ƈ'+j22k0Չ1`𖿱P+QoIht4X^5_76 àX PT"JM'lz \ioTL~۾_Lz\E`H(.dfz~Q:~윿_ [O7}a$ANT~ ^IAcU0S!~ب}c `џL aB0)mJՇI.A76NR1?Ĵ k~w5xHޔLOZyv=JN6[H\-\jH@b &˧mxxJ!xJ3:6%UG(\8||Q<'Ck~eg2-cW]Lݎ?VEx[Ƞʣ=). kR4N:>tQ?} TslMNѮRE$T'=P'%ҟba| 4w5^t\7Pآ(R=*| ÔA3A8@i=sΏgM.'&C(Io.x?Kmx;Ѕ^|dC?~&s0 ˧Hz+J-jH6E:Z K~>+U]E^f?lJkwie v) 6 )ׁ: UZ`0 A,Ѵkyt)EW8>׆H_*1P>vye1>-TJɦ3Δ;Jm5gH/WjXpC4{IJu<&n/R&Eq"_}lL)sFʆ!-՗(ߋ*GgIqAD w@r2Jv(^-Oho dߠWeoPÕh6䀳/~zWZsbht(:Gǿ3[* S2QimGɹn5fEثJ:֓u ~+-RjZ)Eފ9N;?K_Whؼv N J y1CBî/-%pAh>0{H|iY̓hWV(G4sR)UX(m^_kWIBlś^O?W>ҫqSJ*btI :^zs41e 5]P LI&7ފ ` 8i{;A*O槗&'79m5|t,P9+J-' + azNhHqƥy VjXinS-rW WI+(Y%MtK Y!~gAVI[c说~#=ﮖ|LoƬ{Y#-[RsK~ J+B {q^H\Bm篓fіU3qv:)(y:)v:i=8c{O#{Pe{2N+7H@wwog6H O^ݫ7HW̶M"ALżrs1TI^"gHa ' u~h<8$m]Y֢WO#qԆ_ȟ,Еҳ`Uv~UCtFmX#ӆmRZ ys4,hm n;{) Us \c i ]Rvi*j;`ГҔɮOvC'Gܐ!33;nDU _& Kh`Srsm::ri61nt׆T/ Uf#4TۀJHt5e?#Xp/V+gdߟ35uJIb>~]Mp%zy;,pC4[[R]-ۖ1Vl&+ь^fxD+_fF# ?t^}=JC> +OjՙZ:5eJhk'HyI{A݌/Tvڄ"87X.Okۯ?%PߦH  ʓKqw}\eD}<4#M?>$-[NTJ"Sj:4'iҋ;MzA~4nS]p&HB> TcH8TUl{hؖ\$ܡBgؼsGwM?6!9Z~IDil(_~< ?sEuK-YTI^ %U)FkOp:>ԞCzaS5çba^0\euߊ {^== syIյ@ M evR7.aޣ4טۻ0֫mЁR-fvHo`KIJ\՛χ3`;Ya_ 2Qd&Ԋr %13 3n|ULKZn$S:azwBȝP*\ S~Lk۪6V$ȻWx&8?;.- :ʩRע<ƇOH!nIyJbC|TrJ2̕v|Mڋ4),/c|] GnңNc)SCD~.=S]x{sG(~\6^K[@`"13ltTw5ꩪFȱq66C Z@+31c!X?눍 ? ''_խ{wc2OGO>\9Y Էf^=>sMrܫoμƫg.Ɨxg3^{kٳQY, <Y*{Zyw~ՋU?JNW xf)sd;x=WT+v_8w)c'3K l_(~N:(jy-Yy9.fNed+svRq"JgNE#ـY ؑ?9E@')!T9GKaщOrp爂aŨE(e6B}C=`?W?=}íg?ٟCAS<'xmζ {sON-X$|ޖC#X ;M'mE_$ȷ( I7B/ lyq3nٛ@jަ, 33EU҉RMU;qϬi4Q:ggȸTg}~87 eSu=逴|nm7'|xcFQv&+}kxY?7Mz~U}z\#zDty8*cSg ws-n{7ό1lɍy>e[]YP0*ZηBtW_zY}r9OxXmX{^q}E%;ylѰ+hG(^WDIF?(W7([ƪ9?"lILM|rmy7\1q&TyʇgEw`HC|!+o!UTTa򕕔QFGK&>~ZV9;-%=].b?x)!1]e[]\J6⭈*%HL+{ Z*_bT'zݚ?i˯zZ`|/ FJI}0hߴDROPzwHTA\,Z( [`< :b;Ukæ;p_#FB%2Oj&%0OذzRqQEIa1͌cfBSE~ /'B?W}ļF5#S&OQ)c sE0hHjP`N r]M IͽMMLlU`L2c?[˕70=qS)5=|IA Jdy3`DxICOa)<&Fp jkݍU*vȗj m>(H>ڛL 48O-۾ wߝ";1O°L:/QNɕ8%qZA^?ߤ]#ܓ\:PKfɅ,vQ:KϗFgJe#u>%#'+xM/A( GkU|`fE 50m'Q!0)P|$:+&0exEA=mZv@gl#WhD|2֬]~Q̷ rAR IҡaM%#ð9 `HbH~$5Ӆu[ ~NgX"fyz~t% }*uŁcU^#!))&~猒Oe:tb@@&:6C*JV2ghfDÐA{SQt@ iB-f%pԑ1VrYn97=:1>دYvdߪ~ZD.߰gtߣiԲMYDYwHm|']&tlh{{QoYk.) 5IrnGakKJ^juQKǭP!vGS8l}71Jf[a_WS,I,v' h20?T/Qg ],L&k:Ә fW74 1c@Ll애y*|M&bjgAF:ˀi@Ia.&HQ{G3$LԸ5$lS\S!I'1k0+u3{'=ڏtbPEq"w7̳e\N"^‚IGRU(Lğ(FǎSo5k_ ] >Ê7Rkojx+ewfNA7پ3`-1/ZTu9͑FT0l`؁w%~iAxۄ_C )&2v N\,Qːǟ,_42aۿ ?f+ $|]v,Tq^\c(KY%d?s +)C+Eq/EB쵼nHv*TN h=y"0v}G*Te^nr% Beᚤ5`t59wo՜;Jg& i!JW&Ij;deĪ7M؀ &N@o9o>-縆l;K͠jVWѹ]?20>,kojmV4.&&cU *3}ܷGUY]wQ7kU/4DǓ?n"hS իJ07خJH5a4_!fG bZnP_]csa;^'?qc`3uti(1&8jt̏SctlQ@:fJ zy:t`y,+&E,pgR"eӋ-"" 7VMf2; @39<[8{6omx1-XZ!T}=ȁ̾M)rvyxgXy1?+0e[F;w7|;Ge"kf>X!n2A3''S0窒`d<@TQ76%mʛ v%s[n SFiIHvOFKAeWc1ďd<$p~ˑɠ LWب%EEC=3^~WWw9JTs[\_b2{*9j3,Ac$ ҤkF)VH^t:8<1Xq\ڦ_ 9]Ih@~*`5QM "$%ў r +ajtTPnx2aX%uY$&"p ESd\KK~S Ǐ12ulū;v  >܀k(6AG?",Jɀ7 }5Q>h.p3hIE)_kK]toΓ83ʠryԉa<6Z3aN ko5k3}I%Ɛ^ݡ :psuI+U_@gMvVVQB42FWd4gJP](师#6W[e:Qo#]Vē7?Q!(D90|>'a{Ǜk,;Ήytf uɣ A iJSޮ5U>306I5U,MJVf &7ԑJD[VK 69:M1/Q -y>z׬ 'EOPk4po,|aXܓwzgǬt;;kԟ`sk?{12Xl{|`$LY3tq7W™ap?!b9/ Tl*AIɔvѺyW4#<* &ŊJ3aW<~AƓӋыCvLU'孆O8n1DJ҃R?*ܴH{MF.RH0>wA{:]spr9JpH./ ˣWR'KJYܒJy'OU$s)s(Ոk࣮Hwq5Xb=<(;Sɬ̑ ?G3"sSGiI!^EHa_^e}$J$@$N7ǢFo_ 8+F,ˆ# >t7%mc,K[+KLFV`+\F p-LY-򆙃Hfݑ۽hX n9U=H1-"9~zכ\;"(,h%`Л3hgv1溎 )1!o̟w[zp|9k>U}ٞ {|Dl$nЋ?Cflw=MOy?KT,voࢋNwO\j}-/V ↭_\:FJ }b`nvv/x$Ar*5W1 Zǯ=[e< *ZgM(՜uw} WϹí3G9d`_Lsx:*˄]05zԕh1ZT/9t~ާvz?ާJJ :|H[{zF~\ sUxD-Nz5%v[ÌMqz~?%8f7{XmI$`t9!UG}[Fa2;IkWMr9g7BJ6> 69Z\$YGOsӯXi%"֬B*hvۤx#]}'%\ft r0|/Mdɴqg"$5TcA p[gqLd5Gm;x6 m\aOao༨7}^OZnq3-aewwr?d\Re9Dť?CA‘>;N]=T 6e#k6-1T nX.NMHF!R]T ΘJ=RWte*ZI餲W ar=ϖt@-AdOU,ەUnU{=H\"SCL. ^ӆ%.ktn逭 k( *+jd ˒ @:Ou 2 ?!Q_3:\1ےrx| !^)/Js2&ЪQ >ͭSu|eBNFy6~=A SCwq,b`ܳϝ ]Qc:!oݐfDL Er7+[sUfuCb8 d: O2C=5s\ie63SNkv:XjBt И>0װ;ox>)/lr-3!y]V*=yj=A5\H5M'9]nRѮYvkŦ5blT<IF,~MpYH+C B8c%Lq%ͼ5ʐz%U/gi~ޢFx*<6Y}-| gI&bqvi&$9 _|`ducFڷ N@vI-]ܠt㄄kӼVZ "^h-^8 [}Q\ȋu% >~ߧ~"ŵkDsovW͈_+m^gQt8WE@ N.")oYHmmA΃VftFӒ[=֋3Rw7uݩX//ssUuj$i)A^ oh6?nOsߑ]ES젛_kFcf9~M@$gklq6 Le)Ru4m?eJ:2LqUZ jt ӊUlTO/n' c[o (x=LNZ Ѝ˱?&,mIºb4:QW|F^k7ZpRGw#+1tqmd,&a2K.8V ve t:s:M'Րl@ tT+ejWK8__CUՈjm# 'ܦso1bqq.{8vn e.Ο;ybGvʪf|&y #Ǐ.o1^or>Yf4!_ E5~2=0]RR*s#Q <%yt}FYzMrqCZ QJ]Rؓc ``=${?b&ZM-n ~ >vaj"(嘇y+TRCWÒsjyƂPĦM&NW#57a]7+qXtJSazL":.*(e,..q3%\wQzOwR/pX}tK+@i "-k~89]E ze h.|찎͹{KXطRn#x ]0U>@7|z g.Q}C2FdXkYU8"O *jM#iT.eqN cJ02&E.l윞}sFzVA۵8>v9? ;4Nu.[{rYy%HhA]XS{RCpKsCabi1cPMn -n]^2|өr#ʣeLy=j0?ᨴ4q,^K?Iӄ鑔`{V`Ar%N1\єu~W":D4/އ{kޑ񎜋)fR(4& $lS1r2 DD(Z]Gw j\.[C;QQ.?<E`oCb(T|6#7!BjaG0 7PDO4D$Èj1=wMsfĞ3 =%8Z6m[e34p6,?gŭfP,*ݠ]}+n^3]E5Լ|B#iQzP7d׻]DoɊtO4Pܕ5NCLf"ZD~yޗ4PԖDG|71TXۺsISb=JeDс|;D+$O?VV7XaJH`g -^%`-tF')[U>R#۫H)-+n%t|0YqMcnZrҢUSC=0X)H[{QkcʟOPaG NǺUc<0}4urԱ"Pv:$[yfpuӑ< Yc v,i!*/q>duw+4d )LS](t,Z72W/^lťo ,\b5cBhwȸXs7€icxH7vլ/E+c6>H.V]X'.Ot+8懌%~^$AyJV{\q\@ C(cXf'Ey#mz]Yѯ^E&W͍[\D>|BiC_LJ{Hk J4',}/a) _H2$JIK% ˤ?Yn< _x:Vyl3{"C|)#;V!AogБw\7, r 7S"1*ïNP͐Z9ꓨ(aLVݝx0OXW#s̆:M}.pw>>z̟H[e7U$Rrח pu@u`>C"2)~- *[V ,i3p\'󁝰# hZ;C/:"˳*}Go2k /1hLRgȽ#2čaA&8y׹Dō!=;}%5pзmn=Ot5Nga:GA&̻tamV\*.{INzXw4uF^ڹ ڒLJحM^z :(Uqezڵ*=G7@UN^ Q!7Ҧ$s{0Xk ZYf>K5`YӪ .Xk ]ǩWGǬAAy9p>Ir倒qš٧m\r b> q2$hen! ό2 Enk(m~95>߼/؇՘ݎ"eR0 E:vPWk8mFhбܡ)*eDO~MF-/)]5ꯣyR#I]~m|viŗ xJ`l?xrJn;_u1ďx $Fu}ʤ6yoBcf,v30ǃrAM _Ա& ?Ltքh0 HD4׉|>4±oX83|+^)aW_bM9$r;,bn^ޞG QR~'z'4]` Gc1cD=MK= 4n\BtXqigϝ~qx(ϴY.$^ vW9/j6I v7B&<tq@T ϱn;TeOxNHKUP3r-zv)uPi'+~ §ʸޛ9V(jK7ȂO)^#?zNlpeYH/IeYAJ)EX+m$:y[z{ajb&ee9D <,qi}.ÛH7TdrQ-Ib}$gɯ!bV1R—v g p,U5̦u lJ#V#fKJQYU3h4X 4xA:G6@<(Gt@ 0Le>a]ڗ&<~0#[ e 6l]t\udi `V"n[U[W[돊(a#c_Zm(N BC ikVt !bhD1F?M e:C,_B9ZlNxD ;%d۞d]^ D휉&gWfh,:F)N,,b~ɳ4f 6,_Q[ZȺYUgꇟpAS_W&9?UEJQLJERSyWh bjsL_;:$s'QSŴFrZPs|IȀ찵Ms ?} Hg$9rpكæ0}^p& O~׌*aqzdZھI/DI߰k~fOOf'I{ܠ>ۻo:mDH6`d!(BWa5q<&6l6cz4ꦂ1de1SEṴ,QyЦ7N[XQqtzBA\T$&Taݪ:=)2,3bYI :ᑙhBU?֯d?i-Y&-ˡ0Gu \tZ>$Xvxch^밮M;m"sϗB[V" $_:[Nmh .?;ZO2ĀmFs{HnZ$c tQӱz.Qf+ҍC~ע]?+^!b1kMޭ57j&#cds?3(ϧ;t9.xS]m?#D%P$Kl8F`]~DE,~%0//ܸ%wWX Zfo8ۄ׈gțj_gK~dRMe{~ ~ŒE"Hlj@oe-6e >\KB3P_]^ :&wp r&8= ӆ0(I,y/k?vg]@z[|~܊wägͳeDFamGXX"2$/*[Y'AK@s+.8A3V L`XLvOMf!LUl$.'L n3 Vm1bE׋QVB%dvWR4.3!k,v.JRrJ~D輳7vj>A@>U#r!|KT6 Y2SaQWHW>{7^,\7_,\u|.k)\_,\N O'mWFUm[2}y9­w6G+(Qym6lzL?3z;Lmц]wU>L-2JEk(s;nJUB% vEwZqԮhdӄec_3Tϝ=2@K鱿aN{C{qUoBs?6\Pya\8U^Gf#霥j^I/[ըv!8"-`xv;J5cٕyzbB69#&j/&9dǩ/ϭr0?7LZyiW;&*s|nX^"gq;i;|j*; &'~A`ÐO4Q6_&Е&]kEë{!W/Mӏm*N>h3=[zv~\%`2S|ROJqt.V|5mdj3m33%b&I{!m.|_UX9a'tznt,?|wgɗgP?)^(.b㥼\~9+Eb8T'&)&|Lȭ~=~ y#%oQ9 ֦ }Im5!! Sd=]ܞo23"Uț 0UK;09̂x\lTYKrN.Q4**rAWrkxT\( ·9r*']lɳԭ1h/9=mT m8_b\ Gw/ť*.dYhYf%y`>=k+=T6Xx$YAIfQwyJe_Ia&d+Bxr6&Z}HIgT9d雞i?ÉehZ#҉ hICR)REKBcފUV>seRaoh2?5Dhk5em*:fA<*bg5Se\QB`A8:p=Uϻ(nCl k8;toY2k 1h/{Bbc?d`<{c% "HA -C?`qo%r[?(C |HmЕ/̓ \: & PUWKo9ϝRT5BFV}eBfF^fsbz3?t;bTKC0_J y<9Xyk=cK@1GEe !of)QѪ(H K#M~ĜdpoE|zxX币V yu#~u&Hem؄N]4^TWR ({Tٶy]O4+l4Mn&yc&sTKrwda=$dζӚMƒ'P& 8vKΧTJ Sp\.4 x7i^B"~*-NND-suX!FV&1$CQx.jk@$2bN|@tWEYcs7zGL< ߑT)3B>lIWcآ[ϑΆ. / ޔHVX' HZ&&=~n. [Ӈ4DfV*1‰aUY|"w9m[0LǨ<$dUSĻ H発%ג6 #s'XroaO㓼w1)Qi1B ߌd /v:ktC؄AϔkPc!^`\T~蹘#]/}(h\y5^*Ur9LnKL gUXԱ22@*I]嗯=tW6 uynVqży4(j!REWT&&ēal:xn%/,q+iЦ0H '#;addspnCodPXrJ~"gE|0}+lB:ȀeYŒs؂.}}:d?P!T )`hyCsQ{å&6$s!rѐY%_!ے0fԅ.?2^2hlt#ŽyWoKilj}tCQa"lB lj.pJ*J+4.^p E`xlW2mtlm9 4n:Ƌ1L: 4f+ﬖGykK//v}*m{W騥6ht=IyuښBT a黋pi;w$*ӯsGHnrqTw5:;ao*nc(U?>pGMRÁOePӀ02󼓀ى}'a? A7 9:K ڥS<[%)T\IF=XS!]@21I#Zn✌y" v-vI̕xtpd$_pqv 5v@g Qқh;N||| yH}V[&diI.!cU|Arw Fa(fr}i~Ŕ)͜$؏ R~f%rԌ„_gS5TU D3H(qKIAp[·~.޽J[>׻-7e _?E蝹' DV= j+LXOq(QFbitKXa<וl+*ξsް|( ~)@' _p+ ,'YRU:6FٛJ ܱ|it9q5gnե%j O@6az qd8qO4iBZ~$/aZBϔOQ#-x cU҅>MJvk Ǝ VFkXZM Jx/T U@Kh|8xYj'GɧClh\"OInX%惌X {N?xEFasq `DXy}S9- @TYAd'Jo /M0ڡ<l Y[R+T%  3ʾ4܂EDЖmyK6̙FfkNbẁchjtWa,dz,)yX#qmٌ'DZ8v㻹u6G5548v0cͧw'_Ҝ/ MNI^xg[٘](V7ZPD,3R q3EXvֻ2@VC,x/5U+-m~k}ķ_M* :LLȺd-A9|;GPvrd}o^QSjsN9xohj"t h.pyOkF91mA̖u<(ZOd_ŹF2&F|e9.}"(*jG2͢ Q2iDT"FHLݺ.P7$7Q7BZ dxh;r h֠n]ʢ6eTB;B.yi_#e} 32N?SAңB,%*&\ רa U1(3\RiҾF\DźO1f=_YmCWȕ~G20ݭ#=83m=`|$e=R&ȷ2 JkvD"mMP&ՐP[EEޤ—1dR2Aff^E`cVn틝+ٮR@HZl9/-ޤeg &8Dn?}am1nTpI(uLt)̯lJykj_=+>^G. e ZRf{TZa#\{ G< @xsW]*Ԕ sDb1=nHʢf۸/z_QV -Eg_}U@j7;<^XT`,R2"PA[k9l1`I^0kI/i. du͠z/=%cʩ1@RYFJ f}~p&PQ :9`fcMn! \ ķèjv3J$]%v`kWCW9Mm^˗4Ѽ tz3в..ck떝"%td`]&Wٖ*܁{hhQuji]xJJ ^i1O\̑/\8{?\b"ϥdȅ>>s͖yK(7~Ψmkj@YKfoj FTPrxG>湯%SR&cYp3֏r{{(_l{1{{"g!BQAH5bn'cxc*7 |?Np )/)Io `kVQU^l+b\L?]΋-r}m_``}Ө+܎Y$xoBpь2H.N 5V6f>P|d| 퇅rUNӋKm1午o#_*t@[nN=IlPZިu#M Ka76u.VH{o.[!է@r Ykdqq^W9nQv 5fg3epCuc;uIs޶@qoj-|*5fNm|`׾ g9cu.Ɛw s!Xg]cҿOpE|TD-5beܑƕM|{ZBt`уHʬnsyfߞ@)9}d׼~W|je ʰ6ds̚3:.ZX>biH*fؼywbNOwZg 1q<=@;ϋ |ݻ˞nԀ "rBb0P^Q pƦV>Iв' qFY&ؿB,RY*]R4v Hnյr*5JWkENƞn]5|T,3bRL'-s"R5 ,t4+'_=B-dSޕ^C}lL]J1U ۅx͂<[{)@ N @(y(O\du0ZmI bhi)+>gog]Rzx} Z/+#:qg@CC6juQia'6Ɗd3وC=Dᙬ ٘%C ç%G`dP^i Eԙ'N- ]a0Mh?X5\HPYSdvӡHP{4[btl7.WAɆ [S@8;ç`׼`X]yԱUC( ]ˉJ6ծY!U@IzÒdq܅2*LGD&N? **/x- a|ȞB)Lrr.J# )XZF\ա~ Ї5/N}9C'8˵57xE8"TptBX}jɣ%d/Vb HDY( 0kUju032cj7zJzgEE Ppp`կ~tpP|_v_:FR u<07یT&G[ GIenG[|X9h-t{%V"( /S/iy:Sd>̪$e2Wnϐt[RJ^(kߠ0=ĝ9+{7vq{ΓXJ7Ax>F}5!c^#^ဗVY_l"U4_)t>\ e$JHT@-ڌFFrS%i^HU`Up)SE` sr@xHpTtzP}Hycҏnv/w;ZFc]sW~dINFEJ0O4u' J(peY;qtM$#<[5k('=5$pNMCl$[*3-8 ~Zxp5ve<;TN/j;\y,?O%fIJ)6Ig98`1^eXz:YB &auv8ƮAj˨"]ePHWŅsqAu.q܇{D˪ ,Na@O*`|ʌvzyjCCF:]TL-E> o6r OB|63,^:ꖱ¬f7p8v qh=穊l7jn| _!QӅ3ezyOGL(WHk 'OxfUw]_~RJw링`c/;vM>ۻޗ=pRp Si+Bt\&uD&ԳFy5,?jR˕;^)XE}$Ɖe[bUizI T]/v>vv%MxYwS_}R-6G{5ΉI؂BOZeq&V\]f%ڞ{xND)+n"tiHn7x.˭}|ޕ>39euՁSwCr >*yvv$>['|ezkz;KKW.'# b_C4zbg%nr]#CaY*5? {DHp?brNrh\1S)ia54scOYdc[g<,YE*1of?ez23/3y&'Έ q),3FvW4,BO#ύUz:KEUC>N5' !Z? c5e0>,2sd>:ͶUV!4=8b2 ةO\G6>ZÛkyl-V33>9E&_9})GK>ǂ/HYD+}b_6XAT +_3ri0RD0A"E6 k/.hi2Pۄҁw Nx_47h4ܨ]?Ҽ_00lUEz|6 u'\1b|Trt0Keg H6aX輘vky}}?2g v'2|ɪR MbVI:@?ZɒuՉQ;Iȟ|d`}Y)ovp]l1V ciGXPHdY)lkrNЃ*VWD_#-̆邎u.0jGBr{1(rvjT m6D|B9x>':w Ioj^q|<80.bƘDT  ύ_ dnWy~O p|Qf[l&o5Iϡdzb#FQ-3bԹqX ,&rFNHB509dY޺n|B x*xl-\beN$K⻬ű:]kS~lG\{lC3h4 Nl fd]eθXDu8P* Yn_yE24 eCL\P̱!ϡIzZd'`C_%n+]|g%wC7k!,54X]2W'LRÀkzQWMŨ^gcQ2wmK<,T1dgsG[D%4lİ*|:6 /%lF$J$ٖçVON7 a`\F{f&|1n8XPٜOrDplg˺O6#7Zm/ozf܃%ǩ ߆qH{$1bQ'*\.E}MN\M8ipZ.ߩy, DJFa(cqOSL :z,L-QRh:)RAuk=2;kNI>=}}t+*1yK-% =^dgU)ziA'9PC kZa` fxaT_- n/V4 U:H'd W#V!jkE!laljn1nZTˋ P{꫽xNJmweYIalk:Fv;ZA3d[u75t},BxS.D_-.0'Q:yӈ햐=:t{"DxPՒD8>Bjo=.dq\WP3ϐu{h4H 2R [~%vU_Em }wNegXSP-**@AN2[8Rypl:>R%&ra!PW248A?}os1pVUɏ75Ma\`O.N^mFڳHiu3}5`)O/e^P5FJܹ' sk^j=).`g]Ls= y(n@אAcm%3gp(`qq֗]KR\`sQMҌJ_cYuPz26N?HT2w-E8ķyR͍jCR"TVXfƠoj 33Ope1 s`B]:S'&ܠn7KE2(Ȫ(Gj=y/'ԾLI7D,{԰W= 1Pj=8pv;R)w*Ƚ*FA}9AC?^ 3aO'e@BwU٨E.Ppr]NxR(с TLT>臫=]jΘ = }9~,a'UNix }(q&+{1g}g C'cJ9"sv*KnĭhD{rl]@5(VgaE>;p偏>vCh;1m]aMr_øЪ~}Nf帵 2->SkG/dsJƥ(łzTrA2m$cL8i*~`˫/|i4ΠF М\lIɚh -<;t |0N /=U3zY Na`q 욒aQݥA500 dAWN2-1 8وbتR#o1(K;xAfͮE#aAqDd%AѦcChcWPG#yN3٪<єtbOS",t(E򎔄33x-@.(In[ V<#fqf]ב9]HyYaX$ֈzNQȍ$i7Ε@I{+]uƧ`aq Ĕ2H78Pk)t(7#!ԚH'#ؚYzԧZ/0ӏ֋mSx` :>V!'ou[Аv5p>n@h^p9 *`tJ TbgJ~¤R'ڪ2{5JUy/$.N7ٳb[ð#2'z35 xHJ @C ە` F:YU'EC]{k-Zc08(&YGgy66 L楏zqcUh5]N.+Fc_*\&`kG헅He=rVWE, mХf iif7  A|#l;rah/{ x0B/q]UߡV7Diᄥd=.\F]G*Kqfb}^cf1 £˩)YƳ*C3=bާt0e3@D^egocqƭO>Y,OlMTFû zw>ci#>jI\ik+m\bKsCު%i RFU f?8ġ 5gp+,3gTEgxM)xWlF Xcy5>:0fE{DUe3Vު,]{Moꟑ pP&KEEE2.% }$e9&E^@~7+VAZŁV!/={YڣGCq]-AM:f4dZג @%%]ڌEXFW f;WFxwHx[ RdUռDl:lIa0eV/Zuno u=+2u3n,m!%r47b)<%K߃wkn\NBi1oΒ%$$, />dvĥAmPRUF%t¯m7W"A+-(.uh9,i7{Gyt3Wyaz3 uB按 =푕gcR%mԩ۲ǔhme؜9)_zC̶N( [e0-IF ~s,qy&'U43yUɌ]'R14dA6@iģYO2a}/A"vY&e?vUP3212ymx*A(Pd}&֙y9+EV 3[uNLe}i"@uW`ܦ*0`s6n"sKT?vO'lF.e5*tB8i+ e:Jf#)J+k+3+WEUIJ c.B<Ӳx_ AΧΗЗ ׄFð6B5j ŶwC 1i6I* z/?^q.p1hɌ0xn}=>>1 Eb{%v'M H9́un qL6\|y74}4kQWr%궟f.}2X8R2nx} xŕW mɲlmƒ%Hǧ.ƒ,K2i=0 m dspln!BBHkC?{U՗$ȷv}WU^zwE=gj6֙̂m ,h\6rVttZT*EOS2hŠO;{!oބT9kyyGRMZgn&2QsJ+l>ie-ht{jE-; 3|e"Lޓ/&~ZM ljZ2/,9'6]mkT@X)V@5 Yקwxu3J=0%30? =Uլ /FGK\Tx9_n5=7 < vqosZXMjd_ܼgyKvtj{,PzO%@־+Ϙҿ5*x20th;.un6̓!%5ڌxQ:dg -쉘mi2˶ 837l%l`gЁG4Z|p.]C};/pZ /bk)3:ppoPȻsy{Q\ͧA#{Q&tz8QuZuߕ 9akBtNWіEZ"Q& .PbWBVM]-I[[@A$Ula`ۜ7{D#:=cTPw9XpWyّY4M.S/2jF w;{/b+TAN$k+a`I)\Jf{)eg> ,yS\6nn.Vޟ( 59Q[ȥ&.+7Z"x&I:TW<59-8lٌptp@A4 ׈؛ =ꍺ/uaa-NY#W kkJ(iДpcfca r뒧~t_2P>Puv6ڃ&6'~eOAçըݺ{,d0T6ȨoPS.Z^/1FߛZN% 1* z Eh{ⴒvZ\O^U|9w|FιޒȞuXE#@2YtNeG72_wvja@/A:BO2d 5Jr]YNio}\r+_BGQ`  p*'"; ߫L\YdFа ^\8s8(騷>td/*fE\lW na#1"z,xnµ2g5\wF_(d'hYx1K<[1Vp(ͬe!)'5Zūӟ=t5.AE5T\f[`=*c1p7e"R@U_ j0, 7_k2gچƴdOGM;ұϲ@"Ieqp*zo`bImTQtNn/J[9-^]5EVnٕEYvv߾*ގ”SUu4Xn+p`j-ߛ>0q&!JMUa9y˴ w[(Pkw"d7RRHq Q!$$`3 44"vOd!}ZP,FjaLg߶ V2" n޷Թ]kpi=Pu  ]n0a"kOi贿'(ʔH5-yZYi}p :PՍ$,_Y;ٍ25UjwES*nv| _:HhǙ}xõYp6̛YOJS3w#9VJaƚFUi}f yBP:Ӽ?&'B̎={S4CFoݳa*m<0ifPĻt4S_m=Ó3 3srU[cY2}'MWpvx^P7RQY,z1X<nY/ ? zӐ}DpkldoG=…17sV78W+3:θ/8U^y %#d3xCQ2Zo7Ι@|¯av團!e( M=~ = ړu +\E.S9q"eD1'To {2L T'i#S`=g<5 fҎ9M(ꦕN͕ӰهzudtvsӼrd▵[.4K ٣[NE <"ʡXhǠsF2jsҊJ䊊ci>`gcN͋?! s#]_9.N> q@ Y|G|%.˘sy)rGsj"/1wl跔$ =s Kw&mՌ9Z)CU-j,&qdED1S2nSyjY .P3ewE*F_ jƜ'j[󅘳+c6 ƨĜcRcw޿Rqq&PM]@=㋣jEkB_D^0.:;OH @m]+dż,&v}ihiB݌܍2wjG^ܵ#kDu;@Qth$/pNg7&ls^빠?g1B "EwtH]|P iǓdsÝZ; \C?u,G,X42z i1;䩉r>6gˮ9n@:cɭV0*#jSfNҏ;|@OɚK  @6e559}6p#'Lw#qo@O<nF rAB`ϙJ?cH/1٦(Y)15`iyEY'ڹ_&4s,*s9L\?mM['Z38gϧxSnyx~>Uyl(_Ws? -nG 4޺L[tWpL׿{-/$X20UhlY72=^gEha\:` Ǔ]U, ̎@k/=xSҾ~ڛHhٳlʭ-VǷx ՎzF:ܴPr%OwmÌ?-z\많fA1(| e}cPf˧q ZG#{Im΅Oog+@ ]=1ϑuMv am]3 ,ųOqltlЊyѴu,\6yӿZ|o\5҆kLΥݸq2h.+Hcw p۽STmszNj$q [m53ez煢Ď0('=ySoxpmɢ XN*OB:~~C8n< *5>=ԍxA ]~…"R\V9 w*!bAo IVp:tFCl>L}z8?yf Z`nt"4~-&W)zkҢ?n5GZ`ΰc(p-\@ d9mJ4qD9ih(}Q87}`?=_Q΂x+gREO}ƇP9۟/E],mF=L4? U||gZ,h?wplR~ D9f xGopGN0׉J y6-/+ #(/^2)sA4QmTA옴-.9S0COA@@})@T!UƜ_ܼ_^ָͫ0cyʯ.BZ9e(3PaFuus.| FC몳Op=rҜ~jPoZNL\7y43\EϖB,(ZDM15W3#2JmoG 8 z } nKl\j^韚sq>޴e#=K̊S˕fj@|0O-KM^3:ɘ/PEÈߕHPsZ6S=)O$@ [l~ ilRE;ERbS< +: + K{5YN^ @w\vY&#'*Ⱥ%h1[J=H=er4O$VP z"BNVȸ͸"ŒvPIv&V^M6ȭPi2^Q,\ ԜmM fR,ӊ[wt:5ЦE|``},Qŋ1K`lD\; 5m$( Ϟ+Ȅ`b.T*!4!#bT,dG(jah`L5kK{7z[OjW['Vϴ++I" ~g,><_Tm$m-)ʆ|`d.[N"x.N/E,)ቂf{#w Lr7&/e9ej߲ 2g`~ANi?F.: $TΗ Pd#1l$#{C@qHH]9\W[6ȼ^J&r|' $?c,&]C琥 ͒ \cݾΟ 'gB8{Ho-5]8N`!"-Ȝ>[B^V;)+@7KƆ3Jn 7eIf-TG4L&.( 4V={ٰ cb,1\52̀vx;NnB,e$!Ľmsτ4;w--v7.~fMf| Z-Gjg,@#kYMwzvc˟udch{zENw9C4{9`%p,:u1\G-0ƉnY b`6 8<<%Q;Iž>1nId1,bpӌs:饸C'`yf)9W7nV͠Pu6۷ e^Gבs h=8Viw%][ͦAJ%f7mI0jisR} #Mvm*KṢZ7,ƍ?l ƈd6ѫyA/: k@u)+XR{'sT#gȄf|bh}ǀs," hqИ. S%joAx ,}A7Rʢ~.cC%M92 $B:J4! V-tHӶ{`MglvᫀB6FI ՏFұWu-'{uh'I<.VcYy.\ Y~`D8 e^ZצqQuT>'?dyy+n]q ;3[@,]$0tK ;7-'3EHXdxb!*7=R@rzGt @f#F́LJ5g9~]AJMuMhZD<%eQ`fd}e?l[ EesxP2FVV\#< , a&rb_u ?5i\ M#I{{AX9^', Y Փź|d4.E>Fj2Z91pI:J}`V̔L曇(C^+I>`Z"F' myao@oLӕk5H,_)q&+:2K;Tp5$$ CKG+K}+räfG0swWӺɒ"ī fTD#Ar0 %UWLL Z0:t)&1Iڪɫ2[I uƃ7͡H?@ 6ܒsd[C0cB_ϑ]xE|`œ)nD<4ĥi\^8D.\g&a? B ";J v[35OL^re'˱l7A}4vBۑ5][9 o/ @a2Ag9ӡN9r͐Yh? (Nn )+ \%ʄLcw>mX ܪI-'vw0!FW̄g,}un_y:*r[,cFH1qL6*7 إ' m@-ZşeEjZۿߧ ;UG_I1_9[*ɤ&Q/.c+m0ow|8hPM;k6ц߉< 4>|MA?4Qǧ:kH jv1g[$-h )]|O]H誇؝^%y1Ń yUYd6cy‡uz!^6^ 1(({w^  \t1 u?t й 7HͫL:n̜ (/m|wSU_׌ot,^K!`V?|YO]M{bҹ \CRœUSdcŸvG[HdC)zKz)4sRJ2 &ӊkA;dݜY7kQ!Sgn&zQdc)f3;X:gdwrGY\zu3횋iZvss-&-r<r/ wLc`yK9zb<ѻc-$ X:$1my*A2o%ΦONq to7>1cz꽠Wmy;Y90/3oZ, S&DZ0|pY &7 !-x,=^(Y$J) Nہ'♉ǡ~ OZOOH%&6{q_U<9$kg_ v#0.rª4IuzvVeU Y/OdMvAI+@`$  >Is=YW;F!1f9So 2!.%XOXAa,{J 9Iv܇$9}'n$mgU_AO^^I^#k?EV;dJODwʰlRVS\#2LXͰ['o"kV jH#Ljz|7n&7#)%\+#0{@V+#B:W{ 7xM)߾sP{WKj~ؼ}D݁3 mGka-T˾pv뽤n/?W ƛ{;ir5kYldfo'M ms*DW"F 1yyL5?tgWT;=a(=iZ*U E C T{0R=RtL;.8Z^+ȓJJ-|X<փrz8A˩6=pimCAch"I,ںàG6~,dED\0{ɶZ !dR[ラ4-64Y ^iJ#[ uox6,*>Kz_=mtW9 'ѠO:fd1gߊm -D-d`7z(@m()C*pŰjnF #ƃD?!bW#LpzGE/žFjӍ=DS{"^%^2x27Jy zf?täe2i[c% 9Ysӱ7^1Һl@sX$9K?u I{|H3qUx @gZ>qGӎg<\祲d&{*j`l'c2F +pݔX>IZ?ec(ǾI]sPFOzEް1OGd&'!*\*(FٴfAGI1K$ZOG4]uKT J~cyq^MW/j{5יD?(3օ/%,n,j,#_&HOҭ;ˏ>/0#XZty eeJ:4rp#`/WKE6қ`B(5s)AyN:G`[MiNa,F% ExV"<"H,zuٝ; OU^؃'?KE(!esW䆲\+뗓~?g$&Bhy ݼD5ݔ6ÚPɉj=&doʲ !X~ 3@9ΰbtBTpsOyX^0;b|Ud[!0[vߖ<.ssV&:xaȅ/+xQ-A3z M 1YVPYM ҰU" yi%}2R}`?D8!7'"yuURp& Y 4Y:U(eetsv+vۤeOsρ5\-(yVCl&B[^9nЀwla=J*-OI} `I&wgGj+^rgO+X<4%vSұ!~BWqi#;:XA t  ctzR}d4K`Υ 34ǜ~*{hգrCR[E=,ځ{„<}b# xݠf}mR a1l=)8Ck-Zwyպ%Gesyь#mVzh<DPeђViCxÝ{X};6imx+;N/{Vc)6]Vܒh9ou<'Ћn0o3Ӝ(Iz&EYMM$D޽15U܇ǝwX]?8RR[3O{wsğs+\n9"c n8Ws@{hj)˥.+dH=?kfZm@Xcm GA/!]bi6W,9͂ =~ CLlݔ0-ƶO1C0yQv!1*qnh93ߪa5n>F_d~0/TQ/T"x!Je]-y,<֙w\푽D7EA yCܶ0eBAgG"n# =Їnjwa8cyB5Zšgd3ozyk(pŏ,M?&Xm0<9Xj-¢aM$jԴ"j"Џ0QyLIOU;pyqkLl'5+g3˓2^*yPfMZiSQgds(o y9=!Q%\9VN̹ENV.aZa2o7 W?xvl뗤u 9o%|-",U c/$C?+Vu8Ij|du ip4CVq#؎&,>xNgJsd-mf2iUcXt; <@m^FwQlQG<+U. wwǨ7<+5 ?;pTCuԱԃF҆*?/z8<բLc.EY?ouՌv~LKShDV)uު^M(-/iމ3MQX%5bn󪤮z' (}Jڵyi?d ;֮.V7SnC[-5G/Jojm˥sg\TqØ(} imSa&liig+ف$y ۞ntS;B nN^oBaU,ѭu%`!DiVY}Xv}Dzj0@H&{"ACh׃wEqjEtO(ދM'-%IGܛ\)ͦhD҂ #ۘY>Y*v< "~XLpe !t^]ԷN 4qs CF(HS~=@})~2E͹q\,[o^մuszX8c^;\KED1NTAfJ/\)8"';xԾܬYEss7SSq`A6ey+s?EGC^ Cێġφίf˩_.;oES`R14Fs=yG^~K5h!⦅Y;pPXZ^//}9@ef_+V/.{;[o=eaNh \ j}yMz ge Cct5F7;טskh08̰JJ<[f2 K,455㫮l_ ֍2u7x߈.?J0|#+^#8Z"CG7?zia=!Cr)nٱM6GU5n>ڷ;I⡶psY5+1/ -0shg5fx KW/o@iKA^'A i?<5/lsrz7K$Ԛ$Ov4 k1R|_.vsXƦ{W-4ޮ.{(Яj,3 1^os<7o\T? jPD.nq[ Q|X;c& b?|ZO@JBR.aB(~O9Aݺq=OӃތjsЗr`:{oWC;įBv=)[jKz3-+ףHBL!G^Jdy0Q@q1q蜤W"M+FyoF=uJإ.IǁJQ"+C)Z #'#+N׍#g5It?|"zNCT'V=Nw;%[v,,RT3jQǜ#G{В5 Zh&d@ҸzG`kͧlEkZԙq:HKSJ gO#LiD-+C"`IDjm$hDՄ6G׌e;famw+(槶6zԉ2VnLWcڨJ}X,tA+pg(ʲ0ܩ@ۉ]LpSW^) ~,Z&ּQ!.mFf{Wan t4  zƘulsK`ȅ<vCZ~@Pʔ}R~|e`qUdHy5lWט+׮: >Bx,e^?O4Ϊdjc\v`ٻzȣs.r!yD 5uF4,3}#G%ٖ꜔|$[S P_˔Gls59y.N~m\wtrd% hЫSU ȒBU6T"^~R^\m@F 0<h`AL7(Dp\Aq=E CY,TIt4OIh"I@ L@ 2!\AN.Dўo  5F#I#!GP4'L=ӽ0~;Ҽ#:d|ދH#^]TO+pJ'u|nV^W QK(M˰-:Sx2L~M,xõGsE \DNjJ-wf&:ďtpї?VA4xX}O=5 Uy='*,s0ӫ !ICB޽<[WPn&<ʺa4|%c@İlڱOMm̓V; `8ky=Ef=+V̤㫭ǃzBCyU{WU9cQ@g3jWi鴔5T7 Ch ;.Z() $vOd=֑u-ejF&%cABش~8u&>St65(YT8̿Ϸb h7w]!vo)E ] mQ8}SW|@֐$T`d K&ߠO@{*6u?]UG-AO=ͱ(ГWw@ |[l6߰zY'J z7j9`GN=dtayU1ro,^9 \ ڧYyk~T.8~f/<{{_~즒p ~SzMp`7t$378-\K=7ApG0㹛 Q7ps-|Ηײ\Xn)^ sÍ٩= Nj[߳5==1ü`΁/Y84Bܫo-Yn= O|85tv=ܰy\  O?٤-FYUɣCDM8UAa{7wor0)NtlHkv0`(}Re&#ӗ H97d |glg$ Ow%ف萰–?Ny:'ІDsE 08QNo\hC;pwmQ(`|iYpg@K<:)ܮ-o~N ?Y4?_0Xͷ~9bt;Rg溏- tX /?RS4E –h> Z*8ǁ]pU8/pLF/ﲐßRj5gΐv!1C/yZ8gdGGPO nd~jXhObC+[!Zӡg|#6Җ4GƯOmVz:>SD%3٪ $d!9w_Rkh!xȟ,>=؝;"F='băѐHu/,S~6q] wCxm gϙӏ= i"Cl6dH Bh Y났e؈GG BvDj{ڧZ $MÙJlH>Hӆ| *"U>mq4@내s2 eCm"tZ>."FH7MЉS>;g 9<#mE%9 % JC y. =y^R@MQ 0σAV/;b*U3oisRק'=H闗R04T엷ngc, nneᑧ _]2f!Nlk Al DO[CN(.~FҚ(ri鴁pyRj^ڠD2/ h@?"i@6`;Q< E76UF5 @Kc#:]i?-me)PO"RoE,_HMҪNj+_D,Mcy BjBHz , -Fa w'(B ei7?^sd~- ≐AEk&ǐ(R*jOd@w\c2&qH^umq b75"?Q8B= Qaa1a B0UĈpL;`X ^,tI1 BAc] ;|zJjq16"+$c5v}$xRhJ; z y3#Aи:,}|kQ2`hI[/I s퐔s:+kB:un\>5} YD,v ECg|xE@gW%/n\sFa73_,[ #X8iČb ?rJumY߇GZ]Wd9cʪ:^[<a˅ј8 YLiJNצ4xRc|x- X4O솜.tqa_l?6lLؼ6DA+lt5iPt7.9~ t!S+ = Rr^gs;ӸR6C:/PJ6$ncHtp(Ave禦7' 00^+%@ñh_R ,ev \Bׂ٘RF_-_D̋UO<}mq8@Pu =W*`xj)+M2!e1'ژRH>&PmaCKXE I[v >d @!9)mM 9Rqlƃ|i;orDiXq{3p+(c r"Amkj)sL%D釅t/<y<U&A@\"R/T%4Az8|U^ _FV:SUh]8 BYEE<:ـ !5fC*j.]A?[R4'}*M1N ,~bqvR4u$D<:Q'D|ZVFd4R| Ѷ*Xۯձ"T(MLC|&vNdhà aEӜPsLz#W,mfE9N|6KIE9BO@(bO D#!xZ42a P)I{[X `B-˜aKٹOorp8i2"v`Pp-Bx^vQҏARS6V[܎HigOuAD'2M\h/[o5!.LklMHQw #>mlvVXSF'OYYͧvc3M",Z>2IYɪ6!8<4'`sLH4h+bɝc>wm>8_b6Q|8#Bn_1ɲ$p =z^ΰxL?LthL'H4/NLA<_OAbMlP\8z?0i;Nj^Dh#!*,=)S.>Ec)>pFq!"~} zu&FJmoT2itjEE (I2bu|M|/܍6E'ԇl}[ʒ|l 9qT_Uv;(-5"h?.Q6@[Lr"j EXI#iP:5 e##=tIJCx#`NNh'GXư6PhFeuea+ڭƅ 1l?e7PH#!.l5m=y3͑0m+&7$E@ŌؠW+%oiڴX)lZ--yjo 6|.-w\rno^r.obRn?76珟[[xRV4ky?z, @u-rh~Q\XcLPyRel#8isb.ΛzY2RVq۸J㑓e@t50*:0,k|B 勭G`ic7 ֯jqCt `@mˀڣaA#H>8dkSqgX)J4HWσQaK툞([rm\`(pe,̀Fk& Cv?K*'VՐ.]ϝ` $!]g;yC}cR[HI J֔ qz:%&:e i> B( NQVD٩!yH'Fٞrwn8q2|1220逫) GyIvdzwc D38/I]$tDžK ZjV"ò >:h"[`LPx:2DVBiRpl'X(oʶFwHTʿ&#HyLUhOre{j1!"".?ҒIo"XNƀ߆hFM4OByfG @bP,;P?&LJ:yϏ+Ȝ)KmV~:y~Z(LJ[yUʆ5e|駵%vOn6t~Q D"VL8Yɒ@gjz-}0 ܼe]6=ް6Фc|f &~_/ D͗9h2_cU GR~S1fhTZ/1%)(Q*_ ·6yaz1Wta VlfMaԮW F,;=^瀒DLR?ʗU#G$CTXʸ]((ặ_aטIbS8)su,jU2LEj cb eTbXjR#FH&&;{|2HN|>R3qo,zքo@`yn3ch?fyćpނďcyo VVt:{2c%GjVzFP t^EA}We- IҺI) m2Ɋ[EulcӴ)px^w'!oo#jEh-3W?1#\H"gOkc`E$qŎֻzDp2w5DVn@@("//1Q@ mװ\k$vh5=+q]/҂y`#>mT0t牵~Map1(Z!Z<#(`H> _ 3'բF!|w15 ;D6O|i[W`k5g?6@YȯMsƗG#DT|KueG,xOF4in 0^ s\*ͼz]DN1"5cJD2e V2]u7͂>`V,rR#aF)'3mŲ{ٶ7/A(+4埻X$jF, >:dNPpYe41xꓬ0g c T2 d4Mm+;>q1A"zo9JH&HQc f>/sSlLOsSlvmLe*UkJ}tT ?X:wkw7t}9Ovm^U:EVp~g4}Vmy͗XrpFAw|dw^v6T)ĉNufh 3uضm3G^LNT7/?m~ *lyB2~EiaC2Jo}7ae gL"ٔg]EDe"S#8Qū^h|i0ږ(@&/@Z `YEJ~oty!%i"=]_Ǫ[$ӡc&0{vcRjA"Te)F# Q v-+ٶWݫXuĩe+yjVꀈѥIkYs],$" iîKshS#I笟1(vw:./WaU& RƲ("mxElswiqZX8z˜ҁ%d% (K|#3 8w\w*eK˘w)tiͽ^Mu-YÛX 8 ; zɳ"PClje`zx 2a=qgjLWY5H>k-rC ${ixr'N*ILMSZ7_ڎb4yK߯tbJnSZJ̺pg.ߥ+dyk/to~R͕M-뵠5i'>qRQKp,Pq~}1U\ 7:g>R#>Sx˿Vgg ze:@8)W$`pqQ) ;Yl}ow7 cixZd#7*+kׇ3*9?f/kÃ87T/1[ B Z+g^R_IT-?աyMJ@1aʪ 7) g&kUK_(n /ߤVqx.bke7+&`UU:Q$t #u7*_$2`0p?^tz!*i -ʖ,aV dEݭfvϠohq`eÕEJ4Kt*s/_/$*&,Y)36DHlFN+̗ݪlXӄ8\(=*׵xWsnS52O<4PWlUZT1kT4>gߞe[1@s\~m9<O@ik FEw ǿj"bkIosxaQ0QZ~y&cǎU U>qDD]Ex/,6gD\B4k~٪.Ų}za&ۉ&Re 'gϳE.>! "yָŮ_Ȣ% v rzXE$o;fQ*kF0ه_zvʒ|1s<%Jo~fiH~Ln 2h)GZ%'C{p4,^LJrN⪗&{vUء;DOJzUvғRSG?ae'7.* 5hbQQ 6.pthA""VZƫe %㓠'\uuoʭHwa%'8JQ1T>ψ'KN QI.$DSS~R%[ i&o[A=ߢ%+|Ř;.dTЕ"j0XI/ig@Ct]PNl%,|g6EzxށI&FjCK@ce!ղEG? zPX"|\ݝb,EcQ}f~m⏬buW- .Co3b[0,-C_3rن]v6fNZ*:r5a;[}L6/l\Q?-u_a +kpg»3ԝ~m*-+@Oat bz%.sxYN{_e ƈGȴ_5uM}kL"7qH,y7"dl)z&40)Q4 2Bd ),R EB\w^{SnkRY>g1yreVz+\|]ЄHG*||GRMfS}2[)8GI} #G H/G(ukx%u LwR\!+7ےT #親C۔JG :~UAqArR#K IWM]>SJ={Z={j6m޲uw1`?`R8*.VT!= -@&x[)'拕j?֥*~҅MX)t%HMx|eRW)"y4 N:E w+;kM /ۣmyC@drlc< `Ltt!c l=*uor E3}uK iK!3OB/vPQXڈ׍f9F咃e{Lf`.v]yJp9w ,Hw׋s򋔂s{_#xVԁLoڔʙ"fveml4=U3|Hա@v(k:,Ц7q Z82#f:AL7 Cʪ]o'tqDX魶㴛)xS8byMIȽDNʈ NYtAgYϭ$RZ>C{\.U\ 9[K8E PUlyeJy P;/SVY累E|A?N]C)\\ߐ&ugoO}Op RvB%p~ˇŲclNy*# H}H'˗+[\}3N[z 3S9!cj- ivpҴʚ0v |c60'te, oRܴ̬\J=֬esPf *uNG"k7f2FSdU/&ySSͻ>f}= -꩜a}|$~qGLqAv=a`uT<a$E`4[ύñ0lZN[2iqX4xiLŽrQog 91 :høೌa &FՈ_ͯXY[5eY_-ĻoQ5x42?7o͓ANi 1lTP=$$/" 8Ғ]]Rpw2/r!r@a]K(GNZ}R״saUg5*v[7{h5;Jm`[C5CQ x#Qj` :)EiyCgLZ Bk/~,]>c:|U+JRJbWE^?_RUɆO|IgsKE" xA)<2rT Y/AB36&b5Y7_{~|"(2_ޡtmw#LA$u/+IKNkgUÐQD=JSS%^g˿JĂ$-@܂<46wd{Bi^~m&ҡ/>hw1Iz> FcO8t8D嘢aC:/:"<`qlu(Sn[vy,%<]w+ɖ\@Z+9p݊c,#|*Y޺tϼ;GQԇne28֜`r[wgTު$H CjH)( jK{@o5ܱ4?R0a?|I)hɜՍ/6 Q"[H)1P{h8NHM[[2:z]*IeJOG)jqÓb;z?bL9%("]\m/nD8@,)1au.{v^;x])s@۝%U%Mt<)kKV~ЃroS8RԒVà\"3*XW‘.:V{mO]B\甀*Ը+v d%Fyʗv!w%tP$/V̖]~HH d2B9VZBQ@2,B_eqݑHU\{Pi&dx'4 sO"E Fi/)l3rt1셖w}[q@hWVILe]2"MMʼn2˺a eҕ0EoKەdMHKk#Xkŋ1:T.!9Td /* hR* 'wƅxA5ip@rN_89cN_T*v6Y!w(@2o_Higϱ-9{ׄqfغ.jVw{#x%1` ^>`]5G,g`p8qAyB rCB{zB?ȐF]VmQ8kcv]-gl$%"x:klTyX06`>?  ǘޅ33מ;ν0{MQFVK$*T-Tqժ?B$R%LUZUUEEjms369}okǾN2-K{԰ME&Y2?7Mt=r"32!S{H92+!lKJ[KH$#mU>hUK)x2XUPi\ҍcA~@NR2hO&pKY5T[4pY1ULzBM0|~[ frEQg Qhh3s줞[[w4Jdhn 5QY#1Gh OM^+Ts2I˹Ĥ1=b58k#Cvr [kR[̫ lCsPC8+Y5XγMSi{ex$((TUlZԠen Whd WM;uOog;mgU-$jg4CzRwV_(T3pRJA?op}dc''[onk;Rl+QIqRI3oG*)S-ؓ{~p DtLKJs3Kbaߍb>i?Z M끹 2huUKiU )PYq i TK%U.ٺϰAvH|<'l0N!eg4z"*o-ld #R*Ţ;O^WŒ q/;!v1:Ap%}vxNFt.z1;n [}5um6(]p{0knsù|ESl(.)5~ִg pM\fs ,z*&U-2^7oJo@ƣ@Եv ʜp}~jzvv]&@\]%7! +d$$&+qUk5,Wkuh`h 4"Q̫mcvGk)y}vȳ0ֵϳr2r`оcJdԔey_i |$` 45 S $ Z(Gl5BvL%xLp4 e͆ H{f[pĤdq8Ţ BysGN,KV}o7nSuJ+qGKŹ)}wޖi2bJi0%,4WPX'v&wHAb骂FoH$ d}oBr.CMR`X}B~ Ɗ6 sOTi0w>l <FRJL oR)'vp@2̓î"mZ"áP>dždAHlw|KvxhOq>Ae'Cef`o8fЄzP^w-`4\OU:)L0xp5Ulq?cE?r xEIC|pIZ=ZG#6a@t#@+87vFxH*$@{DQ)Ah'|I2>RGc`a}^ .^98ܛ*-n- 8X&DuB9lފl=}=6E߻K%\6#qbt,/|{JxZ¡eSkm* I|+==e$b|{K)Yhf&8ux`ԑo 6` 㻰sxäԈioAZ cܕwa'nm {=BﯫalV- z.߸$WDHG}C#Z@D?lt~; :0ᤉ%)`+_>^//Pq ss P>Z0sp/\oXBQbm5>, ޸; XGG3Py@\݄燢yRJt ӑ7p`\oO؏IlA*H`jek?:E_"sQ;PS4 v#4)j#)s@%cb PCAxap,b1 oܽ`j^m\JK%Z} Zb/Awx."yŏMWIRK) pwBd>[qO~QlQ]12`ʵ2wiqUhF:ۧ擔c=2ze+A,2FWPdP1&ojJrt+Ul^"=^r2.n1w4WsO_,%}>c'zH ħdu4+ˆ~PG5؟e=YMmU'kDN@lV*BۏEwN˒iJ5Ǯ5[qca ;T--BpB#밠 @sZPwO'3:n6l'ȣD SF?Kb~!8i*qA&,7u}pgD4Pj8lmU@UIڗ%ɮ3ckg ox~ab̉O =R0Hz6b7dzǮ2H YCLl8o>H`pNw3 rwŸWh;To@g)0pO^L@|dB'XLeP r%U1cY{OClc'bR"гWL˾37Sc ]7~ٺ x@}TW[%{5yFx#J)>8J 9ġzM6pADfpɞQn 9/S%h{ӽzx|;|.,;<*Rp=> YN傝;MGFvRǸ͓ܔ #ݰ#o¢QX#7؝Wy\#7ОytgvQ?h1>ۗys d<Ђ%9i}e<ƺs|>/~y u`h঑}x`=|'r@b߿>UTmHRYWEQ9ūG^=P0ߑbnq`aM,-X۱JaxN\a\𽅖9ncJ,sxY,Ȁ qYre2 G@oLOg'd`|?;{)KMY \ yzx > -&w/j]fR j+ ]iʭ9v[}=]+ǀ-HW[_7rWo`Pq[ؖk䒏d]F9p'uP3r(kXwO]Bⷵ_G,Sp)(bQ CQ8^4@턬CA^0r5޲O<^iY6oIO{lԼГ&wǤiOCG"7zː ]/}tSx㣛ufZ'֓tB-u,JMQէJc$[ go47b)a"ٻr?TK\,'~GU 0=_ACAf7 ITcH&ԉ.(᷼pkiػS}@[8D/A +$^'lpp3 ۃ\sum`0#yOAz6| 0鹇1٢Qp xo_~uYv*W_d `c.7^ |b͌{Q˒|I|P"n)Hj}~ hn~vnW[>R>g0 2ŸX(CkC1v =>;ZH _ho9pyP/&}\."{lwTş\xg{7^Zg9ٟLq_]WH=ɻe¡LW>k\BtE7 ů7/x} xGWI,K[-Hmٲ۶رq5E Òp$4!!'@8e!.6a9HH>fF_>g]WY}۲puʘOh2i$gHuo+l۪arM'Ը рԍ썫DXMj#\\뺼~%NԠɭ˭[=:mO۪lJ[>PLٶyҹc?H~POFkskGhp&HWʂ=VM$ڢ ѽOR5o#!M)aMA÷_M\t#?EJBUeXXg x604ghaFG%+ɰSw|6h|VJsqXs.AL9fBϖgKW'+66U[i,joT CLkɰgfAзn9bsZ wL_UFPB}`fl_5CͨlOjY] Ta~zjcrh9[y OjoZ"_ٔK7UZ>׸ziU~1AHQA@~ʁ6$K/֓KVPjMujL.Agk{GU(o/pR8hêy5{,2˰D>bkd#.BQ}֨?/*^kO8>@).2(p m/Ԑ7y׫;Kvz_f4jRst[Wzj5z2ı^#XIa`XmbS@#n #6<1v0# 1=ve6q U@5ѽ3FDWV>^^^͞.>Uvϔ??֞v.<#x5 9*N Jō$Cx@\A:fLyhwX#3-tO-7w 5JH!y6S\ojCn{Kɭ/W Ք1+:g7/m/}| &ѧJDK&d7+pNДT F&i $Uא> G6óH=`Q(Cm_ QeFv}b; ܺ.9h d>sBz؈#d*!b|4b.EgG{O>SxC8-5Ó BAڗ(J蟙+ Pc(ɘg]cBSNev1n45<"̶1%Zfԏg-kzlɠ0"J1K\Beɡ&z+즚f3N@gj؁~!~awꠉ|z@yI#*.?Oӂ}Qgה9V'"LqRY1CA'ϡoٗM???X|GJ?vɿ7oϭkUg/|>77b-LJljdjȠ*U+h'g9AM34ڻH sJn· iRL׎MuP<AY.%# $b`#g` j)sfU(FHhd]wTEPl>^r~_~#db*g) kY|_=R=dCoF GRe>F5ܻaCo/58*ؒoP\u՛IcLh 2 jH(KAr`| JJh)}~,?Zʣ},Z>vRкeGZ5rvsLɚ!J6mH9 P6Xa.؅{ G5րd*hz~|a0)ʶolcf*TiL Ɗ̹&iSgz~2380n:>-˞tDcpbuc 6X >?,S$;} v[l踨zj6uYvWx|p]*ȚZ R&:I MEۼpq=aP2aUAU:+>KФ3~\|2 flb,'>&OWhgNzV&Uۀnq [q鳼U_*%ŇC\ڌZ@ԚR:,'BИe{XVAmD/"ȗ|$rCީ,0s៿XMgm$4O V8a'A ܺ}udo&OFŤ)7aY*0}pҜaѝW, 7wto+s9\څ>L>dtcvq5IC|7I™3Q^44n9ZRzm=t U4 窣M1n{ѳ W{aS 5|^ U\B8 s;®fSIN 6yo}L&aHD-~Z>RX˩Pܸp " zYc\uCcG,ufQWQ}j6A~{[TaT/6)dM1:c(ϛ`g6A/Ԗ49am>%)Pcy`+#g/-m\I FxmavCgTqtTz󍱂J]HK.tj=c#=uy)eDs]ixIG$\Q,ʛy*Q}z*շ*b\?zS InI Fpئ6^l+|W ZP34/VwJ;>e{NJߵGR#)wwkײE3 [ !K>> Ҥ?-`oG'uvՠ2:[kUT|)Z4v+)yOUbl}{־ŝ!=Q=5իлߟ +Nw<$34/^T/'v9.})aM.XlZ`<N_D!.-Lq3:Q;*)! XjF"j[XkKjl,Kzl͝6\aH>`J0"7oq8Zl62̺U^WY`:GMЅgg{İrϙE -ǘ鮫HS{lv fg\nKk?ҶU"U/cLijWki k27lW#1@:&0B=azbF5 >qCk]O}tSO2Fn|0tڼů챎Ʉ"&,QY;¶+0Ά0& 39znjX79[^'}%nj+bf(ajL{oj-rQ%kL <ޛO'Eᦀ .ʏy7b&??A^ -_paVoYYh5ɳTaEa)䢈*g{7DRC9,820̜xI2?Т0 ǘͪbqMZ UFӭu[lV:leJ`ݷUos"#(F }@ۺYJ kDIQDџֽTLbq`*b>n9:q}1ҤF; js0bQW{*;A2h|zwwƐ,xgD/9]%ל(bN*2]-"pٝ엕wWM: ,.bPff)H8gŝ0{poev A2{[R>M_nH<-r?^R`D,SUs}Ͽ\Yäa2JTX _@s_uzYdnM;T؁!6e?6Ap~a/wWϦ߽?/m4_tOCͰ3̴qgZ|L|` }Z{ͩSG*a8e"L>j|qG\&E*_UX*pRmW\;w[p$K[VͷOZ+[)(ITam[#(7S'MĚ[$E]*)IiCʈ6; _jIEmP@z,"؀2mJis }δAuK႐0lk#|bQ;sx9WZuW󾾩,թgDǾJE zw5xwmXypө6r;teScJq^B(b 0 !L7=ޘ=㛺mFE: =;Tim#}-K'*1Fz/`'d`Y0ׯYPDOɳ3e&Ol}`˟ dm D|*KP'DAf韞Tr,mN*`%@ZĜGUIJuwAY5B~wքۜY.=~`5v|5/36ݬg**hDv(`"f)_ *&ܘ̭[O(nˑh[bA44 $[r3O~/A΍H;}KhZ2kmb=twKϕ2*!WyZ '%!`BŠ9ql橙1f|߻RV УMG~y:vP?T4*MMhKYk7ѹGd ̏6U`[ WtpԺ39mdK:imbu{LKd@1X{IP.\-{"mdOkm*,vt f̀d0g/ .332yp2BBS?9èPi!WVg#Ne(k>;QՕK'Ot_5><)GIoWU?;y^X~¯zWʔU?+?WJP??|VI÷Ͳȅ!-dUG5IY/#}qբdz 3peNE7fMQA+54LX63:KV8U"!., uY**Cup[!d,pΖe~h;wOVZfnf_M^EoZX;9oZMh\UY}tAZ_QbLѧR(}&_d 1>dхmJ*1# BP S[dKZ湭3V w87F8&IΘy(dՏ x gV(/oW}7[&5:Q"*M6>_-2~EY?|koȹ! 0;+X^ >f !kvs ֯LQ3]7Os:܇! } `R Ҧ0D_  *p k%14˦ӫdP@Dqz3Q8qK} @Ӳ蛴xR Ptɝ,y9sec^5] Ǧ9IRܰ3gGXw@xLZؾņ2M&^s^,B/J*X^,[1̘S ocz/_mٲWv6ّ,KOi`/dytD|ǟ r|c;qX4?QhZ``0Tz_>.dg%γ 4I [Z' i$%"Qlxq8ޕDR'gc# ʼ|SHlHm q1̃=Q ̷$ߵ:ZRHvѢAH LdyZW_p N4BTK3 "jN9OE9mC,8Y"̭ ޼4oYMʰr+k٭ ֑ ]h]DZ2Bt V{ɱ]I6nUa^ì"{ qFq1+F̷Ty;H SͧHja߲҇#ZSl,cWW5הQ7&u9~jRJ=E5io.E" X|ALRȦ ;7=zX) ТQ4ivQhMԭ<n۬M(z{'v3 =p D{Hj<~Yȿ]Qo^F[8lEd5Mp4d]ӯr2}@nUaTs v=Y"$4ف ,N/͋+i͍uYJSpjvgi]X`%5ƵxDO$K(] 2EOFSL$OP> ,Ҳ`I]iS_Hh\D?2TC؍]]>*w @# ߭~#^ o1(F$4w;IЪ}i+JY"[R>8f޿t9/]dצevoƺ*4ژ.Ҿ2V&7rd9~&&w&Y $,dߞe|Sp1@sfSU]-{H[㫃{HYM6'>`&;w,60,#cdKBe7ܐ:rO{IGefXٙѝ$ x%IEO[yO$IePzL]ۘ́-?Miҳ1=9{&{\~. R>5z4RA K=|e;}) K3'W{n3ԭ`W^ʦ'H #ٹb9ftQJ{qgv* GXgX2D^v<,w7皝DME.%dVk4WqR}NHaX`J$Q[IawEZu B4G⭷1ñIΚL/i0?xi^; 03w]A6>ҵe ^o8I4q8Bhb ,洣KaGЯ%E#[Ic>xߠ,x&d/j}wI4ufڈxy2?.ew* C\LZLϋ82X2&t07Iw#oFp8[hŷsp6'GI93J{S. TSA8'(@>c|kHT[y YbіF ۹A!^T^8!rpXqRUAlso3 #fd[e"1xy ϊnsxv5 d֏; ºvY}QP4m"aP zQ ;82"$ GgQRh]EG:b()M<\_u..Ǐt>őAmFi9F٨^ۨKd.Ý,Kbl&ͩd/L^iqRٽ;9 RдL8\{Tndtw{m}),SܷJA07x} xGW-eF%lql%[vd˲%;dҴ4=GG`%H hrq0WbKH8\/ 9 !^Ut {|W^U7yw*w⌕czJWt%eԱ6)ęW3J&vJO߼悢GW=)}}ji3kDU[7&e1_Sv'uPzV٪ᯝjr aC7)k׮n^LlSΆnl^yfe]kk[OcگYuXkT Tm6̔nNkQ-ۼhAOz3Mє:Rv[*)=)ixi%TuC4s5Ԁ B эeK7+fols釅3+V| 2 j\7WK: 55u 5p~5crhiˌ; sCcڞ(?T}"WzciEe_,&q/5A>1lyO馋i}f88kF;Ѹ뽤y=Ö\?T9RO)FGF@6aEY<0Y-gXHKi-@WxZlqh }\s+[ҨQ+^] Ĝr ^{pU3q-MѼ|LN?>WVo^ef֖myż [㟀Oؚt'T=@zR$ikGo:_\M–QSC*[uOz ](#琞Ȫb c.2D!z`jwU K\6Ÿ&שh&;O@\,L DM_D&L8#_J_LÊ= -ր|#D$.9܃llRN ^ϪI$smK.>a٢f$򍺄Nx~|c- s&'XIȔr_]"K|ͦ]?n:큋.U,82b `ޝu2h`om/U H FG,M6 Rcs_|~Zq*R1uLqrk꾠E1iYZ[uwoOvZakтtRY G;G{[wh)ھ >L)q rG9ɜ IFLdR9# ݠUV$;l 1Dta*1ę-エ_;Ŀ~yQH]p F[4xۏFMKR 9߶fj@7LQعO@{j:iʙ$ p hs+<^ĿٽJ4{%aRSGEr:M&uJ]MEpt3;fv~.q.I9^"ԙeM$gn3KĚ݆Y=$ԙf:>T>[#D5[OV;LJJ`$DL6G$jKGC{Uc·CKx1i*%yJhY81i>`yވkvꈆ|i͊ Njntz-ڼp:IaF O vqON4irnȅZMJThO๩]mY43Ph؀s( ֭{**y/JM4,,SK)NvqH"][2R T>9Dd3V -0v(ࣔߝ\wyHREE8`ݤv.:wM0QYuOil=r̓lGW5M{cpS®@Z:RQDc{H>`G\9q^mӯ?2:Irt>s9[`W{{K; l+X׆MP f4hCJMfk?>B{y}2Rb~4]'8;?\x*ΉPoy4]:7kyJ^AbWL֟3O2?=B[z3,៱ByſXJQa#:U=; 7&xSfA"FT6L72Kzi̔<)–O/ƹ"eWBI;4uy}vbJ߯Ջvg 9%gѬ~z[m#k ('b . ctP'97FvcMKn3+1?e&_lFhN=P 40P1vtidz*.9c:Y|5Us;dD]Ӱlҁ5 ,sH#s+"i( E9 xśI0{Ězӑ%޺bYi]~`N7X )7xYb]OCyΤF5x!'~HKJeI;$H[X&ݻg}a$H⸆_K&q#m6M>ISO*$|)l"PTw02-Ry. Z߼:"\$.e_>1^;xJs%~מ$Sa!uo/دF=um׆3VTٗ&1͓ͣq-%(ee&mWѕE+hV c V￵kܵ~Ðп<EU`' nL희ҾACӒ?hkŰiw&lnLZ>Ui|ZX!4{ߏ_*(qSz,T%N?2L4Sm3JbJ7-xw` ltIR }h,-VucϻeRAmܘc`y_t_~SyWKFZXERryЈfĭ=F߾~OS/)WUzࠖCyj2u|uQ D4ޫ*_w*~nZd@:1^)wtOWd F& X.LKty w-9"ɞHׯ3FA#o~Krvt;WV[C*!WIM{67\2i#7Ts#6*غ'npVֳ13l F}gNpWsn 4i2훮?+oݝ^kgVQ)y*j* ()?jAo t ,7Klbڠx0P޽Æ.UUSp [\m0{ȵݡ<=i[߳e_l.\!Dx@, 6`E9oJ7 *D9< <#K|m8^ƀ̂?P8֒>PF4orjڽj7r#dfoso]T![] "{X;n4" ukK\lmO6@$}f6:9 %B1BxCy}6}j> >XS_讓6?~P $,;M3p^~{EsL+ 37uYjTGU&܀2�ex8YHIuӭ; /`.Tt1]bduBǵ8:!'oDY9ޫېik3ybMh9eJ7}*a;n|| uָ9R2 sl"Y@$H'HƸ,O31swd*) $Q%J {KK4EV/PUa:p͇W ƹzۇ5ˢߖ>kf 1-KzNd 3'Yҋk#pxʑI~G4$}".$IF6NfY?Zp{?T( ]MBy6Ӑkkl]w~lE+2 @%E:4cvkޠҌhKD7e^؅g,#1͏lEPtFVg?xٔ8?Y;Fـ6u:dǕ9ݣEɠ"WWyPI5L9q*쮅şxU^L8ʭ2VF* FG% ~7d(Kgi4bO J~j"v5s׵H.Ts*$h+ÃSfGf>q#>NBV_G%87|j.pW)'ˊxMA# B 9^D_ʊ0zX${#Ǿ3s*wqt)[@ӠVOl/S ~fe>ϯIi2&SRG!;k Xm;w=)1jFI3KnrG v12 iM0;xk.ڌCIO 4<~g=0ԇҵyya7Z`2cY#7C@~Ad{ 6&2/< Y(5w\恠'"zƨtRs'9m%Qp ^+C*@UϠKAAYwv/B>BxڋWftV:]5_ve_MK| /ny1$y< tOG}ĴO8K%80 +]ueROZXF,e̦T(|[z9xyQ`3X*(6EWPӍQͤيU,hw &uѱɠCq l)e' uq35תv>Ty HΒ "^{bx<5P)Uh̹:a"c?PW>TzrˈkM7&&M/[/?fSGEDb:`w6 Ötm__iHOQ3dV__DwuukX. c!K$AxpC -_y5Q!Ч"Gf.N<襓7*D®Vt߸:OWUЋNas5%X1 28f =Ԟwsya@@̯VîΟT,*F/0IG~5FJ>"vRj.5,׾} e)ʄ$&u._8 pXɹ1t861ʐx դyW ɷPd ŧƏ蒙~02@΢t5R-$xXqՑr%efR$p^âdBzC ^O?ZtTSm@xF(2?E`)&G6F!㣏4.=L%2dRyfqr`&ƫT)+<`fm, 8|@ݵ{$e@È\ݦ}1:![]~j_Рn"<O?Z!=Ѻ{%}ف@{ylUy9T`mxC]u q_|5Yc'x"^"1 )WWr%<ۧDd]1s0xaF`x=_~\y^Dg~b1O WF% mǟ_4&{'[\.&K} ~6.[//Pqdei!u%ک'`G(E&?: n1$RR1h@P ;{ՓF 04RS56_v/b~Ë5'b?j,>h t  mYF=?Z:>i+hQwP?j.6flF;v0 ]0 Ŏ[LޤbA옢[ggF&=i+堷P{ OQ-zmE5ब\CR;RUـB AL$ =XɾEII:1LX%H7I~Cw]{rP:G|S'tꯅI4$P& dOܑs/ĴS¹0y)#xۏe%U%^d`;ǥu^Ǒ"'׍NMl1fbMMD3bJ5=&TEy愗L$leLZt/S!aoe,P@|;>Ӫy@F\7 3q+)tDʏtK`݄w[rE/5%ـR_ۧO%ԸjW>-P&^݂R~/-)a2'oF 3CAzJj GLge"\-q6ij!{unt-^QeEѨqwMdfZ! 0E887ƿ'/٥y]?y}nMvnU?[ΗrD:TkHY yL~U[Hjq¾hQʏbEq3e jEceaCpVym(趀dSxQAcK= Jy/Z*= 6mp}ަM2'ݜz"LLM [$GPQtD$e%6c&^c Vuʂ/Inm[2_mrBxW~Ҡ3kcG[Q@ 0F B~RF,U1(jעcYs@-3 `+[g,TS*w6lXNLF2Y KXsPה[T R0+k"$t%}4;Բl!+lra,g1PeyJ>g@Qyk[w33c-ɚINݾm[9I8Yc8P&6m9+s޶Ԟ2Y8sJPrH˹0E)m]@t&m8[sm9jaK{ J lY4}nOv_˴fƹik\撟܍p8^B 1"w%_c.z3w Hk(xYNl%ۚ:˴m8z5#;bUlq\`f[Z-qeT\RlE>fqqjӋƺjV計D`0WF%t,4oҝwT|LI|U%L_TqgWD aPgcT#Gθ*^ŷVPBLoDY 7c.s?X*tys% F1UrN \id< +ߩj+gZ_ icfdSf#֜C}9?TT̯bynئVaWU۝W%x%$ iC D[&#fcHpsƜcEMjzS5[iOu>^*##U+"4&uT=C٥\450M5l8Gj؆q+''Bl t%hQ@ҧaˏRHAD{e}I˧)ղbG6ZeLZ5&AzBJ R ĵ'\ ^MfU2_od%r_^+.jcJJ7 c+Ž e1v0V I FBcrJY\cD;yd I破la32G-"6M\@dlaΛw/&'Jmv eX-66(T3iiӎ^Nx/u _@jޝR Z#S efe U7`h8V_.<2}]|HQk`2L*GŰTNJaz,Y!Ĥ@nH&I5h=؋SR+&Иn)>>}9Xj4TEpٲ~q%b3׹Q$۲AKCFJiY_ӄ̇vNcP%e9c||`[!xTX뮮H{o}Gz>oelǻu 7GQ[YJ݌'le{wZ$ .m^y(YJ4E/crқXM E 0xL6Xy`% 0Q0jNJ|ҹ&͖+}ϟd c24[0 )sb+Bqafc&ִ_|޲5?7NRxZ+Mܨf&&}UNY\ڽkjmIxYh* 67!'T;. uvN;ŝZʧvo[؎5S_'CagVvf0!wme% ς]Ug6 VTX l6J~mCym%b?u-ӽ_H4 ,%H{Ö-mI\q#=À ']{`gO P=_EP0e2 Ixi`mv5MR>/tsۜv =M~zԳ35ɧ_T HiȰ)d LfF}3ga eϫm|u5t~?69-װT, k4Z 21gR D"p^Cvٰ8;Y}^P%áChwe*|]n˴a;svֱ Ž3QMwwb4_XIeKV?3 ٮ+%#PRPu7v}Isw'[֏Ux,Cz|9?`.LhOn^}Lԅb5{a čd9or;X[QLD7vPQ:T+3r&K%HS#H6a:(ٖ:R+c TqEw4ڑ2yK24a` )`U,tskuC&a@r3u 4`8N3 |¢4(V  C̓I}0 %23MkLk b@ԉ 8Bq/u`*x&*^!gLu?tA}.EՌN.2Gl)C; w9y<{nD5S(eNWꎛ[nס3jt:}T/nR.{';S@@vs*פ@3Êsn0#Ηv9tL g-x>mQ7uiê(8Gyfz˹q[4;a-s ȖHD[,b+{Agm]Cm| |BN;@y]W85E[2~2Ƹ26->֌~8uQfd 9;.xގ=o8Z>'}M;^ʬq{@s 9(F(=T^[_tJ r{:[ wc1 `(ylj? ϭ9t# :O&+ ߍ}2JB`ia_DrƒdlID}2iR3T?[Ewr|3W8 GXbMC9qU8qM|y Mc▉L:ΉJXlZ{[,ϖ"-(?v:y,H"Ȍ.6&eϫR<{o> "p&rye1&{ؿ"'$k1/IZf]1ߔi[uF6BurVXu]#rj^v'ʨ=fIx7/8+lKG )ɯax9kl[y[R'$[dGKdQ|)Y/[JyK^C Y u:CmHx6lZ V\X[x6`-P ѠZ-KR ,=|珎s+}dUPC*;_?dVCUMd BskzL/PC$9VO^*.4L$.TSOVC:YĄ %1k=9᷏OmA}^[6y͇h;AGYQK1c*;Leb'wʔyoC*}jvw:<2 T9O3}uցbXo'ҍ|LTJt%$$h){<T,݉Ss_Naf_s%ino?_>@\f n^ǓHW쯺ғyჵti1J.+9s1͑m+\#FiT!W-7J)kZ3:Н,9Fܲ"g56P>6q/u6 `?U(@ bmԂ9](7g.4{}Ykk: -79r&ƼPst=rG$O9G7'UhWGy"wQa& I Mo<#&2Lr'i/IK2 6H$_sH[@3-?V8<&*U`X&D冼)2!gK6(^Ta6Dftgqbk ZdAbE2\']I"s6)]/raX>v}/cKM௺",q^}aHB2x#_6sU,a]t>逩7x x#*Z2V"{l tG^R4:< ԁHYhfg]oAax`1/j&!jTlʊe4Mg? S#Ӂ ;\oC`af(tLv>=<5H ~w8?[%G.CL@v 4%23q4lOwCYϲK' X,^o?Q8A- _1#u$p1N4 y`i'MmcUcٕ2ָ5>xW)GFlLR:DN$m):=IfMB2IQMU=ddǺ!Ra K¤OަcXDnUQWO"hP\hK8:jp/:p ςP+N^X- E~x8]o 8$C0̆{:WR9[* h@-a-AgKZQɥ #7=֍ bCp-ƃW) +!z!몉$tTk)0$^g*#p֟^ b>|'Ihp K \>-V\U*wl")7/ˏ{Z;X݁N LM3}TEc@ÌB%_?~&E548TkS7v%RAaTk+U5Kl`\ip ȍd%7 Ae`%bjDb)Aύ.A0yJ`^Lld9<(h] & 9G9t%uG "УGkͨ`x= B3U##{$,"^@E[Tak{cGoчk=aµAr9Ԓ;tC7M!Y-~޿̈g./5U4}B'_ rfQt2)>&OZTy[lݨO8tfCa KaO#XTd&9\ Ui0M鴩a&[Y1c)gLM<c5FyAu>J/̵UK^Q"4#ğC+ZQ%Fsɺ(aolYv3U߀<pl͟|I+ܫʏ_?v߻??G%ȴY ڦ(I[agrPmļEaJUTr ]ţs^:gǡɎuV/?!oTYӢ w aiFň$4KFr y}J4"⊮Fe~Jх˛ZM /DDPb"tNMD 82&:ѬUA ŀ!Qt#,(5Yd%$"o PjB4!)tIu>RS^]\oI!e^r0i)Lo8-R2:g&6NoM[40\N{I!JMM$Ke7M&a>l!i$3Kdά(WUcW\1B(Gt/tvRޘ,&%J3zp&&&=eeFo֒M}um G#|lbMNq~ IZW5/`d<*QUyd!)!+C«*}rcYvr/d5L~Tl;R@5: F:/Z8-o/9̢m&ͣA:xz?p*$9HŹx.Ws\rPIyy XCڷ~<cN5JЋ. Pl7lيjG5F$ l!vJ]Rn^^՟a!n}Ņ%$R򙋪 fEk|`0 s\X $o6e):[i: )MBlT#c[ A!1 p@ /^FU;TƎ3g(IvM~`:> 0)w^vI4M Q`mhA12݌A$y䧎1hrӾҙ}ӿط AE#Iz j:r4_#J[Ӈ9>N0T( qv\1zP 0SBAaɹ|5nB^ / Ånײt2J "&>hDI֌*B!p^OA(A._"x)3B,- h<1pɵ##Ipld4j͕L֏fI5߷v"hQ[`E" IXS$rV,%D@`)fu35*ud2_.[i zf )&ddLP'kb:yM(7ٯeC)4 (@ WX9Fd!uyƖn30uc)VLOEцwfRނ-pmRi\pTpkT9"9{I*`k!f@B2 x^5 f!i /qs!=Mz<)&)H%K^K 9FD.Y:Ζ\.![l[g$U3Mb M|Pē6s=pҘ[N*elxqze#ǂZ|51Z3CFb@ "֧'FW-q2wMX,h1-[ᖻh],A1H~ ;ikCp-UmDx:?6БRؽFDІ?ne`/)Xh:os8| S l:_K%2Qdã{+>F([dMHe[׆Z>]3a]##pv.W hje+z)]= qb//Ȱ@F6mNlџ/0Ax! mAFc&0 36A"Br̐@uM'm#RzIO+. $VJ޻|#ڳJޞ&@W+\# q%3+ 9pR})]r6o+`,D&貺2AT!5V$DrB6. I;>&q@Hru1IUzIÓGAc O6)8/ΓaJN8q*Qݫ >-!\qSH?8pAI@?(} PczhDHr|+1iI~8 ?A3i6wesbt0=U g jDX9jb"@+|xl^Kݑih Kxc T'9Cޓ1x%6]=3tKח sїD7}&G=lMK{8 fqhPaT@ˌkڈyEĦ<[@!A)@|/Q%:m|U:48h3ySO QK20FwC3ŇRa"ͤBr Mhv͊ xYGŠGNpú!\FN9d ?@qH)0jOG\J!^goZ>(ǘBk;w{l8B6qmvhn=wcbpG,8NR%Qb,u(3Jp!e l1O!Csj-D;&~x @tܤ5Ia ʯ.Ż2*!=՜T}†̯eχ5 Ls6JsWMV 2">ʀnا[Ügyx_wDc aEP(`z:ypUB#oskXif<RF GXPI6 ql}0eۿ!_/;Hݓ{Hl}[xdY.NHn[H:/ q4M?=R8O @ݮ(#Ȅ1kdFAY[򷈺K""zT%JzsoΪf}1{@Ršq;-=Q4QBiM8;6S;+;;xrn-Y2>XGw݄!_=K:*6oO|,(J1%PDc$;*2OޑPP^#fS-a rj] 2xw=#}Z L?ҏ-"E?lcU?( ^n2oOQݥh;f+Ø RL` nDXF3W0èk4!E?7f:i&V3D>Ԙ$&e-_^ֶOx.˘蔷='x 0&D`%OL鶰NC MwSvn<7=.c$ ݶXa|dlQSR;Wxm:lI8UԽѐ $%p@,%Uq|"-?aK~tor Kp~;X cR7&)>D5d.܄XV}#y9L5‘GxZ *+9=v)ۆGgu6Gs+{dq4̶i0GwnT_'ijh-J,$x*,Sw>DZD|lnYbQ.!=XyFs|\㎘zI5u _&T+kh=ǫc.LGC:-h}.o@ 0GkEe1\DOU>Xyl2 e?ձ;~T$_K(٤,%gz}kD_;w iHI1TR 0;w.PG冧s@KrkOW+3XĀ ɑju{&ϭϴX,cT}ƻ'´_ɳ0)f# gvS˲]G&T8\Ctg+V ,y >\2YjF)?G߄J~ϯLl*LaX1EIV狈%3_XQK^vZ*ZВ85Y]ɺA ~ AΓ]z2ڱYlƓ@ژ?'yUٚnZYkP@sj=bmhK 7B̑GR|7*Xq)^9ac֗_*{ѲנPG|)O#`CB:jM{)W*'^)ZP8nbB@%|eSr=oUWs"/^HʧvJ!%`*Z=P2ZsyXJZ],*&g_4oJ-ogC.,POƠ[4ok&]z^KDBdzŗ^_V.bƫ0E|Fksu"˹҂I*Ys@c`e@~v>d?]SNkK6cΎ[2gh(!h[Eo..[2Zo )}Y MS7 ͸t>ynXuyL:^H~F#7|Y>hqi>:Rsбi.>`eEit8dpy͹vFj5uّ> 9֏䩏f %kn`yMP+Ok;’HḥEyXFtPa!s>1Vѹs\Iz8o,M%.+jk V.8˃cҸl;lL;쐉)^}tfҸ?[b+v73/[0jo) s\}B'+٩ } Fm&Wz$L'0<[X0*?WɠQ5%pgi:#ŭ,qE dq+<3?ad-5 IS܊.W^}s(e\XbYԄXFl.uV:}8;@׶m=;;nnJ_rŋYW>R[==%Q)j(3+ʸ`}(Z `\VU%><˸Y5+(9gʸ"iI\3R<@gB |l^lvӕ\̭^-fb\[!NiHr',46p%*0cqe WևXwpK8[U1RkiҔZAųEe XOe+PYKNex?0W[ǭl쌸)&sJ2#=gشے(mK91gJGetxQ[xde ܆] K +|H}d5re܁Xƍ6M?Ps}Bl8Es~5{Nr;S"Y3 Qc3R)0vRx0-MNbI _*1Q)2sVg,9jlJi! -lO)V| W|kh᪳}I*7hjST;VnY>%Cc ^>W1yM˸ QAiIZ )Bl`Um\CՌ16K 1㖈sM53@80/{]ľ;r^X%&bkGkI]q]3ZWp[)k8s6px?G.rzu%W럳=&VqTmBF[MUp9A>n+Ws%ޭ՜ȴE{FkrtE5\A,J$ўKxFlY22WgӼB_;̙^NѮE4OCsHDRg+XRQDw9sf2E>>kzo]Uy ݫ1)$8-GM슪ŭ[TH!qL%%v?G-J8T\9Ҹ7"͏"38͜HI2ѧ V\DL㈆50DG& ֒j<醽V[ݣe:ogMlljWEY tH") +/YOaR2\Ҙ>FI';sQ؎(@Ȫmj̵ VɄHPD聣U5PbơeA;w9ѕ (AY۽CLjrNKZW(j9W(i)Wdn]yv(TR9{j{po-!E5DD?:0p1!4fgUmSȃ_~/ۅ3 {w%p%8s͇I::3Q4.Z\8t0+G>I (q6j 䐄oJZ$vnw?9{ֶB%ȳ?kbQOIpmVpX)]-` " /@hɵqЊA.ƃLTtԳ]ƙȎkҠogfCБp k |/k|p9bBP;*{"e93dC{u`GPu$xQ#gA#?_QVCQˑO/38R[u,p/<*nD4C3$_6lX>| 'kIזiXdί2uG櫋@NA %Y@u$Q:$^_8ExFKc}-%(]=ّin`>s)ZhP 2H rKHb'cMwo]:,2ϧxg96лM&3Ζa_bfEj\ڹ{vn+<"Wʹ[(jJ+q ÝU(v_e'@dXQ ԽtSr,`~1eNSm+!&J1b"axp/Bٖt-"n6aKR{h@ *D<|tn\lug;{ G4L Pfp[^a{Mv9'//Y~9(1+A:QAېrO1k2/'LU[.4$wpi i}cqW& YV޼n13s{#Zx94#T+җ#.nβ5oTT݋d9!ci٭)E"'ɱAXr9`XAu8lΪ(ފr3"}Wo#Sx-z%za_K3"D_.LaLGV :vG6}~J\AT\fGad>4̅tץ6!P3e.z\?;:=#b?HX3rعv`93Dפ/[N{\bˆMo /Bn}tcRe|n7_n.5R[K-OnLLbnkMP6CfO@X4Ga>: -zp7~xi 'S +ۊl㕮w\ٚ+{J0LJ*a g;>QK->;P5p/dV"3f׭XMXu8'\'3d[ҞC*$ 뼪Ɩ_*`P@Ŏ:8Qq53i)VoTp/=zdo⸨B!/Zݔi]'A2f9Z!%XḲ$Iw57z!%M v2'qB:-Bi!M}90N БtH[_.r jticƼEr89]w|J#<?v 361+,Xˣ_\^5\/^ G!Iţ DliEC,-FvK^Z <`a؜WXo47;sr1/{t9v59gB#;yçyjeeDBjgz+wcXT7fU)@a-z)&{NJLo /LEEf"WQZ-Y5G0@e,6REaI^LT[yCp,TX@–!WZD^b$vix!)QgaNɢ37099"7&+H;KlrRyW˵t7\wXhJ?k $F/]V>cfBs}I > קbdr|7oEY&(<ܑl ٕN7NtĩIO3 rxcT<+72+i,feL;H}<`+鬘9|򡎢 R.?#;=Ql0h'v)gՏT8L5j.M=2n =aUdeъ|P,bYؕ?6yR/M4 EO:쟸 Ma7TDx/upy2wL iN6ldeYɣîx37"rGF\fԬ y?7>*YḶ2`{&'z2m*Sz,?$?ڄtR jIJh}粼>- ?u_?Z{8kO?|]V/|/վV^="0Éo< [y94<aԂQͧfjly7*)=3M<*.t/y_ ~\CM/l@X/Ųu]K1ӻ]|:OxL!D6ЬQſ?0"t_EZ"z^yf(߯g\y$RT3-7e^YٮSiFtO<}rx6sXgyvͯ6sӕ4W]Wu\m}0T~n,EU <\o<_q]M%%_x,4Oఅ监 b,<[xužN(S~ĆRt!ooX|\N5A d"DwW)~!z`d}bOR1t}tpw*&0d_>']?ٳ MOZXok ΢Ouo!5.l[5KQ:}f6{1TG "_p<xQ,Fwס :_.28~]f)hzŗʽp ;Rgbx֬b؇^^SAϿܹ“8C/wԧf%-#UD>t h^_@d2$-'?ŏ"2RA#"K@.>9흙GݻS~7{ǿN)ǽ^}G%m+}J)1Վbx\^ 9EkW{*vNO^m/1vM [;Dld)v Fn'`U_+Wѹ<}`k[|zs\OGcGDRC !nً\]'0(|Z˒(תJFE|keS9R->hIt$|Nygщq^)Tf/n+}|Dpۣw\phhmI>.^D6*!xF7ZFWG┛5rhtz++lxv3^`26ֳ@T_>z%\4> 7e}FAYe_+K32̸#GStmM8oѷL a4If^DA !o#xs}%a+sh4{uaȧ#<=jnqKJl[֧^>\*VsM[x9sзRɿSGn/kV'f海A[xFs=/EGq%l#(abN 9oJ7 [fӫ{5ya_~;Oםe} ]!6CT]7Jm)P*F'BČčYӝSCAXIc P0ރWOǬ7.ڊ' a6O66cDh/ƥBZ*n}ԥB7-VUP/uEe0QPfN4s ) DQ{Cy+_|"H|A|H!_h|paH/?^9!eBKVTL߰L`^?~Χscڡ~9 ŵm+[˄]-MEBHJFDZ,Tj/z0VBA\9!7-\rHhY+Λk&r>^YKȸָQ|HOl-&z0 SܘѽY>G 뜔FCwХaQ]*c#65)c|}q#I%>|J/gSpSe%BB j~铵Bl l87LMl/[ aK)bnP_ʥ?5xS,m\8^>BIL)臘놭LX_w e<7 }@]ʱt>^haw\qCz5\ tP*u BK ch7gx+Sx"L}^MM+i_ZZ԰DJ+Is2o?+W uVaȵ.s6jHFag"7*-@F2s[ǻGVPjڜ[_XV%GޞLӶ⿰RIk˽0믭6Yh$wVmi%1DE,_F[gE_]wT[E>~[陕0@g~^CzyԨG3RB`[&_pp?x؟?a\,&B ٤KRlXTe!GQՂ5g7 MYnQJI.ݔU|F56%#2"O:=8"t>[d<}|Ёm7p+ 4ҷR^1ΓY諥 !f0fb/k3z凄ST!>$ F-Wz3eL,҉b%l&{r̹[sm5odnj7P_ovmW }}oj I栄0&TՏZv+\Vo` ]3֭ K\½Dxksב ݿ^ئH(1H` 2znwX=ᑥg %{2TuUވ>'O|w7u? ?J~ƑyQ & h=lA}я'n0zWvw2+ > ?mO(B{?lnS=z3N3zM{Vja8V0'|aN)Ϻ~;셉w#'}GD^).;H[7ުƪ1/'xxp=Ea~oi~EwO˳gKöwf uF:heړ? i$EG7~da7%+I<1yςK7tifo禧Ó70-|vZ={m~9FY/넩^ ;;7ƭɴh޹8ix=dnwDH{[a뭳U^:,S e=FF]7>^;~̈c8Ownzf';aG^aof wQZ!{+{z7pO/Nyn=N>a/||)ЊEϧb9VW_N}v*XgGD Gj нm| (3M!4_pNn|M/\7 ^ʘ? L l=$,zm-M#K`VGPG02x(!/[;/`AhA٨@O5w<~N,;2x{+æX,1-'Z6 Jx m/ L kF= xJxB ݗE+ g{?\&'B{rIh&_c%y3#̳Goĵcs."SGx˪0Z68jRSޭAt^3Lk`nUVz\f>-آuiXeS뀮9ء ވdcwm-{~̾qH;-kU# LdQ= x QE{'! bŦ~)O^6#`Pes2#Ǩ<@,Y~fz] XE;qW2_5DXoKQ+`  - 4(@+3MNS PGRPiR7ی)VYdBk^ClGawjʐVchnq,K 2EbǼnB=[%Ŋ=N&]]I[MfeN:R3WѩõlߥS=a8+իwn T`s lS`f$f 2{n!ߣ`'Dq$Qv_A''#J:@rpJ~DGQ֎'#Ta \Y;Xg7qʨ^1vDTSt +&/+T1CģƐ+ "́@’mnmwzg 4ɉ;|D ,ykKNZЏBQf}ٮ8- ҩV܍&j`Ӎ @b1q5vkvOTPM,׏F60|2p-$t}`RwZ7<>v `@<@KB 򭠁6R86uk.CO}JO}͵ ;5+>uxk.[vk.UrTzgj^[PVf% anw篦qwc/1Ӎ% V* dnFKL=b~Ĕ&=ّ;ݑx)MLiQqw}m%s8~R_ 蘳6 YY>C T\.?H|Dyzdg/1*D1R➈%cx'aHŌ=R h) 9& xL{`kZ Ӏ}k̲x` [Bx r G"HJܓWJ fSZ[)6hrsx-f%W\?1o6VfXSzK{;gqdxk p"p,m@#HHtIc- PQ R@V:>̂y,!e%SZ Nqc;m<+O[Q>KP08E:_uمIBs 6E> yR-끶HFmmM|w (|=3Q}[R#a[J0@2a7^,1TE_SA8_yd Ў JSۃV6$~޹M) C.A}TTzߠůЦM[gdS_}+S5vA]4@5Kϯ7YK4!B5!|||H/iK8AXK$ۡ.T62䍁qI:4uٺFdsMEX6P$5ɏ%'d6oVN@7L3;*6VAWHlvJC̞\5X ܙN<NJ4YyࠫOxzcɏCwz:{~pNU:˛ T2դو끇m!O^ddS-GTn(4md*Iaf$Bj fk2\Yu;0'7jVdgXrrֈ+T j<(:"9LK _bI,[ebAzZ {0WE;!mUj\)Fd{wR/iH&Sn ,ϰ vd<ޱ-REie\>X G9Y@=6 u衾+gƬ+H&&͖Jgz.]a H2 YbtBgQ*H/0-="㐔c*ljGXBXTT0=` 7 N'DL7]r">#(Woɖ\%@a9!yf]lrM4bVNq瑷wadF>:IbfwD8 ExC3Ҹ,Xx"J;کjp=.ybĵZ5%ps1ffcSo< wB%Q߀XkTc8^4#fy֗+ !R{)HwazQ!^pE)>[:ZaQ4DKBH㴕w$ C}_|)J}1뺱}7kΐ,Q<[CӾ#Nu.(&#R#Ҹ}wjX'_~6_; Klи t̷RhA4l.`QjRZhRώwiP9,D\fA*F"HR݀+lK{,$1ς. jϪ`8W,RAK<+Bϻ(.F |^0ȁc4˱J2Y39ƨR&l1-xV8(|ævݡ97 boBVDv1N-ǰAπuoA޸p0?ekU M֭njz5mLur1@gaS`λV)~%Q.VwOr1xƛ[>cvkKfʹ$N$eyĥŸyāH}ZCӗ([j@Jm;G34Nh7~7CQ(zz|Y@@_q^2z*5֍U4_h1a]j\:!2]uaڕ8䨉瑶FsjL6/]<-4p^-JZİi:S?Ѯ ]C(aot֨kjP7a6Kk45Gói44,ݞS**&c!!`az oe"t %cD \ʍ8yT2eM@ɦa)T`6A0RfJqn|۰싷pY’ !Lǃe^V . GXQ/8UMvV/93‚nG `dM&MViѵ4WY,Փ: JXw͙cvM&-eFz~O쏠4Ee%/s5n66:Jid,֩MSxCҷS;olz/)8:EF0|ĹE?a5(h݈FT TO#3pu6heª1m ޣ&2S;0<[,S4(a/d?ُak~wSU(@a!W夲 5Q)Hn`o}X@S/(ލri%!>y0)Ih0s|ꘪ|\F=t\;^%8kGRٞ4jC̡B*p^4 ٯ`GL,wh4P?͘GHi"B-Ww&Q'#%RaaL&iez4w؉U\0Dqz:8xlpQ5N{IMƟs``JE)D.(hcdҹaLsGT7˺&f43_`:ԚT'+% XI·͓z<WN\Q C3pN6)UZƍ;TCzY¡Az|5= 9Пҁh".ҨPNӒ C4GΠ={mo-ڻ|5kܲX3I5M8aO7Gl? ߝ:@Rebŧ"xvQ5@j !g!Pn}K̔9!IS ŻRW:˂iOЯY2 =P&:u%n! إAZ ה3v3/G>5o;x[ٓ]t^-$Aq4s9w:X0qCPq1A= iD.ۊ^ ٶU< Z`uF}/8N}";#%a<~ 0F[qؕ/cjr'hm Wٝ%+Q*~G-L./s`}h\/aoSFU0\d1 psOILb^+D5דxHfLhd@~'b N~YH^'-HUA߹Krx>U2I#C.볕'łԠzl+N6CuP&ACg.DpTs~r}[ReG^$(*ϵu&?'4Ë8 Q-qQाnIa>[R L{N(h|VMn8~1))O KMp;;0)#0 pL[d,m 1xn NЖ\ۄ2B2rTgv_}*0E=G bxǢ쑮FCXҳ/pJ6H1" z.Iњ}Tk)׾;=g仈I7+d L-<gygsSLH'ỵVubM_R=Q0)Nr50wqu+%Jk[KbV.=tImW~mr]eɅA:-$l2E9.c8΅(=-Jt4Yˑƥ4UV2HS;g1!Rb 9ӣ[iVg.I8 6G`bk<+Yj?޴]aL^*9tghh2 A=aOcz5X%Yb8 n)!%˒,Iv( χ~DJ. ږZx˾D?Lq/;q$'b8z~ IVêlSѕKeA] ܅;~}&Lƻ收 .}X$onUn4u/zH}K$*? 26qhr28C76mlNS1~>E PI>l1v90Pd)L H0ׁnBe=&iLn7 0̠B8+!n4J0i\H!vЇxpǵ58˄= %dY MɽB/w0 KJcݘECB^\r1HdhVP0ܻZВYpa R͡r?i7E<9uH+qtS8 X @yݨELSc!g b䭄rn&<}КØפpeg$bgbMp~K8^N2uٴ)ƨMZ6n?\hu@i'0:(&Ý(Aq6oRjDy1 &$BՀw/BL0B1[nDmTUBPdr¦ I[%i=G P=tA._‰]ӟ;v;{9-]}L4 i~6Xv'Ct5Dm%KVT%ðg B⠃l r(ĩtF9BJ/(Ws.GYwC?5Q+ǧq\@(qPcf(`;ABIQƴq`mBd }֗1" ;GAXq{zo-+a6I' '+p w.Y_ŏn5}+WEi,(G 1S&1Qg9cT.4n*ঽ'Oi$%ςurO$ ?)_"|EƖBeҧp `ݞ2\gZ%M˻cP@b9&ͳ?WG$cw|}GCpj/&띌8bbf6vr"Up<*M A7($9:PIN殸4D'*_5 'nI3#b.ᔀKÀT# `Oޓ3x!* M."7.3lWo@}sCRݠ-tYdQTH_lKEQ<  ٛZNJ N8ou=g22fn/7[Bq=! %Y#_)&&#svOIq2uʋ- SuԸGha="@"oaד*/ӣC+L3kGf=Y'䌼o0=l$﷘wVA-QbM?[]#FUbs$L=HG{= /^7}r ;~a$7t/ S0iμy¬)Y5 zp@5o-.bP~*^gf' _S2~\' @ P,xr qgVY7<"c%]Nا c'O&{~ c|wkA7iAٖ> I('՝ۿ7 9>d\SI+{||##04oUg[x 8,nIw-3>BX˩0Z>F3C)'#O)_v2lc;ޙ:! nYP&z;q_JB~6Hz_[ Zpߦ!Cͻ}Gl4hD kﱣ؝ccm@aaBӠq yP)nCI Zq7NR]Uӧcb^2{yZr`خ;j{򉌰:'w 6{l{bbC}ӂ*q܀K@]BvL5o&ޱfIquѶŀ)H^<-Y6vyV-BeF<s˂;FStRws:o T^_p Y̓{P`3ǁ=IyQg?F#ƤAz›I70",@RDϖZ:CXVTu.B_G[]h:NBH)<{|*G'ug`W<>AC=#!hAϑa13Mu^spvswz9ڽyyq 9G'a'ZK3 ff\aw)>2aИ{>EA )m;P@}l $g1?EG"'%Ve,yiLA-t9Y";` TT` DPeߴ ;@! Qxd\_4PaɀRϯ,2YS6hiZnXZ(A;+WLY)e8`z2 Ua:@ӕXTJm +Qa7 vCo A5`Ze@0 RoGUb(r 0E=ΧMZ~ uοO&IU`fsNU+W {H?bwz !780tՃ`T@tƙ )Ct.QPo ҲD~`؏u`C)Ci+@mԦ |-%?M}lxcnZӘ(,Dq Q-o= RHō޾Xذ9҉c,#_S<.,/LfGfvAMXӟ!me Jӹs;hf?Հa)#{ߌj--Ko7Ev]C]w*69q:ڟ`oǍf3셧l%W4&Cɭ)xzEh&Ӿu6^(I X3BKw -O+wER XYca $0/\Mh>O$сo{ěwV}۷޺|.D S5| jJZM!N j0G!w8Nၕim4ծ)od0NmΧ6+(pcs;jFN=I@͐ KrTj1ᆝB~=[&t ^4{8 h2=fgVtgosMIX䑈1i[ >гnv4CES„.&ſ{@:8C8842x ! ۃ^o[IM O>Ǡh\qYckFqЙ?UR7lA; 9'Ӿ 1 l9<rj(+6-wr}n'-PKf[v)v"p5<~Q̖}=\^?bÿ3Du( < $Q|: (qz]J8M!TӞJ[.k1bl|>Jm+ڌ[lAbM,ԣʬJ6ɈGԇaXm^ Q=ƖvgQ|oR}[Bsᔘ5m4D/JV*a,bBRU]Fig.\s'dޛmi]n\m8aptJHvE-!Dy1Dꗋ}V|?gV˕8f(R8,m*Erg->ص_25$>3m!5cod AI=6g|`F$WOsJ!doGұчLO=*WѠ=Gs6PKNl`D ha1ǐIz,[^imD`A $~ ۴V"[jy݁ Y~mQb8Y1A/Y_9upeມ u{Y/J[\ny̻X|\C5qJ9́"ߍ6"lRbw>d{ ;R 7]j(&@ڠЧ KriOGo[[~w8speWkyQsj %DrC&95.砜NaSq#ԥiVeSJQB <џ/}܌3ZlFM&:ǘWʌr {Zu5B !Aj+[Fw6QtY bS H2(9 vV v}>팤E( "Z)#$va Ύr<42S 12Eg& 01kJ6aW,My[~*-8IK(!DGQ1%Z%3m4y蘜SA1Rэ$nZ٥ b@O\*=0M+;>A+yD[|hisT'_X&wƺt"Ѿn]E&E-z0lY:`Yhg' g@eҥ.HCAZy/@Wސ?,wSqƊO]5K*H}gAԎ瓝j[(3MmqŻKtznvDq7^+8?0PRLpb+_(G㖾!pߣD#9snJFeY3::l~n+=}KNXܘf2h~ʜ}RL\ytMx?cfs׍V3{|} *cB!ەUrN(.lj Tmyi㒓w@7f\mG'WZBe 'lCBsAzP]Yļ{ICo"[w"}z ա^#5{8 PUUQU?`?gBhJkIIW<4 QXnBh^/„1~ ]ÌBI󙌩|1,27-oC[ent/yY:9oouK E*$266;e].vǒjyM8x cnh~iC&<_OXo2tS!zBfE.I*DuZ>,퀁6*S]Jpd|6# hfW/,CuqH\}YqDL\ h(\F} cLg٣A8HLD;@OړNz9/ZUZumi8<4Z^D%fٕVvW1LTK/r?0־p{B)?I\Nֿt^f thƞXlȩΏz#nJ9'QXsHZ! })[؏i{!݇7 g6' oݜ'5Boj23ct1p)cN@QM78(zuI:v$&O>V'yH 꾾l#|^s`k2/@KX yTb]1 mXQC(XA$Cw:T/5KVmR.v+jȍ[Щ e|&^vKm/+:N%\&em],4:Ԗ4jf58݌9^]YAV0c`ٙ86 []pkYL6nnqTo]`Y10|d|wObf}e5Y9NP[g|C'9e-0^U{E-XJI)I|!B70 3rVʾ nXmRocOJ}$e>H<d E fzjj^Jjpis\*vʱ: r)0:X1lW7Zq\/;?!֣Rm p`ŽPd;Ʌ**Wp[vk9hux"'"h=.]+Dאv9OG5eH7k?^eXr<REWdpV\rwCI@M^;?5v£[Z?gr!(~^$qG3ca;bFo6._ɾ8ܾ1fW[On'wm!䡸d,a賘a/,M~Z _¢q822ʶva=+g˾I p0p8@SvZ!~e{ſ*oѩvUybS7`~9&MrTY?%P(de0r5\+'8;Yqr5Q*|Z 9?eF٨B4ve=+1[~+ɞa/NVv"KHJ7]~=mMvSܛourbF Ί~<U NY^y$GdHx{F @XJ!zCШ7 ZPmzaV#ck$ cu': u*2銈tjABq'mAvBBEk뱨i$ r,I{Z7U+B'1tNyƄ?oX-o"Zg|Ȟ16yr1 p3P7t3 zuHNe}+dۓ~NO0DhExkq8.p2=dy)~d_>NxXfs),n5ꏍNIN =i<&?V;Mzi; gM}snƙ JtNw I]CFZwOa&V$ Snil?Į"jRr= q)7}I#\O#4)EQ.K\O'̫SN9+;.rʴ'E˙#|4o00<ࠑ$م0Q Ǣ\;fU,a9"|R 7*k!XtqxV;47l'tڌpv]*eym33~čvW+No&m>CQ"gl;ʥtgON+βyuybn@NJU1ޣgMYhAl!i/Hj/ %/J\J׼ԅ`N r`nT<ȼT V%t0Я]ޚ^ùFঙ }oxm{Vmu(X ؏)E`YԒ I/Ps 4q_;ȦOwirW|?|rZihc;9rMصFv WwBpL07/%^ڃ:Q~YZ6!UkX02(~ODZxuq8vѰK:g Y M2@ +頭YK, ɫ2pr n ͎r@rWtY Ub /t{ hȝf^hEO\uSm~nзw_Z4*F'CJ}]A5c̫N??)JF]S,?"7e+¹'nJ0f!NZr0P][8 сi;PSqQ1[\I;7; GN Qꪍ^pwo^KIAG`祕Au1FSouˆqu3a$$쩯ip ;DAG'qNS4И?7ϱv(YԚõmȗuh;@]W=b=U͞i#,mZSXUC"Y+Abi~ؽ䬤"UW֎rďҮM.y?p;k2܂;0݆> ~S:z4kR3K;}kVңjWćIu tGT5~2SSέZSY7MCLb01mzb-NHJ2Ree3e?T9`/rS6S46Ϊc )|tj侹{XNo:RSY=yj73=+H5B.S|us}F[GMĸATBt͜yZ7qр8ʔ6IXlPnH(iE^ӕ 6!y0p򱕞T hv`-;3ռ\B1ALGRd3*YH*\?[TXBDuTT4( 1ÈI"sf$S& C93 C;?pPVAxĂD9;4f^n4ALl;쭅]!NPh<83,1#u1l$13`(rvjJsys; ,eU9[˜?s'z~$+ aֿZkt碈Ӧan whg1 0F{=R܆H˙ xhH,[JIϊUS~?wky`uȩq%uvx.Y{tKPw{kk]y:+ eLEzOٵZe O;|.+[`6U\cR-!.ۡ|9k HF<bn(~T)Bo'<ac -U԰ ^:P՟YPXꣅ4EoM1LeJkz'Q@7L~!r 'dco 2,8fff6 Qy<[#`Y8Zp#ZTxYp6 ;-Sf؝m3ܭT4|kLg{CN5%6-Z$ -*tf6B$.xv^E|ဲK,n{v7 ڡFLՃM23ZPo$ )UWUR T\h/)Fz*z|8Gnkɛr~b3fYεmf.{=Z0S=wjLVms\-^0Q[Y;D_) Tr_1I匄$R2o3l^]GEoij\bZBޣ>q{t u {UdkDǍ͜!l]Ly;ys ]R#o?f܅Kޅ*V،D9ʷ=WLPSsjjrϪ H%M-eŸ+ 4%VΫd\6)3qtWI Br"cAx-dvd~'-=y/򑈌Cv٧ ;5_G3z*P{r?X..:=oߺ3BfcnA-af cDbK>%=kJrZ|}N`#`tTGBɟ@B)jwO`U2+%9B ڲW}ō}ƾi:̘Y%8mڗmԖ!,Ė:xSH-e()LIC.@OMk^4;gjfvɹcCa.('ə0 & bʍ)񦸑95hPȴVV@EYeYd" L[I(`Oka҃,m? nOG!ըLE<",\j5XGl0quÿ p0 /$ڣoшLL)d(JҗT?12OX,`7\ŻtOKT;yxrMKr}CӍ6}u<>gd>p OK5#b(!䍡]&C~bwp@ى}//ʟ_H{Kǻ؀s^2&f 0\fCYx-- / {T˱ 0Q. y*w=JP)|)=g.K&^NM˺_@3 +2}@P rqS *۳j(%!@2"Lwom2h?&Y4X 1GeEߪ2ns'G0"Vh؊T4D(1Vc]Vw$iQLQ]5}Qkt=Koii 1wA5?\HISrS/5ZVkD+ُ ]튴`Qh-[1,aC?T?_{c~>7r4gә5E͉ >2Aj AFaکߜV]Vsz:Rzob̍D +ԧ!ūK,)MTI^ dWFm_MN#F,¤I0ә/*eBh*"W2p3 T7g@]gNp͠OKy~|"@#2.G:ghR{/q\GyQZ 'E/a6uSW.lN\l׶A%Azy7 p)Zc"^ttڰ YC'OmuTZˏkP.Z-6:E0kb"S"XD<Ԕ ZUXL%^ QhDr]>HC~iF;Q.#zXHi`>?O Z/T4>GA;N|oۓ*,dc_Ovl# p0u4 i! &6Cx- E9 ޜ Vmr$/WР:2qЯ4]di&\ؾ~T `ky p4!q #zXu>ùq l*ErLDٙr@~eYv#1+6{4B>K"߼/0] g'U)di v4#2E YxGlu S1 w?jxSNH9,N0 E4'VyPP PI"Fa Sv/crk⳰4> g/9A`1 /)U,qJX/'y/:KUI0η!ZG96we]xQ>ZPצ 3e2I s\satRћ{J}q1 bXLvxZsbOٜnEt uJo@!]=o)YRQ8$iХ\K氻dj"~7d`9F&nD.EܒW.טX;1m%By ?TtuD6vǽbR5tbcsWj|IS=?dTrS4 p$qFt.-8K*w¾IuV.W5x* Piߪ?=ˋ㕰; {x}y|DZ| B!BJ[2!#|%46Z{ dxpӉhB& 8s$/<'s'Ny__y9$9WU3;3;+ leW3]Vb(P:C-E65S#[]7JQ2*Q#TnDc@k<+PQb]J0آҳnݵCu;U/:bʺҒ `dA}v?oqvRPvBhԹ#@ps!+-!P9M=G ] (]~|z=Q +}3V3\ST)-X(e5/: DEuZekrh# Pg8ZtPʎR6uE~W8 { ;:cdYmEMa=+Jt̻'gÉsJb;焒տ8__t2}f?3Sf^_v٫v=V\;gk-ȭ D Fp߮uT{N}z}G3gm]b}v)_8wOq,=\"wugXX%~xι;o̭gl/>wCk3ed5حܠ6&a Тvw|W.GI,[.Q]ᠨk%Yc],d*dCv&f[^s`@RLMf.əL}_,eY\?пSCRÁ0)=*("#MU ǔVUڃX:(ɞevO9o^h~=[7_FgO>{̣)9sy%~_\_客ߟ,ׯ'߭k!@'Z;)\gs ÿ  HݣEk೜Fѭnз{}x͂[0ULGT?lIa[* e6-Fx2&| ęgjc4P? 1SVXe>.oQ~">-_W^\ffU܍K^l2wueoY ,zdvQY~WRщ nS~6ƣJ/4QRlB7n}$ 6'A~~>uq,gDhzhK޺ʼ?4K|}Fݒl3*\ٶ*?3K߿=>T3>TFx1TPW5fȃ2ݹOzzwvWz~} meQKW?T}l},mh X)QSߓ1`ʟźgo^@/?J;|Y5ԓ4gFl}iS{!̦X00!ρv#>BQTyf96~6[qF=ڃ{{ U~)3(ܺK@}kh-F{`)}H JԳ/ݖ\(O? z[Δ0b6&T>E&4ѠܱV~On#[o oTĚ;Zz-E-9 P[ag?ؤVVF&ȏܝHVĉLq/K^>~xuU;ަ8}lVEUTqCYH[.|2@?2ng!j'ʪ+gjDjĉsȷ ɣ2;pu'յ"Q=õ/wBEpF`uMxߊEn"3[pmQ{% 5e]8Boah_Uɹ!܉~OϡAQ=ʻ)K/A6rӳt%\5?+g7ET5Mk.aE;ebeW7H[A| (=pHX7RPz(C4loeξ%C?Dcgbb>_i"uBo:$ڑۗ;Kq*຀9?rxmQOĽˉߏ^93~ n#zw꾹MnWlK+շo\=~!s?L\Oޛ=yGکok{*/T- Gn(P5/COmUZ#ᾨ$[?~&w0D% t$;޵({ŲX?cݕ+^C~O{rG>ب5{o} wb ܫJ(y\yh5y:յ3/׿~Qț'ɡU?2^ TYhroTW ޣ?0硟MO>QoJ`WzGMNTÅaKHc>zd"¨`{ I0@TSoҿ GNՓ=y|5|rou.,o}O(Tꉓ2_?>[gZn]v[\iоt׹EzϙZY>Y^&`ϕz˹ k4Jo̔tgXmcJ==8؂LuG.#q3{';_Aݠ~^1B8K٩?^+ZkK~⎈0FZsù_ءǾpb?ƾ@kgX{ỈUu~K@c!mSGpeVZ'wռU4J-]F[=zy~LDMP6Aa&,qi*`*^ˠBajuà[XNP8ʯ@Uں E* TV_^`z% pd̏"~ꮑԑ}G+hɜX(N/ziG{v}X~BJGU_B屲G_8kV '~t@_ޥ}1he7[gAV|.7+Gort%PvM?_"=l[~Jw@WY2c<צ- PjO8O/}WUlcфn3%)e+z|,]Mg(!aD?۵yT=$<8?F+Ě8#VR}^ Ҭv Ɓ,'xX⢠<1(N(=?ȡ ^Ex:ŃXBP t |4 ON  C&b%_0-?ogJZ3m^]+<$ ȳGZ-A+\Ԏ9"LGB~ ]Hhb(C()eآa,Vx޿8 tTY\5VPn:!Twy}zW6f_WV?lČ\>s MdLT=p!e w I $N“Q^Ub4po{m $WT{GC!U.* B'8m08yFb&_5+,ncT:ڤܲfWdK<ҕXU"p$WR_fM,j>mae|27/aelRYY\ 5hY?3}5#9lRâ'/@8,_ŮGfUR^-&a먰 r-3J= |eg7m܅ FGE3A(bA~B О灟JV[kH;^1?' ȼtdu؅(ܗ4(-Hi(c!k1F{$4Puhע!:nAc!W?eg[Nb`\ [ȕBWl`JXD~\GC,7!IE-6%'ExvA0XbqW2tN,Xd5bh5>h,OK-} ZA0 8KkZF Yu0- ;(GIЦ"˗bD} j+ph0 3}wQZͽeTVSհ3_207pL+yjUԔj_UG3:! ]m:v#}"$LJ*T[UUk.&?clL8*:C;گMsJ0Rq#Bu;CE;U~+l*7Zj7*5N9ѭFBjP)Vn G:i2|0OU@JӅue*ͪp!TAUKB* eyrGq$ l> ]`Phfm* ףeDluA`m"\Sd$1.lwASơIrFL妖0%aq/,( uJEIw.}!?8t=A4ݥBSc15ү4P[  \FQRNaZp0yt/<k˔%@C,Ynȫ(1g}`UT-vbV9WV,6J5|>Vkx>R<&_TOi%/jd9H̎"i mN &K(3u ,ZL+v9J޴̖wHuy)Ukq 9di1#ӭ@<.2P̏0È5,Xke *O41eN#bEHi lEEilG:U%l"Mxﻉ?~-CSWX|;frV㩩!_8jJgGgy,fV멩gYa)T:/FE;rL,% &2郬<Q;_DႛoFfVXE[4io%zQ1*Uw nEu;@i!s-~D[Z_m."걢wgV ӷbOi5VVZhIC b7 _VCUF4zOM%Ϲ.1d=~K*+ 7Wd]Jij-Kd%7{/.!^xTU8+Dw!c10 v#~]WF+HH"wfU@1u֊v2ZVK h{=`WwsMu[;ْ-$_'rcQ d PE8RC,t戓-X/Azq,U`{8 Bfzarx2t<.ISLQv&[7M`bK;BpaAZ4KTH+IبM+σlgE/ä*q5?~S^]Ԥ[˲ dh!iMKχѻٍ-Ƥx+ӽ8Ch }?F1 +im2Nd۶tؠe1$VǗb1 NȾ5g2;.adg9N{ s'zINs?)%뽦Qo)C2xt2Y*Df^ 1H)V[Y)fHsR;02P[F( ĤS83prML;`{ o` ç;9xzݛA%Mh\gz2ń_!21ѫ3 l䣾啬T:Ǯw%1C"{NL̙7'a%СlI}L2IS)0)r0BfTCKzU$2y c_cu.H,9ɓM 6n&H/ Uy׎(0{>n(}h'_vTj PmE)D`b}~h9r>Y̧焨q"~L .gCKjw VQiFc`g#8\SB4>QV4h'"ͥQY0u3U$?] ]ץ~x$B[#dL6V= l>!4=[V3T/ç+ GY'Mmo&aFNfq,9[,T)gKO MsSt4m<̬ϱ}',ȥ<5 ~9uT-X~"/=;&a=M_ݰ ,\`;T`=U'PuyQtdzO2W 0 c,I5v {S㛾Š@w5TԠL%`Q[w=)+ rpCI*:]UOՀH)qBcLlԤ M_e?eu[}]s6k3IEb kH` 7\ trLxyiG6lUV$wN8TT&7LX-NT,eE:\W}w0^PuR uc$N:MV ?}r*)̈́UmHb^]0)9YY![V2t]Xe)JYA:~'g wp:F50|RI1Ǎ.H|}WNX%dPjq m!5z^T`S?qFnXbx^le eJX_g0@fW=D( ?bKVߘE0tazݏj 6?c_m/S` 'SSʟ [0yv Ev6o=/bM(f| ^Oy) LY@aܡ" /UfJz?";igsx%`Cj_>!M9ُ@} |:=2 yed[ű ~|ae^/y֔4i)( A6'1ōA~PRҀ;H^ _؏%R 3ְBS7i0ۏV9+0 9B 11Q~*Z5NA~84(31(I6fa T#p~6F^ ꈡ^=3":$]}+q߂~Bd;p$O.p6湭#͜INH0"PDH0X}낾pABY2VGt((SiNf0yWwF'~`:X}/,cFYyyr0?C\ȏӛj>߰L[yFL:LgV> k>cqOB|̲gg8Īj3O-W=3`5 {\) )dJђaIwP߳*KC-mgY#%=ȝ@gv kZ %ܻBއyhG_e7}=<$hBīaݝpĸƞ4ΒGl hrc>?Z ;-T]k"XYRsbvʶli"}!!8`QjgmZɐzCdjC+y1d=?gJ̡BeyKj:D˟87lsby*ܿA{󐀰&IN 9 xryUyީdd_BE*omlԅ殫=gTɸSMÎ 6>itsLxrᤳ=-ܯ`K1{H~gބIΝ. ʟJ&HAf{rph [RN`Zs9#^%2KP㹱"=h,A]urϾmWCpNK`mos=u4;؄ rQ '6寸Q5St*.x-u,Wx6#)Gc$d>qEF㯭wO\j!I{d]w=g2R#q+5,X ˵X*%IkIgf5a<)ѳ|t~K{T |EUyuɥ"]V>&AU]=vMPW/L!3] [Z y)lk|9V@tXoCMybfZk1H<5HPrגU;=#!g[}+Śf _+gq[ AkIr!:KZcad/ݠbRw +*;d dcJ4`bw g\YfaY})>_[^eL Un(G_˿J7/;ה*+5H%a9 ޜWYv#'l9j9b^Pi[X Ib=3H*BM#pPO&)򰢝6xQ<,uq]2tps]LSSMK!]^ÍL2C❄y;3 :Zoa  3; r8 L䲆3;/,D{&~ yGl|X!{i h7hy_e#9" 9';,kubq;^J1O)sCn͔=Ec4ω ~+pHȌ1 rB zVm=lLvDK!r TVyN8`9n܏k\КDs0WŻ^mF#lݏfœMЂle}Hou^'K9"^ 69캒)R lNt@N\I#Ltʺ[׭!-ΒeGܜ4&+ Q;+-$.RځSc#jKCd$ Ғ0sn _˔'4m*P زf%w&iA+.>i '1%Tĺ/"nQ{3/ XnY`9CNia[՘"穜,Kʩ, `Pd@WuxpD ?za tqyX4@Yo$ܦFVJ MךQTEQ-Ne67)xTc׮`*5YcMxk`g@i B*9wv/;غ@D bPJL5ewL遹UvAD#€ v0th- _ [ppSyG42jҨ[Li?aT Zl3!vP'4]Q<7/,Ps*ӭ Jw1} r0=N84<ͼ,8 %e*!ԇ`Gۺ8LH 4n8br0P^u&Zx/Js?G9;hۺQth UKj%FSm1k_T]onCdi7у*Xî1 t Ai RxZp̏E;A@A (ԅb*F7P'ڕ0 aDM *}D%A6e"^NW+g"sCCA7* EZu7hP{*JQ9hDT;,@ຄ5#h 5}Ws!>S(% Jh xxR{?tU*+/.iD)-?9ei.RCGlfEOnY[6CY=4cU6 e6YH m^M\N>I΅9#}ͭc苵ao4(YZg(-!O8Li uJJAbd@{9:) xuʀyF&9%fv)+2Z@7('{=4In6l GT4Z:02Ÿ% >LҤe-5RrӪ{?h7vʥ;۫Z i-xTqOp:JwxUp lNqabO0Rl`m^"d=`kMS0 ]?4(:LIWnۻ N!ӐEB?(.qucfi{wQ{4,@ Z 6_iw̶bcX3(/9 :>Z7,x ɐ`@*" C@$P듉&f> {1X6QfN\r􅞤q04<ۓC{]ug{kyl%!heM$"36>:IB1DZ߬PNGf ,ԞK0FnbS}7䋙)@Q8 KO蛶[h@iJ;855;.n~H/,rK  a .X:lX MXxFY0ĵ?=qBNL"6eK݋&MN2)YSr+dTv&" 5!a6ZDe]~tB?/巯wnq4"@yxwXlLȸ OLQqT^*[_W@ȜH?Vvv S"'uiٹ j:YݦIK}4s{"d*2^<=&-d;ɣ"'&Q[#TC1E= j È)=,29&'-g䍆LJM+h0- V φG2ak׾0ns(MXs! 2A8ah,ЎmګmoVV|J{$pZJbMi+瑱V!]gCBCg](‘}$Fr .&E)4C<͆AU#ED  cQ[X܅HCrdUtkW~Ʋ%R ME /Lv| e|k\ cV.L6?Dr\ٍ>0.@=#q>!S\+}(t<]:5T:FM..F5v0JR 'sZᶦ,![i[KX j- ZnJ[[Z\c9a+-p%AWNCayr`> 6 񻂊SYw?4][`6 )k:0PZj}ӂKWt16PJ=%rhE>|)%MӦ7\. dGچA1~+ِ]]Xq7#3d0pwզٰ#,ܱ 2s/t{1;, F@-QM2:P T@G ʺݭxP9nkJ<PN 8qG{mpۃ2g|F#m2Mt~K#"W!3ꠙ'8ZB.#" -Se?&y5/>%p&!7IdW!bCVAHS!Yy{ B!"If S[[a!vhaDkmlmD"e)%I8y=ML @m t($i;nĔثE^dZ^ raZ0J哅M-T>#cԙrI0Aۆ<'ӕơQqw $\J5ۙQYV_⼘nxB^':̹0SeI/Α׳ЊҴG #sx󭽐f\Wjo3$k/8"ǂͽVj2Z+0%I!jGSVCq eRlS NLR]9-p1ߋb%bĝFQ晓Y] Qsμjع':ֆOk'D2+Lf&؄+K*rAU55=D &M9qIL7jhRKmđO) ň=,y32N4 'Ojܿo" bc@ ҕi20Zo7rn%owG 9e زDM\y*pY6{]N$0H^1~!34T\]%bmBPfN;IWv`[c,T]j zӿF%hGҝRJ,G H`ZS"!QUffKP8Ň4!zF+b*ȓf$xj\J3L?'2X6X`Nbe"j#yX1Ƙܠ &Hn+u_4ko^eVw,Y݊L `)jVVmd Kf/9UgLLyؤB2G,ǝIXEYv5" GԎQ"NŘMlmfYG3uv%rp gÐ%9G/IK "S*+ЙJ8/ ~Gt,$'VWJA~P΀3ֽi#(s|wq"vKK.Ye`[d:TC\B܇m䜖_r6_x}w|\gqd[dK$K.W5WI%cLݳݽ;Y& ^ @L*%H !|S|A׮6!~떜?,]==*[ך)˺5)ǔ񈚈q}=+S+i,\I`İ"'LM5jUonZ6,7='G5[.fqPZ.+ɻzT=\Tbu9/i2Qz8I1Da~aN֡A=TbXѓ l _M|֨ژRroqyJXK\S$|MHIj Hr2Q?`+|W3~ax0I0顓>cޖӲ{p؀B)ק ֜ j3=+4dtㆬ"܍0'.@M5K5jhDō&hˌq.=ywtڪIYCGHK+{zmy̆ZA ,f0C}v{.g3iQM`rQr,>qg*a]ޗk^T5$,/~q=0-j 60&}.p~%9JJ0T$Ȝ8K bq5QOV\D8]824ۮ5{V#1.C:p x8z;23=g0~C9WT C5J<Y\h4/L5EVpqQ5Aޘk^;|qO$vlbS+K@ 3L$(!_T: ?+>hJKAMe@X9 [e ᤀ|B65 P Ay y2AXq|"'&: )Ʉ8ƂX嘹5vV>4M) /b%$SNwEδ=A?cj0_jύrӅ^9h0_ /K<t@ L܉[H퀄y0[?PZpl|[09wg#̩ԋfŦ\@lq픩|C? 2??8/Y*}dz>)_}WOboFR 5lJRP{59:ۼe1REP[۵̀.M8>sͻgOL7qUxl[ruQ> g ,cm|M3L0lcU kհj#U'gWNv"7IRecDfbS 8A \' IN܁,5Vjy:SųA}rA _oMUGNwM W2BH#Ok>(v[ !XVp)9ild'L瘿k^ԴlpuhO+\40 Z&ԞԞm)AS$iQK"tFHUWy3`{T \\w6-SbJB h[En$V[8+|eq|zuz5 Qf䭄 f$' *qhM4Dl nLrtaPtϘ}‹*.h)DIysAV5taڈ@(pAy\6/h1f+2I'i#)1% jz}~. eyūf9k&ԉԗy1qm"'mŁPheMvնB1Z]o[QU~%Js j4jT:Myey@::e)pTCJBi6__MSZwAUMR(uP2>rgKkW;Xv{L Yܐi'CmOV5g[c4ɧVW, ߚͯ%\XSQ[% Rq;W. K<)&E& r?վfY֢Ivvz ӯ=o_sLmu{ږN4W zTT`}9Bbۙ%G@ Efsl24p{CIF9 Ѣj8,d,Di[8[7_Z}6woFe}~45H|'l[C#N G]LB/pg2]U P @]yzMFm|eo޲u5Yɕ`Npevh~w"lGwE{ 42ia2I:S"-C4T Xcty_r@b} 3 ycO`-;NF Mj[/7`YX@2bي֓^R.rvmOn4l]QÍR% KVR3XACS{XEkP^C"D}?*D IQ24^R~U0a%d7 GyŎAKh|FPsKe 0..wG/  ?7)Tx_Ӄ c q|Ҕ 1.$x]Vr{lزwAavDK+{K'NOČ3/(s ܵYV `LB7biWr@M~lRmr=}~ǃ9[$f40scZĦsʣz8"Uf=义وӱg<)|r21ʝ==:YM6,7R?0(iP, aHm9KjlikuэH@lQ6?,0?;P:X#nؕ7m, |ݞk޽+ ̣4w yUFAĉVN8|`e23vƁsfW /R1@ eP}c*p,]A43͏.:%f-2qGH@s M6l0pȝ͹P/'xzmYkL7/س>u3%-w{ͰQVĔn\fEͩ @Iy5{؟rnOHѐ۳shmD NQI^aZ#tPOҶ1k*Flk3 ^hf]`<zg/\83}7O.lJh_2}s+Ǽ좼]pZO/]X]Ԩ`^N '}`eZҰ11JY]`@CfG_M.Q1@ЂEz2x%l?`xe $dNG,y؇Ԁ[Yِ6 j|U*w $#= 9`^9ܒ( `k$pPFO0_ k?aRAjYzQxє͙Ug?&yi+4%ksP.cz<4\8l<\1u̠גghdl?y2|bd{&tlAn~7ڴ񋋌ԶY䲀EJWe<4';{ ,%6ݑXXSB$Tduc+NKαp"3.ՔʦIΔ,4y` Jmϊd~mX>:%w!j>F"/H&1Rx>cՅ*?k3~{lEu*LadjHeKS?rÊt&0Z\0gþA ]K ;h= ^oJ=nȀ.>E6 pLv5 =quDXs{2ФGlknSy}=u~TrLϐip51ɡ3Y MY})f^ql; Jx2yw8u 1[꥕ =z w<*ZH\ۉ. YJjjA=ZG)02F-5v2\Kxb܊99fxhӕ $&l[0=w$* :q6hm6LD3Sty˕٦+2ivaqmY }sU恫fi下%ߍ5tiD7-N]=_zf3Nbl8cgs2Z#|VRc] J(:ktcWj)Fk2Q-9hpQ"5M,W綝C+{1^\3wi=)NFygg"q]9@5W{[;w?)!4~c, Ibj;+v^:a{OC}FcRCECa-l>v}O9^i~RbPKtu&C4"bR01G: w}Hlr"Q⃚; S0#;ʱr/wNg9}}㌻!bL?t2xŦ_oP`fM(":|nvt;OP x=5ꑉ/MA^-euu]}Ydnzūx5B pV[2霥?й.B?A"q!tba8n9P9SVxvgca ڇ5)=Qxvg/%>y3[&\wON-iYF Y~A+GF50_# -Ioo/]ѵ]tBf>^Iy9S 3-x*`Tp|;yPibDvv$F҆SsznpdJ@Hnޚ.nzTp- o||~Edde%gt9&D;bz0]TqGGﻡ|V1D\NSϼs2yaSd2߿g(tfU  I!Xy7TN//g 7 {[Ȏ ?ߝkc=|p?GgYdζ`J񦮁8 poޱA$o5C uHIhB̤+wݼڼfGg(o@BJ3/ 9~Rs9?ޖS< gN".[r ,oaVn۱>Z4qf8ɻAƓK7qr'ZeF`tO[tO? Xv1pkwT fo Fզ0n$OLŝYWאH$)+(B A=(6~r!7Ϗs9%C\o/G1hr<4rg+-Е;qq> AۂhB!-Nt s԰#eL8uj_UL4TŴC-zSM}`8%#E_Xqq'q׋~|}xm*#=k47g\o}GwN)>}Z%?!s?] {!2(dҡE>'1$!5 'o(eF6}hُxDd!5j$(KSx8$2py $c(%.؉ ّB(-W]/F, dG%FFJ7?hcq)1i.NwAj붘aF5_+*+O߹;/v< oDFy("Cbڹ6>҃`W%=T'bF-Mqh)䢝<1۫GZ\5_TxAѹ\T`\!#h!5REXԣMaѦY L] >ljJeA #]X Equ6qi4: XUJѠ*1aJ?wڮQ g[B%~U< N.f`q=gF~1JaRXGXW'䜋2pbbH@bpKg8ĉ1` `/rVf]ܣͫ%Λ z<ꬆp9Ӆ'8?sbk*у翜Hbk\[c%<ƀHlQCZ2m0sy 8y=`$) w`Vg;W<kǂ18Z{( N߅%CO9HLtLܓ?.!~=\Rׇ֣#)5Iu\.N,' M04!r\FN~Dqt.oɅV6;帮\sDw-yt)sˠq/j;H{A@gE =>8Gz=r+hR^H6iI#0ƛ炇kXU!<0?lV;@CU} 8gc8;dlZTMm{md8-\9>Mge(D 痐H;6̜(e0/~|"A=#՘5+{XR\>*aۘWȵ\ +PfyEJ0"~3y"9֥yf5]ʃ*D>1I.5_.H]r1yQW|!x~^?cS~0FVP"I&('+Rrxa#0IhDMW!!G"a ˍ4C(Ⱥ=2mq*֙}꼎`MF5T@ޜn{yQW~v>sӗgV~H_:?lJ]QçR_&eMZڳ(_gEHd]2E|<ƌ0.%.Gs/WzZNDŽ|lذjQ=~IJg!t5 0B89-p㒝,SvfE왰`ٓ xK`ѨMl==f _`ׂ^ iA__mk=S0 >7?eHuy izjàmm\1yyul/U![M'y96%=b%TGO};'M5,|ZIC e+f~?kEt[F?8:2tZv'sn0eHZ䌁<3RPCOt?bzRVP6*c(EOfx]͟?S6?+Ja>Bo]:qxK໽Ӷq'*~4w7i)OZNIk=RoO]ߧxĴY3E%C}0: [QTw4my?^ġ8:9ER 5_Qÿ!B6D1~\+.4`\:됞4KTk`>Tb5Oo=bӣxL}:luᨂ1QJhH`&'~:yP2C+,@BڑiAJx`I\%cWޜ.RnR$Mˤz%1nԹu\<'H[E~%KbPb^BgEKLGi#ޫ*:KυLq_ʔHPF %ʷF;~wRš v!*U4;x|d4 5E0})"9{[51Q`8(XxY 3PPq<~jf$2ǫNR;L]Avra>W-:)Rע~-y>wLȀ<} F#юl-[j/1<!G}n8/Uor,rmW+n HmZfn=<SBpUjff׆tL33]m8v ϗ/Ɍd%h(|慅Ɍ*2-YM=y uSK2dZͲTu,gÿk3lQ_U,sA5+lr=zD+|m\RD!(ʔ'BnVo1o߲-Z9ـuYmeNvy/KD7$no;)7"{ rZ}.:ҝMON6C%'qTU.1 α{Jm <wP)&M9o`_%-m1n7W[w]VMԳZ20JW=o]SR/yvc ~|isiˀOAA\j+E}t&GX)k.Hk##[^>軿F H+اId"T]_ TxB6 *TqX/)o@c|Cf:vդt-7μ?3T<:?]l&o:& ?^3{Ƃ]ͼVevVtN',|X?j wLy"VJL.1SSW-APW b9tͣoT; AhcOߐQḷw>^b!*s$Vm 56ç՝"v-Omb]ؕ :gWbה_m4kv_ l/Ma݈7h\"#v626Ǻvx`:.~ϼomʂ-Sʳ1W {6[Ns5p85ZOcm o0?!q_Y]f8(N_le\wt`% i2hZzd?qïA%_sXm!-O%UX*kt>ê }BY{reKl!q[tQHQ⚗[;۹)N~L,-S{\KPbib4>5ewlЛ jÚjO+˷UN%# C|.ko?EpcEP V+y,XC'G_,aU#z9on *\*{ᓐԡUUfRV$ \CϚ'z93M*cKf 8;8d }iٙU<.g{sL$h%[Td]-Y Q+|,)ﺜz 1SԠy0UK'N`BCܩ[FJcE_B*X8ÍE^DE3S9y"9&wc&H+ _*B&f}{MZNvz؜=)@ke ű#S|WO~ ra /cC:9i(jDgX[IJqi&ye*; kpQegf @Jl{eozAZװwg>\RJkO+~ξSyeKfU}c WF93]F5Q!,6qG<!7ո?/xiGI^/4Ha/A)>&X=֡ ^; F٘ÃiaZUI;ā-w`eF֣'ʝ|@mU`UU]@Ȼ{3]r=@QVV%R28~2M ta ^FFi:>a~2@7GOf}er\]vh*ܾU1@WG}#yB>lIrײx 'V9X͢ V_^ѻa+ۚjAV2yoc9d7RRQNAJz5;8%w-31P2ҏF+vLoYpk.vYz^h\/[%h/yl^m U|o8\<ן%<@5 htzւ]V{Oϖ b}'][Yt6a$08D#(.ZD2T@7rT+!*v j]1s-' C4V×i/d3l*:crA8H[` *va B〠)ޓةvG4]e8\8i[ z: _>66sj "*\ OL/ˬM3w e[LƁwb3y8ʚ %i=/ŦeӤ Fz [2jaaWZ#liS?hX0ƢWI1J"]3yCCD҈b5Suav*q;0>C+{`5O Z5-WfJ湽=?PTpAvYg+&&=՝9.8G*qOu5Y en-ϭ[&Ei@[;٘1/PӭlIi$0^.A}}2B `kl}%f FZe'C%[3ú(!#BǥV%lhu[c][Iy+z%Kdˣ1VQe }cp>{-*g]eew=5qYM䘼W)fNⱼNކ+X>{UIutwh?c2ZTp!_ 'cǡ[g8cFWglqk|jNJ-5fiJ+z5Xґ^SOxAݶn:@ UeMJZ?}&Ɨ.-G0f~`>Dǁݎ;fX?.ĕ;!/“Ĵߘ=%vYhc+%ۜsqu9q nINg*<)^)J28(WlYXZ-xS!r띷BZ}e6+x J=EV8Vj%x hz-ߚr+Sm[Yk֌WG)|iEpKm=v:eJ[Y/;|ǬTq;Aƅ>ƶJ+Y16:1uwF& koT8(((,<˥'+lWօRPNݝC^m5,x l?×plZMKBJB5;Ym|͛i;.^al3b4!@<$QOmPS= h|V-b=lG“5n4<c?es)k_h4ԋ|g@| ~X`~uIkV[oYW~?JFp [-鲪KDh ̌(`MRr$^l^Vng: U8MC49Hn|.'/ŎjQo+VpJa[J:64UM6 wnPzY^s\hLB&k=,<#>fQPXug2O< k"Gyv8`r9lyIj۷jft+"1Dp^΁ZRz~l*ګ{fxS&_> {T{zdmkl}әvYKq~B/?b=k~l>oϱVNy}}eJCL˭ds}m)鉎j<gɫ҃ .}[,6x-Ry(X "PU/>汵k? eG"=B[8 /k 347gCL=:|ŕ Vї  $< U '0h[06V{SdWx󌡖N p^h},PfCg,{cy<X5~xEvutu8VdR򍯲4nr/~I>1k(ًe2i>?dO@([%J8FS%`ž*ů+w#ut .lz*[6Napk6ecɯZ.xEkY,Q|}-ÿ9~Ni[+Dj+Akm&k-w&=IjoEֽd |mƖ.ṕs[ O L>y (c oنEKܝ|OĄ0rX!냯i=`xmYpnpLZrmZUd=KnNAD&vOtJhNhp$ƀ$X͂K$X3`ѫBeʔXu 5< [?VчEkcP֮oy Geƭ[͖7#4z3o;񽴰:$h9O1oܺIֺЙ)WŬ+fUO2L.n۝  ɐ[6ʙuzwXay֦vm!OaK2CN}Tfj7njg47Ola1VAy+ &GfAz_lq]T3lTw\qF[3 s3$SCzKϰҌʹ Vs/V,SCt= AJ$h t 콭5SGo v<.Z;Hfd/G m@V"e}/>F+s\7ڀ8=ӿϮ&耚;""O%©-3=fD[ P["{W՗ O;?[X~*gt}n}fTW~j?dCݽN؎l 'L7tck3mmzd?bcgV/ш}@ gl3Yaw ﲰJOZ2<|ִY |ٯdz5k{;,'y@G΍: q%ܘs8$ +9Tu ˔9=LT75 ̗?e0w9AWڷ@戧 z9 =*"O !bv VWb=݉C1ԇA75/ͭL}E38q @ bAk)V02Eph,7'Fd'FjŃc|/H&[(o(Ps"/iLji Tq8~ ڟCo=p'ҫ{X[eDttxU:Uiu-l+uI~Xf{e?uD#$o" /zWo z !wܶ.*S̮D(={" pRN_WхVlҫlTz~lGX~WC61IG@ HLȦ ݏh-}A;F:,ISk=ʻ5Bڬ3JywKҬ]"cShgiTHuSlsT<*g.Mmmbj5Do6a_T"-k,n*d:|D/؝aKo3HJPZ"UMg~[Ak=*K3Rߢ>yxR=\oȱ6$bޒh3PR')1W5VϫVZJKFxo|p 9eLGeJ@UKS jyNO[]k1tnN5kqhY2hb.RdRUV!XRG.S\x!J[ MdܗgMLۂ< <,bUHJ-D'l OgV 5Oo:/KI.6jVAm/,bv[C"'ë 8Ui[<sSWhO<坱Y-w~Kƶ?5dJ ;VתS=Cck F )Od!xDEČv~}K֫5žEݷEKg 4bZآ77i,5jKnTbW;q n"Gpz)G u}XRw(-"+, ,̙ғPo\^,b&/, 83/oU"һYv4%p/G3DdY\1bKV{BX嗻1>8NouU2l*p4;UR]x(0l-6-'R cRURB{sO49k+0yck4;;_ޱFj(+;F w ``!ۥumi)=Iv4MW=?1zD;vdzw.ȭ?K0(ZcJ+ܜ R[v҆f !U-F苨o_gK+LJ25T~_ )\FUZ{H ei͵ RuÉ ยFQ)Sc+Tyi:8\i\i̗"v~)$qo!֔~IR^w_?}3vד1KxD̫e9뤐xRP޸mn5_E3P_d[Rҕ]Gj{w|#&dI {Q8 5-t*fY_(n==:p\䂟nJE\M"QWܰE.,E07a EؓA`žo]z2 !yS0u^VRf2U!o$a5+H[W)D?o42.kVi} ʰC`݆GQai}b(\ Ni#[ؼMw Nby" _^PSR~Xt9V4,8@SNcQkv)P-RE[0 5T =]: ~r2MLNMK퓀wH7(LԈLbQva5R`tIkTjVOP"k 0֗{}p뫔!7c0[ 7yk_a2$+njÆx=<-x} x\őmYe[$Y}#S=d0`o4O97FMB9 `I8BX/ B9I0$$n6 96!U|ű_WWWWW=x.N+V6EfjTI&ԨVz,ĆfdW+]hB'zeQ[bl)5Ae8hAذo@Y nDucoEVF%Qb$eE15kXDk%}:@w뉠T񗀶GkFX жUqGzHU^=J_#&20\w9͋VeWmDfhu(do/a!U&2W9\)p:CK&(` Z$]Fce[{ۊ,*QEO,Z,Z_?rlqҾci{cmmDjj$2'14ՠ<P K.4Pj ˕xJW-'t"zRioYڲϝ| ӢA5 ɗT ] iI$8&2%Ao&)^%&jX?2U>eޘTMeWP,15cUբE.C*`754Œ&:"3I3~%7Ic _?;1maEPRBquD"Ԥli^Oח=?2}:eBC:+&@ag:w5qeT!A3l§(lnĢI׹W̏Ge Nk , O.4Ed, jDARwx-GCftPWD,|f74s:99^/EBSE=GI`8]UPa-IiݻjCV?/!!XI%3 aSOoܗ4e l0 &I\qP*j^HtZ=# >*,>`Ni`Rt`OGC2~Cdq6e4%aTlҌxLGEjkd,( @0%ؽZ\4Z f t0Jį9/pQOh{Ӏ\ʈ520v$tJҚjB 76#(< djD]M磃Y3P%eܐ⑝)&tpgu BzB'@7b FJIl~}坨φ؝@4nhۍ)D3&l|1 |u=ůUC=l_v-lbsj8U%4|Egǜ~R2ޒo]djơD qӰinW U=8Úˆ z=cg<"X=4TꨪQXͻkR eD6큄%&>4ϞJ5؅[V~OίTaxvYЌu5CnM`R :HiWaKG f9&Dh%3 ~<^Y` `,~q[4N{Z8G-+ s:*?m`uiT_ >"+H= g[f$.qzY!OLQhh:g=(qCO6꒧A`,do D1ɝܜ+l~s˞1LkWj3`[Z(5pjxȆl_F[@@7j3bB3E2x:tu6mky%7+̆uܕqy#:(a0 #츔:\QH>c 8Ӝ%4˪#3q>s-3|AbD *Ӧ1aAጽ`g }}5Qqf n]n!uϺ!I2)jQ4#io.X?i=Չ&BPu,A]<49Fj2O[Va+= T|ii`IlPJKJL>@6Y.˄M z+@ñiU-[T ?CK49qDʱ\*"2t$zC1tJ.~+ (X5A >DeEhqiu(j8\QS_"hE䆄MR`ōUȢ L$E;Z4`{u{EU0m,~f_ϖQU)9oJ]DeO[&~-$# P#UxpݰI +aP4 D J#ۍJ83T$zс8gZG{fFZT;RF 13}{3ˌcaW@-MpN?%Y%B SyIvTT_,Px`aFɸ6‰|8T5Cx-JQ$C.q.%$nRPhbW(ۖ-c5Bp$a[lj@D B?}ߘCeĽ8Gg57ÌfXNp1H/R]ݡ6믙s4:ei+ ,LO|Ht^lf/"\Z5'nPs;7h^!U{!y'4^g YssgUUNfUnDLVeG 4 tHesegcg4,R,.+H^9t% *44[i9|9 3Ӌ= ci%d8]ƈteHm'0ny K{=#D(qfMٟ+2m(߱x@BPÃg R"qr$vm|mUlvAɎϟ3E8 K :r_(ӪC@񧚬'9rRE(ꏘͭ82x4x ޺,_}a%楾Ctb?fEpM~R*# ilo:ߜȷC+W%=BC/+kf #h`$P4nw 5*Y5@iZ-1 @O_l_L@m>zml^5Tߣ =d`2tF e!3&!XS.hK;- +Sn(޾ע>am2gE`A3m@kdU1xazs&0^@\7C+8)㺇in -8*v!5lhff3>Q2u!f|u''AJW:Q6f`?ph1}"81IGE0 iMsy,j#%NYUWm`6E6HHz &52R,^fGw$g-CDY򌄍_ɻff񗮽vIw `>Uȃ (BҌd?*@Q99BGN)S0g<mLդ`O$4&G PS$KL򵊒 mU[XJv~D$`)?s9DJ DNAu' W YV)Ϲgiש"Ȱ՘/̻a<閤^r,609{'}"B0}g2(tMPG{B*7rjwA@ﲵd 2һ}{)c]g|L$t|޶,=1@""Ht=T4{,D'bc֐C éwPd|f-f id! ӏČ:_T&*0D@ 㠣BbfmCAZ] r=^s*䙫}h{B〥Pc?:g㋚le3 2|~y[И(aA2,5lbQ(ar'_0>_Ve?Yh{ r_f(dXumyaTH|@Ohd "D,3AIp]mx3 oxzg:Cj3!shG|!u~Twe(/DG*INVPTѭ*>dOcc'~v5.xL uᡐiJٞR.om$̭Xt +$#a_G=Bq9xJqri -6Ljӭd+/ XġȌ ؔz$*0v5]N^FLg Y='͏#_jDdB Mi{(~I^vX'#O 0<:k8ö?IHE-DޤbZvT;U%a8Ch -h&nL̀e *`l @NۦKB`X8 tmՅ醁I&RK4&\d32rcPSIDG%E[3ib* DLLW8+ES-;dh!rAnyV^qUU c"1hrrc$D*bOӯACiaN${A0Fg_.Q'UHǬ`ӹK&w<2@F>t#5Ne81ZfUZߌ8 X́EϞ;D̈Rgoͯ F5!*s sH8gGDfĖ|yOUd%I^##$92h < 8 둫` ƶ=k<*jOzxl~nQψfX0EàKZv~#tJ-*#=а7): Ȩahrc,Fp/`Ϸ/p28Sg51f: RD* ΆtƂlQij̩`B&wB-oF <)%5|cQ!Э?'y5l|c+XMeN' CEѱG'\qB`4Um2+m/6sUW**~zIW//~~VZd5oCc2){ Da}(Iy02dn$]jK[C Ub^jZv :饄BB>+H;ME^*;%߽sZ3=>}|oN-3ZEF0^J8'[fKaF0~:t/WȩxQ>m?S8,?IC`p7q,oǎ=7єS[mh8ix N8l/h8Jq"vS\)l[^*EֻaSf>_ʜ {fcXnfWzsl~+W S=\eSf21Ғʕ{eK)gߧX5`EL*Pv/T0jG7 *JmQ+dC {G,kS/~şM>z?{Lʆ-[e_׸ѼSy{IU.Yx$WOF,=fZYϖ9uQQ,&٥@:SHdW.ם PKm<˪1ͰaE, HwUjS4+ -?q,Qi*[K21dem(fĢqx|ĩy@uϵ^j &!F:WƟ'NCeb=b8uc=HTTOV@8yt@?vsҏEP)7UU)mѷʦ&j~[8 :uM62VwK^S; jW!E\]c)̍P6{ 3qt!outEXwLx3 I&L`^/ks~yt ߌJjSAw籵}J3ggE8-gEŇgih, ̟\>,`.+' taln?D ,dWLbu+xLX93ٜIOy3Y~:sL٬5/[3ټGZuX~)hpZ9Ŭ{l?Hnh)ҧr13[:7i%i1=JpUYYlx_?Zua{RY6Bul50 jqPA4}v\ KU<50e msڙ@By DVy9+n9SE!™}Xg z`)R== D*c[ ֹ߯i@x6{Z9Pރ7*YS!ϬFXKqZ;ɪh.f˪3gv|5h8a42Gv'&YgK÷UzV]mL8-,[ ?.duUty-%ZVS!lϷ8|uݚV87 om,s4z0,4z6yBMdثuw U̚N%.fV;NêG@ʥy>šmr5#VԝC V^+š8:l{;9vV_9dCw/bi>fIo4/fyvKN1e&Ŭzb4>!`)`ie]ìQ.e8 <G䒝{:ԑ.-_p<36\3xRvQOwQM$,n׋{-Y3¬RңC1զ^4V%,z /j~* ަ eʪかف/>/ϐI^0wVb;Xvgml*ŚuΡR`Ȍnՙ-rG?ؤnu?#U`=iJ.H'>YZ4ju=Tԣ'|cewVjg!=Z[ήװ6A&TUftr~6ۍ(fZX ײLQ,wvez\p=ױ)("nD3`&ԓ?o685ٺ MYVIGՎ ha*1-\n X ihT@X7n?Վ3hj[of>7i][ٽg`BofƓfc0+*R9޺d;X_UN_9 BQBڠǗϠLW*}CB{lc̈mR'pf gdؔ":6vu;4q_#|]MKPMM}#. b h aTG0"Tib TqS*OZ[UbUz#.]s+Y% !zQV@Ēۇ65֦G K9r7^obmxB\dTT|gpAqC#/:]K"t}wE[{Fvv̗I' 1[GY '{724 T,Z*4]b4 s c]n!EIYa_J,q* ¿ G[_j'2@=V2u^:]B/!]ߖ"_1#azHyF%ջ!,ŢXx@#ǣ)XlcYCjdu(?iAwx\SEc?px6# "N:."SL kև`m\I9KA#t&Ե`,Rk͐cYmJ1PjVlW:[S[t@֜NFxwFבTPģ=8zkGBiwގ@/샒~yyppRd(O%ţDgs⮏`z*fe6(72]EH,bXxI*fz/ *fC}^Qve|~aWu%!1G@v*csitX cpk!Kق-l)&ޖˆY>֗{z ت~a\3]ZuleD䪭u֕F̎Iiixf @r>OWwױkY,Smhz-:Xq$]pױY# jdg>$Y%ln72s Nf:6XnbOO~!VdbŇυ)<oC%7kRos*흷T'oͽ.r*RoblVaN8(*>i9Go[%K}f,=NRDºbwvƐ=|u`'4[݂VZfegؚ%*PIXI0iКdAȾ_` /cx;mEL9 mH 莟{p;T ZlLS;a2:N?w$n6+5VmlNG(@ǩF=xC/?/  Mzצzt&?̂EP+} Q:haTu**^]Oi5©(+|"yv[/ C61 0w> Mc?I%d4zlO/c힔FaQ;/"cycߧ{\43k'=uiVnx_>H!L|-, 8'؍g"]vB3H`f[/ۅ _?`=M} N+Jk?>`@>ShC!Ρ/J6e:#%1=6Yb4|iC%S{z:pAh(6,}-8ɺ;uf$Ln :v3ajwYklVܶЋlݭMcgֿȮEx 8|ɚ8+}>VڮP ߆]?me/QSQ5z^G/c;O:)\+3Yh-}تy^E${/G緤WEst Y7DWou^<~/CWٳ]N&S!6-e񚀸\,uTg@en" A?bK<ǐ=b h~g9DG /P)#˽+6hnxc"Lc" Re&m?a鯱u GaHZ0zZhv]< RH4Ο\)~BO"4F;K:DZ7^܉ֈYR H4; Խ.x}ksגwe ;@1/cl=X6RwI]j7lO`pxٱƒc _Kdyשꇄ1wywv{-gy ;&6V0͢$>1BKҼx5.%'X;{'^/u:rté$]>y^?L5w{i7FyG&i+{{nL$y{94 ?8A!k92=82ۘfGNLƅj'ȼ\Kig Ol9>]Smj+^aRtOx9D-jt$˝p9MlE~t3Sǩ-栬8yx-?QGl)۟^z`_ `/iLLZ'b :}NINgϷ쿼ͦ/RI KIYr傀{ŷnEaָL^-8<8eVIo*|GgEq9;ku~~qW^mlٯ#u_ ӨN˦f;S׺ʬtI-ڎZ?Nj688@6'6yk~l^m~j1~z_u |w񿞿xQ$gbı͂˚i8(^87z۫ͯu Am<_3~(/0.A6E]p&,dN\j*hrby_7҄ɿeLeHwp]tzNz1mc#n;'Wh=s;7?YWOa] :0cAe`-SCl,l-z#b3|5i,Oalqct . \w>xCOejw/XWxV)U! ' (I->No87ý(@v|jSC”>21 8K>=â%Y;2 4Q+Sf <Ԝz'o$¸R|^HɧcU?[$&=ΨI.ıNV5[\CgA7eCZn:pGЃ=Ȓڣ=Y<| Y}DҋԷjhY~V?ܑBqRkEH,7QZDQ8jW!c3Ӑ 0mD4I n :k\o02Wָ/'Tr:g) $|&_5fLlP<å$kLʳzAh'sᲲ$"S_VwH%ɿA,G{)kQ](t{$t9ozĉ̀8?ؖZJR0l5HcxD B{"ύ]u_ƿ"+|(Zi/>B8'QEȤmTn$`#K R{Gm`5עiIo 'm8?SJr K(P`Y%a6>&=~p+C,PO\G/jlSo=\Ei`:Evd}(8 0Ow1{bqO#"sR:z3) W[ ](sʸI1o7h=" UmaHs5cP AG ;`(ˁ>IV!jk,\+%/e aS !bN}VwGLS@<Ŭ<_BC(vv5( a˸i)a'Yq}]:] B-鮩?旖%_->[4oNٖ`wOzfUupCK\p-)>oͺpzX6"gS%ߦƉ@-!q@rt77wӢAv)}P:z+]$.JPZo2gG%PIwfJQV[W\6}a?-^6EYևXVc>t^)Sy:IKrUKoVPn&YvL8ٖ)|;rp-wm[V7]xG,arx+]\s\!z3oB7Γ_Nsߋepp] h) )BpK/ˏ"!rw^M/ݠ)~l(ބ)33IIpsO42"NaWEk[a3 q9,"ڠ&*"9L;Ly?9BH -Q3%ʦk= KҊ!w G9C\|d?T|ò2է%06ab,sxB;G׶m{IT}~"wr1s c ~TQB\CѐU`qjawjad5 j2IED+ \q&L5vkȻqO]aӽl5Ygt34m f1N'p,B^}ppLka4WdKS F^ý#-n!Ÿiz_+>% ˴LVwED# u;+K5'_HSE؟Ui9RG9U֥dSMeh t$qNp-&AL("s94g$VrF൘3c9L ʩmIsCMTl%c(:|nJ=% > >]MKëQϼhQj dZSd\AYDI%XfX!3JmPO u7W^zHCŧ'fxBIZ +b #b#.+zaBE8'S-bfQN%kE)'pAȐ # 2%R>pzTŒHI!Gd^!{2@ǑHf*[ҕ}'E2N'%\H Y7MOai~-#L+9qS['}u\:1FhÒғxށ QL6B#s7C ejx*ϬԾ#h-8h v'|xG{N9΁_*淓qZ즗؎IY+d$q~(;5hյ'c(-,r[yi&PִG6Q?Eq\ ~/9o>x$KRKjwh/W7]ʡb/vX ܖ͠"2ٹS#O S iyy_\7'YAݱ|y(o:Rt,'5. 8Z\NŕRj!\=)5-&ytm/6Dt6dLG&n _2gVgd=@ޠ'dIkrya^G!;F* %m]%Ud(W=]oADH2J0JŠɡBS҉&å,bC G&q~RcƑZtm =ؘ(0rj>,)qbƉDi5$˃ŵD~w+l=E[=1|vܝi[1%~+S4OH l⓷OǫL{1 Gز>5?dS_0ng.Y |_COb 8duSv{RXb;'/fK@DIx!`gho&| q+&-#mt5l#< X}a(˓ٛ[|8->[NׇߺM"2&AN[Iovâ^j3עK#E[ngr<`]hMxIܵWvs!,f!Vk ?M9T[Ut:Q>x܊ qq_[sM ?"VF<>FGr:6(>հit8XSμg!lʧP!)u^O )fݦ !VKl'7$oXfK82G~1:`OUc[f]]*߈.qOE0GBIPhtݱ_ޅ#%ȷI?wt8>L?r:S?a3ˋ<Rf2|0f?NjD:EAy?zj;j6sq+|R-Vt%s>PH'7D y6[lc>:%Ѝi=JARXɧ^Y礠8/;X+%gR 2%#V:Tx|1R J9N/b]7pQ թjnc̕rqB]+hhySԍjFYO_[}m B?dt:6kW ݒV+ yu3L4+Coɽ8p`!i\tQE섩; !Qf]:=xx5W)RdUe|10WC%FcHk{)ÖEK=6&utMק*zO^ƵscpB%׮&O9K&8H*YWs^Hue9%`UH)ǾLX_YsS2FqޢUe@=MTF媹nqw1 mr[A'*< Ͱ]v@([p|?[[Haky DA ÃJH_>$r&J43Ӳvr5foΦ(.Y畱7z3=(ݱ?qIE)lWLV׉`yr%}&Wj=Dm@2(եɪqvCoc| WH(PMUƶ 5=>UG[ ӌRǡ}24]n^ KzA%bSuP\ Xd`C  3߈lQil%Lިx9Z)Y,Be~ W<y\0MLT37qa1~*ˇeы L2 (''CcQ-3V2) /Ẕjа^ :b-XX4H`4Of+Rxtu% 'FDPn{#aP(t>NSB=boeo^%'^TGI<G-1RuN <*BY"n:- P&L/*Slr-qFM!Oj[vDݵ{j' 38K<BL9^LاM.sK#>f\޷?#`0oSp3Mc )Nys xz%KT Jt9: o6g)ԧqCpaPᤞ[䠂ꖳbDrWq\yҹre>R;Շ˞4M_<ˀZ0{ƺ>egy}%W>-$rʟ2~O]PǝB8C=_;{\+HW.1lz}wBdmPTe_VEyI9X)+Myҝm u2>sMv3)*:>ܖ2@EKTAVﴲN^[FF%\=_ s`TSj=7;g#k3se+L n&^Cʘn-/t\ BiłH#;m#P8Hx){~mq%HЍpjJ!U1K3kطs X9= ?v 6cè;F /L?H,Ѝ)τf`wΛ4G[ eCR i!dƭ!CFt@[Ytc760cmjÍS(xkBdZ'?gp3 hD]xDerظ&i15H\_`wL,|T i3;gwN0WJ'-K3+wT&%8an*[#C̘#d=BB "{&*GI,3fL۬ok':'rlm-N51t12{wi^٭75k\5?Q].Zveθ8vT)Sz;.gv`k.C+877W/7;x=cm|6g5&fg? P] 5̎nD+'jDptp! s`Pْl $ODݴ#(9B(^8J4)U7d%2T lHUԛ"E\l9kwˇګ6 f<#RS3jĆjkYiPq_WE_g]fk+nmIDg" aZ)dL!SM8tӸ0Ȓ8 KK% { K Qާ, !$~a@q>ǗË9<[z)=13HuQ D~,],.}UՅg2݋:<d.gX:HuT+o#ny`n$zUܧ]]~&Rrx(VQVsgg{C d+f3T>}Ha^)i/ kejVc:.T?LQ'SG,xE%T'^]:pT=\ *7̩i1nq-\0 s,L4ZZCB^K߅*Z srS/`h *3UUdPdY|OMDpk5FCkt+@hu=-;dM8i% jUsp:GD*]XXPJ,uGJ@@pf?%CA?gAxg~:?=~r@ )J Ȝ.ӻA,v6B*[=¾00ְH>4_3c{Uj1N7`etUC2d¼JW@Hx-6 DS86Ⱥ\o3 _YqQ+⮎AJ*>{GǝJ&j2 ӡ}+QTʍ|GC>Sx&ls;v"vʓPmT ߈$ úWǨXcV]4Fӵ@zQ=c=/If%f}r +Vۖ-`DDPw c6b,EAؠe4A5=}6圸eƳ\'ЉFkثi.@ [:k<1 a!'qH[pH& Gg "A"\z)_,o*^mxKD@!z"kH˻%8T09YORQE3-+9<~x暌'6_nn#Nh~Z1 Ws!Z@khR53TqTvmV̌W~hRVgMxQœ%#6+pfj[i\^1:68sVتk&GsȌ 'ֳԇČ ]%JuQ'^!hD[B*?_>z=mmH9>;3=%#>gmH2s܉#> _Vʩc7a^Y1n=Zl14i]ZNNh |3.&"n 6HOhLHXJ"$"ѺaEi"GFLD'J2ruj0{hܺD,h!>E2!:׋F f j*Z^8{: r(BN^ [cZ~\{T?Q|Zwt:A%?QHazJN~njO­Oq+M,'*6>]S~NUH'M kVTV h/'f!INlђ/hpp_™mUz/զU>/q?Y}Ll5ʛmܢ$8.N!{׉U%>eW"UXr'rVA_7rd٠z>7r"Hό$[J.Ԡ͕~DY-=Tɨ[5=dY4Aj@+imQHPk+vO":DGq딅L$_LΩ^CkuiC5G R]Z+G௣r-L $ wjGBELeX9fթYJC^SepbKRX W> f~̴)2\@lHG6Kwyȑ(1 a===0%.OI_ŜV', Pɦ m`&ٳ*pdP;2H΋o:1Dkh2V(s$s`۷c*?],`.20r<ʪ[`NvkILyKH*9vlڭ2VԪ2-Y\Yn 6Y|`jhʺA7e7 $;i; #$PofMqK=2vS=W\F:*R2ؓTҰr(["$@ZȐBӍ,vuGBSBes2,ȸ2F]#{c_x?!T m(QЉ0_KBޗQ@n&Rdۃp;vܛ`x+ "Br1$E{}9XY+B4+{$Wc7^ Fǭ$S}7_8qȬBm(BQ]?Q0E_"]v5Йc 9*}plrԏk=ҢC$F/8a=O|AҾ|2UxJM4-w~@ȣJ_p8{H `G|qˮw~DǼq}M52%lv T T Ea.y*O1!w!Ҽ \-E%A%E(j&I/FdH963ĵʑ 4'7anj5Zm+؆zBف0!_auILԗ[AM)yE7lr+ʺS5פo014@i o7z&U]_1b8";rW`\ U'߆8̄8X3 ^Ta 1j) ^8s'/}r y9 _pW !N-OVlEt3VE}~o9庐FIKKQQ:jC*"oӃ}/MF-xet(dgj<;D]c 7KmzolTgLY~vH)ETVnݓ1K5@KS eew8( ڠzn3+GC6-/fO ~U,4Wd0Gbk}Z>Ii)q/VTNCGş;Ӝe!d4\/9 'IJ1Fl{cI9ݢ99I;85i?GUSC``=+CRGyG#'aFUNۅas˃,$|3ȏQ #!DK!Wn> БcbV`;ЯFyu+v%Φ8psŜfp6/CJ j'o­'Bg[2Cs z:Uh Y-qwQRrƨ! dK@ߐY)dGo'4:|1uc!vSGA%Iq`\if {S}̎ X4$e׮\s~1~]mݥλ&K#W!7eR"pĭe+DsT(&QO@)}j\_?QBU:sq[a6tf>o~%۪rkRϙDwljCm`y)vbsb$3Dxvi&i6ssCpm7|ϐcҞkڶP,=g@{+**\,!xG/f D8J'c<0)0B `ak'Z`(nUBUhURzMJͯ kޝr:cL}Y 0x7Dfg3|i$& K{QYȻFt1,l^d!Z Ckddz#D5W|R9 !5b}1M$͛}$r,/ Eᵻ%42 _`p!y 02xA=-!\YVq=G"bx2Epi٣H)>Ka\_d.$~wwV=C( _Q/7<L.Ug%koDb]U'o2SZ sFe.zX]]3]bvBs|eu !;C˙Tō1UdQi}$Ka)BȊ$x$ڹ4*Ċ &)*:%X{ߪЬ"'Tʶl`*#lq&]<\BCIIa:߄&e5t!Ey}GH*w$H0;(w x~ey}Yۡ9c#b]e.c#6ϧa/H{0A`V ĕҕbf'v-'|0l`#)*XũR).t/1Qhh-f;IX!D{^s 㼳&NSL?4Ƹ`gOә VƦ)h?*78.Jn센>4Nk+*4HChrDPL"1TaRO Q҉!hgwԎdT;BGElt՛ǿE4U*l ]_=пLF6p\0Oi*MZ(]5y>H{(2DVO35ҤsMh,{}`kF'6X({ l[JWeQ+d2AQw)5G4%QHYE6Zx.7i_ĩI`eoRjH 4[a(of V-tѩl/..2& I)ԭ~O`*iPGQH'r=^`)Ff O᦯t[1rmԮ]P =шpLX:eGyԀE@*sO 9w3ho >D5b?b Hf(xWͲ]4G2Կ&ǘh *#0ןj~3~i& E 6+aXEM')a\T3D_d"*&!C?O"Oary2RňiV E_D>x$Kgr 0siN$OlJl 5"nx$*h$iLUy紨?ՙB5@`wF}]^N_ A88xdB>4-9qs3Q{{@. dG3?*_%d1fŜ3˒hn%1OU(1rMB;pghxuy&(< HLkA]LoQ "XЏoGc#,Coý`"tzA>xt>vIAnVGF.f?XhMZųO* XIm].՜&P.t$%G0̅$QiγG^fgOo?>vwH}n)G{?|Is{DX! ?I:ywz Sw'hyԆbNÈv4TrG?TFcڹb}+ jm!L90 ݉oߢd4dTwwD$)wwvP$yWDHnGPЛP WSZ6 J** S, & )ڂ Bڇ/*)v] H4iKE{̘~CjS*Z΀њvv0())aR 䃭%{REsڛ՛f) y'^8IM}޿2WhD;xL6L!rPLح;g/ωK؝7K))6rdބh(G A+ڜÿ&#YLXTF]M "~y=_r.+{}N6b>9`#_ׯОu; Ԏ#[$º>'K hSԄ  j;fDg}vRcv L Rww'% B(E@h~ lٿԙ,h/D-MZ\ vaՐ_!3s2i}yrK(!icچSgZcU,l9;#әeoV=ذd Ȧ;$dKi= {iA'Fi45mdM?r@ߋ >A $dAȨAb1Qi4CuE+  ! xҟUW.I.!F͕eJ%!![$W&.H;Z8tzc 7D/#;FwZ78q,Mon ]}݋ ]ڰ;iwn:Жkxǡ֬#]m˳\URDnDɰCN- q*d*_mq^-:lti8&uqܯj}u-Ea鋎Cm(=Ӑ/q‰/\~Qի@W{G֮cmZ'Э^]rwvj8ԚQ֯-W;nݞK eB/x{Ku\BPZ 'Iԣ%3}Oϳ~pC {&7)Ej0UA \:?j C:%@xc#qpL"_y]1T3W]Kg&_z CK\ (˼}>\囂e*\xFWj> MRd4 3Z~4N ;i{#IKr AU,J_{X,Q*DHh,yiv}}3d\{c4Ypu/e" M w?K`Vm9^hYG֐d1|B&s~f* %iKVkF!! [鐉|D,JVBTL6 /V(լaKU:őbWDf_,Q?s< #;s2I\zi0;Xmދ"{P"_y$ݑGh ~o޿C<@  =8x6UTB ]$}T!_W LCJ 2Vo}KũӖg1u tlGm﯊[ijAQa|xrڜVTF4]]9#5Z _26ጛIdhI[p|DB#_檴 'ƓѠtlcZYWgko|\n<$C/K/h$>J@Y|gj!o#YҤ[K:r?wlY}qE ;X}0sȷ4_D#r;)X`>GJH&Q{rr4Ycϰ{Fu]ƌ 0ND=N)$6E^g Om ww_[DIR'HS-\X^fUekK),vJOҸ}DgVL;DҬ<%L#sdCpqv9  3SIҙ$:GO;mKxKD2P #OP @e38 =cRwxm#u3;*0DON @Q>Yy5pDH;wHXpDܢ H/\PeDphǶ)&'Xċ<̆w8$iNz%P 3>[6~DL[J\ a)J &'äqΐ,+8q*:irRg1֝2'4L&%pXJNDR[\㴦j@Eg8Y%ν[`6 "la#tZ󄽗~FpyͺE9eq x7%+y!*JR ƺ yAw^ qOD1.,^f.62}Z5]ݯk"s#2+ '@BP%#'v#SSrg/!:, K8[ྑߖ'su,ͣh L*tU ;Q{%d`kW4~JXFK,9-_T|ar R)S oub"L+'e`58'YUD 4-"͊!_{<-(̌-4YphdCdQYUtֽ4Ej,X7,%mD5a_̟i8d?Pp:,5j"]ƠQ bijt~ڲ-XMlԽnQJR}D 34`z w,w"y6 o\>ӦTQ֚Y6 .=ReCKc!OU*^#<ҀUJOGS;Q9[Nhd{6Z* &TԌdCR߀6ZWz88hDwr&א5.fđk'k3b67`Zze 2%nCM!67f*zP向ݕΠ_馩LS|nsF*:;Iu|EVRBÑӱ34p !.~\g3 -5LOUcnN>˿E&+5{?6HĺKZ#PVе"Bi]?,g1c' Z\ͲZ}o jBڷ=٩TCXV6m¹6@u%zkn%3VL?ݵ 1,(q53n$|!qnt9 Elvx:9 `&ui͹rY9JCfAv<5˝5oMޚr"QZ]B8GWCQeVZE6UKقKh^Z}5$S_}ƖTrqIf~ %E:0j8IW=\˺qƞU/o<-ܵP֌Tų~^ĥ_lp[C;ܻz;Օ\[-ۭQ-mJ-dÌئM Qu)ZpIAU&L!B{f?5 2tG)c#ZFO=jfHl(lī* @4I_zN ,9{WuXK!Ҫ0:G5$=ENĸ1"]a4S;FGT-|S XqWeb{OpY:Ya5]M^hWvېh޲,L*\!^J6/~vq.dSFWJӄco,/i9 jeK&o|$ RTL) y%7O=|+ۯڼ QC@hըQzUCt͈/Cz6ehagO/go0UA.D+NBF8@jK[-(QnAgvnVFQ&I]9-dXtUg#@ʔ$~\ثC uS 8סgoZ`V˯Sx̀4eؘ a*JSHKHܫpH޹B WN_h$hTGiYer \7.hrJ{wlj;Ε:9^a[Ϩ%u+ܒ$-,jfz Кke=o\]DjdS}(5TVGazC+U;io1l[4R_kklْ&u-f)j 'Y%|b7HCHP#%j..1MMvM 0#0ʞ0/*̕Ϩ& eLi'4 ߥF4+Q"!UJLI3JU0zE} ]ٸ$.WsXKBiL. d{\fՔ:J(ɽHe\QsJUhjǣ+\1#Q؊SLޡ[po22[PB!@ ~P+I0jl%$eb) E,Ђ !Ú R6p$F6}5|^^CX#kQd4݁J^PiB<aJ Vf2" ?/p+-B0$=p-i6XAu  n3vVAI{Û@:m[~9xD=EՖL=3|e#.|RwbT=U-tk>&.u@c6+~UJ䕓tثFm]{4s:+TGw+"/$\LgǑ`Rj(1Qj*~)s*±Ai q*Q6BdxIx%=lge): q{|y‚M3t' dԇ ۼ$K[^bav傅f%f0ׂWE(dG:N0&"cȬԫ'SG&i^$8wbfv1T)-h?Hҿ-1r*9PJ1Ƕ\JXc02}mWT^h[>6B0*E{އ]ܼ(WV^TҜK#Ato587R 7U] ģ?0 F9F ~NcrV6C%5iMw^KL^HJ5R.i^/!O?qijBtwV*O3JVɞ"SY "I2oJ5RiJGq:'zUr,<& 'Py2od]Xt ppcnKmhwDT~ 1ܲoq%0;/iS݇6WhI Ѣ?jPF㑯`ɛ$O17˵AZfEaƑOoZ]ݐ,oHHQWݫg;6@ف/˧ju y"0;Dn֦>{į/ a3]n˽5ŸH ݷC%a/rbHb7R,0.ZVm[WRE8"*=`7˲f0q#fŠ;*(>aYdҎ?$. ,̮7j\--/ZO)*ŰL ?;[MUϓYq־f߈&Y0=aBĺuD{[ Wv 0@_:iW<_5ۥn2AKRx8mSXi(.d|R{vNx1*rc%JcŅLΤ?Q.^3J#! ~\"vAbeCj[/r2 /cE r0"&!mWVKԿ{_PnɃƷs4&ooֻUׯ1T7F_7Ak"1DŽQ%^(\A ߬տ;Yq<~zn ~mЭ>|:gE8L%*g q!ˋgo_x$.aVO 8̒#kđ%(8WʵWr_Yz.WWDDoBC,oBs?.̈́fڔYR,^6޻;www$+1U%>GÛ0^g706v|([0hq?| J.?g' uceΣ ,U"DU$p`{ZEK{2#P!Ә?vYr?o/4Bl ~PԶv4~r59[}>Pe~H PA1/ϭsiQ*o:~m̶voSFfJ-hHD?Rp 3plݥV0( cؼ 8xڠ^ghĭFKnS{V`n Q4#Q,,;bYs|"M&?gc=Pk_ӉM8HO{TcR혟 y5sܳIG"V/N࠳@M) fݕ[}%k.%2Hܦz"VVt"6/zTLӁ.y]K`ouT `IZݲ\ޘ%I/%6HuX5֛8?]7Υ?[cP+t\hZ4b"-b%+'RrDݐg źF'64^[R èB|2L7仢2{ÀxNc xҙ m3AaQW]2!/%d-/׶bh, 7fdn-) W)Q>/ ߪ@~qNnEՉOqxP0PzpxB`(Qb#)݇o0QoNVv[EyD>2V)Gmr?U)49xOF3O4M|ɔh6A)Woߵ848\8ZS<ٙʷlELJ e=xc'^3yp1^%aL??=yx3vi餀gxk2vF*~ 5RR~ `;nxTz!R8"엫̬U OВ`zȖa_8Ҍ[.fڼ g8oGRACO(3.ZNweV-;PHb2G^Vdp#+Y0TJI*bu ;VП _]38ErSfN;޽/lr+ϙ0!7x|.ľv“uuVofbU/?Rn$n3x=')0)(PkK;>˛c7!Ur^~He_ԟ D!ݎ|цC3T=&3Ns@lp9jf?*T*KhUs܋Jb mo6sLCjk[z*zӽzm(*Xʸ LߚbFVm#53n9~Cܯk; 9Y4:x܂&|?<=娞&{`..pBzۣc/V*hyȞ:=t6D%?k]tkE\g* -%4XؚEm'ҕV[P9w 8`;]Xsaf\QË4z! iZ(dD5f¥6.ĭeԿRR>o)r~4c|&ŝ52 9Ӷ' E>%C^4賖8NYDR;ZiNMoȬ{x q&ЂUD/9,'Nmb^Ruu”C z]6C}X [·'3 OEIQ8lؼ$r|8BXx?% a;rWʈψ*r_p+`o=uAsXFUA5J‡y7u\V $&3ɕ+=CIyf4 * &4VT7`}n=Fܰxpo(j<{Y ~(~S3/x,\/N!HùOe{^m3ZگaӢo}4XXMyÅ|$nD6atR~}}ā~y%дToja}XfCL"doCBtd]$s/r-$tD)Ir =3:K6m< / ww[NH+EP LH+KX?8&JOʋlmG5Bo 右B\ # l)OQƒY݈2 ցU4DrZ6k4-֡Ê$Y&3W3$Zfօ[I콞&bZ U0 !cdc Ȗ!Ͳols,/Cڵ"29er#y6杫AڥevE};X~޾#4'[38Ydރ踊bK^}|8]G^PVxmhW0ۮ| ,s('+@|Ag++,a \n88̴~9^  %sRK]꫕Ьb|Zݼ`xpZ[7WޢB5mL~hyN66N7sh7|{uV 54;跲`U^oYqfRЬμe\h\% ]f6C)Qi p.aQ9V\c+8D|VE<&=pr{ұ3Rs~RRi==mztZ)Fͯ?e3elB:͸RPX Jv1uȗS"O(0CӂwcJH(sx]5, j>WYVe+AJyccAfDf 'aX^몍LM _da\kr{j<րs_Y2C!DTl@e [;UrvY0*a?G 5VG ΉE3iXw:T%wr*R7 2JޜQc<>%97L{±Oy +F]|3Tnle `Q*#MF BjdzD@l!Z1nSkPq+/&T4pJ|G<<(*B xLfؗCA^ݶ{V`٥c߇az視n˘D}#w&M1Ԛ7ThTX7]T;4a`/$2s֋\2DT۞09onC31[@$F`LGbX^ok>t_񦝆li] fm8gT6bP?]t÷=^ YtIjSnck S|Wʻ}vj >J1NA`lDH\D6SjNc1:9Ϯg t/}ofU6mǷ/nYҹ*2'wdqyG>vusI+tf㜶j7hk\+,b]K?v7V|G~d,a`Ⅻi8(tʇ%a;ñ~P<HׯQ9tD\;snzR'}uw1J;<߶cpb֎ yW~a3B.4S.leX꿾$#yjB<ߋ99N99< [/=M i.eyTw Џ j: t<.][f CK!;sB튭 AfHYmsZo*'U'[6Q{@/q8IbO@}"V_ 67Lk'}8@1eVt"ɦUhlF;<[O@y/?p< ~L JHAozOS(3ZtCV2(_*g#S!w 0f,*90|+_<jKR]LMpjO)2ґuH(OXN(Ϊ~wwwY8>YAfa#i7W@Ƌ /SN #Uq_k]9/.<Ĉ$٬@t ;fNlF!=>u^?ʼn!iLtedK'siY+F&@f~ؾXڴ_fS{ pQnt Aqr$]p1 )W0YxLl*{\Ӧ>p@VUvhju99yYfJh +dP>իZ r#J-miDQ٬Q~oK<\Ôo "٢H6߶eP b[TYٙMV +faddG=U5> 8^$6Bn5 f x䶐ܙFT ih:PjUw8h^QH ˓#ENjM(=،quVsc|N (=8#^H4Ɂf<]u%yETsί?ΒTG&2&J͖p~*YHJnbZF|{*ȗXs\dϜ+YLisnkc-pI%WB[Yx@E|ɷ1䧨<1%?9k6iC:-Ezѳ_aa>'i'}o[>?@NU}nIeyXz4#Krqg02 <ÉY:YiKsF#Jn!Xet u܈[9bm7fip>Oi &nI8]zsHϱ澞U|tP9X 7W]R@+nU}7=/E%U%3/?FDeАTˡEduUoX6z^l"s\7]( d;GIt~IHbk8I\zXDa=$Ǐ&+LcD:Owpg+17Qm}ͣdNU70;?xpz$ͮpOn*j{Y5dHsw& K4nZjMyCEX߮V,?WTPt* Th_I.'hAo4A vx{-<0;5UNx)FZ 65ytOio5jw(rϡ /%$( O-Agҭ#QtI \(Y锭.Xi*XHb%'H;*(ӟ=f郭 .jzkт϶(:NLJqv)vVjJgiQ<3CJ=TwJvhro4^ǵ_D(mwcǫa w <&8*iFy&*dCCHZ˥O#ɣ>0H^"m bF@R tdB~Ob:==jĖJ6Γx\=+9J*u"Gu?Fzl9-`D*? %Xֆ -u| y]LCu$ȥ1=gD ݿlɾjs1o,!56|X{͸1A @A3TI](V 6…6 qe≋J|qyy1-V '|qMXDE׿$BP=[GfDn4c? m|ˬKRqN 2\zk$wآrME[ӿ_aoJl ȱޔ)T◭J*ɔ Zfԛl#e5xzƔޤvK nז2rot›UWP>i,w!穮MeZ9/nR.X90YJmN߷4!};E`Q1+[#m aJcU*=IƓHRCztiծJw#X{l Z)|z”Ny !ј,Tf_P*VU6bQXWУ*o_z%A$WNGb ,IrL.}:| /d\3VS(I:2bO4%B0)%yFZa`_dI 0xW͈2]/0BK 1_%-J({$Zz7˕?c=c]\.;]Ôx|,irGxﳱL OOY~BMaI("Tp66xC̞kjnL-c0sKI5LqG:?'QM2"Q01|Ie0ܚ!)$MtHc0ļ! PVhs?*6Yb:^y&1I*K^i1 }iYtՒ\w*3!RPe?s۵ۤ|(ƺκа:NUn$m-gW r٘@MY@-[M[Ʀ9lZGѺ4m\ɬ2v%|!Rl $Ei QXytCWxU;JASj](i'H`ނI7B~yjT]C,D'GwwrseY6\5vV`;@)j7K?ڻ~5|لHZŸY 6:QSNI|E۷|4(xw8EB²2H]*) $aZF9zA <OeLHًN{F2.Xe CNp>(w.(D[9W`LfivW}R._WZݜsJ֒ڦ (F1'm-)< t!mM O\QȮ2̌jϸxi2qڷK!ǎ{ܵa䴤ԭGo<<$Ŭisžt_B͌ɩK EȳPU,TzexذYvƪRg#ήkџ Bqp5hkcbqY 8nRqDꪫϯPc ƓXa FUBiDC)GOS8eDVCi5.pgSuܪBǔi bi6tӶXx E2]EXHwϿZ?X oG0 u"@|^G?&>tW,$mNiֶiŵ|\CjrآˮmE}f9};8VtmMϲY1GSۋ>{ s߇@C\9,3 "!aGT&rv0/ .Ta*ȋRlV?ǩu4Y$Bsb 0~P})k{'HmVeXuҒd#"6ߴ36*V#FcZ=I\"m/~iJLa'< u_;h8Tr'L̅Mu74!G[?H)2qfU貓:-tGgB`;rdYVtz^7{HW8y!*>LOvA=/t-@kZj.ɍH\'V,?ՑqMH1t|)zHUH~ʴ;@ 'M_/!3w: ncAg08 $ 'M3ҳ V%Qַq_x; o:`WvOZ7^~L(\..lrQ ,@#Ѩau>):I;(2ZaDEv *XyVi7Y? ?^=<ǭ! DFA |TNלUk'{gv$l{BoW]3\'t1^!k~>|ytY'(e )4qQ.ɬj 8P0t4e1b MYV*'0yh==9-YJ 5%ݍ-!,F*B "!vBwgs9wa~%n O{@X鲢 (@t!;:ԒM< ~T)GmRJ"kfS˜֎^ T4mB@XlwJs:}`(m5ŷƣL$6DatsJ7Y<$-]ᳳ[U(s#tJɰEB6鋬YbRt*n!,^Qd6pV9bŴHxCūl|dQProx߱% !KF>,%{e&x#g‹u/,e[.,9b+ Mv?94h, Ew|ڱq>@YtG3u3#=W'åՁh}WA`eDƤBj~HD[AWb mESS]Yi $sT6w ,Des`e[qڡxp`(xTcDe:b3QBdK^7*4 h߄ k~00Ӯd$K 4=Q\ |2!ɃqIz~6u}\Nr8*fT=dFB[;|N}.,8xnb$fiHq76bd"J9g48-31#>~^{?JOTtA{MtWpI}\e0!O }(z5]E7e_ὖI&R/$J4a2ǩ"mzJu%fw^.q联,{\C܇:g_[*xYI#nZus='GLan1(}Zy"ONH7Zv=Z&Ny`۫ҶL9^*Hn#J7kHH㘑 T怏: w}#Gmfi&e@`@{{뱹O #rg{hh ]`%ɂ?Y/+߾%`#i + wE]zfm'Yyq[zȝ{ڔܟUYY^agt}`o_^]g "trX"c3UkgŻ8 /:V"+ݴXݽ*kiktS`їJktu ^C[Q;2A z=?.޵`;ߝrx=9~mqZ&ռWC=Ү2 {L}lrPvqz-RnW /B澠%s;kVY*D2Io5麦+vHW߾g^~Wb{5SVm{\tۤK|է鿺U8={?b9}[.C)KTư7і]qi' ML$#'Q>/FLnK[pJ&z>]Q#iYۏ:>9,b6[;nt43`\\@[|-ART$)Z"٭N}dfX609+"6;iI9nܿ[<=> ՐV=%燗5ckg+ slvtm1\iΞicrᎳtiy<6m8O1v'\mz^PD-aa|D~Or1EU^*tICl]#>qV @k)(bʴo,b[nhivL'˸:~`JRNڏJnR.x.9v=qӑbTt Ptf7…Yf ,Ǖ5i'ra*FJǡYR&\!J3~}CQCs3jglč}X||E1?9c=7[Pd6L% n#&jŊo rfLAj3U/U(!k;DMj2 Dh?ʹ:/6.HOCNac[\IEʉ>B:i rEҋq>:F^,|Z{Eiou&kMIv MГst9=fTbM! *ALT$SRoYv0JKUw$>vUVɆEϊ*|{{2f4FxԨ-h"|􌎅1.&\$:J1rDb= Ar~0r+X1Ӥu ]{xIom3RPu$ђיX=xe[j7 }Wc,^əHWkL*^GI7'g%xbt X_(",J ]{ޓ|%'&rS#jշ>r) Ѕg22\"×lȋ|d9sZx|՛n]-It QSv۵~b+[w'۴{|s(Zr_1gS]mXmq=մ80u(&jEctPyb|6ytosIh+C  ,n:hPрi9G='i% '{B˦lsƣHQFnU3M$yAxl"5:xAR0|M&THՀ>ӤHVD^O6YQPYObG 'mBYKcfNo OưePuݘ37Tu1yY,4k PF/]р҈{nXH *_$ihw d E9hfy $LD#;^| `:(TSoTZHE?Sin[ѮҺn?6XQ_2nQ=NKC0"1yV\d(,<5hGY5 2p4O^wܾE&9w]A{ck _[D`#nCf w}\?BZ^M8cޭVw_8D޼Xf|?Tw}ܬH@ κ|~ű{@Xh飇75$_7K8 O- 6Ådx$87M5PrHx70q]7pEWjcqbq.XkumӀy1 QFf ܷpKJ`^Z~z?5ϖMٯc5>x]OU]$?+*~:DFco]ex1)ajnvWDċ!e$nLy3HIJ'xVz\O9F&#=CkCTA>7@D1 BCΆ 1A]ӚW2c~Ճb6a= r}>IigeF{.ԅ<+ufnFcRS5䥻N3[Y/54Ҥ3k*/$%f:of觬dҬwYzaEᇾ羿n!ÅmRwP*SnnBMh}x1o Y׬hJsiZtެ?u /es.; 6-*a뚥obʃ9MK$K<=J8BrK>B[7m=2f:)5oPֳTGOu.KȐqG/&tH[olNh<Δ1<'Ax&M]:E!2PX!Xq>J te^H}baI>T읾CzS^v!jEꩺD'$-3?c 3TP8W_5QDy=tI/Vo S˩ `Scv.r{w okٲ ^JZW!y_8GhBf6:YY"}W MyǍ/+:MM_Q"z`'7+-+ySʁ{SyuѹN_컅SPhvպ[bs_jp1_-8WlcM)Rw;t-s )nV DƱ_ß `Nḽ2'2߇.L :otN*WWJ((FpB`:`!lCȹp?Q 2p 89^e^n{Ç%nY66or/ݟq0l. ;?- n jY8r޲p^yBW njYb6ûiM#8#NC";zmC#"sSG= ᾝat!3I@rA賊x@fp:L6SB굾h+4<ψyb*Ķ]o?-u$˲P{.'(f9 #*kx7VpF9kx 쾋J H:/r}n dϱM+!*#솯ܱ+(5d&cG M`87r&45X/9ih{g73<Rb|{y*.v8WAx.`+; 󵃨LΨ}x>5 &=,MkaDo)bT{oǛ7\Xn>G縋*pQ!2sDfcv䱍1O10awn&|ߑL 7Ce1`!Y艙˜ZM`{"歐sYO^Fdia{^=;"5fJp2R5ncL\RGabD{P [y9^K̏''/j A|h|SAKlv.F2 c`-Scqж\戬bnEyԴ&r t h{KP&j撚o&eIΕMNaw`/W!)?,UqY[:-,t[·Q\f󉤉bI] +<pfU% 5BV|1w(Jϴ?BK֍hqTS!ΪIȻ==-"Tpg~;D[σF1C1` $гZ}9/틇UUOzODe%n'9Wfh"m] ntrnmXt';rjwӣVrD0|yPR3Hӕ٦  ]B~" ԁU 9UxsUί)-W X9ByKA& yf]q n1{J||%5vZ7whͼԚ%n<aش&6~jx4]#E*X2Kjqŵu׋$͹^RXc^~d"8NIXShжFvKE]~ܤCT@C[7I!T@Οǐ/lTm2;%>&KynC%݋LxXv*o* Fkґh4TV#/"PTq,M-N5l0z{Mj;#-V7w ۈp>ްE,єQ#8h*D)ʸ^ '-H0)x8Xx{F=2CᙸH,Oy,>t 72(8al#CE[rxgS6q2ko[b1f7w. (Q0=CD 1̒ߐS8C4iYD[AZgix~0$ o~ER.ѹC~ 7'Y//9t!ףdUKzDy- L/1u3&yB6'fhҧ=Uf9&L-ׅo~OM4N_"MAkmϨܙ~E74~<Kr:CCuJk0JQ:< h&NhCѕTWu=^'Dte^ W!wUkuyI]*mە !o"Ȧi ;U&=V6`ZW[dz"2+q'0nvk-"'{6Q2{7.7l|TfƁv{tuߌ8s_r^#bUG ֙#`6k)N2kcj+) sr '8i36@uX.amlɀAq_M<.E[D]4nTh.1D@SF)gLU~-ZhhVDYe2KN68|[a.`\!r]etPyP>9`n*^5k0Fk:[͆H5t/}g씴fm?Z%M>W w`X;kBHNwzw .8M5m LBIP ֯kØ̳2%#T_XCw_dϪ])┩HIr:*R`&r1Pu.Uԕ;j$]>/|3g%qg@dHv5.א ~jZp1Zh 4j.SCy 㬯vUX[I&7&-PbzYT/w3A~j»NcysonU**h]e/.6-C%yGŐNl{9o _r|O/boa;#s8bJp~;RYoxZ ^d*nu %\T.ν"fy]궿ZΚ60wgEv .j} Sp)6z?yjukǏ;OE˛ZSvj7?n"6TOӇ?E=9 &DL;3FfvUNPPMin_^ny{~ʤ~6}?;,h΢CMVB:QsCs be⩊-G$Wٸ1TWF9ȺB(fat HYi:']f4\k: &X4¬M/gT W ;a-hK LlK&DOAi]8ϚX&/Yu:d>bWkDq^]/H4t_]?PC>SAmxn ]@d GR*gUjtӈkp P M>W}9thr˺Бs*{L> S:v.y.SVu`rbI#W[ߍqvI"[!@ tʣ3N'oJYk,ا|偫<Ïa ,\0"gUiʊdPP49kCeBhT3Lsޜ#GƐmN 7&̉}w68^AпL٦h$"vD ac Nl0CIJ:7u;( S0;Qs3QC4mW茮8<s8ɴ+pIs |aQf]o >L@|3C)c/I5!xJ/VjNj0]nD'Y$.!,kךH 3˯W,fb/M-wԗ[;bQj|nAUP,Njn\,' UUJB sCBUIfԤ!~+AghB67Y>+LczL!>4[?\Nd9JHǬcK)#s<Ǫ_~ Rh@|g?yeٯ)8FK!͢o_xܐvDMJanTVOgBQvV2RPI$ q@y -4킶#̊I_&[Y#+]0P,iHCC건{*'sr\\vDBaD7$HHS+yZqeɼh}fQVփG3/9K?ʢ])֬]L {ZzGJd-f u1cRc {\ۦkH|E)zS1څ Yh?n[Yogm$ #a8W0S$\|5h|ᔴ&V4>Z4am'c Ă!?Ule.8=6@yg06^2F~.WBzS|5{YN-,{D+bp @b 7_C6Y]mVQUȉxj\E[Yoۈȓm&ԯTdpN 8ŏXig263Z>z5}Ǐ@+_нx6z?ٵi3 w`1P8҅'~h BD+7 Vgg^m{qE?l}'Cd_h>n%9'()д䎭%t:lŖԏY)W$M|/ )8C9ӄx!s&MϘ(`3 89’^NL}zV2ˉ=X.&\9pkjދ i{NBԵFjnǒKU'j۩+ bMV ~StF@z4bMί^X}Άe{j4jK&/ e4T6"==w [dzEU 0AvӇښ8 X*X"*q!^^ *Q)5+`oլ!Ow߶05=vā5عC-D %"8歟y|r$5RZ^8j gL֋~>˔]$"oޜ&nfDpn"'_|c,#߱Ki-Wh#pHlC׼NE:|ȩ%w"' ;c<a7KAkwKpO3C 0H_Af6?Rz濺>Lʾ/K7%7v)tGHfVӌ5;O|ߜ \%x׷梳I0IXC}EH({1Lўk1xid`5 ğiNMi۬sH3ȹQqs~)|*iHF-p̢SY=e@è-4F@8ŢqN隩8Sۺ0 cm9tT>Kny~`MԒUiȧ^jn#ͅ_`D'mS\% RhWb~r`r=u4@#oȖ4e8]؜~*5p&=Zjl} $g̢IQ[ӡq{VCsC׏J] ti5ٍz Z h|LJ$`qrsvl@s8td.:S1U՝mb:pURG~ٮl_?M[q7$/E`YS{D~ &d/s6$ldsS3~gz=gT1YoaHe-L딃ȴhׁpfNoj\ERgK$Cv=]:RMU%k?]utI7f.Srm*#f=Wޠ~!i2W-/"?hDPخ%jqnCS,مm.fռ[گVC("b9.Gx ¼l_24^sӞݲ1f\mɉX/%3eQp%3QW[MvڦjNl7ag}lX[O͊uRH:5~m;Y}}R[o5qH?A8:߽w@FYLP?gF_[.MGUtB{GuV1USケP%;b5g(,VϵsCi(v/3sʸ<-D|EBOSؙ5^H!1MdV!'eG>jx(MP(~%lYC à߈B ?͛cu*7BѼ_ qPbFbxnG)e٢!}/>%E;}ldKجGo(z3م9>ׇ6^& ivJ(>EE5)еtaCzitp>RL]ug1+ rQC5gܦ.&S;Bg$KŻΓ\@"M 9we2ΐ4yCF" @[H^{">uv0F+.ب0𞒇qE.)BǤy/"+xbӧD2vXԐpb8ɮpq"ogM^t =l.5d+Ye]Eg3G2.̞*;Q 5k]ĉ * i~7f2H sn]c,p` ٔoA<rN3SϏ}%~'iUcYk,ן qLήؘ0="qfHrAu*v]u>?3jR/v]EkwS~ƹ XXu"P)o0UlwJksAhOo?wa/0mN¹p"a^VC[3-8.٢a?qieoFMW6-,vm%6E6pJ[XxuH5I`YQI](\uMϚKш"hHsb]ߓtu^1;TՇrhF?/Oޭ1*oM_oȭr&p=$)\T2:kow~19weUsYePE}n~vʋj;M>᧶ #5[m[ie-jĢ*=/X1ڭ;Z'cwZTs"8xM*#4ٖN,;2O TlXf6odrlroN2xnXJE.j;pӃ>S1a'4#v7w$oޞ_>??_X i/}ۘ@l)H .~w=Gl?|4HHdQEGWXˣ^؀`_íf|D]&=6O l-ښ|bؾЌ߽w#$>;x}q Kɵc^lzw[R zT)X9 A < k%`>G%L<NmI=^9ã5 [P;r9);@2Xfo*W3w̳OWLR@ߚ PIi;SsmmuwׅږӃN6Cgw` IhۉGwba:d=(spN _QD׭WsG7fT>x]XA TQέiհ_8uWJATu>7NnԌ(cg(2e^iR7'zP&%v͒*{Mސ*UW}C?I#]6sg̣5쯕iƣ;n.~<>)]$f7@Xݖ2-N8 K!El&);~HF@#6MIJk7I3 >Wm%`2{Y&iZ/ a2.UuhJH2bݱ\1]UH//ڒI2y"a8<1uc9cL䭱KTnkY6#`Ydu''w:QP(ٖSݎ<g32Bt.9ki%'sa*.B9ZT[LÏ㈈s|wo8 I^ =Cm{8IsdkL`gتQCu*h`9;0R{̇95ӾHisrIj/ƙeqEz6H&~}04 %0ow /Grc{g=nN̞֜lgH.'ʡ͑ݾA䨽1Z.=f$-a }wÇs 4:v}Pdp7EWTGf>ηQiMzLQsђK8yyym^Y]Y$*=D<^/;dfr?k bBx#da9_WY+JAdm]=ve8IOzH5[!o[ƒ{AV'݉m#ִ`iǖXeB. 唹>|X'•PIZ Ѻ}ƥ@4,k%dYkDQt%EλN{~LL* `$؍5kbB36C㔬NWk<^Ac%7}.1~X`2#i#Ӻ[2Uc83 -tpEwk.kH\eg7;ftc:ψɰ5ժii޲/uF`B#]d;N$KartVɾuT%Ct$\9}~I}:sn:ky#O~iG(%"fx9g`h~V( - o\~:,X<3X"/׮LFJ/B#@A,5 QL ~GO+=vE&]xV֏'4Y𢆅- 1BQ3gc3p(+sk=CCP:<8^۲1 0`k^H ܍LyKvjyuxI8& ,#BSp9QO[2 5f&&*YR* 5&KCdDg&jbR 7 "݇jAey;AS"qٛjDDZ;  fTZM973C;xUU/o;_6 9E}uhd$SR(|Uun|y%+;o Y_AgGI֢ ZOW5h <{2bQSݳUIҨ6(Zt&S4vMv15MHz8/&R[*bXrIeLVMХϿO OΨcXDsvގy8/\YUP7u3k&fLCT%LLJ< c5[ x6v|6ň!Ж GƮ"Raje0,œr }Ti/JA>'װ}"YE~@Y3B+Hl./d)l_u=% 0*d튋5w~b y/|Yo,GR2)$8#rZ `/EepGe 40O-#;3y}se$E7Aw  6/̍q,R%e0FB>cxL o/v SD ZUM*!)0<+*#D80WyU+a!(BzNw/8YljƚNjwIEfoW9~`Bu4!Mzs e.z4is jBw1Ea י8\ _I+ |Ng0|t/yED\VhaxL7_>KuƐں>qc :<] 贎8& b^[<[vq`޷ۢp]o$!v:yXv0SBmqlݞa | 8h^M#GK0fuvPbvVuy4HMg\[37QlpsG>LV/=k̄7絢M懻!;eao:ݩ)\/ 4!8<m[סryJ.5S!nThs#9{Jd)_jO Oe/m0e~UEk/V%Eթ6z Tgaz5-|!37f޳ZWl8e9o楝\ X}8X+:!ohe;O6~b<9Dd k^KAO+<z`4#fxڴs es_ȾʽDC]~ÌR0m!HB.4ܙbOx.q(0/-[T1CoFuSa8 zwd,EWh}7dwW%vi`nbV@dc ~E`A="ׅe%Ѷ^.\:Y"sv@B¡{f>GqvCǟYNoDz`^kq ]$5CP*P%ج'A =d=q?6IW'x%]\$>>d}ζ/7;Ί]$+ttra*El,Gh^%і- 7%B$> {^58&9׎04Ũۊ%dx}ixוwK`#b/I$PKݭVZ,bM` lR#dDЂlC0`c$Edđb81I8cYM&̼dR֭jIߏ}s=?JPW)oy{x[骼ڈU5rES2᪚ry񉆝!yi8;$/"5P!T'# ;kByɅ}uU;Y..oh.$/4+ \4\bvyŮ* "UUZ9:xw꺪:BLp`gyCCy;owΫ]^]WM;y;BrPEC^!,T]*"o^J9##E|hes8#%cm6RZ/4VջE )ϫ2äqmC*K suWjh#(ݑ]}wE*zV\q(V #@sBP]yj^whۭ8qdO7]X&D(op1qKÕ9py5 y]uż\ KEfYGFRB9" A'${K7Toф i=Ҧ|c#R{o8rii=-O# y Ef7VG :9h=rCޜ#RWrD" 3\iD {ZeFW (jըkyNFB _&;+ҠGi9L%]颈1zZi;I'l\)օD|@9I~B;K;Eybڑ<}7ah7sI,{N"bc]X*ɯMvNǾeyzsnDW0;)G=Mn>`!=͗(y&|(Yf#޺XΦ)Yhs~rkipBl\G$U pigQ̃&Ӣ\thbK|P@SCͶݡJzc7?.NrjgObAZl'&!ء%og̷m0#[M\59DUnC}J, s9r- L5sZJ~oC_%=s*l]f04 0qlȕWVחo U(CU!f4!'!t1~jr)J9UġPsBL2D[P:rL{ sN*d2q; qn6b9//ņ֗EfeP1Ϟ̈́&f&?l ʇmS9dٟ7m1<&gՙ# +1{11NFE]ܡ73E8gts}ӹ$]&}_(2xj3+_h$GMA>X  FSQbl^āq›8re6StD4 <`i|sƿKVGn 8zB3>2̱Bl<4EU3 "˾duij:!-ZL|̈́N:GRT,ᆣrXx$ #O34+?]BE;>2i5ud%asqȺV/YP e‘n|[q&eJ\uXAdZ)Y`T8#mKQ&Ȑ7sy۫)B;@NPaшZ[SOO.֐? Qdc&2!!Rbr,J U1lCyEd7RRGӱn-BLޣpW,Ym W3fΈ?mg,;Z *-DG"P~;Txb&9$JLPRXY8NXCʑi<,J TzZjd=>?tH@8sÕyC!>,\bdNnXV|`zC^PW~v!C額?N|02Y(uJ[yl,H 5{+6zŲʷ&܂z'?)&fЊ1 (1?岅.'bqc~J:!KQ]BXaz` aWڟFM9ij?vA5>di)jEG!b!5^Ul Z[ڃH+Ԯ|}VPu!coJ[ZP|vaf2ܾĿΦ؏ϩ$oHQ/2"0JlD$;:y- +a3piydZI7zmU #\2 hqGNMNqC1j+h^zbuc z'W) ĸن k@ 榱3QNvl$z ^,饰 ^\흴5m(k 2 .nXMF^Rqb[Zۖ]Ğ#L٣:n,Xxag)BlLW$Fl}T,9rQ8tI~ [K%z-HVU`z#X'4fyf"IK{9bls*g;|C[ռӇX:ZNTM,HIVݞZ(,>OFyNtu+n~ cسKO+FL"ND&T|ߺB%=bO"fmU[dFn۱!g^B H w3I q)MI+_U!5؈}]aki(5W&H/5M@vjvYq|l݆m@G3_}: h-m.n3(M2l{;f> ,19 /QvQT!dY->1_wb5ƽæʙc~P3[Ev{+tiw-y,PuMt4իUWxW"90yhJAHtOdGG=qzXIHaJߨ?ެ#qrpMp0E*Vl7pruC*zhC˅#&T ÆX;0t8,#b<*X\v껜 dgƪhy`PUyre{WPd߿6R}Rg͛SU)n~/Em>35EUfyjsiUVb~&{c.xWM@qijԮ.PKB݄FGpXy05.^aJԕX}\â0.F$ϭ)w'D(zv|r-Jvwj=0m2˔/eq)[+lw`qnA MA-mKsƜh؉Aq.^f8)Ӫ \Dxі =>9zAFd0#os.,6u܈`?NVӿYK0퍺H0" .Z<\EyxϳH -Rɷ>C ͦpc0i<]Xt_4iI :e]nf5D.ڟ]\N&+MSG>xaLS`ZjFoB$Q dsjȤ%ArA'ULzZ hSKhECr c&=GhZN`Qp$ڜ+Up=m`?)2! TՕ﫯(R) tjܕKD?٢J(% eYyE|k[r[uU7gͲqΑ+Q'\a]oDQe+_i;l%q"\90mGiډYcF&d8|;m,$nNo}madDOVpd97Y\J;e A |~Nc3i˶;adpʺTZJWȈ=~\'$A {Tը5Хx@^UG1bmĄMqIQJNF!Y{ ]l8`ۻ{wu26k/?~J+kpuEWjzfo~o6oq1҂1Z6E=Y ՟d|&CJV+^ȭU5ORA >G |+bL*ndho~UUojUB`3 }~5YKwO4^ڇFWDc1Z,G Kwl&RЍK(U+Fxh80G[bt25Ú ?`䬬y!tGk4چ֘װk̳}Neiɳ,.4k)WVKv&S\0T e?D,1p7O}/3MWN1Of0B$ϭv6~P#]fk ˫âQZ <  AC3"ޯ &15;2"Q>Fru9"YрDb8%w!X, ybpg)AO n͵84eDCg"A_ݏ)|?x2ƓpWē%) MR4آ_p8x aVD!UCbi;BB㥆k0fx5SPlIzdž~T%v[ـVHN|BkGѣE,64UP/Õ?X w 5U[X?;K7:T&;cg@=qPˌm37g%PkUU,Yu<}q(J,h-.q]0%wC_$${ "P#&5̍_I(Qz=|R?vU?[fj)S[lPL(O^UKvR'0*.|wu8dLdhM(Q, +rg W,֕/bm4O4mxMzec3zSbKv^6-e}A8a=Va|#C, _IH\vvai˅- e%*RObQ,_F2[뱲-3-5s! i4F&*hiQoN(ދMb ;[$ *3eTXX`G~ $R4-VJfh^)SyyȷF>/'Z/bgawpY_mqԊWU[^ʯ[]}wUA_WQq 1Ujr>*ʌ,HȋO׊}hmVqE|7EڟKuX3F]JEs{OɎ-'MmziZ.wՋѤ!SXړAu'#wxu|UqdƊyٶ &ۯE9B`i&Y)Ul{ ke+#B8]҇X# ;(@>>׼,G/ 2ᔍvȡ` 6yاtYj6㻦A4L3iղ2A3QK'= +qe9!7Jzy3c0]#S|R}oc虱x0]kf8k o moTh_%Ϣ\ ev0)p9(y10GS-7Ia yI@p f3rJ^E9JB( ZrvI v URte qd KD™~B!!Əq"X[1c:N4I̳,ԗ?HwN笘FWK+UC_dcI`LJ^>Y^W4i"c։EE!|6q=v"jHSOq4F⡀ _Ibv'q'/T<4jUKq6 sVǻS_N#qlaS}aU Gj"UB9&E O)twޓ\Ay0+;~Fq_ 7§|tS>L^Hk3ryK ! }c d񯍊 !&L ;42;Jכ)F"sz r  Ij|iܗ&eZEtڴY-sMC3(=y%B4V ZtA&{_@eAL&j%U#=(uB'{F,3LN h_,7e$ m \vo1MMXv M8?8(GgaEOw z0agun4bXKX8( )m:$Sǂlم3!"xb,ĈT[0df_ĝߊPyQ}H`oBȇY <((P?͵cp CL;&ԛjr3)/I`<nLEBbEefWCqn0_"! Ik: i<cG0M&[CY@@4ky}2HWCy1sؤ 2 S@ e9LCϺE `2ߓQ^(y  ov%@t0~z {-KSfQƋ/: I*a=*ML0tM)8ANA\33ABkکfµSA4rP˚gLB*,˳Q.Q,dmri`(ւKߞdtYt>Ʉ1"L"7fγ 01ސyB8EEy^p'Ji+{4ܟƬuK'"\D3p zSL !OGG!(9;f$| lv2qV%4)cy` $Q%xQb /%o%i-BPK[sý.0mq*Q|/.Is2g&4JlgHyn=;L)h&OWq:(AOzp?.{( hE R).3oۑ_$F8%!.B|5$7HF4(#&hAKlW"44ّfx!X&`F 7!i{|ߣhy٬ۢQvV w7?,$&ycWMK)Tv I2 ]֛8.(m @vYd[׽D Sf>)P,0~2dqRAE$x~IO "/E X,{G*('PT["@'#Lme 8()}_PN<"VP{@\'D\uݘT xl03l[ckF?m$ME g$ rsB'Jg2ʱC2./%ћ:g`R4aRRR| ] K<I xמrY%ڎ&P4hM)HYv#Q)؎T͠DOf NCqU[=n 'e zΝgV MMDq\2'X(3bG.63h+Zw:js,olwl s,1opᮭMCq@ Vd {THR+r/]&α%JbW=Ҟm$4+"kBuG%0 mV2O/XzXS9µYFPa.2mKэ+׉u௜6]'6{huk{ڑ \GX/Q0}\Wx .7ٲG">u>ߝmv 8uy)@9NI8%_(⋲$h@I"Jt⋵%QIF\uˊv4Н>`pVҿ2S*l=C @mʋ>/-/Q>4M\Oosqe};xBMz{$t&pu9?e'nqP[A~;')-/m_〥~{0,`|I N-Y=-Jקu\@G$INN{ejȭ;ДOƾgWSؓi|n Y7D԰_wJ v6|P'-sA.qXZn wMm<IJ=]6v9F5 ~V ,q5hYݎsmLŸ fŦ l`jB…@}UVBq{#g[vdkߺ瘚&Fм~7ȅ߯P*,_'|폠~m}ώ 08{E(-26(ù9M[#W0m#tu ySŶլ=@#.@y=8XmqF⧛FwF!4%zHNԆ 4-5 nX2 y+P}`}?j~:f`_n`hMQ// `.quǃ~xq2w%yŇ4J\@1|.pQWLvV&(r:|b~zV8GNpbfG{ g8 ^<ЭK<33zd0)ťEa6BsQ? yv"kʝsb&߹Rcbs,h̜ӕhn˶li>KS@I:ƛaāGR@fg6 oQJϖ^c끸#d`-NǛS)<oc+kkCuy_O#feN III=O躐}B~6:f[xOKIN}6= ̏̈́^I8<_~/ |;Q"#J>Sui+.c:4Ccg4!pj|X?M}7'ח_oʕyخT@|J# suwh 3J@qB%tP8@ W6u;,໎Hn*Bq Ϸ:ѐ:q=:JBݶ^k*|6|8ة8* 6p It2RR0z| q9J=Hr g|_R opzGuEyCu$\O|&q99&B'QHxRrRBh>ǒrR6+JR)3 km J ~Fun-ך}?ʶlu2ŴdUM/ 6Xv2K1}u4/֑qjov q6k7MJEQ8DC5p.6c23qɎɑ]r$SckK? ޾aD?~Y{͏`ڤj4?;0>"BsD/gDxNMLZ):a6Ʒ;R6neR+G،"< eZ TO/{gLգiE㈣ j) 7|%'x|3@>2Rfx1A ?} L{kTEwjdB\&z<̓[4u à+ZoكL,S8)x_:f~7!^gnG~*}861 _&kg* G,wɉy+-1YGBn|dwn$jγ`<;z ,@=XX/nbet:,J1 <`y`kHUf[Q-`>$|ymlkF66>~d˓mxǚ0wS 373)O_MEG, ?km0؆SVr6K4(Aڄ@4Q+X? ̜ aȡ=HMAUPI[>3VE[v0MMC[E'oP{o|,E<-bP;iw )6dy3'|E u\ <%$f$|J;%GCE@aԘ aRvA_1'T)lN*lI%vwd9~DT89GČ8c f#pVLgMȉl$/LJMD.( *D':B0e0( Cσ R HsÏm?xmPaq?JBx *^[LV a 8o5<dϊpP$vU6|CcPgў ]] )+"yXgòu+/]˶o߃ ? K~YOm57[[:pbG`:8 qȴ+fbI^_'ž$gyjz@xLk_S Q>)U?iq?;D680'^ 1Y2[RƖ8(8zvmJ9 YAfMo,)phDž:e7 -2o (H<5*{pOw?kխ8hEdn^bPx0M*0CMt8)" tݘ'o"d!-X`[~ p}sa4Vfb:iV~W-M^? D3I?ip!Y4P̯!@_黲DE+; )jr[袓*_Kw6~!:{ލ~ZޟEE&/͆3&,ba=QK\h)s}h-< 7ͯU!~l.ok6Үclm{ |_2j6+ r}H 2,y`) F_y"W壳8{"^{̥k]Yrӡ{t!œ_[3ʾjxb|в@ڰE%:L4FP4Du_eDu[Х8Y:l#L%0)HpRGԁzF4I)Nd'?C'2;ۿW3+2zu&\ÍQ!;n V{(SWd[-=vI y{`kl sSx@v.Rgh`c$p{`5.̊G)YO6| @5Rb?kEy_ʔ0S*/ąg Mlz:*[4 sY>@Yp m E. 0NnZm= :p#a&ᄁFI/A*0P4֖4 bS˜B=`tiLL%+=`lI4L %(Iq Lf1ЇrJKSJܞd u+†[RAbz:0dZvٙT `@Pn< P)v-[X+,XvoAy{i4$L|W82U]0]bV@vO{[2\w-vOcw*2`䌨9M$ڶ8=ȠOm.Cݚ[~/bc|EFjz~yRes*s ,K6&y;haRfg&|wm4ݝ$^IͲemhBziTv$&iRvdeFmy8Tckl \KȰYRS:&s;,Yz IxFǓZFE`]~4:3`oگ|l(;oX@Q()FJoj~8KDnU3 ³{,S0r3i3WO;;'[&ZvhF G*񠳴g֤MJPĺӦX$nO .wȕuFmpي9"GJZMeNf[>%؂粐g7+Tua?-0\LfWG>hJm|Ţ+|.{)] d "P-.*0=6p-P&`VCXX"BOnJiօEZ@X+: idJBceXX(GzlU#l %1ĆI%2H:8H-{3]Zm莇)?F捕&gPn!`gPk$/i jU}6$M^+'Ҥ+,$4[x[4*qSX?%,?b|_pw]yN& AaCl] 0NJuw]>A8iҼC hTx)7$k07^=7X̭kQEKpO'H+t.<3󛎯Ҙiivcy̳EKy8f4JbBXuu!0vڲL>=Q@P=̢^T-6;{'Yf IR~BayqE j}8j BYRָ*vt4.&@6^xyIc6I>3q:)~2MJM60(g0 %^2Qf ;3,ʖv~$ִW!-cy NYuq~f3~!¦]^QLw}HIQ]=((=*VXdȄWS~)z`X{{Ԩ^ `+۸z(bjpH6 uC/F #\ R'/nkJMNqDiKrW% ctG.)oGa ,*tE,g{zF7%61-Y 0Oa?Z1 wš뮤Q|iAg]桿e:JSs-)5E]lN_AҦg,U7ᶚ}9 ^$lMr0E8AQBհ$YJu+M`p&Yʘoedijnw 5H1s#3=NN2c"=)Eʚ zE9𝷤)c-sVc_<&R MK"ub -yFYtt/2CB+}i'[@h]=wmhwdouXΪ_=7XӞu8أpG]k{JhR96Wx,%/Sj^D=Bel"$DEv7Gfɕvr3~>^ygHKܨmQ dVa>tڳ'x8E[mk/~^.騄璤x<84o.'C#޶7rvG*w׺8džfSzJwdD/d`Ӭd$Y`GdȁRvE$iw[tLa<ϗhei|Գ\k7SkqlXEc/|bw`X{DH2 v*gd}UكNٰSH}%Bc"dJJH'\#hڸ+6q{3!Kmos<۳lƸzۚ%EQJ㊳FR?!De46N% =ebޤn;G]shMB3OOR'(smI <u; lĮALU^,,2zmxřbiZFIxXrmKeTi /Ñ+T#U:t:/mM #HF?x}~Ȁ7gI}'$,p49]2o-MIe[# fΖ  n 7͖9:,Nl"Gǿ1wc^6%E mpN#)63{~Mbj*4Z'{Ydw/ȀSDG,!<4 ϑn(3:^ަ6,ĜPb*A5tkp\i݄ژh=Ȑ Q9:BȲ:-*a2bkE/cFM9x}w|]űoq\eK,I%ҕnʒplٲ)>H>6WȔPN`I^ VH#%%R!=|3{-M>wwvvvvvfvfoN||(RݙB`W a52tO(VCEM:_'Imjӊ+665&t<-Rѐ4b:uS4cuA5ԯEF ^ k})=2:SX"Փkh:uacc#v࣮ :b5-ل=6!Ca-x@]u4XĈ19 4_H.?ӟKZcQǎU-/"G%*iq+eH,9j9w~΀A.?9R :RFzv뉄nN?ִ0`yʙxsCCO":RA&>!30x0~ȯ0d҈! g2`8s[t45n(cQO -|V:vmYߚЉM]ҼiAcu\ԼC3QX&hBs[ؚLg .ڗVlVVOզփcΞfD :ѓ ݤavK[غfJu-rT*Ԥӑt>봺n֔qw I'lTM=~Gs&kXz3*{±sSA ǵ(L%ժ1hKi±X*ЭԌ%FH ՚@&46sS@+S`ߗ2Pwzj*iP?`8l+3д>g}9~Sփ 5(,:&^:3R-yYٙH dj*## D¤ fAC`6ʳ_5wѐn%`15*f,;$ GgzMɦ%E2H2rOŢZR"=` p~x? ̉n6P~29[{khT8p,aZ(19to"`$Iw=ԧ#Aax@ߑ^р{>@m?ZFj82)|bEG~Yo-h]6x^'Z

l9M}V81#MW)BX%3llw.8N^]0b0~eyuS@Sz~l_(1tڤB)׍ueK__pvPfƁHhmSd5&;Nd1g8xd`̈fd pL( $C Qq ©hZ4ATi [½޴nk @L4B8mx麢̚baٜ0n_}';ٰXyRi=]ta,mT:~(#@'vA6齨塳ZT== AF1GM"'T+ihLGDx)#P>K V)E4aQÛ7jClj*>4ECz\nrvTM=J#IN@Dw|<L ڝDXFJEcI2!!uۡ F(CÎ;+&chI<*Bl?<kƒcqHL: 뚭u3ʞmm#E; OmKz*rZ6,dVq-hB !܄VV/m0c2~U7 g.~Yi|D#a? h*`xi]cu˷ݱdI:kd(֪pA䧳~5L>βc>4A7)< 0"ns`4GE=lB7>,W0ud}}`uq;g %yH0m?cW\gaOn^UY.:ialYkwXKYڽV#%=EPyڬjp (F1t}IX,Ϻ9 {T# <3'Y&AlXP'痕Z[1 |Z?<}:qydcXoEZ"V^ܵo59.}|r=Һ>;<4DЧiD 1-g-]4ra[lo.֠ =huÊ]XIK!'?PY5.QOr#LM:l,]'} C݂ @Ivز M5^$IVG47ë?wyda57=@ӌf"(s}t͚a&ipH9ފ^5<~2esئ,krƫSkb U+NI^φn|fj򥵳cc>d}sד"D(#`&(Thi$Z۷sѼD "v*Ƒ'N>}'G^B'DVSSj m2k6hOe&5kvٗI}FM|PX>o\G?aq%;vCw'u ,/ &C0"ix=vݶhL] Yxt6'BԤSא j0AOJrrtzúF[D=oYHnR$x #)nк[{CptLb@zp=zݷVt} |_;/bKހ"2Oḧk8pNL[9)dIBQz0Z3hUF{#M,,\hf Ϥ+*o~pjyi EBRMM$Lw5L PFD zY=Rˏ4p2:]/`qSʽ0S]GWPNisznb$ oJ*FS*ⳛ6vTݏht ײ*)ьd0qVŏX?ܥ9$0 i*cAubxenr.Uu_Xz6y_TDPm2a|B|Y ?b%X97m:YpԻ^u͛^8"] Iw\otÓDzO[7hjM8;Vj Yt-H5p>#"zW0e=_[_]S$f}ȝ_lٌyk^& WcvO )F0%@OZ(dzfYw`]{OR#K.g9f_j^> ʝh/%n U~lo{4p'κs.F4}R8;d=3CG*ڜX}@Ǝ'~UU~۹YR׃z{, q ̎lBM:Н2W$7 Eszcr/;|s0;&1 +1g:aCZT1T Ѥ4CFa; T@ulScNhĎaO[8E7.Aꦈ1ehϸ^AVBPIC~t$c )JOx;D2X5O}3MسafBԂR"I@?b9DƠ6q)`[_r4-R%hD>-yԚwBRВRK5i1D,x/TnrwUE`,I͊c&"l z= dR9v:E$Q1nOF'߳b݁u߉0tXtQ#CG{Exbү26]rljU7LؓH$qgyXczZtm?*zԃ&x@:Fcj/YQLUڣ~V%:p:Q)D۱Gf ]AaΫۉ)IdjT8]Nd$xaiݥay o(&KOT8Z덣M֚Y+u@P`otW0:R{I|2NE`1`vƫ79FƯZ|0Lj<9 7>HA#+վ0)} "Em0^.D cP#68`QVj fVܼ2h_%R*kQ9H͢8rAdL3*gu`6=d".PMsXlu>$b$OHLc1TAOYz~mVP0U.nN{d =ڇ& $mKsQ]:ǫMB"XK@vzD$ }xE(6;Hzw0Z#C$u bp[uӬw1zmYO<1BɳnVG岓dX/{5"W&%gSy;CTFP"K%)K&{df00c㦓jF@:Ld2|GMIV hȏ=.m-Ⱦ 8r! XGu`NE T=4C3MNz۟":%Q7E|u%~XmӢ13>6vf Dwv2'fN\!Mk4,]9H[ |E;P \ c^-z̼VN,2XtХcD`/ qO,>< uf6O>^|ܚߎ0Jҷrk[&v"?iWodZS ᅫ4dQ ow1m>I[ƶ`B.UR8;cӬh=Ru)Ov|ꚭ1;`kYrlKzYdȴ~z嵳Cf0ɺÃ)f3U[#JV :cϴ5YiE`яڝB䵆rA#?{xcsx@-7!k}g֊_\<8l_~?DFGx8g=J+/ygl>6 y._2&6#" E#[~Z"uU Qifn~&v$oMf5y忹oնZxf^b'}2vK?ʹn].*1T8^%SEGN,ol!?V̳sd"TRK9T{/ mdžWWM\ngo:Uj<*vyVks+'[WV9ɜVL{-`5E(~Q׫ e F01tOo, 87MGuO oTMWߨKiiNܢKq' ;*O[ߜ ::zޜ]Ó,kI So~[Vɡ!=_KH?݂>aS8"#o7X]:UGlѷ݈R-˶->'('=cnKeabJtצ_j˳wn"lk]EHަw,U+2w:[7m镮|avjOꩶF0=G:6+&ttNӹ%OZg,et9jUL!H;vPMC߳Ǟ"kh?bOo7^0͵:ɮgYN|gu_AfV >M=0<Hk03m1= 50~f^Ğk>#j>%s"Kasog,oaIƒ\ez?FVأl' /fp+;E@;Ga)CV%>`fa3bf7?QoGDz5y1]-.-$QDp[?)DAί1,S ]ylx!;ǒ| FT3dL-!J.A| ~v UOYƿU'1[GnfaK٠mg>GA*~$>U$dO'ҡQ9FNfmN-z|)L[nof6Oa-!8hMzxH0|;ilhMp/v][O'-\w# ؁i-|4…S'fvA_Ml%i]m-oXn'b ;MӞoQjaSmV1_\?mH_MkحΖl|5e|1㇧3u& {;eE< tWN+<5fʣnyL-a3'tc[A_1BoV9i(ȱ0B%J:,AOӁltVw|<`$*efJK+R~^;wKY휬\ - Q"sYp/Oz/09BsfYH>-DM'u6-]2BlNEQu͚ k]sXeI&u ķ?;+JKoTӇ :9UZ~[4R<_j VQZٱzUd5Y_jKb&|[nV.d뷖:輫͟2#A4WQkXue{ƏY]j՜}MֲܖD54z~d>]ОQ[Ԍl^UVH/)WjkrI.:rVz:@ulnenzvNZ@ye-?P9HVUl56|86j`WԵ]Eand{s<)XZ74OJrLbRu,8 ?W \}(V"G,O5 :ߤp7L#)SyzbO!='B~B9eow->%p< `b!M/6M+VŬevǨ,'`@~q tI͹%mlz2f濖}KZoYX6Ηv"V0c"KKr~f^ḊZ~l%X9Da&p8,=u{ WHi`?mW#A/^wqĤݳ.O68{n-%:f;N Vʇk}D!Fz>>YŹ~dL@slU>pT#YVm٨gnJ%*}h䲚[,kwÌnB7 XZP Y#>t$J _ nfբ'T] &9Nȶ"A ڹN_x@xVhMAjx|vVdW'vVv I T{j!џ#n>1STQ= [ߵ<&ڊlW_hKJ s;{k0`wmgA.v8]38}S;ٕ9dG3*s ՓÈ"erb4 Nc%|\?,> vG[p3x~H5|bUNZXгFTs.<@1q *ٷy&8{LD{&[m^[vom4d5_i<0[.2ݎiԐ{/Ƿc|^vuva$9}oS?F0Og}-*H=`VN5-[;Z5G޸ n}&#k-AV; (A;iR_GC,BjNpڬ[n2ʹ_- nlکht6w묲<9nW$*6 ?;mq͟e ߌea\0,+q |[&-8SGrRV~LJq:tmxGSDNFca`{sBO"0q;?qWrqG[vA!%fz;/#a2d;JઆY} 5l&'o\Ŋ5Qv8 gL]ԊcaVN<gߙmWbT)==~'惉L0W b$=H[eӊ`O/%M_{Iv)ds뷊 :I`,A$èTN! +KXߟb`rz[__.籹>,AFa@9Y3+JZ_XiNH +|?"k?U.dK=+=!4_[_];P0tӲNH(jZÙIs00ƽE},ʟdVKte2 ;؆(>2"qd_;)v_\V7Ӂ{2\!+l$C8DrЇ@$^aVQ]8 WeH,"+a}Wsgxy@}˩uϻxP@W(ac,5O:TZ[7\b_+(lF #0xʟjz]$O6רY?ቸ ٮ[M΀N ^ 8 +_kf%ce%̄t%cJ ~qdn^^Ƕ5ױ@Ǘa(܃i0ᠢg%F6z &$SmyN21G@֭5EjOs qz =k)LSn`yXҨ/|V{"+᧪n^p[_G̑NuB}H"3׳Mir2է\ EF)iU\,^ӮW\7pbC \)R6~ף#2@xh}ԃٌ 7߼MVc!ϱMżDrqσ]O'7mRݓإ}i;DXT &C$k_rC_O~=7OM[֊9=YՒY STŋ/OnY1~t98hSEnb[JA.ؤoT S)By͛a3.XobgnfMV.+cit-Mq `27K7jX̴}&wٽu`Sx[]E HjTo.L[ QgN.DInf^+s$=""E_b/bF(aȜ0ŠvhlDN&&YT2>b9u?~;)-ƣyox铷wIՀ21%?|fMGzǴ9;o[n4)S$?lt&E'>"ml"QvろY9F&v)it[n#NoMVAθ}P˶>z *pgfg<(Y ;+aNa^vlU=ŸH !~FzADWś, vقl]6@HhQSVv+M ݣL6w4t̨L ̑Xp">64q6g]NWjd\LW̊@- aRK6L99W~]X'$Ά Ycv1{)̛`s4eY2rF;;ml,2KJꃬL&?&ӥ` 8|uS'&': !0|1xV:s}ϥ~_UujQy!cjf9ARC|Sf擆 .k^p^<9pgo8[]A`:5Kz!Xdjih_coLI?Kk1Qh:51A%?-6'eWj⸚o ۣH×m7Ry' mOˍb˧z!e6ŊSl-6->EprG{ٟGHOЙ.N> q軬L]eLgfMO ( FMϻM4L~ce%Ϥes;'ǺtOpoMC {pVe*2DZ ~*$ W' vpyS I{^oRr{<΂;$rY2~,0$]sGPk̓l4-(?oi] N5PIeIzJ"{b)v~iҳ)艱pSOXا=?$NpkZ^:o8# :EQDL&쯇?c}Y xk pMJ![2G1׍QR@K3t8u"J|u3O-ӣ XA? 8aQ*_#<Ҟ8YP^4A֠ڇOf繓ė}({ۦga~]`=cofU,k*wVܗ3YV7,5^c W-Q;pni1Ԇ%~C@} Xދo}g$k^gcڱufQJ7Vh/uQNZQslK@Q&;E{]`3V󖟰 4zkRA=^~ª C|l m{% FʹgE~AB19@xyV^o!^)s4>).z|͝S$_ %;0pGRq_SVYŪ]%HOڄm(VTCBp_)fkٶߴȊs6 *YFhlfevݨy~%VĦ17!X9i_b9'^֔jwh2+:mYFzMuׁXҝWX͌ p ?C#6sQֲ8=xAb3 @߯l6#}#Bg,{=nxJ$HdV/~jLH qcTeI򂘪)rzUt[r^C]LǮҕ{U^ў4B_svϭyd}=sO@_/UO ݝNS嫬*fk`Cs*ptO=!QWهO6z5Y}@ H2z 9OװڱK7k,̦ӻ 7ق:ͨ?i7osQk:Za赙/h+ɉwE8c|T\F 4):PQ][U3~>D@ةi8!g$fWl+6m19uFM> =gx{w3+־j[8݊o8Oz=H~N0hmVdˤ$6+%kO)b ~I\R;n4֣O*Fb/voZ tTl7`o 4ǻ.i_,Y1U=cPpr}F.bpnx ~~tB~U1HĶL%UWQQ<&Y2lc8P{aol7 ww^jzss>0?ɼ,I|HdK4oi$yNh?MlɮIۅ]sF㋔-`nXThسe=eUl8Q[>daJ+ ͹:NsYrb<)_œ7::?eXI᯼Ŧ' iq+TZ~5Jsf3Yt#eМ&:Q5K|'0οWqa.YUXM;ʚ&T$o;ce&z>'xX cU?C ۥd0 Ve v+ @~: ?76gFD1-!Gsʿ>Di|YhH 1)tf1k(!GgT&4~?XC{"?ެ g^S*i?Jʶ*M@]0t9{ÑSӕBΦq|X"$?TSzx6/L˾I9!sR-;.M¿"~߬pMu݁:&"m09 0z nɵ Zg׻D,9u'A/ G^oo86},@$"ЭS)ej'h\ޅg4Rh#=H#ͅ|.SJi8qbaБ cljZ7Uj|spk^dI`}cф g9X_^d 3?\E˰g"WW7f_FKo׍M>zY>'ӴRqK8;E%/NPfuƨ1|e񪠵}BuŴ5tgX[ʹgL(Ydnsްt-~4~jRHm S|0O)57)ŭcyʼ8oJMW@ &C0ʱJ(3+3Wfv>kԭL{sK<*%28xo2''*g#^cVK.ToOTfؗvmԲA~ϟʡ ^*|Z &OyJ#&'=_/cIJ.M@"7@RN̯}-MVVluoP-kaSf>Tͺwu|9>ۘ;22мɄA~ԡT@_̉L%eJ'=ό۠\}v;}}Y O<{ ħ1yu7l[h 7W+ں6QiʸQ]]]BaE`h`='F4 >@u4(Yi?'^S5*3ʷ(JŤY8ذBبHu.iV}/3*RJؘ֓^)' (]9|tt2ŠLW7h^< @p~nتM/i@2:w'߳FJIMy(+VԹ9D'%D %ʜڜ-`g_2S!ѵ%†a!g>k%JIynvR¥a2,(`^R |AVT=c}3o3Y9Az_3yT+ܙ-$4P2%kReԎ`Y*9x>L[ؙH7:AĈ/h4 a/B=Ӛq5SX{.z 2}"jJD_ٗi>`ZckLe^0}ۮ,=D'k ss+SxlqTq9JEu9dO8>o4COV)L"RdTaUs_va:yL ˕I0DBY"[&-R˔F~RouCR>V5JT{}WFjVfd^ضʼmYLJf2gt%/XTbج֏3W)+j,Yp^UʲoZYWN*[hR|14V:tMh.4dNJQPHj~aF9hR`UsMNzTu SJl^7QVz 1msލϯUxZeZs[2y ӽ} $;ʆ၈{5 SJge KڅS؄ξQy|B:<<'6lgW}4~IR6Ss)`Z_[9YFmJ2SJc:W~ꏿkSN*iQXc8<7n.lw*Sysrod轫]ҡ59VlaNثFh=Uf>pc_cy,gdo{ +YG"^ - @BO29=}atrvu0o;Ms,#!kykz0TC\T[MJvj6)XF4ܤldsX+&e8YY8lV-ˌYvfX&7+tjà 'Λ}$_D9e}0ʣa3.`e/(jnQ6.}w7aJq7Jeu;Bi ey{Ryz/yN=ЦKu){Os00Shbͽ #sSgy f`6c]J` 6 !'nW*s]_!&;k̷:IUÌʖjͤ|YB4s̺p? iL[ͳxGRݩ7O!kJ(\۪]ۭGzB0^ū%b)8&lSA-<+L },Ɋmc=xg|T7+)Z"8 d&LJu \vQQد}faNYk۪{svƭvK/ypS;{z].^T_WM.Uos.,3z반<6L0W Bˣw,(ײյY tTc@7=]eV>jU׌5u9fg2fћN>bZjg<Ț!.ي.3B0nY>Ut[eMV^ԵZ]kuez6OdzXi=~VU>15FTזVUްUsMu)(;rsMnOypMklk괖[Mݲ䌲:mNWg(y0^_9rB)`uX]Fݳ0p&]^QCgY͞6O:Bt8p@>g,1MQBXX$D4{DH!>ͬAظ-JU$ C ؂)QbrCL>#@wxf_ݡuۘ4ↈ~Xty^18FW%JZ|,7:L V1=ax2J& eI%ot0i:+&TG^vyuK%6D5)Cڔ`1e~N͈op:uOr-4]e Tr(1!-'f^tAv{!6Q1El%I;K6?0O_O<-o``VgO=o!bwE̜n*vtd5jbM,qްS!:đ;(hj,o 'c Ŀ Yb vU7ibmDqb]I&(xݺiizzb^>&8JQ rKKDJixsp3&9J\U'+#͘(zv,Qakđ,5g jzX Q9SԂCtc7ݦqƐ!kd9xӆet0ύK >[&\ O(UPXX1rw80.*Sct!A S C5P90~Ģ)>0rk Mm?5`SSGSr[wZ+N_Ѻ+Z<;cxiFQfWeX?).io'ͅm~^ڻnd4e,gfTqdf^b뀺Mv4\Nf*?gq,܂5y'&]7ESPO5۬T.P ?kNBF&aX-Z(qwNxmLt5ehɑNE34qE~ UTj=s#EW̜.n bDռ"Q1/3@+K'ZmLTdYhqbg Ң=e2/ƨ#}U EgdķnP=Ucѡmg䊻HTh:fRźg% [%?3Uӝ^5"{gGQdnY(%P˺E6%u{X8T _ QیHNTG(ibّ97)Z#F#0evȒ 21\e 6^z;0zf\EcŎE t{=PVJXaQQM8gQZ[abn2zC UYwqxDlϪo%uEt.n.OȷKxjCG`jR5 :ڪ|wVTǽw/Lܼt Nc'!h9#m[.^\6ZL³Y#wƎÏ݇;]JqƓz"2!Zp d!lPq[@3BxwO>/}(HRuuFtS"LE|zXtS~a(|1p?RQ&^g6[nP^$^y!6r-@D3^jIqC,=jZj=;=P%GE}Uk_.}rwW_nqwc9Eݞ [տ刉{Dm= &ElkN<ȐH#>wh=%Y;r\.T,OaEDk[Mlv'6K6բoWbo"QE7ׇ*Eכl֐_#9[۹e5>r;œo>{f5x{]gǪ;HRԾ=BL;SmZfr{ MŤ[Y88qM@ w{Gs`s/zLfbU}d@R-y\\A^Ѹms*akRcwWc(̾[J5CCx 7x⣭`e I:U[\QI2i19x~ ϒąWK>dǫoC?>;Au#-,Rb|.q’D¯Q?4` ,)~eW@/L?'uͱ~bW}_+]; 9m@i12_=!:E m:#~7!$:Qu(\lǞA%#y#Ih\>4kzt_Xyb K1*;Gt(@gX!EmXvӵL8x&=VG=^w|@ |1[׏צ!x8ώ[!?ju.CX*;u1bJqӉ6NJw9Ѷr[ƫq,l$cnBTR8=0-4Ъ/''ܟ {6LYbϕbib/q/ݟ&3DZ`eΉq .%Yx9\=U2D;6:(%Ʊ|qS3Btfm1KP" sL?6%ŝ.652z\dխuG&./SXmg} MS- zofhA8q+߹Y,c]&WBKb}r9+]}M42Wlp0f̞p)T™i6Fz61Ss$ l|$̯J(֞du tZ}1?Mt @F42w9L:{ hfgwx!La/RB,$".ekv;!ga,wZ|z$UPj_VVۗ'`$Z.*R -:DQN+3ؠXb]7Ym ܉ VBfdy.|\9#@ yrT6O= eN+I-A֨A"AuBX+cEI'Zy}y,hA 4”W2)Q[>&Q1z-&@9"~y e9U&/MA!I BDg^H_Sy++%羕'W;~st[MUh"V˪f툠JEW)YN&PUΧ~P+,R a%.Ihy2 {ȝCct c":ZOˆXGxU@dTL= [j40_NkD{#k-B(`# I-JGԥҮl"B7boK\:vh*o {JIFs,'|{,ahVȬSr ֱixDGogxh_%*Ik lI.7t{#rڨbT4!y%hL:Kz2 P/Y&(E1+ıexX73]ьo$< [rODޙ 1=>dAG UrftA lz{;Tf9l5: s؅ ;P|.V-F⢹pE@ϛb}<͂Z 1 ؍6S>΢gnEz,iz&`W'9R),>(J:m5QTofE6er 垃 a'օv[ՋX96&[ZXHΰ}W~87Y1`khFu|IhJ?>V:j)N[8KҐ[o)bQKa)r5?_bi6oӱua]怸K:jc [jgd⏏W&KhY4 ـ,+[\FTX`йOPy-e]/`[ڡ.%~X4dW\QqT^0t8f2hk=މ&2,aУK\h cC9AjTub[YGnwϳ,Fo ? izE~([:%nH WJ^xc{ˈ z|'˩8+}*ͯOW95\ La =s(i/,K<"g/観^gC]EC t>x}?|?Y=ݺi~6NiB,C,9ߒh؞70:Tk+rh&q/%tih蛠}>7Yn` {)- 7YBXOӤP%ny c{[/b%3݁MHdinq"rDs925}A ssfөmxok/ X;l5; \hw{Ҏd.KKi{zSA@{C»~{ νX_eHBc:.Ӭ}LC794<ʂx[)|=>.I輕O`z4}a0 Ph}bu (q}})bsC0!Z!.Ep?ч0~\\~~BtB8@Ol8٪ZlՀ@>%c%>7 1?>z+3xu| O᧋>4TG;SO K%'U'pq["TS@gl@x<ꡩAg:DЊXDN|&77SHsG ^002߫#" >?m W GOe87.c(@9GLۇ>cqFlX}ڨ;ݭ;0ob8wODe_Aj Mz ||s[UptyH0aA V}ȃGK߼ЇqqKY[޻ ݞoݵݜ}iܙi u1Gi\-n7_"Nl"}ߢfϛүZ5/*~ =,̤߰%è[46(aJ{ƒ*a|m0/Ѳl`9ͦ^&CyȎꡁ`5^GN 6c"avÏ0DSbST O[|,kɇ!Ҵaw~f}K4 ')zaa?jY iIѸ*hK o X>W^&ѝA1uv;d"7В-6_JڟΓ}Ց4wĢ)}iJ#~n >?]T*;-,␩$_>'?MɼfS36ܼٛg 0ޚP\JbC4,=WkA+Ϡ% @OO}eT <\|GQU Ϧk#y /4EER ^Q?;g+(>(Or/ !*qъUG/(KN惢:6E[揢y.u4:Ǐdy\DukP#h4} 9tGK/RAp>h$y7.zy9۰-Z冡hfLxQUo5y0>~y45hC&57WpIφnlV7 n5&DJ֌H/֒x;s;[K4.2 vvNeIT2Ξc<&9x q~t>{E"R6Su;cH∝BQ3^4_OjFM:Lv徇n~Llv,cʃk//at(+Q~r*?u0eRHV.yL>ꦞelwJ7³ VºV): uYjzr>`(]О_&L}d蓯Ѹ/9;|*q7_eZ<kU*Ҍ@ eKiaN4 lPtK4` R^7veK]A|oqds "[ua1@WJ,^ѭυ_Tt]y9w BEw^5|L|^wЌ7y~Lf^k&4C\?ˊy4.VxؙB@$eW ;wќb~kg^:s2B26zA} üˠ eloGxY9Wyrr1V`@Kw16V"]3@WU:=^O5U_&'r۫xM jL ^IUH?j^NmSne\>v6ChM!Mkmj5\l|Wk0 =DWΟc:zp8jyqb]Rͮ{ &άeINE:nSMVyF}$űvWxcbl?3mb 1^z}H%~S7Io"wgMs$/$H¯}2Ԓ.xQM7yx-@@!|z'f4Cq=Vѐ}c&I} 15cQcc11.Nα|Br=8TlxVLU#T#Cl2K[AU<|84iH4'_73N2oˢz_C- ky~M9s<^ĸOz 1! `6]E7 2xEꄩZg{N>S5_LRjjLoB%4;mڌN.h]&&qu"Mc$ɨeI| V+쥫`2]Lww2p~mhWR3f5Jޣ7AVix34}TTw5i77$M=oF! NMgِwMjV^̴wمpn0O=0]Ki鯙 [in ?-Z`S1=Sy=%L,fM#IJ U)r | tkCJ[giCmjYI]˷LKX & (M3vWa֐LAB  w@kG H)/L 3!VPNYzxYa wyAt]m0udCb]b.OK` =<}mzgف4K}pf&3ダv(y0ܮO5aP9IK"+U I "+:(HV&99 s|>O^&].~ U/ɵld/0ӻs~>Ȕ;d 䅰ad18 EF3yYTU~Dxattnyjω;>jdӴvLXȳ`L yi<̫Vsg^Xȫڕ; Sͼ +Ff^a| yͼ== m~Fo[0y] =cc @-9rh"0[o\elP*;:c {zs'K Ƀ*N]wɲA (i |t/Kﲚ7&}f -rzY!]̋)e1Le1Lk1tlhˋ=rhJI;6\4;; 6jY}_7wyB>}N56t"˓cB/Ys?0i!ޭy5-Xi5/fzm5 Q&QaNwafUZږ[JUh 7Lвb,vd:~kk0EՎRZ~!<#)/w94TyZtO/4"ܙ{ě_Я./AT`b*cp߿Ӥb^7qrz5~ mjs x%(&R1Qo4l}3lR(RL١KaF4D #]ǶWrܱeN}ɏm=ώP.3 7ov:=]7ژ69{4_0ozdL^H7hws^WߡcswmKm (F ᡍ_PT_Ɠ|top{/%6Rv9X,_dQ#-6/U2gXG|G/ÍOpY;zf]s@64 L$z,aSD8 Eg^K<{]4H aU;?|PT<5Ղ$G;N!*$ԝgnE`&ۨ:bJD֍IJ+6ze@+~Q [׌vsV-]垐0WO6yi9vmUf7},xuO!C @&qm 5a%=$G *#?eIJc.[ۯw48^;ZUWیѡ\+_ftT[惘8t^bҌkxi˥k`kxּp noqA(Z* Z*zF\˧ au[QQ5rCF]AWP0yn̼ܶν{E7_^HK!c@U^Is^s#vU8nE_鱚\&~9rt. XRh |.n^dZg݅[h$T~k~&En[mYJ(O=Π;[8/[3 JCoBPwBOnR&4f%@Q6oc B7]7ú^{3,7-T@18[шfؤW{*,kGϲnE /+oE*{>[h\F;vnvv>8?Bf4K[̋UJz|hdEt w$=@D2 cȝ~'Z˝0䐫S 'ĕMD޹.>lO`mem܆$ CqdVý|PTii{!qZv>VnCn{ o8>Dn}I}o'W>E3\92ޏ9y~G##Hw+u#8(8bp;/,7@a7Bh㙆>> F 6@|1=L+IV|?6v??$/~!$tt!g$"v m$/[wB NEC -\Eݕ#|#ᕊAcAyELɴqp>qǿ㫏pCJe<48;4rr}:Eg φ]<.vv$.- _0Y^+, -؅AY N<+r>Kf& K_yazw-Ӌ3{ݍrOzH|,>s"{t(@O=%=f*^ß?ǻPߒx˂D١>6"D^رj`M ?g >i3@7pg!cE.3t3(XÉ%-^ͬ>Be}H !fϣcbvql덴y$<$Fb ho/xu.V"i r /0Y }0 dydQ/xVe j @K O~Wo%}'1q5֡G :%%4핗xa*N?Jp;lf9Bu屺yL8;e>{^ g4ϚC _JFIAlsx ˟CɎZ(Zn4uW8gi.)xLS!}5>/N?YV)#}PX増 ^5ҿB~'k/ڷ˻ľs탚ǣBOVBi-)Rqu>%$}DUL+R}|-|6 yG}~>0|׫p t/7q7̟y{x[f!8y m }vL b @{N7 uV r|!WƷ _<˓5fGw|yRmIu84mvZ|%of>><7oB2lӿ|7:d|L1cDe2||On=!P9*a~!W#?cJK]1"#}Nm6L8x|%Eb'p$qŧj?E+gw9m@%a}ˣfjEr}3}K# 6b\ 94sg>G{_dug˕/xjT^z uJ͝To>|>&&kK^v)}%*KnW$ѿmBi,Ϗ0^r[q=ũ$$'_.7B-=̋bڬc[;# pю#eNbp:G@QsQH9.DG$(fcS6z4\t美!NXq cq[^KbRǡ |һn=/d =/$+4տt{wL`~0%3XȌoWR $j'֞%|Ȝ~>FnF;i?JG>U3^] G.)al >00ć$y-677o*Kp|grTA1Z-q#U19ύR}Kb}HlD)WɁ"\+/Kn]z,sFю_amUo#EОE^_D΋Τ%n/k{$=Z1? W?Ԏ?xF}JkO^+V[UO +$a9%VqZEJe@uνiV n禇q QLN 6#ŹԪVdґWViʵ:3=ib}Hp]iRGiTGHQ6Ѳhw4>Z ihXVIôtOOrJp->ܷp9RL1ZFEjs(-?η̮ϖfF|K6Ҫ(5Z+SL=a QZ6 #j$Z+|,{B=.%thi,U-oMN㦽1E~;2 Xt~_ FcLնӛZ}&RDVnc.CBh4-^36/׊U)}9?^L`յT1?F-&haNkf%h}XZrΊ8\渰'h*é0=6ƺD6$BKD%b%i. Xz,I+iTtN2dНHKA`)>M=) t$tiZ;NiZ6Bq΢t-rq՝5=r×ۺm+4Vљ9vK"je)@K.?}Dr(BW׏N»dsFą`ŒS 6 Ceօ:efjCSCN]z3aޟg#H/MNӥn*ub, eB~5K+; %o"JGiO#Zm !^? t8[wn/Xoe.+^dlv)YDSkrٵۡ6.]ہarM0N$ޙ l~_˦ZUȻLzcK uRjyT9P+0o +ԵԺh{6#G9(GV/a1tD1W#/-.m6,ж|)j*4P˔BiEKؖq\"8Zs uZ/JbHj;U[FYgnR^ TP]D[,/CsVc@q@TzcD̬Rm ubj#RmV/hm.J˿]oMA/ZyFhKVٷMiz wdQMpոXY^XSgƐ( Xt c5~Hl1]F`?Fӆب!mZlHcVņF .놢DbV ?ww7p|%y6\>Ȼ؏osSQvi0Ӫ,hG-si(ӈ.р%ՂD¢Z| ׂ&^wħǸ턚7BFGU#5]m5 -#Aȓ\x׋#!ۡţdԩN(~r+Uī5@/FF9T ].DmU}6n zL<8[K6V辟ɏ^m [9gQ In5 kӠڝ|֘ g,qZA_,RHBit39 FL)D Q [\Uf#,6tƏDZج Vq0iԹdnrT{~n{~nH]cCw1NeR߹cwQ~-d)оwge̿r$JY]Z8=;鶛yqzoeJ/'Ӏ-U&9,2$[(_ =`b-a~:$ jCUajf'i7[~NxX4_﹗9UP+87@SHSW}EnLҔ凾izp%Z*>UʠSЗ ҍ%>y r!ZCwd .XCuwo"Eސ)>y/Xu2f XSяJ 'D@p ~\=_ W іK0\[Mג?>OG=-;x;lmM'3юo.OmxȞb: #+J\ Z VDkK6$c2z q9\܂ e?{ )(^$NպvjaQpmbN"O.i;xDZ@nzU ~xM* 9W}k*7䩏:(prput!"" b?B=)(N5vt*!,yR"u2YKvW@rksRH[x} XUǵ7HQ|(qgѨƘሧ9$ FGT0FA6moM&mӦ7mbsMo5><4ڛ~"gZk֬Y֚574rOk~AuՒ#.nY,bqVg.m6{(=fXi|tg/ZmlX,bݘ^p5{w^ NF,l˶l)s+WNG؜ rSSS}o%"cE-"o0։y֒[lFcQyBo K al.o76ïKn n'JllP:^(*ه"NI[FČ;Gkޓ {} kz4k`w` e[sġvoZn? kkn}uzL Wq--"9r_`QSՕ9; c-2oͳ@~@%'גŮ[7Gk(t7Uw0a\WJ!}AҘ934n33{n{aiCRgco+R@ouZnCH 1S2/GcJVôqTvop4ܒeŅy| ]>>8~y:R/յP01H6."$ 2Cu.9H*g.<:;{0/qz ã 'c|4o*;\] Ƣ H `tI+â@a[[OkIɅ9Tv5f*>.<9R#]C'QOx81PqN mqpG]W&Ίwmsql@78<ю.pqu@;\]S ^:iєD)kӒart(iSٿYi"Fd=6;)o::7Z$;[9 }aH@!= Ά̾_ɜ4&?rmSB$f>4j\QV 0F:ZȬ dEbr B%}w)aEGAJYVc=g,ejV 8} '8gTDkz8Vޗ<%AEŻJ KWv4\WuϮrE$4T|F<%X;, Uä 9*0~GGab"NR/1 nknUbu ` Poa5 ޅPK#UbA>Vva1C A,eX= "ѣ)T.j:В2&6Ϫ.n(qf,LJ.y"q4@Z ]ܵL26Wǥyy}\zT&`b9p^>|`)!ehDs~^}~fgaJ!b墶9x*ZzA▝[0^TxRh5= roy*x?O|畩@Ռo]Z" w#4:_s InAY:Sw8Tے~)iI ء#횤֢3`"niۊإLs;u,vΆӨe0oѺeDT[s.Aͻ8R2mT6\zg㔱qk綬c'[ 6U2|lz(e]-v dz)|Ҧ9νhتezlW^:r4 r[ОvϢrhotٜ_8o͡rP=i=Aɝ#w73;8|׃D:7QuUjFO$,zAvە'uۏM9wga˴(T~}ez_R;.Hؠ.OyYx]Cy 6F/Gmτ8N˛SP3:.g&EBΊ7Kb%q8FYM ANڳKx$u>;&qu} OImpT` )qk& BZ$}5,:j|(#f с&g٧9QgGfA>bCPmg@RK|Jl V:Q :>VF?zy7*ɵ5BF'W컿 OQ*k]>ӣ;U֘@G%9;`l.;j|P1 a9/Qn ;җ~@WIP1x(=+7/3V>{ tEn.bE+%ʷeu>D@ħъX1р-yQr 5s0ygj20ҋ鳼z5:vN'y}`8pp]vCj {1a7OjF%r̿ȯJJ]aTp_qp\m uclLn~oj%֯ZAtԞ@!>tڂC6zMnE+][X_^J\ʻi#uJ0\/%TkΖ8gn#`tX:xT%}ώP$r)ǡj\퓍~p _[q冇Yu򇗈JyGczB>n`w E Wtslu xRFf ҃ؗh-GǭXE6qVfd6PBI%auuh--6_/"F}5"n-s@'b g^7Y9wB8{t6qst@yZOt_}7ApGdz=O˚RşNM Nk/?2R*=6X ZY`yη@*q^-Wr,jn֨@^]j<24&l7bgMj>%W=lFP[S>M4R:uJaGԪ5Y^$As9\o&N.+"~7&Xl\sJd<{DzPH4ɽ{Tzُ{.{c-qz]*DWK+;aY~cK*- PU`n@>T0 5߈qQ:3>XiC\Յ#dMOێVܑ,>@ڝ@#_\%Fb{ؚm-շLϚ`Ur P7RnO'RH.%|Mn"v,DΞ~gW$n?4}28d,J\Y2:,;&7 rfc&=N\b1}v;t!#u6 p! +f pO9WtNA/}e*n v {$req6[0p=KeƱ ~E+ARԫ}AP۲?8r#fK%&)rTs`AvGi~R=|p96uKY#("rվ5gn:ށ;dFUAЦHt<Z~7?2`1|C0V nS=9da6? PqW9iUۿͼX9Y+Aӕ\Z;7:zշ Ϋ}}`؊C]`s0 ;DXYKs6k(bholV[,u'RJ9<^ Y LX6R;Ns}Ǫpv`)`FMeqӯOj:vRgqQ,\iS0}| vAπ'&guFx(rw=3 v+n5+WZu5˖j+MAc[νgt BS힚ǰ&W/"zV'A/r;jyqE+Ǘ;I=wRn! N.׌:ziu5vl _j7"1q^BJR:M#mm\+>[7Cy}ΞאhW)\qbX%5Kwj$5zXÆbT!s&=f˓gʼ1}μʣc?/ߊ /(lZlٖ9Ϟ=7ň9Oa5q\c0]+3ս垓C UoK!9ڐnW56kuI~E"P7wc3`KE zTRid m=+?WwXcݙPZ0$uV ^ F݄7P'Lg,]-]]i ;UR8X\l;WL{ML&Pi~/rBp՝ fN2fxF&lW8lփqҗK|efpA^IVE[bLl3m5gH`[ ,'KNcW'Xv 6?NE.Q1N>$դįo*FZp%3ig˖C)J7~KF=~,t/5MquBME^Q+Zv܋Č^ }wdSX g3U;8O[㿱F3DBԬ{}frl)w_Qw91-.f< R z3G;1&P2?>!w]M\`CeLL/OIxnͅŖoA<ٍ |_C9SOv#QTm\JX k[h`w`ʷXK{ȜGށ /wO8#aȊm%%45R.?n4dh7WE*n S ͚sZ13VdƎ#4c}3R58bVPz{riA2!61_pa['8C_̻5wG%n! )3.,˳l u՗\ǫeET7DZ~^;hi35=Ϯc,?HRϢ:/kc3-J2Bg2R g?;TPϳT6ܥ_'}}ˡ̀.=KCA`U([l0\1˳&Atux Dn?:$dȮ0qW>edC_5҇޹^ُX S~+#7O ?K^{ Cࡂ)Sz9Ee\>DkpC)%EA+fXX5n est?v;V"5nJ,6kqϛ6jΦ?G㤝M bd)0 <?~*mxl~QO t..W}¢nhw}"3Jz3,Ȏ*('<9cG80L[:v6)!O BU\wA>wL'U):γ`lWΛas8z^Xy{Q]%}~;1n<½F/bnkWoW\wLgwO'&Jc/-Hn@*M' اz?.)N%`ܝ -jC @&|>9gmR/yodq)o38[0+RNf>S ?N sO~/t3q0fqe.ō/)-bLU{(,(Rr4o 9$O` + NijT4=wL?JjBEHh@"4RdQ؈Iir}>"vrEEGv@H#1<RΠE Tadr`EY*M0H FdFRS}ɤ 2cRNIVEEDg_|*]2,%)p(IO6ivsaEo&k-b5dr? > T6\g2!-U*7nz6p~IiTYt$0 2)p%uR- &RSmYKvuM*ʙ`0 %=~LPrSdA@JF2}v wJ+OCC$2sUiCHT(ob !`!S~HfGu C? dT ^`jvﺵWjg03$[f.0g[RoSR`LυBg룠<}$44Ls8wQ f)4u7La*K6x[ CU9=4eܰsS?Tgϯ!w~ CA|sk>qN!st9<~q,N1iXY8bIc%Hq@GA Qx{P8D6$S[Iᙙ4B-M&}&lC}v"Ksk5֒|q]5q^8i)4l"z$@~գ#`,t7t9,b8Rn2hF~kRXsL-h"UlzS$$ Hσ)xDNF+G'eDA83LACE ƄyJMc'@Mj&}/:]F$V38ΣTW5I͂u,X7}0Џg9z>2R|BSpp_228V<& HLPL_eqdB1Vcf0(*ۀB7 OBl/3x4ѿCb0vHؑS#sȌp2۞dX,?P&2Dy@p*n'2#K1Н df~/%5AKt(oDHo/0uCX#ˢmdɷka8Dɖ-1drP Ci}:̖BZ ]N/QcR=$/qܭY2f'l曋ucڟGKnqօ1E.$\*2ȔgMt 2ŦkF$Ͼ˭'^2RsI<0b}KvC .J/~> - ߟGa9 % x`>ynY̌擙+t HJTw =F譅\ ̑ =Ա$A,O]I"Ct[Aq 2PlX u{hpsFaҘV$(u,YF.i|RݙroC[Hd-'qcz Oe L9i>ZA]jv:L߶"\|DE(-p-X mtJ2$ը37V:{ 6j䚄.X  Vpo/ 仟x1yY" qUZAݙ tV>wde y;Q14s N x[!*q]RtFхO$Φ3*7 W?+凉EHIeLtZ2cN*KK5F\ci)%"]kwtWWk1m11q2},f{ƢgaHwhz*xwwðU :oS2Ӽ#^f AQ#$ _JY(vb}ĭ1j2X56 zEK1Sb&bʯb\ CI&/}WzodGU/lOgLS40ID﬌aE< 'z3 ~6?CҿfqIT8|P:|K%jJ@i=\nfzF O̘Jɬ{cFc4K)*ݐ );.5If^}2ѷ;VOg%O"lhk4w~F¾/ )\t$S Q) kyQ d$j6r+aH5$ZeH%CO^IRNISsJA'"%V a13Ӥ lՕZ7%mҒ$:C`*:*=}w-^㨪0 5dٿIZ@@ߩюpp:Qۼ]_hŧ6B@!BXA-ٞle.y^SH.C`FH\qVLѬ; AtI#aWud(AɘqX=iu I,=4sr4=>_DZ6&wi/2.;wAv2Y dIoB +*dV>|q[{[mĂ3cډ1vd];+q3ڶ) J;HIW;HrN7L$IdgO8gI\%1@$xD)EG+5$mHmzl Snh)J7^#i16*U'g\L  hz]HZEt\'If>Gu_ .!v!fyM3֣f6< 7gW7ITwsEȵ A{HxWrjR>9D(z+]SKO54Skj]8}$^0r-ЈuctyqjiШ70E0hٱ;#$:boniaVc#M2)? U\K~!s]~ZyFxr\wͧ{$ z$jd*jnLAjK{م_s7I0wI"uXU."4=b`{d Sg3C}'7֩S~FRg+/$?r8m|dȝ=rG\wKwtRa zl3|}x/nm E~Tl]J}&Cd st gуA3|0RBi{H(<=i)ÊS<+PxezT P`; 161 shߕͫ>-SI˹΋[лrGk똻_}DUq8Uv쭐+xN\vQ+~+swTLO wӫ,}"]gG KyfA˂U{ !A}*֮ anieFsǼYX0`l12؛/FINN--,EEVMd)b3׾ sVNs5kq;x^y4nD`\rmDp<.K:`jhmq/iaS#w]ɑ_ Ӆ/r̵qb7hs60&pw0_(l)یCuK{1H{]Hd2>UpCB{tߋyb=ծ< gա[A{&cEo v}p2!@<:I>pOgarx}e:FR#Fx3 S@n@)pAD{ ):0 v!6&x?% aAx&^ &7I[@ ar,c9#5t,LVAѣBLZx,@x4 qJ.~O7 A5WymC=$BE9*ne1x}^~o$sr^)4܀ =Lxt3Û?~qWk0!&Awuuȷχ bqeF78' @!*/ZNKc(࠿>ob'rM($G::Hb߱-tG{ ly|Xiͅ9bNu'ѯ[VcOp:s0;{؊%ijqӊF7C.(ɄI~<8є„Z0J4K3EuOuwѼwD=Ⳕe꘢".^p}Ct,gIs'*%dV05R4ZNf681 xS4B+&1N*XN8%QTA ABQ:6@k_-Abl h@gy Ϛ0A4 qM^t$p,OHu^}o܄%;5X\J*mpAƞVRv\NV&9 ';X/0"q4AY au/TUesZ<7X@տJk1qfDx(aL&1_h;hCCXLwD AG$5T qsƆӛcg"LꚨA,4a8UvOqg.dGSS=UP(uK#iARj.)LP gk[LvNW'/f a38,H: B:͈* ~S1xMV/`-%wtu4;Z*m?Frvѻ="5[dJInTL`rD1f0r53` 6teLE~2 ;$HtOqP>z`(Q TC8(<`ϵ;4 3IxлڤvdO`jnLj$= W* P^.o^\ <Ӊ]hA K3q1 "ʡͫ0(u 답U?/NegEny֭3ﴂ?F K5PX*؊7u^Qn?<ɲ79[qW S)lPi-vgw+ ŃAlV;ɜO0BELI4%t {| l͹ZGvD;1s_m.dЇR10 41KxɀFe sVnfmÆ`=ĶbhBvD%v;vOcq0'TQR-s!97ޛ+$c 'B1.ЁiŎg&R%trDmYCڿL8O? ě odfGڦpx=XUG"E bcFc!JD0dR"H@nn6$[6ᾒ7&l̙w}ES͜6gfΜ3sf/Gu֘iҪ i R}F3SJOMNKMOLIRJS&ƥ$$%$'Ɍ#EEDDF,֦&$HSMM֦d$s9҆0iҺ[^#E=l+Lڔ"-K}*-=6iĸ O%$%ǥg%g^:GA&$  X<%6@lXJ꾥B eE\9!}))c &&ť$hh0f>-oJKYbxV@ǎjT;dP P! $ؓs)ʌP7%5.aORʾt(V8cĐm1TBaQkMÃGMU}j9SGiQu"@ք*msg dM1VeY@|XrxjH|x|cզlz`hCjf<)PCh\/RK/BӍmg-Z\NwۂՊ:qYe,m@>-a"@Ĭd$0<0䀆ղs5%)i)%G-D5U^~ 3yt.G6Vkݧ,5"KU]0~@ 8uD| Fy6hRR.ob(dP]'`>w_gbqф Ջbt\(;nFY|$t37^,睞Sv [ɥq7e0 F:BCHf:ы;  MI)&B"kzpѬfVY1 hIaarRj_dh)=%#n3 p "/#52XDj7ra|`kؖ8{zZP5kSCUz6hn\4ƍ\Ʌ^F,Mƶ"pxݡ#]2kHS;e^b({\\JѶ{ґO?NW{V%3H!Kkg:*{Ƹs U(X EScP+Er[/h昝fnyw99\;55WdJ˿}ǓvHLS|n B Bf2wnƲZ툟@L @> yE vf?}+{/ `BKU1LW:KvJNx+~OF~`?ؿ XZ7㉐5bGc>wjcUXnhھKfAVۥp"ųn쑃Qy3zHj~Sǐ24yi!]2y,媥pN08rDCGJp(8.L W/YlVkRuE*! VJ2EGXJxBf>MPNs*Ȇ suuUso;:<%_/a㪾pyx?=kjR u/+D@S$/yᒧaB06?4i,,08jz3v,Y]3 ]PZ; YnjYϳ.|)@s)xfF@/\̜&,V u3 &f|g Ш \h"A}q{GQ gnMJKF87!~|sW[sd{=AÑP XҠVۆ|wc4y]C"98nR ,夣WӬ> < D[HOp!gz]Ia_)zIBLOAc(gn  _?EeEF*b4iV̯ҢK8#x8VCYsX~ Ok|7n+q$g`xv$U+J-|K+Vm ܰeU{P fX=sj[Q5վzHrU5sxZmɒįSC4^:INyx@zViJ܄Igm+Y!දwH~t|"<~mZ} ;6v@e5ZNl Žr٦^ jG'0.&:D@͎6o)Ttڂ_{FlcsA ͩRͱ.Fֳ$\ޚϐV8 C:Yzvamw;Ag-$h Evp|59N Q;[ȘsQh,ty E`p?LJG>Xڶt&υñ7q_Դ'&BAL'f4A njpYfvZjRSvŌ aABcKN|TXZKeFXr,p]eoD9!4S7OX[+*H04<"%rl&pjyKN3Z!CSOY0\3ar†[OڕOB ~t Tk=nkqxe}W{ ESiPMl$%MJUB׌r5&ʅ]QEBc&(Ϗu Hyiw;Uj5xuŒiv4fN1FΊ-9VdMa4djاb7W:6[KДBXT2!Lu@YZZijډcql}=k [)1=_."S#ӒO' Na/%'f nrf$%Q׉ۋ2Y 2h[SeScC1xHUX|z߿31Ѧ0b6_nc`ջ%gT#k.Tp. .!liO&jݗJ2+U=!H(NZ'K "0TgKöW+P8R,P`Xi͟pL p5S#T$eZus _}$JF%n4BD^@~ W˽袩ʷfT:H9v9/h +MbxU sTތo7mXJ+!b]~1re3~?ze<^K]^rS^>RiĽn*Jk0VC“Pgp] i;F7ɬ'^# Z*+^t$t~uisO?*Ӧ'-ɺsԪS*q]57gLA~7:_^c+] ۏ٫-YN6fXqU{T')Q,CI^ adۂ[]Wl&eO< N2ZG]ujֻm'(v876kghrqwho[3I>(J9*'̙_{Z bmgdOe+\yZn4GSL ?Ko?"tmm86UPsi]^@뉦[˷Gqk'^F o-՝f2 XUyᝅr;0MD|p9ݘI6u 5v ?z8NKFb:vޅ$}F g'sKRkN˯NWh, + #ߊiqXgy$s !ߔ D{ˡpDׯp PvTÍn@{?ZAbXi >`(L2c7ǧ25ŘSy\h:ހD1)=]ć$>s^ZDy< Ө؀rI3&q9+/eY0\&0*kFTsLI~T x_1Nu}_qAm*e)e&֓79?Oͽ:Win囔֭e‚E]wHշ?M+?C%S*2n! _OwyRAoZ GK8G~5ntA=vd>VygE^Q BgA~u 3W>~=KAIiT-[px :'@,yzHkmS" j) FFi}&G͓; ^%O|9dV@nͣ/xFȐ{Q1rrǟܧޛ"mHT Ѫ7$ϻ_zȁIweuNHk#E 2/ i_Κm؞pm:`G4C 6(ʁ틞/pq7"zSo6F:$:FosYd;A"`]X%?wɓN$LO7ѤwTB^А=VڐNHKH?{ |C4݈м[09IyMߒ+sxTOɛ*TqY$/COh T n$NߣMOd3}h[ .AXPE~ e/;aFƾ NC(a#ٲ%Kw\cEq` k`c-2t[#FUκ_me=ٍMd47IyV6͒իTVLa+oeK͵M2w,i_b+v8/\"voӲ/tվz⨵׃p73dkQuW{KUu"6]=]W<٭Jml7iKQ=>tf6(}QO톞T7sE9X|^P9T۩v6]mVS0X)xxjV3ڋaa.RsIZq/ "ss樱LeݦI9YyGFn]yvI HY(c^w"0^YܵK֢peЍdCG`s Lrvo+*”w@O0gUe>p-=UvEP9_f)鲔ԕ~BѪ+}r"I6F% 'In(t/Mm`.uռ:ʹο[~!^w &tU/GxGsw+VRbflnsvIͮ2^&v?;mbnR_/izL+ xsـL[e!ØUƭaQ1,QrhY;Ԛ4B&:*h[F| W|6el=nG`X#Jk7}5%l;P8f#]ٵ-+t1_sEbr [s\\vK[+GSLUGD,GaG_S96_Yk]~5J [34ŠvKuahzmcVgXc c c޳1#cDU3xe dѵT4 }ʈl2a;Ԏ<>DW9>x"Uur4r(D(D%ڜ:QjaH}="7wiJ}f\6.8bԹRHpX`̦Ml!P n^kԼEٸۦ2YMٸ]WEs%:,Ѳ t zmz;2 ߷;эd1ow8Xfki+v#ۜm< 仙엻V'Z8;mOX'S+0&^ &ip/D9]{JG9v? c,sztSl GpK 9L/86F}~3u*Hjk@$*; ͳSݬaͷҁ#}n]vVy#+3cWi+K5T9-ߋ,='daҎ{Vl޾iŎ-ط ZxŲG|.Pf?p=Uql7IO)Xm_ε|<{$O:30ԚzT{TPD"6u7ƃso*Ұ&Xߌg 5m ^Ao_{%w(#A7YfiQm^6T&޴r푿yMP$'}tĚɁ+_$=a165 W^3 3cH-wOAtfZߩ?!;ŬPP`.r|)9Jē]Wv!:t48 +pW.ў*c|`v Bqv\vz =ʞ"R(u&?6s'$>tm}_(VϧoWV'HO9$9@ҔסT@Zfgn,wբdPu4Hם}(*\eM9[')Ji]'%@MAƂA~V JތBpxR]6L'ʔ h8D &XSSmZPP <^ @RaxOO U] +$DY_fp )lG#2VؗI/KLT:Vs;X,kO,q)  |@qļ_5AV$TvC#Ad]#,T~vkռZ8Z)f MqpMnJ[Kh:adTDwGy7[7"2J9N0P]pNQ J{/9T6wrgwIcVLe._L4(ߦ٭w''JJVQ~&y[[[Bds>7t\~&3|EyjVJXZ%g+Q, \@ԨG o}C,ST- /`eÔ؝"S,6TY"[,69#/pOb?{E>ԬnX$U]㏀>][_fQjo%V7FuQy]C~,Gm/-{Ʈ3[=֢XP<n"V5k1n~|4rQ\iӚՈz8fý-%qTë,};_e'yl|Mmw^|sklƆihBP寱ʒ}D-d%Amfp7g쇑TC{xe68E0'ud_0?A z؄S[ġ^gHJȞ{fYqovY6 7ضO#zeG Qh@5Z 7jAh.dr/]3|KCSg*dWs%jGP޶Rįnr5&AڥxZeAnR7~YLķ_3 &3acB1DRӔ~g蟨GJʼ$eczT.ܰbgL[!~ǝqWTy-X^2mA#|[JwV)sm9A{ՒNlD:듙|txUko={7Am<?_OY5S[:BzϞx ]}1JYiry: ͧ3rr]&@EM z tx /SKT Ǒ 4lPMի`Ѕ-[$x-ď]n# c}o98.旿eS m!6׵篕qozfva+;gA^> "B6 kcwvH9;juXǴ$-i?v6p,=Ҫ8/g¬ ut CU6Lr߫*ݪ!$fW HЮz)9ݿ|&͸Y)^XGKwYej;F/~RuLMt{ =Uqjt _i4TJH: ǭql/֑~˞O < ?P_DvJIL ف >m_|]7H >YPm9gEX/O4޻s ٳb2]eݐ=kf*UA36dΙJfcA}l3yP0; }b׍UJ$G{xKxm7!yrl4y_:p `}-R>M/@Ѯ ZJS:vXl'|Z$/(mڱ}G=5zpƁ tp%l]=Jn*QCݦQE_0Kĵ0QΜZl0]xDXL+ӪbSy lsԡV˥{nFљ_V'"ioÚ/n[/Y5 FM9fXۻkJI0g*T$<߼$Yp߰S=[mjn@^n_<fHtb?"lvzS>2W>3aşoXDUD8? DisqM|ۿn"wաэgƈt'A Wm=Y'// c"1ْb-ϔ1>[gc  <'h1hK h2{Z6ҠZz+ Ip>ƒ,Qmj*j1 8!JsUQ;ׂn@.e,[)M =ax1@zL7AerO ]o UDL!H ݯCʖ<[Тzak0L<'%i8 ft;a4Y`ˆ{IDکʷԤPgcfGs߹ oX46,^;h ays64쉗o& a.Akr61}&h"w.mmVtUUu\Y4֜A v֭d "Z -'ZUhkǗlSװ8Aw9up]VLY8 D.8hzn&{qa|}B i?^e Y#G'3'% '>oOp&'0 $ } !h۸A ]!2C NGp[緒]J`֚ehk׬ 9f˂&@}UJ #n V<~_j' lo՟ "WZaQUo݉@Ϳxch̭-Tw )~.Lͻ5-fMfa-qs)C'hʚFj%i T; *E9s @fސ{OPWQ'D?`zr쑓XZLv17Fy l g!UQP)#{2[6Nqes.lcGˆEA ] G-*.蹸GrwQ W$mh6 W <"aZQ0j1AyۻHFH3~,ҦQدtԒ˗6x=?X:$2Z ÔѶľ{YΏ,E?R h׮ؼBD ,IaF W0kĝ+V,3z9D8ǵb\[y`W 8a*f0\QjϬɎѴe؋6߁Xm:{}NRt ; 7.a t/\Έ: ULl=.0,5{ xbr 2TC0CG+8H~ȨH ͍M໛xb}pSa@g{ ADIQ+ 1Ă ǝ19~Q$1sTsek}hU`}OeuMKtXbhn "aݑ ᜉъ)Rȁ66I6Ǎ$7tI`Z c!ƦқdsҸoQ%nJJ{ԣ[ø@ nK1L`X଴$% am):dZ`~n`0D-Yz0N+szA4%:s GVa>]сr%b i4hRk$yu)NƑ֪ʾ"8A8}e*)N񌢹,iTR:HĥVk чڶs`wM745Դ_-2gO򍓻F)=4h _&Ӛԛ4NʩH {v7g`c}_|۴ M~ ->ǶμSs7-;jupExm5SaLΥEWlhw\:مB?:&Ϊnd̶SzU`=\ Nhao;giZ&I@{O&&Z;qO\Ѻb_ʙ қ k? wpN)~L`,ZRKwϜꐄ/hdDJ9{jr 4ؓi<F'D%G7Lg@! LתRE*?rsfPj5*B|}ѺTSڊ~dߵDHj4{Wf6O)ZcZ:sZ@29%vaǤkQ*:>WҧIn?pH&5[ _<߼I-b^7 2nV#EZ1![4(5/C++̱k}P)ĕMizb4nUSߒ SN]7"u PZ,Ac)&kJ:mZ&)SվƊ@םZ2E ¢pN @ EqkdtYpe@h ;fhϏ-p r s(t&V  =gB"7V<(NGuĦ 1vvH6ND`VFpm Jjn$ĪA9{e@$U9KpRNV79.pRrьVa8X|zSNTkS]'okz2Fv_Mw9A4u~;9{[R8k:T5ɛI5ƻEZ;D3j?th>DS=qFNc]i}^^pF]<5E6;հzYCMڊ<:)}ˮrː|E+s 궎|b*VO4N' yCf!jŋ;[#9;]}ls=w&(.*I5#TO /9?`=iq nyBnWj!cM&5mOSf\q(KNKsh>Z#уU 70u1vǀnUs.oKgAж[9 TB 1G31Ե^BBˊ/_1V鋓,­\aW9-?!??{Lrq5`Q"0a8~Օ:'PlsGO^Pݢm*7y_ ;T 5Fٟ ~hq Jtj;YӅjoBB9DQMKdĹdk*mm)UZڕխA]  G7/L !({%RҦ6ݺ˂N7ũv/?*mHR6dN&2RI+ CVkvHibikIO@F iwn@Y׾Yє͛X;IYMQ#ҩ+2Ҁ3~Ϸ_*Ufo( p1efg1/oQhi:4 If/YHCJ ,";xTCTd8Bl8; XG,9Z;oĩۈץ,.ftQmO9$u5i8qW7A*ϰyc0ŦTBf׿B`6P3W*ٲXCtfBjDU޴W"p)!w;1q꣄6 fLgHt^fI:ڏo!ysr1Q70's% #{W{/iir߁jLi %)QUB9! fVi=ZL:̲Jkqß1pr 0[`z t^v:ᶑočS_bڝ0{͗?.cp3%U#ø-Echs@9z|;Yy SHD#ۇO(3U\E:;neRENtCa&O!jҶ3\*[7o) s*Kz.$^rN"4(U틾 _ng@Qv ɠgJl-k? *mMZe(ԀUpi=Ozk3l9ݮmذq+g eOܱhAy0E{" },$2sI".z.[_=wQo Xp3cap=+S*{7-ʒHG=4Z?# 7$OO+wnoA2u8Gd*|I[54V'kQ;; ' yƹ<JB : tzejBL,.z Оgeս'Q#MU? QL7&L (`DsT#+)> ZIJ Md4Cd%b!(=:19UMM`6ӹqMx#%Ӧvks:+'v(: {{f:;#5 tsA_I K ) "R KQJN>կK 8O0X֨*8\4DE4, ڤ(vW3)Zf˄38Zv!KcV=%8WJAYo.m:C/ yZ5#iw#N' ;!RFV@".Ş>b%XԸnQmF 8)s,([tEni]J5 \awV>YX~V4Q㼺2U)E1Bל$Je$# ̟'$@sSJ'ɟ-0ؽ_B% fګq;MxnL$x:;& XJYc%je-@e[JIX,JPs&;!2jMNv [ ŋ 0 q~At~wK_-P<[Q<čѪz"Y>э43.56J5ʂ2ToCRڍ%1amV5!'?4Ì5Q-&}%#$@g8r@Fr":)8 sJ8C1 ̦Mα#.%&9vtz8=S[*Q"˝4=>nNr{^9szXH* R[ml0hX4'?gh:^_a/xt=m`~\OfZi-TIX"`gϐA<{s`w0-zl6g+-饃$Ͱ1YC`/yl$S Cz>Ki?جxFbXpEHjfίQ񥛣p+٪&i]&o0l#5&ݶffJ?~/}yzpGbf{fYGSLf?=~[zbkn3IzȗY UR V;5PZŢӊ=ci |$M%?`K~tbl:y!%OnDpS8gr=ɺ#NBNI 4K%= /:?q!D8+Og;ES n$.48+SL$G!R];YI1HRt}1' #i&_F&C~7˟V?͹|ϬMo_I=B^q{'rke27t"gt}Ow1 e7<;ctǟ;603xa Ϧ^+S=tWZֹgLaV^#g ώw&ɀ 8/Z 4]3-վμ--g򁱋j|w*KWkwy_<*燉Ry\n #ua wO^nawQnŤ@eB{ዟTVIac<(]J_qvui8huP[]xXʁzútߢ%.~gt{˷Oh,6.lR!txplۯ|y,%ȰzXe#%<Gm`׭ZFPd:Ը/FMS[f:qCF~ _~pE_S50\׎=ѺrrsH3 ҋ _7wnPq řTҔV,)7z \LMA--a !Ju?ݧŕIFk 3zJuo 0t)uA,4 cJX0i4|^ZP)].2=:4Y#" @Hִ}S6R>rϛߞ1 ƽJ6?:ֵc~wm…QZZ :H;;%(+GPkM+S eӔo8B,tGa*\:8iD@nkK6(DL)Ŝb#>l{ջ[^n͹VH:w?u{~|˟oæщ`ETD0i(?yWsEf|ݐ= N|opд =r&~ Ki.~K(?jj}_ҷ뗆;5tJ7 L{ߞ Vg)#Sgb{%&m'_ѲL5gO km{V|/iX lX_|PW(Y1|goOi͖ 6d{{ώvveulG4ENMQrl6l6|eO`3aRu|BꙦuyl.xiCH}'NJ n;Aҭac[&VMAlSGX|[\#CcS!¨BzD/ vH]ƯRD `la rOTF|haO-`_;1z6@AIc v=`Cۓm ;W |1l8.S%X61 R2MoSth nK1UX`XA*UgѸ$5.b6P0b3IhXAgaDg#;p\9\8]4;,)z@ܲ ePyJ*Nh0!t`d".bB@8}e"I,IPFKDX⑳=J/-Dp`=+wOf n 82pO6FOe )lD )N(Ywj7S68)W @[qXV}bk{yQ4V2zuw*ց/zO7+a5½'"1ղ~l]= %%7L/ӃY3_Wʦ ڡƩo/eUk`3qMJ)| ?WaT5=m Sƨ;yK @ gL؜}7:A\YjKqXQB&d5N[Xws͕!LX|[R=P@gdA\[*YUMYZgV1?W\'>$9fʊXs>>UW:峪Y>\f姣9UW'r}o ]Od/*ЬCK3_=ڷ67٬rFmhO飥Kꃵ 7ֱ١ ^Mhuq A v͜9XvT B0u q,]탱 ~@s0w(`K#=sP̠rw [e%}CT~.g;Ay&8}Cp<6{v 9?>,%lfImuwoGu07/`JrM͠pe L",΃N m}G术w{pxURK5Q[SL̺F {;-a3NS 0%lǍ2y fW!1',Kp/[bFqjRyjL.""\M,؃u%۹$|܃^~ث7WjYWX0ҩ;KOn+X͞#c6S4 3컣g`` [6Eā~* eSeZulU撛Ӫ{dAm ]ځS_7DDld+m 7dX׍Yoܾ!vP"L$^}ORMvgMn2YYYR!5.Ba6=߽]ndAfAή5(5Ye@|"dqt]lKw~Jr]Z e?]3Ks,i,} ~쵠@rڳUED+cHjI !^tFhg}nOI?87]-}QaƺuioE:7a:eݝ#IGҎ=csd4b?Xm?THxI"<9!P[Z5-!21\λ U8_'W2}4hc\ -3k{3Hǥe/ŀI1e7_­>$kپ7jWT_g1MjB=![t.)7}~B7˪*k˖s33n@0?eNH^t-X-vpTLѢxj: 6/B9^lHftO,d|zv(pPcUc|Ti1vc16epR_[q aw){Ftn2~ϵ_bc|rRW;n)s"M~AV&VS1Z[5#Z(U|A6kKDL:AoLk2ĽW=&tn+,^_KO'5#ckWi)2n(4/=|qH.R+3Ð=I Q{j<&CkL3.| |V1,/~yaVYYܺ+򾶂>A5q Vb=}@ B6}>KAjB V\Ⱦ2,&f\>?aW(ZAk:ŊN}pņIVc|$7krL }Ǔ>!4bo@K.H{*^]K;3{QGW_[OMWMi`9 nӁ~{$-8r h7/[K|el%{:`P}4+ʍ]~!(+زӌWf Bg/ݓbvr"\W*1ΧW q=㲫XX>O\f[Y!7Y_7n,Vi)6xVa ~QvpA/Wc)KTc1v`=Kװ+F<ĩ͈07ĨԤ#g?/t/qdZv5t ~-c{׍>q;{6:BL:v&hqM=G9KMn5Cj}#nMg}9GUeiL}:ML'"B#j)(ޤ)kC~Ţ-l .,YA,Qko?"p*AM7 ( m:He1G^OhtT~m$i`>ohӿ1uG&E(ii4Ր<v #Mo?  ;ofu_3+{$Y730C9vbITnf/lf}&LZ~X@]t C[=.'KetXHqk8e|&e\3#p)_2neV{&sC'M?Z~NmcWP ȰCxǕ2\zu.py%d`Y:^vCdz-};k?_gXR;0<2+ N]6g22ny~|{8rRʾFL]vL\9}¾$Ȗʡ`ot&Y<@'{4S]zYr4D!к좢MLQo<K] }thzK}a#Lbe^ROdeaJe|MPŷٳe[zq#V5SAvm`:]Lo=ȮYiwz5\$Kস{w% V~N> `7=sA4}P%G3.EeTwD6&*z`^Uc#>{}iF..yl'*Mi2H- 15OHogEG=4t /OV=`;GYwIclA&m繂]uO4`_7]}tBr``?|팫gݏ3m/;͛~V<Ȍز> p ~s'B7?dsGb%FwyF=G[=y2{To=\>zd'j^C(qm$~GEGqh~)Ƚ@]f!fZ4+auTgӚfv:b<_`o~ݔq~ͦfdO)&\1[9;;N"TFu lTDN=.텯X>J|)XV`:0 uVa]8* ,`CO<D7o\s #3umS&oDlT[5G:5?g戜UAWη":U<[6犑>UlF) 4$9p O+ 4%d#g|xf{[CىOWbZHyLNlpܖJ l1l|:`_/VX7\l}ɹKO7قɮrpZ/ ="+/ﳃD\8)Wč!%V! o}]-S|l癛_fˊ( 43^fK+ܗ3|+l*/|F_ws +l6MKyM [1c!o{Wog m޷A~`н KKE%~ (C˵_͋ 5eHOAp'A_Is0'ibU6kA蹙u8pe_wU6aJV H+e?gd2qB| tX]kTiN0y,)5,͂rkrD!?& Ƨ+zz*g&M,_JY,2v_S^7 Tو~6˦zI\F;V7g~.eJrJjɪ#>lS}KZDpOm@CegEQ{u*YAOǿ.;ggLQO4x[,k_y߿OM xKm\l%^K7eZP76&'8 RtK'iz]%`ܯhquc*;q/-.NDh#c% Wэ8` ރ0v,C*/ۢ[JvI ) 'Ilݜ]~g>[w&6~X{NNԚ&YBy ޹}G-ߔJ7tG\rT6mko.])zДbή<'F[w?6ku*}H ; bB;}p?qKr\?+^O[N(rVWp<݄`Ƃ(ߏلVp{"qFJGǽO¤oq S thBѾ4*^n"C)}7?E(|?r;ga%cB%8X>KS.r~f;7]$CYHbhw\v >d^+WV*JqD'jgq)3?OV=TzNwʩ~\K%oܙZNkoλ+#3VW7sV" O=8˫/,@ΨkMP)tZ 3 zp~^ކMoc&?5(IG孨 M7&KU_ 88o"@q:ܣ-}H]V,%r*bYw&1myEf^ ޗ?QBAx|ixוWЂ$}BRRkXb! Y.uRvW7Bx+yy383 qb;ؙ<Η8!l/Je2%L ૧}~fJĹ(m_y<8ꢩz G T×>g᳟37aڔy-ʮ d~p=R(b$]  61%I 2R=J!t́ )|gt^`- |U'2ņ298-}AᶕJ\g@Plb:|" y˄2V4>[YKVLJUv=sKSw-OPSEwsDV+I'Jxfd+2ܲ"R=fz*[#,'FP61.b\I9\=gl IKG<@aKT#dPd"W!jg<:Y !͎d\XƑ6 4\E9f-!ʷ$OMjmZ,TӐ&A 1ai= oIOh={=qh}Xqk.j"L>f2gix-Tj(U%Cxhv}Eݺu<%۫tY=<lGjC|ݗ+-G0ٰgDh3Ӧ]GDRFt]ҩ2E )Cx/NK)9c"*Ɂ΅'f+OP49gr+)s{HR"Ke[]iJb\mzv~+KNԱմ*.0c{jLE&]` MAu3_πF_OWN/tbyxWPCe(w|_#bI*#{&S.23O aG2^d2 6,CE&Hd9U2#CS 69LLQ9GSh` QY͗i6럹v"İ[rgQ%wTƶPGPt Gs"snDHx}\MgO@[g,]ó1i-=L"7*Z<A0d7R֓ud6v厐@E9v._YCxD`Frʓ] x6g*#<ﺘ٫*}Y FARjL 6 SYP_A>_s`c6|`9Ԩ2_ցnWeeTT-m͆!KLN=F8~IĕCK}tb q 2,C[l2cct1ӷ.BnLΑ_/aV*פfϔ>jƙ̔8{!Grc=w~`yr{ctʘwxc7UʥS֘(wL&~?_DRr ## ;VRn??X>@6h6C8 2^9K̼ć/IPGk-WiG-R|.̱jttQ]׫= lUGpGAs%0.QǻfkPu>Wi>Wly,ժ© U ɂUY^9w.UBiTg΅25[zBI\>sKrIDy@ ^cK'9j T-Ҕ/a&0(0yLl|0ΕmT&C̴BV w3񆫱 eu-I0mٽF3.ڛi.&906cD ;w3#HGW7ɛg?UMLī-oU|fӔhD6ح:vQ'XJ2_gǢr(K!CEmϭe>K?mjGY lY+F( t,/VN@:6hɸq?3?o *4Pac?V8juVQy 鸦!hB͖#z6 *F8u~XM>j2xU1P n^"vj5p cTV4q:'{Vmw_~VS#Zu:j#s_#+x)%t{$aq$Kc)޵ @i+ݚ+pwDUE ^bD%dpLK t5tg+͈Ev3%|q&/O!zZcLl BυeX,3/g)[GvgVTG#}hh vF>^jsCb5?m`WR@n!H٨c8o:`r_Ȓpoj7S9:d%%4:Cf2}_^Aנ7Dl~OvnICLV|oVmVxQ34`]31LiН\C~)V_}.)\2ZD. m 4M{LQbBĶ>zy_ YL%] )x[;;9-q!9PA%G6B֨TTz9C5u !+u>adq-Ud4p6l0̮ XST>|m b}VljR3^o8<'3;yVC]HO? 3u3!wإgae6vlqE b$1_gf5MB|\K/dwF<̣Ǩ7[b:fX 'a6O #gl,^eҡ=!i :Z%ˉ XKaNLAX-bZ@sx `JHŒhj$ é$7uUom$67u74lռT:7qO'gj3 H!Qi[O ~ez[؈-l<בOk{zbZqad0Nds/ A~q0ySO)кՌް&, !3fv]ղ#l>ck0MevpShYa3"+~<60Wמih2]P@V j<t!;¿(d PoR|lwSC(~P$_=o ,)oS! Ƃ^svcA, H^"=x`); Tju^0; 1QP-º/~Ǫ'ևa/.{Z[*D|؆G;R12q8[٤(=+xZ5PHǍߣj<ƷPY*ZBZ1?)X*M ,)Pp7Ozv7 >/f< 1r#iO@n[6\~  I،ӞWys+eB\@u&M }=^`U;S s_0XinS}CvQ 2ll0]H6=xHqΔa>Ӏ˩gy)rG/<!yc (+, - ٦ Lڎm-8m'CkBVvȉB~:7 ]LM;wB_A?|h/-N^W+|B.6x)Ƌlu«PdRo}̈>P:\ x|Z߁?7Gg*ݻg%fzuxI#L:SGoB`FuA;/P^!nBO)r[R%ݔP%öuƟ!LoC/OI[iE;®V>!*# WPo^"=Bv^A 34d T2: i*iF?h^_9);~A[a_g}Y@zy[mQ;ĝ\0!h5@u^J0+?9Թպ)b$%/TQ^c`Q+FxϿCC,|/x"l]wÌc!(Kn-EZKٻ\C4|Kbro_{qq^ZŦYͺuv,%܇_&ncG!ꙧTS<Zܬ^lc~;^ Az(_)7*l?c- W%kcUSay>Zߤue2|;Ŵx;v֚<.H*R.(_9H2V: sųbP|nҢٵ,bCU܏<ɓ[ \1׉lyTvOd^]A%jv/ꇊe6S/pjq\ n;vٹ=+c\bG{%q8Do6 U߉֙YGoɨݟHÂ^UOѵE׊ 35֌<//z$>qb5:Vېv}?Ƴߣq0$7j%؍WYlxX*UԕlzE4\cv'Mʎ{;[ Xܫo$/`Vm+*+:i7[נTm3k$ζN69"F?UF IMv?z0wh:a6^c}*KNOP^8t'WoD?A~Iy5Cد6_Ro~ 3 _t<9,B uMh|) ۜzJ|m~o1|-5 yqnW&V^ThOIF6Zi=7Y|CFP%/LT!.:Dp#0T3J\\(e DDZZas]3d'4WsI7J^fG~#{-R=9H~xIDŶJ>&UGZMa7lv^']$B*|nQ$oqO!-)9ؚYz6xukEz,~:"6)_OOe_hfwg*@'i6 _lք?cxóJN[,y> %x}r9|nf-^uUH/jߴ쪩FHBT'/闩?zOؘzkHX=en~~'Be&TBqgjcP*6_<s-*-vt2߉i;J˪HuFGՉ)TBϟNXm'z~VJ~S֡xv8/޾}zpGa7m-fz*Ҽ@r{q+qt6<+;dA OdQwG6"Ǫx([AZQ7\f.;r2!KV2xY%9Y~?~w;yw=E ݿw/tĿ fnۃ/cݑ]9 We2jdeU0rxfL͓;>??kO܍CU9*jN}8(ǺpVU?QgyzFQޞj1QbJ.1K dk:680ӟIqf_Te=e8{h;DbFu&VFqi ?($ * )[ 2j&k\:0gQ.f)޵s'l.>-;}=-8yƙL'1@wZV||R?juدV܉S5Xk2z8Jk]o㍅{ߋtj9R3Y=S8Ff蚞}FkKctm.k;\x"2-}tL"sp?\Z'k@UHu].A T'zbU!n#@軻trX(\Yot@cK#/l^Wkj9p o9}>*xFiN0fC^زfk]0./ց<߆z8@e:/gj42ƴ$٤5Iy ~HL;D.C4yP}_}N28\4KEIɹb (`v8_X_c,h[_6X ۱^BND‘ Șt5rPa#ȈD^UC7u@B.r{%^-!DųB WERu"!tT@MTQVe*ƅVpk!:DXןrL8j d~GT.v9r:a}H=7Y[^F,]˗GxXU=Adz4yG0%4{W0{ׇݭi^y~;aۻ﷮:RÐ<3}#8I`YG PRhTŋWOvp:# &i W؇x ?,H ժDJ?AƍH:.+b(/@0-6_ Cx@Wʵ MRZvsx*ezsG]-1yG9<E| D<2mcp-{ }\͵}\ȳ`(X>H4? {iNznaIǰ_ J}ݳR'|HBTv 0\2Cs=0!~Bn=3.qe-YCvԮ kπá:FKiJA۾ .\8<%Z $L qY g;`v?BzV%K~66R6'tm_P_b@f_߄5 ;r0cSWA~8znEZ6(aWWct ~xq?mͭ deĞW2Yz@ w)Zp 0ѿ %\0U[2<UN_4Rb-q&uYȖG4$=fk¡G"]TúFzcE;*c5<)|n^Y|Ufttk`h!j("8#.ȣ|k6$+XISk(z"E]Mԧ 3 j}6ΏrnN֞)8 o\H+"ӛ{qy7p=[ pq훞mW"Y+S8e5&bU ywF)0p?%h|XY9H>]s['VȥżjgQ`k*k}Yr orDw( ݍ"$xJKvev sZuK ZegVK|$\pR4%+Y(>|rf'`?Q=WB{[^hϴ]Hέz=]#_eJ 1h.ć776)վ;R#$gu Od>^WΤS @o`o͸ 7[wo8uUPlϿHR?QBS%SBducWe~#{DF5oմ>Wwdsyji;Tg*/ NuFL7إ{sɑⓅL3vXn9j]Z<ytv'E@> r9vF> V B/@+\NTn^a6tH+N5fݚn_5R\3:n.D7#ueIĹm8D2ER&XU(٦x_3 M0uNii,Il6lRЫ쾁1ޥr 5bA9DiUcr"=_A&9puvЋ F)BF2I}W/cn/(%gJ7#l[d@!;Ct pɌ1: [fh xEH]nlD5Dp'(Kx9ŏt%\zgVAwM>y{|%&T@b4x45 &ŲSJd:29E #UC&BBCwQޚ}N]@ Gpv}bwaLg!nCǝtN,#b xLoo_*$#-{[I $LU/?A+.k 9/Kt[!zav)wxHk  \uic%b'ykd?JxUxGVUGXtUR Aw`)5 ˜f>7:%ez/ӍxR͚1f:S/#j@W WƭaaGӇ\ng'}%#I  QlK%ң~NG JH8/r}䗏(^m1'F#p-#q<0A(6i)4=}nDwSڻIB'͌E6oϿl/) "`i=5p Aꄤ, x,]~$r_;e surl|H/7ʉ859%ש\OYh=٪p]KUhksss+H:'8p'9\쒐҅0S܇3{YoJ3:b*>Tz!;#C\{xV? W3_FAФb)t|W\?@Ӄ GzŖ[|c)V+)4+JqN܍a݌RPDM#y9}g5 LbJd]na -0^#%AvhG&Epß"{8GK "M i`c$ ~Puܗ)T [21S&(;z0SŠK.5%%}a5#xq -U^vKrAc\6N]U:/} u^qe ]f~d&izփڟtg8esUxƎOw1=sX mr~,{38A>Տw˦z\iRey b KM_5o?g"·bDu6w{{bFn;yK29 Tكe,C'` }|Ot>72Ka㯰?bz5Է=FK$e ;4 :IVg U$ѳoN ZiQ^/evD'%$ňz‚ft@ Rˣ:K7*U0I_:0pdoz&6@&h[d+B,uG*#CxCk~GCf!/%Td& sx C߲~+h\Nx5E ΆqDH7ys.w~Yw{@S_uأLd.9nen[+e cUqӍ,Nh~  -%$M~kN$Ѕ4:JPfr,)A&VX$<6Tʾ&ڿ-s}}ODTJ&diNa+P%Q *&M˄!"FYysp>iJ͜/ʆmcUИGI'gSI\6&~+Rw{Lms|AW=95'L mq+|@ȱT\J Na1>puJ쀰.gUL`zD@Rg oR,Bwxl ).Ң6NijbNKxSJj*['PCZ͆=Tl@{k K a}%yJ؂#TRΡJ2i)!ȱ|Ok W (ۛ:Pي@tZfi8(KI|M|l(7Q_,2``xgl`SLH:pb2Jb=(=Q@"gO]`*EMFX vO>/ Tkġ) mм t yq( P!is5z hsTJP}Re#aX ~ca_ws׹ߖlgG7%$ZZ[$=f7/-rG ?vfL)vGdwMJhl -.mHq ׀ps=ДM|ǿ6Ǜݧ_tamʌLl[>ŷ:q1EFITLA ,eQ٤yh.\Xܼl;6Ʈ5F}*8Q C-҄Ҭ ȲWNn]|^l ZG+2*B)e.RS`U=LYXEhO& 1V]UXPz8)l)?$Q%1[ k})ϟкgԿÇȎOWp OdQㅵX/E褋W3ϣO]Q`/@|"+OSO1j`͈pgXvc:8ݨ"#FD,ȨS19XmI ڃfsC921ir?U@Ëb֓a1sg*ibs}+/49tݏaj'ط\.bŅLJZZ<o0fnOY縸Frij0--5?cFh7?">6_9~|/b{z62Dh;b1!&Fs1B5&f茼=_hJbFե=.N Bb2ں˼ͺN8՛N=꿂nk?e~0aup]Ppb>3G)ܛVX8[w"=.år8Wd*EҰij69l %ESs tJON,ALnƼ6 GO _Ke qjG~';MD7mԾ-*>F HuVg8@j 12>")7GŹ|NL/JaR'ѧ]q"b@*8?I1;G"Zc͒\lBDQhYԋ܀=RuN^Zʊ g~TD灱N,GOgj& vȫr1_&x  4y1=,HMb)oLY/VZ\cGhCVᓎyV \j({yJƀ )+-cM\-j =kz;*;nt%uS(K4LSa4sa &:P^> p5F #r-IMsXC, Z1k]X;茞'tO9hH KiPcV(YV=I?)f EUZ X ثc]6`l5H~dм7"&ZZ8,TD7b_E> bf$:  <rp~>@_=-}vo΋_Y_4/NW7Xzha96Z[L Cn gukU R3ys=<i'!76;x ղt|^w4:% [k𾃄+Lеd\^ _A?HcXq> NˆP.#ܹv>Et,/%B^fVj) #v}[.)$^ LϣѠ=KƬi^DհL]ytkt|׻Ib{.jy2M~S\ qca츚irś*0,gɛ3Xl9CrfJFC2\V$VfQ}GLAYLfœ ShU&j +k؂덷;esoQHg~˜@n0VbƝ;Dwwkv(7aݘ h܂Ḭ& kDJ s_J&GӠISj[w{'tVjŔ_%9^ &CQ) ~xSi>jmMgpv{3vsݛmJ^m2] `OWw$vd͈u m`,덧*k#iCr="I G!(eȸ8Sv(;PrG0c3( e[40s`WLZ'\SU4SZ(5|iTxmZ4(%CΈh;\ȌM1ani6 #hVՄKanBTy1 b ԟEA&^K12iM꺤`$BJH1اMP&\V!^l9j8Zp_o+³~wH2IJûĞI1T\tuTٜ9:8/: wQe/B/bDp&#_FQ€xa2F.p a #RJ/a KNߐ{FCb tZ*\&zZ|P_;3s|1fn]xےk7$̢J n]Z>Su\ dL`#̼끉t ,R a^OdA6%z,))|DL-$W-<.!.!2iIL~  lsƠ(3 v$cDӦDD@aШ+]Z a$}Zih<=.,moeưC#$v:l:\09yHL7nh|$iuO—i^dqwVKlF: ^oE׺ʻ^-:.5+u\m*8/ip]2H(tL-'R @̵'Y/(Xkt/d]xYS#j9-,"Yv}#B}闥%sbԊvRh%etw*an(X&v_a`Jcg 7=7⣼y ƪCԔ gey.k %ye\q. bSĖԿ-0s:/JF _^˪5%IK hjZS+O7qYߑ}$LR0is@?ZRuZ,+jW6G{♷m +4~9e^!-g.}oRmb>{Q s,z*H=7*PiH_h*cFzI}Jjiw5@Jɛ.(e=5)ӞXp;f< F&b;FeSD>:K2lP@UdPgW=k\=UhgGZ q]vwEMhYP9w{jZH:ԈlD%{OBS 0r+ } Kqo Պ 2guo(DelfJEerNљ)[a4n7L;3N -@=Dn δPSN0'@'n[Q\SH |BRKPIZ#?XUBßS rR_Ó`<=*=??d'O:΂cEw4 J"+֭7K,XcQ0L `f;L1 fф"aEA'O1 7i5 ,fq.]s>8>5S򳨼hcWkdABSNxJ ZrFda>stʕڜdhG #MS>p2ih.]r ^Uׂo:}y܄]x@w іڋ`I;hn243^ipurHݴ^}Zz7rrqrKz41R&Ppr ;#:xݲ#gEK^!cCg\j cITt^)ݜQ^ .5? DM7RڕbizC-E:;B9܈eʑE1RY?֩y1RFP ,cz7&Q1[#k FS۶CmŇjDZ`ŏ%\8_%F\zLu+<(b!x O8GL'aq! GȁBu "[y͵ puH-E_S7DP>,(,tC^#?`mSL5Jl v?0\o6"$$xgNJy1خ0V)~[<4_fQX *f:}n$ߘ8A8!\G?IWȽUiM&`"ꬢ"z mvh>Kd %#bNifw߹N 4A[-4w/(}$%0^"/I0$ $xT(vAn!^p5Jz$ᅕ%<#dNJɓ^no?'0͘)-PPd"d5fQDr1? ogayCK9jIqVa;JpÏ1퐁k3nP _ךC}<46U92v 3BkA3lס>R4[,#Y: x6QbT Mƅ8VJ[Jw]aQ:\: 6H;k^2r k&Z#sSM[`mLȍJc3; 8o`I(dJNåmx0^lUm>SsЍ{8$6&uF7C( v{ygUg"Jb`BIzrs)c|/B1B&9ѵr|CQpC^a N9~LZ/[sFX)h`i@K|`iJ”m[8rMZ%\c|7^Eʟir*[0- &7(9XJd4:BgV?Zgz4si4''23 냋Q[|u3L)DDL]<;ZRx0GY<2@!<7KmnTS=^P6UUڔ.Lݭd?_iaQC-@l#n NcTűK*w9 \$VD6B1IG Ɓk]2E`clf8bچt`4ճ`hz*X{R{8a@ 2op( iy2^gX HRcȤfz" k|;Űi"Ź*T5KT <ع;cdMȚgԴT('MI[m0lMx-}o/5t40{+@679 xPʃ\!omlЁ\T^@xM5;*Me39!ۺfM:2ҡw:D % 汬8aE:,NśAiF{0e`X(fJy@ 40-!~Y]J_ݓcwdU%v'$oN m<&r,.%jGڐݱ਍3$:%Z;yǙQD*?0P!s, ʔVNpK9Jzq@ȚJ-:H1t$葙P\QԺpfq=:6wSõwo2BG멉1nǶ]0[o_Xz-){MDzA筲I/윒(@v[oi]kAz :s rj! tN^hr@@j3j[%v . &"3U~%QX e67*+qn;z-!ıJC U7hyBy. 技s wp_qo<6fF$QTX~q9LY_绔ڠWjYJPbx}8?̔圕$AwT- .1f3a&Uը&^g5y\SLIڬ[ǭK3b Fs5dgiռ0Jy -5K`eݬI=<.Ju28 s/;2~Y :"$YC}o#8> G_tfՈŵT>_ZƱiדM~H '2KM֧cҙョw>$Rbn=m >;)Mޝb3 Ey^L,tpa8鵛im33Sm{,oB#L%]a7FG8_wq4 Dn֔Ete& G#%1uMRZ\@(1 e;TG>fcGkwY5Mr9ZL!Ck+  fȭ04ןҦQ,Ψ?+a3qB2h}V/14~?۱$:Ktv3Ʃљ#oSODYY` n+Oq%)~ٟ:Gf0wvD0&y>[r0bf*=n.p E5P8RTp9bEF 90'604;n[# nݱ&MmsA䔚Synxo(I^sA!M^o҄Qp, J`>q. _Gj;&[^RH.gꤞ r¶ *w|aMZfQS<ІDQ:G>^wm<k@ @ݿ> K!ä }dm-0g<8?fI+zڱZ'ok74XoWT/Ԋ\Dx׏xɊ_{i &@`diBKgd|Э:sVUJ( ' =іl. u QߏX ؊UFى!}ZX:SuzyP "|9 612\x5qeZ7N,#`Rt :@;vbbZm;GF6OP(ބ1@jee^m- ư,KQIAvϲXrPDa:|EqDRg!1gj1ϾΔz1@[7j{g}lɧ~Y$Hj ӜGN/L{Y7|$t)i ;opKמ4KIj(ņ&Y8?]08g7"]KZF]etDr6/pĊrzI@ bWwRXe vA'ԧ gq 6W5 GdɏFti] ]fq(HM} pP"Nw `Pp$ i)ٴ7 Y3Uҍ$b:SZord3WM;`m47&j" Ƕ^WK/FL2(>WNЄ~͟KZ:_3EݰSœ[8 EQ%kܰpbIQ3vwIWaZ:dn<&r:MSYTTZ <,E 䓡ւS2lw~FM`eHΔLgɼ^2EEtd0"7hPL-%ʬͼf/s~b )R(ȂgXV75ahSQw3oд3"/~vvlgTyc]Cw>i׬l2n 80b{o`]ͽc0cH흄\wBsɐ oۺwN)j)S4Д{_N2?q<Ÿ=M":1{`#>b*1iz[$ o`pYU6II8ƀ^..bjC"REfkq0|i`SQwT ;{X})c4hmJZ$\`ND۴dUڒ*Z09caj8e<;lPl+ؔǤW\FYIx;.*|wxggΟk=qa??왃d |w·u H|0w%; o'~S0}8_<*ovnߐq]f%OSX?anaG^z\o 隟(.*ZFv˰b"$)Ե,*iL1uR zeuR07 wÊyNEDn-򢊡YXբѾvMk4#,4QƐEVi= Ogdjs *^UԛP++p+gS\%"Nu˲Z&OBjȌ~ F@7+MVttg- n 뷦eze9CGGX)ĪeQa._Y\0e@eʘmmbx$}S$g t2gxb9S ΰ*C#N0ZH |px̟F`GY—d^1W-=# 4kl遏N}i (%j".Dws{gbF ׏Zci4, #IP@K!CR[%C26bгYAn'5Zb5t5(^Oj^}d0\Fɯa`E2fh; +ǯ@ۨ=)xe|bV8CmG͡"ߤ E/mX~Զ$>/n??:HGaf1q8 E Of'rGCCw|4\D4tg]pn! hEQ dB*76y\Jtvg؆S* Xoc1 Ebb)#wP^~Rk9vkO^Uz^l١h&VkD͊ƶ'k3#Ncхx^t+4=e@5N,3)\ %)RN%Q  ͚P.(I9G-a)VȉLxD Ʈ Cu+5eb)h㦨X$gWb{s-m N;=õ3x,_cI<&Kq `s m{qp[xYP/z$]hI,w?k',l8,eYx%]YΓN}f*4V2JC0)L`C,2N,O)u`cPx4>rFEJP%N,W#wG=˜/T+Ṗ0oKG-IM2Va\̙ - Zeb)`W]ӈłΒxevOw8R~bС ~;x:9,`obmg/y^"rzB`b!EEq#ҢlX oP05 A Y1SUl^O 748ܳ5&?UEyx¼I8ZtIdlH+AG4R6pEp )} k꘦]S%U5,y0{G[lke:r\P4x2<%FOh۱ӖDhd.q|So(^(u]/baapL-QC( PH :pJ9]ƕXvjL9M8lU5p4]vo.b,v%<FAU&]ek)rm>j5f dč%̾H9)!C$*>孎H.ٗR鼮ܣ2QA&bg-End ՊiSs^r wNUSYbmܤ]O]-[bRg,lTj6Pqc}q, O`0}{{(1NKgA8D'9ܟ؋cQ7ޙqpuz><-WӍ p3gGI>>#/9&Xr0Yg3gs5/kz pTLVLYI: 1d,Qd!+{ᭋݾp q) {Lypnn9.qxպ_iriAyȍ;?ʴna:WIktu@)xͭv9i/U2q g{s;V_^`a18&?g{|-5=T8&f5(wT>qgpyIT,pFp3s+Ainkf,׹KZ]9",s{w'Vu=\nKBg[_3l{Ýul~#])reȏBF[)OG) [8~uOXNPe\ɠ'd@ r>HEkv,=)EW4ӐmnVйQIqql`벂{TC 1PQ̂Ծ"pCK ާ݇HD]"AWwS:7ח3e͜nґ_w>_fxFޯnma}ቧ s%LyV-i1/5ve%>M-Ehh*ظ8̵)f鉝[ѐFAPâ ޸3x>ł ْyK^k;wNUY pkkziIO(uo]JHF2 6K#ހ?!(_OqK:o{s3sޥGakYʼn]Fa޹[ģ zY8zKA MLu;{ԇW~%G?u?u̥w/_iD6"r٣&/}%Ai_H{?$A;r~OG.ѯH':۝Jԓe\"(NrSd+IÓ'Ne}$LI|~0uGݬ.gn(&?>;r\h0BΏ7HHbp\阠(LSrY[fVN. x$ֳ3S3ٕYϞt (>YB[|QN]!$S$7=ϞW~v";ue{HLɍİ?{Sz+M$z7D]JϓZ2{QjPw@^=Bz8u6NLHN;dmDYz4Հģ+1t- *>9pGB%NYBz.!N$NsJ* [?o@Bߦݤ9]~/?d{g aX1/(/y 3Zwp=@R D jKT iuzCc=a@`L+D$?GBrw`ێ2_'=(|ڣ۽tm;Q%z:)uZT9}󐂯?ĿO y ~X\;:gPu{R\_O3M[L{7DEqQy{%( vRPRP{kʊu9FHkj Xt}aR+.W T_ x{}"W(/Q??O -!/r+ûR<woB"P 6etY >S90q3Prn+|W7]fV/`j)eޯb0vtctRYf[:'ӇG4n [d@, 쁶*_7 ZX%x9bC$&dBXjE(Dpm3i9:YS+^:yF8xekQ ѕ1I^!~BM qC@+n] 6w6lc *2=2a=@'b;k ^эCܭpv;wq Y&NqV):g ӝ xSNffB )(yI@DIc^LcT.ƿ{m7&UbJ\vDysPr n[{_½LzEG=zUK(Äܣ n83K}n([ +b/>P`os s`FFeQvgTHMEk~V*-3zP:gXI(N4P7];R.oҀnz|*zQy dZXz65"?րt blcaEZa00J݇ZA7I+K݈h@N\׮T'0*?5dKS?)vi!<1Xk̵5.ZzZZZjUZrZB5Fe˴FåJFӕJ\ۊ~LPfm <(ZC 8L7d v9ygtrlWͷ.VQK\õr!tB55\e4\åJ4bN:.V 7p@vTuBx4sʯf5^ЖniP KT떆 ꖆkU閕vuKCuKӅjꖆ˖閆K薥6uJMل~l{F2F 3J#ҵ{Wʃ vw}Plג3& PwE%:2K-M{5 CW"p# I56h>WGGX^4j 4\6ȁc8 o]ƟMCJr5fA7@}iuYl,{z^|2 %LHB:Ӭ))l낰T{O* Vl"5 ua(H!yvS)fp3c_t W,g(SZwee7>d ߙEXeˌl],$þMM]vVb08O/LDe9{ƃrx ãt :iCuqgI  *(>i8vŁG9.-A&4vC07"cK*h3ʼR MrW \(~Ձ~}Ef#2njC"f߽_"95VŪӝjjb8ޮ&?s8w𖥙)3NbGgXMT<*` !m^)Juu(KTꛄC#RܬSLxCּ9,5D&!A" ~;LF'$e73:qX'ɢJlccGϾ^@k b)ʗ9h3jZnD/sjQ$3Zv@gs2p#j@&}^&;rOF)#씠ɜ5"M+[u{(H|C|7'՚xrjئgL{ICphy (XPyixB! 8qAbr[#P~v4CHek yM}lCZFwge-Tb_0ן]K(ZQ2)Bd .Q},UG)oMv2/tn\~Ϫ\qwZ]N@ 9A'סߑ`/V vbKϢ1v! [Z[DL!1=ۍ·mG"еMC0zT(HF^ݧ>N2vvk(M][*3 ӵ{|Gw)5Bg\տ>ܹh䦭_ڣ( ۅ`کۉ篳O…u2&]H6Ҥ(ay-5P ̓13RImrKhŜjtTrk@^1'cOqJ}1Ѹ2^&d o(W&|K @u4vyH:6ݓ IYҁ B:*HG]dW\fK՞Hu E:R- {[~MRL M.Y 9t.؍aώ]#>k0_j[zB{.#{.lƫyk./p[_La .?޼]k:D$v %3jN3u:HemӴ糌hհ!FYsys+T$]Kui%[~|-STq6*(eROfqpv"`8O2{ ӋވOsAj" B!?FWDR~yj_LίTRuy-=qVU1BU1c$&C\}kU`v4_\ܕhklbs]m+Y30JMrNKsw=ga}JmY"zՖᜰG75PlMfTMǥ}DNwO*=4s_C<^ruدHN)>xo$z[ #Y@%\'H?L`3Ø>C#JisZxj>G~{=,ADsI^ji4t7ۂ8]*:Q?cw>?;m輣A_Q xgt4ƒ?zjE}V-[dURL &;nJ?jQ?Z׫:c?HZe(.T rC\VAjC9"sI|lE7jL~S^N۰Ot4hOc sm냯~ p?qNi N'#y柎&N?bs r44PLA7~}ؚ75RekAIj ?<>vв3 YEW`w^DJ594ny3{ic &KWlG L4.r=~VׯBX-P]^L"~wq\L7dZ,h0CC;<Ca9em|X`Jj}9eO^x=$M5ՖDǗj[&_FY*ZѺĉ|4>f{NC/k~Joیv7>lƐ=%d s2Ew0mϜC%ָh_X[<lydU\΀ͫF=XʴzfjF*z㳸I&'kk/ӉWh!bWLƎVAbS}vWcݪc_ Ъߴ+W6ݏx=ć? j1F[ m:4ZoF;.f[o+ cM:ܑ/rkM#7x͚TV }OB0Q,H5= N_]x EL=f!vOOn48*ka|.?ĶkZU[e2֕b"OF]hw)纈]lhT~6bՆ+1+G;j<"14ۧ)ߦ%\rFǖm.jgP)`&yAyZaˆ2!qySLk&%G~~+IoYKEϬit}3Яv<]9!X.B;=? r&%~83C2/Uީzಽ̛goFκ3skZb]RGkNRfE?NfLu2.=Lؔ_T6^BmG҅\>m#ًz0|H#ȁJ%H[Fu1D$G/}Rdѳ!}T4| Z!cTDgN/94އ(* XD5/*S7ǫP a'O.YϜ?V= (^"dW;YqG 9!/Hy,Kq=Ņ_i^;"#kLqz$eRڤ4xɦ}.A|CSgs#2ʨ j4f>S,By}\M_9)m͋ƎXk3n^bӦiJĽ{L/1G7[^i?_L|X{.:[$݊Mܶb͊C McjO=s NAk}w*,.ohm,fm7;ژTށ>sIO-Zw;޷Hc1o^{`̫L4;EH~ (|ǁ+{]@?AfڵLMJrjL{?at8)7o"> Co'01"8.A_A?gtW^roIʯu$GI1RZ_YlvsQvǎ!umcd5M呁w;Wb(ן]7JK?/vֳ*P-r>ߩBjJ@0Zo6USu츧n0G=kti#ѝi!nWʇ"-j"k @8at%y\F&`.91-J2t9ZfCW/Ǚl[?8gIn\9 /q&N2lޮyqQiLS"aU:k+q(ֵuu}-)=PM%'<`&T~ECMWLW*5njm˚vr ݜXg4((|ƛjۨDPuqWSɦ"knW"5o9JQQ*)ڭkc%EK35VRZ)5GY[xDɵ&y-K'(n@;'~X)c"DҕESU J u5qЏT~#(I07bAg]o0y_AvwŐ~7̥1+FP?m/Ж{2sROV~ziEm{ >$Ay#Sʶye t,E׎9J+S#"\R*ԶDCпL[$Ǜ-Uݙ)4DǑ̄=E}/nvb3=]y%˳JfXZԕ!POZ1dO5lzFGx(jǤEx ,\ I5#j~΃0S?L58gJ7I' ,y?HxjR4J`R-(IEM5E\K^dȷܙdfq%Wз^:ggb3ekȻ3{hƷKI%<SOى,{K|s;n$J)zSS#9.ZS_pQȬ1GR#%:\7yZe\SfotGvIkDxoKeѯ? t]cU-oc5w,JJoDEOdO[+rXɋT@a RڀЭNiTm ؑ g4EI5ZAO0eyBqϣ‹uvL')3bܢXOϩc?E?X+Aĩs=q@)3]-r#%a?lgzzmNhD{8 yc;fiά;=kaKKKE{KȎe<2^1\h"VmWlH\eP`l=M(:$S7Ѿ:}a|uǷ ?j-i3SKO~3B9s9>`CC*E3򦻄Ĭ@R3b$HCOOR7$WXwFo'/IRAkQ87|lm }޷Ν>#]bm[U1N;I+/جd1}E&"_zOJJѩ랈,i>4 Mu,4M K=`񱯸ցkțmHoW+ V_iH.uq3vfv*Vi|'⟔.箣iA\Qc๞y+ח*2v}.Nots+2Hv''JNk\p64UH cw~)[Y%>QqDt'I"snF>YOƈtFBH7  9Qznz+w$@Fi lmczȏTn[)W(CuNaNݪML0i7sjSs~ulF/rՏk&7>,g#醷HS{o;sjZxAvgQ+&,#V({ ȍa?) lcI'V. #,] qR#RQ/|>9!KB0& U:,#a\DIWE */~/ا&*:Tp5UKa^P[iҝƣeBBHQ!Kn}!E'>/هBs!ŅV$(*C&2(p}IZFJ\jwr;C-z/5ðqd-?;fۈY3=b❳BIv*%'twqPżmllu=Di 栗)+|<'k"}ހ<-A{[̙qf;#{?; "?M[h.ޝ[IЇ ,յȺT$bWD껧Z(*콶s/3IjΓ_卤;eejdίǽtUoˇE1+6lOzGjTvjPxȈ.,]5r?N+YCR$ oQwIg8_P(حl1v%Im=yV@O-ʼ_e2hh\)66^Q]dvF{QvT4*oJ?b"뤓/n۬Kf4g|v)jkRo}Whh轅(-2:U.E yM'MeD%Bv1ZrF-5Ax7ZDX]C[zsKtvaNa so쥥y뻃(K~Ҟ]U$8P|%j}2180Tduoxljq aSH5[Z1-S@j] ]е-xKc'n&'yض-͏n,ȍq9 :ۭ[eyf 6,М wmS"buZmj v\5uۯnm$b^m.-n-oE ^vXKMAr'>*{!3e?" s[b/J'm'6Cz _ :9$ ͬbͰ~kְyɿ4gYMHP>0l+PmvR dw_vYs5b K_=rRʸѸ=U㫽ô'@ 8x1!Z'PU\^ag Q,9!" 9Y60]e҇l/ڒNG&WjKutYKc4QE Cϓ جOL7Xq/DAf Vf7sJ"ٮ(?( C,lc5^\e^;& ;Xh37M{iBC3p}`Wdڻ[ʁ"'^vڵKšzAm]ZwkU'6$P1 8CF,%EZ8D 7 ^5 qp6ԬђvYzV/. p ƿg5񃜦ƢJ-2.-a~6xe)B_j}h>Ei˗Fʔ2y1[lۼX)xa#^sAW9G.Oj`nv;.yxNrzEN,*؊*M3XU~!H%a>`tI҉! JW\a.'{ii ToUb~q*.m[@7 ٿ3:ڢsƢc6n2oFdw }λ AK:v42֌7V՘wb4rz[Gt bp9?KӞn$heC*>\`nV9ڳܾ˾^B89>._fraY"2P&( 5ӓגn~z!jݰݎ Jr@b E ?|d} kqK]KXfiHfSnsؙlfEa&Q,{.Wk."h(f^lGOCѰNZ[Dz;6}j +4}JCXe ֵ2 mc`EUAV6P]P %-K2<3cpxw7cj)ltlS]t25%3dP^"9 6bcԢ LkA80߲Vh# m0 64puKnM7u}Qsk[\ȍQ>q;kTzgH)%^ ~![8k g RI]Y|C$j|qBrSkMy0_ ǔk8,G|,HBڭOX2HJګMIYXXDf"B΁ĤoZcڠüm ZY[aE5TZ8^ߊ)63,no#l`�$߼+f#QϠt:9ҩpjkՉ띩ApS nYj] ^(K\N"〽ͼ𕶠lIÇD=h ~3E mybX *Wx2'1̲v Z 뀔֫2ήZ ӁYl*yu6yq:AcgmxfP7 ON> :|1#n=82,]VaeL} ?.c ؆ !;(4j H%tsƋ[!Qy>n؎<:lBb#Z![͋ά0Ks\cxળwx?;^*o}8xtD࿼\>#G }loO` 1~+I$w?XY&;HM՘ 澥ZCίA.kE<|iZYck?=-sn. fVc7? KK i.)eNS&Z o\]!p#SN"ʒ1HE N6yP©|:a`7Ysܻ"Q9bFqhTJ$zp]־jI:$LIqx4;#ڑ~TjK +&%iBh:6aq6fQ,sɏn"Ɵg"ܢ,fwR> s8hհt1Y'=ijA$\/m3ҭKt g+s-W=fƗnS^Q,zF/&^R&FM3չZA&"@UYNsѰs>iJs-4S qlf ~W/A(wP{u]hne2l6qP3vuvb{#ͽYXLfc8k t8ːwHeω+ ~}Wª}YeB#U`ҵsY_ȀmAʕՅQ׊F4epVNM #*chԀluVu3Cz%^m7~O1"b <|Ӝ~'ݢJIƙr(o; X*r,U-:kI2P_KNuFRVޖr8TĂ:z8si,f}T^զ#Nj(<ֺ.Fz}V*I?Il..y|Jx -.uShbq-Dq 廨 S=Ko3$Sn3GT 螠;rfʬ񵨌ob|܀)]^.*^ Д- ®.pm4l|Z6~`Ö́0H#~w?1ף>ڞptn<ϳsgk~ps꺌(NkGQϜ2AgroS{k}2==v+\†A}bSY侐bK.kv =v@+m 9jY3ÿ},NkxIW6&_YMjjp*o25SaN-q~Ũ=;>>h+9\(ގɰāy;p;9w=jj&B@Ϙ>5zvޫ5q%[#"n=S˳(º+G)>Kq-qMw MT5_ykTDUm3 R_t 4_݁;Zl ݼyDryKb+qEݬ1ȋVŨKa E[.M@,_ Jfؚ~XU/^nQֻ7vɂv2jn"(3T{9`hWK(bTQkgeVF;tۆ}n6{N/+snyy5d9QX\Y4+.'%Bb!_N'(*h21-=a]T gN#)U e%@j(Gpy dhYyt=7[)+3n4& 7V9X JJk`'Ogqx51Tˎm Ȫʟq ^;mUgˏdST}=pZ?0P!iO`2>$|/`?|{PqrdtqPH `E(-_4c;?ur^ ^|,'Q߯͸ ̌s‘9^RpDv4Ԫmc&ڥ(6˪lJO"䅹XZ=z\>Km]}s=l_? RC-F?!3q4/ɏGIkgc`l{)'?tyv3Fq.z]HbQ0ߟBmDq2 t#'صl RiĵjE@n4O ڥZWSpTAԡDR{g 4rft77vE:2x!OuVqQkR_|?TrQH.wj `];SFeSs ^Z(hzxye0[ExM8G[4ۢl34-̼݅JOG^t歼9 lOf=GaYVIC'W]pG7KEutzfѷ :'Yq1OؠNiJ"J8An_E'Wu_u9SUhCU0҅.@{7>츖ohY:>lBj{IËKVz[?%S(O$~A7V,`p5'BӜ/(qljڂ 4,@k* ޷^*AQ20X*#:#jI--![\6r㷇Yg6NfzB⵹/,{Wuv[W3s Q?z" 'J}KY 4 PjbNڒF讞E0Z=gG*G3!F@sot^E`D4 K3vt Ѹ0OAlxH \'M{Y?Ob6hB@Y/0$K<=( ,DBf4fcTI kۑr vvE#~Xgw $ӥgA>":cb/KЈ1ysHTqeR<aeQZ|* -ÄB!wիtkv a2~l7c?|.*r}i"˓~ Iz#҈Rբ5ZeXi@(wX9u%K⼦뉐VtQ4Dr)]ͺ=99LܑN>gOJ-.{}ۛ׬ᖌIiJ+vnjs 7'FDB_|XPviE'~,P4^>Y3`0`î}qa""^:Oڨ/-\ŋ쳚Mn Yve/o')zCV'+؝^4!׈!qb2 kn~l^$ v%7XBZ9o?lOto7XfDER'z[j0B5P dUa2/'tTlJȽ=JˣTFu5\yaTI+&}fʝ>"8j`#Ito04N2St/YdGi޼;fAU~{Z3w[u;> Lpp eH=u1 ToSk=6*VOlK=-/H4pX4cHd(tXZ E |-A&HXWij6LZ'alU}DS^#R}a:c[ԃR8!48,aU#._tO>o)!`Zt:ߣ> U[SR3 *:}tkr]LEܢy+׵\` w/]oD2ڝa~Q#{qwL *;A]lzj\K J/͸; A'AUh 3_#4]tUbK"˝;679xo^f6 1 sTnu]r~~ ΚJ昰Sv{pRݸ|pyewg9ݯCýp-8[teuomEdiwEw{W,eqh7ǣެM -BI|yw(I☄i[^[ .<}vE﯁+SݾwyhVɠº4|,<JZ*4j[-O~kNL T}m@sd@/?gצ;<;ng65 UC+ %3 f7_KLYIf绚ޡ# 6@fgi,,HNB;gj;Yt_=r4l=%(2%&DUJ};ߚ/^XXAgcȽ?-ӶSs$z|ׄ(i <*֝q)MX9jG܍ٜJ[ۛsqHkqRbgO%cf-3o1vИ4vΗx,.ibp~xNzΨ{`,:!= 8P\x\{ v*}'[r77 0=SN E#̓g)1P 5 JoZW+Z%nl2],EUP;&Pӟ_#I (b Xq=H+5C=MEGA""Ё#`i驿pN627wE)4ø(X't6Q̧g#>.Q0_^uKxk"񚑀xֹ$A|?Ԭ|6Qn}=k,/@ȷn# }CE"dؽ j+c=ɮ X7ep<߫i5pO>/%s◪4[vP38BBrcgLn e6@b$MFmWD{>Euτ-- k0+튟P9[L#jSzdqw k~>|)|=ŮlSx* e(܆,^#l$Q0HKHN0C#RR ?+Іû SӁЃRZ04^3`.+{,*~66ޔv9Krn/K֩n7͇r)tlZ>-j0́"$b$`WI$XU zd.*>U,~qޞ[\gBv>dRP"P 2WL&U4lx6MGBUvf> ٭\'_%=/:v_ &sK17MّPSD:Pg@TZtP de-4iF* 0(c_O)<@eyVe )J}*hi: xP%[RZ4qjFcr;ʑ "}5VX UtUzC< ղ>KQ&~*4K=rWE]o~mӍ6<\t'A;dfk ZG\z˥QԌ+ȆF}w~=vqnMi{G@nx 4V 4D]u1:%RFC?";Ȉo5W ds[}d~MHƚ1Nd ߢ-쒘Jm=ξ ~#6(O{uu[Ъ/]w3$eDIQ0]hd% 6Y!= xa`=;G2LO>XM Yzai=tQ4ƢL:ors&].\zޤzh žg՜2A:=6_34CUc9[M1R2یK5@¥h<66g |9TFrCy^H6=ʚ5z@larDfdqArOlRFX8yiږ˥R4}bTiFQ Ճ^3U4*?tsy&0~d@k҃Lg3WFfQ\B޲t3!M 2NN\MbNKTm8C彾$eN4jt*c,R+"U}[lW 1p|n/X ~]ꊦt waoJlH8 u _j ^Kٱ,-#W+;l-WޮqK$͖ٹeRdFKruc=javMA˽Fg\߉iu`Yg 9p_[|%5lҗM'\@6v.<:H'qS !DYa\mj\"E,|^Q$xW 7TDF ;4ZNfM`^)޼6Dž\p\֡NЀ7Xm@mb]Kg2oxUU=TQG@NS4 l:~'oʐsx9o`a!nvȨR=50H˭K~=3\MF#X |Sʹއ;lwU3!R% Q#UhzB,rprR3{WW" aدcνϲ~6SL@":Y] (:^eZR:TBe|fHYpvj -ON<ɕԮlFgR,8le<́K+8,P5=㼟$ʛ7oMN/Xwd˧Ϯ{Q&a){OIޮkqpϺ׎'Y?Xv9ڿWw'[3z\O7YS@b=H BD/?P:v k9LĴdO=T(a89vصs>yNЁc|0O"eľ>=mk'g*& n0ryl x_A0[."2 _wg*1_o7{LX -qT"3Q9e >JP@"[Ro^I*;US6hj}YCmF-Ó0ts$PgUO YB9)謿i?nѭ,iv9֤ցehr@h5m`Y3mPqA*b>s:0an~t>3)P{f0#ЀhJp簟Vr6r:1{e)1S9r i/?:L 3:l`4xyxW(rBbyw,[d[-Y%ى-[x-q'JuwuwYUj$a "$# ac!0se90oX]{{nk 6%;mSѭbk.g S>URm[ӳܯCo/7lJjTɪ ^ŒWjʻƯIRZg츞 N#j^SiyW.~.nm=YPA.kBW{SUgKm[D"X}3W@Mdq^qp]jAP̂s9=9.(Z>2 Ы :@IKʇ0Qa27LHBN( 0U}Te/{r/ VG`;J]2lEgƎ@> TN oN?Xq;44W5.@tAW{>Э|=Tk-o^U]IG;>L{;X b%.ך7k*gȫ0g} V`[*fےcsr{cGEͧ_{:&+oxD JW]ci+@1S;gr \թWCGN;Wa;v|T4kLRSP4L;֯ IK:: 堪bf|&U=%+X#jņRF`BTڲj,i*l^9oK+,XΖV~=g Úq>f椦GEZחI ΥU˂S6|y iߚ.E߬Fj4fLU' Rj,od8 Y& ,ivV3T3-&8 &Aes9+'LL$n)ï9Cu R~U5638J5陕ۺhIF訠ZaD oYCer\0ʘ+,C&/}Cy~ح`BvV|t3 1x\>jx{I> hkNjt45|t)T376mlf$0.` `=>DCe MeoV$Z,I V|ۑ'=7yUj\3+2zdɒm,Ρjrfe@ܘHJx0,kՀ_=_Y8 ~牒~=J>}(HPull5frfՇ\8K 6ʯ*G]In9Gj: ^;%-*=qpiS;WP` Bs'/-r95w]5YB'C?/ 9M5ۆ'34xp!@VvvUtdrdU"XNSV2܏)L亠MLcEdlP1eM:v UNi*EBSٚYY *9p{5R-4-ͦX*6J`6. *V2J9@[ cR"g%!eփrt6)RעH0_: bbQAtDѲ1^ U\~ue2S 6lO(,#]  ۠ۖc!jS8z_qcS=BVKt5T0> CAzݒۘhR܀vыz[qp= lcG#*غ(YЇ)ށ(tn3uF n֖Q@HP`fYtTMk[)H^\cQ@ei,xCǓ)-7ݕw;6|440Au@#O 8_TJzڔ a{ШG,_CyPVHA >za:H3mnjBgWm#v>ȍ,4r ^5 ?^4ie s0lԃ[Ϫ}zMuےEתfePĕW3iC}U{0 WFw? kpF#)peшcWc܃j:hÆ@JyNjo2j Iak_vF%ɧٗt5xK/]ȡc^g$yݹq~$-AŨPW<9PEFSF]p~ybS8WbǺo];hk;{Mt ֪2W Idy'o1y5L=f5 @/~5.I֩PAkD})]Rp)_ 7M WI"Nln~Ө0kO2 ;W,4b譂iw5k{cwGH]{ԼKӼ:YGlODD7ѫ6oX bF1&qHh7#OT>7i} s4F;To\y[: Fަ9-Sd}2Jr&FjOyUN}D$댒ROo\qH4((Zxێg,ص偦`փz-+~훗VHO`KǤUϼcg{ڞi脛w&60wHߕo|g9̺w/☢7;.\/Ƒ{Ϫrtl׊ʅ;潫:+27U?x5uY$y0 (\U6l ;xb-9Fi{Z(D2H=TWhr!P `\"b9hZԘXKF^KM |Ƥ~Vv|9^cTׯYG*R}fkXcg+`U%fŀ.P8Ԧ5݉ ;FOcKzkY]>2E_ ԸȄYv λyf/ϕi$w}tQgJ7=ƺSL¦Nvi]K8 :c훼)Lf| Y0CErlo.t}9 saBT޺lf呿k8*vL*q5Ch?%X>Z|8 jf ؊#+@ ?/k)nȇ?Ơ({Dl7xH{Oǟ8g|TǧA>$!`*'R~xp\(y+D5009bk<0)DrpYt~q#޲F|^ ^l8><gNa>Ӕ0x:WIJ)" ;##< j;~=f d%~],F1 NA{pfϺ;I2ąEfޤ([fWJv{@ cy99"UAlfزR6woGKQoHOYy7/fPM<Ǹ[5S#AinbgQ.S,ݍuq: 7ɖdk,uZOxI\XgGz%r%Hq0,1@̋TpQ6lLt5;89% in\=򀦚Ua1$y7He9:clM>A8P=~1k|7_;r  eY hْ'=z:sA ѺH@J y-@2" F,Y$!Ȑ+i<{h\V\MjB1Lû<ݙ$/g ^M ~G5MjskxGC?I*dx(WeEkr9p]N:x#yW9mFy77XlU%G1L"1l ”l 3ߓ%SUJIp)y> mEP+T1@:m,tS¶qׇ[ɘL¾w\:غ]Hco;j3$To 5 l -}$EHߠE1orቩܜy& IY>Mm@NX)p!f[܍(,>N6I;,j0102 =|U IL癫؂ pa>re*"Q{}(L 7iW'UA-prC9\*x*8vʽOj>f|trsxkK"͘iHBPb;9'틹sq C?lHKS̓@ bt-h1?#$QUE-Dʥ=46(I~YeUn&{i{ հQ4 2A7s(9t1[ غ6?NPk)MÂSJy f; ٫x u(Ϝv4Z(j~4 DlSM)š;k 9GRh)hBךB0Sk7=:Vy3<8ku;;7hܙmf=N;gi"e B&i{rm1W&1;ds vrL>]uf-A6llņztsƶnJis~O2XUmnH"t:^vKkXyjִ`%oͶcN͎J[bZvwi>iSe@f(el%r-o$dE,+^.x>¢e< ;7XPQؙ;xU 6xp_8M"wgiN}N}uT%tOp&mw>3=xLHӝ3'yߚتZV7#woNfn`^uW8(y۝l5q`u;!ۮq'Z]yxL(@0hy8rnESaW[BdVkSYYUކnyۏkO/YN{y,a=m7< 6f^b;l\'3`MKCWZΚWRTeO8 9fR@?u[G)UIC 8LRީ#K ^z}OOu>h5,@v{W8P' ]Ȁ K.w߰1G\dC[6xF5 qe2C[|qp^:-\3фV2 ~)Hn~9envݪw_R 꼾uosQF8O3K{༺[v&aE`SNN{96͏O^#@6,RKtw`?4-x6[U}sm :J5~Y+܀gգzMyPD_yH_,; _n_3lƱQpP TpjaPl̪B!|)iDP!1o[=kB o?gNPaH? L[=V6 n-ll/N8[08hIDj8fs[ hR#:# g.LE5ap+{UEw!Zt΂ u0 X=T5oتYQbN14?cCOMW'N{~y8L/}%<ıK-p˰SCOEh9NTQE{|w=Dn\ pB55wδ1Cǔ(`o:^3I`qRjaᄑuNIL=_i^gt!BZKp~Qd.9GZ:k D1]5~SrcwLv`S7ds*9`V{ T>hBz!{oα1p>o1Qb.%e, cll)-(;Y㬰*p`pj7ln5{(Y!I&Nq}p0֝'@n l,BELH"3y?49_`E9>BidFO.[E?߼r\Qc2}fa^rew4ʖ8~f;K7 Σ/Ult<.p.}.%z dr2 ;_}x8fgX;ٚ}0&7m8! }9Z}NA+Ůk8?z=rիT`!T~[|+ٙ5j~X*vW9} ?U0Ϳ-⠡?a˯>$tQY*DMNkYW_-kSǰ*^a fb #C`~}_,fs::VlSJюHg7^zv#Q!Z~GY,PYpgnGyBx'> SmRM2G@?g.l 8G}#]TT^pFc>a*?ZHUHܛ& \׽3Z_kx_eI/qنrtA+>fe!}+X876AAZmZr>|;{} oaM ~:K{ kYl۾4z襰]Y.WF.[hX|Q sJ~_OЀq?ۺ0Uhz?- 4ƺ7KG`$c~!ݼpwmRyl'_6ΆܾwM g*IXΟhN]d_&45A Dݾ.GI{haMݟk (2ڭeAd?Y*@h9<[5]aL-+$2V,^&ŎIg`>w"I%5Z*D~ 3lscSwy1*u3;_ $jxZs?I[L8IvtR;+cBmo|^ $L]8"| QiMUL_6'?81qjAѹ-y FX%aD"adEJ )lGm\Ldᡇ6O[]Mzycfha/:;?ϰps\<}p|>Yn[pdt3bsD! 9ָ0@QI˜{>wdظhD:˿K]9;cΏZdN̨XδbaÝZ(M;vXAlJ; ͣ˹~Kmsdа2{Y+i) %J/G'8 kt]ϰb/vtsv9W|%9O3ks[d:0II]?S, :kY=օ:Sxf(`enE)sNS7u|SF[5plo+,8D9%IQhUzہa* PsdKoEbVfo3eCd&Jn΃ð%tZ~̬r]UsFxU;Ū +*RnO)N5]` ZhA,u)3½_EFTQ% |IYEn9&p5@iujM:74۟a~[9Ңw)31:X1+y-񃾫-y{[nMr H}ؐaYpsņ_8=cX?,% #A "SP^-מ-X/Ў0NoY}Ryŧ.­rT cp>+cҎl1^5bPg=9 x#@76q6qΣ8r֭| I6؉Ϩ`n「h߃ =[0%9:cMHvr6/#ø2]Ҝ{*7сx̃7˜!Cgr_Ω˥Dk>=i`otKˤ׮:5*f0(IŹt)Iҽ i`1IW6~r6_!YRxWI2{x6H+λŝ_nۘt@tcmNtƫ@#/W9J]A t)̗sAt_9_)3> -w$]m~ ܑB 3Uc,foxY=m)1[+'_h$҂;@J.τ'of)'2dSe^'`]:}lhHpsӫFa O>kt lsꐎthߏ::f٥f{}t]OݶyȈ+0)k=u_-y,i . 1 %ԼvL&c8frZvH_xC{TF^a- ="4]IUSkc)ᓀ!#}GH`% I8% ^)vx6]zt%?$@D>'wI߿%<3H(чUr2%(kOt}syEmûHP5mTAIQZԝa@?|zԾu;>V:}ҙEn*YTnn,JxqKl/5.%%-[IsL9 m"rճWܓa!+ETB4?pPӵxALqԝJ`\U8n@Zz#:.K!ψ{؃ |0H/_'.;'KK'2s*U hU+Hi{#i-/FsVb 0lr1mVs,cGV4B5f:ȍKԎf"A:`f!a;&~s:JOg-Df scg C/;!0 Z%Ľei7~h\pIe<ܟEEmR+?aڅ勺sJu::%5=V%i󷛤$0K|焳 X#nۮʾNfebh#2Eg+ w^1tdF+$~znۨFxJ$=yF{CWK XꜿIoFWw3m*qDފ 9t3tvnYZ5P&t} &a,p?O*{!٦[ oƗW"GpjD:s(4jxQUn#T>*], yݭR\m6;>T{Kӊv OƶDkeyCηH1g_JZ3@r\V=% N2-rIuLSA}Ĺ HtZ: q"+e]SChaW2RGy K3ҲG^!|x箜pn8 Қ'UUAΫa=O{WNڰYq'\9's_F(nsgr*rC08`z^5*Xw u7Ե`V;?[^_$CNΗonVn=Σ cM꼖HEi3c n͛sjU…׷K7= P;azYZ>#1^]&m<~矗FTyxfEF5tyCyʗ0˩h#uA".'tUkXg,XCi/eF5[z"@z#DʻNt]1M =}o/&)cta&dy X t<4cpg0ux'7S_e;"#n7*0+ȩ )|"vP1#ƳΫ'J,/a@CqKԚv>۬DralϬL6AWJi'j?ZliH=.]^ܙHڻ$|/PZP@-.(lyPhBza0\J6D(zEm |8[?RE㓂 ."Emp"tNQ/OU?'MO 'z $󊊴Yq_8f8[wE"@15 wP3i{լLg^{蚧fۙ{C5)cDaSm{ibBKXMV|"1K؇^zIN}`|~#/u mV.CSkLmvp##5r?dϩ Z*PDѥwmթ`T' NآQvzԾrD.'a]~$wIC35%gsۻ_q uK8{#wY#ia`.OO cE|+eDktlPHł j r^/{w71.qF +d W*tMTZZ(CXV\<>!kY0ep5kn'H9!+bh& z8o,5Söt(W+!ڛa)Nf*3Jk'T9H̵Ӣ [!cȁHt^I`>N7Q3VxLdZTRV/TZ ["_EA;遡,{".(szCݶ7Zu#{B{<ю{Bû%^&y%d,Cab˨ҴF™ \wĮ%Ao9ʸَ;Kl۠E؛E5PSUC8Ym?t!F[SacޢQp<}3%P#T9ߐ'vnD3!aPѭ/ɡ:~ !4#Ӫ |YEZͶqбPihf;MuauTG_zpPe<#u'62̨_S+ y_K40i20mPqfUtk ~0-ܸCX67xde9AטܷjyQ# ;z~16) 5;y8qߤ hn EzAM(Js࿻AB^v-)Qf<¯~:Alq(j"*v.e̝P"Õ2 BKA]GЖN(v&Z  ~w ݤD4&5z\*T&7vCi<{hS#DZPǣF tMZ~ OG=z\oZ&bdUhQ*fQh'>d n%Ť\\*mquuv dv)|LV% \AS͠pMUN_@ʁL}%e7tD5\G@wCS%|y#x[#cGA΀M`u@I~g䓪 2'J\31C B rxX gL b*6{2UZi^j:eEfD.>HUPc@bOTq|Jkt7QT#RdVZ՞{KѮI8P1|eny寰G0tx_yE%*T IPՃ@\ ɬP-~Q A:u n*c6DTR)3'd|vnsw I|Q^ Fj<וNpmOYXIrEyWԖHRMV@5$xl5xl%sD dD)JI:n'=6JS9З]jLIIhO *{Yoqfyv&&g ~Jr UM<^쬬I <%pV"*M HJA@*մ)΅lm6FU=-1U?\\ N)?uʁ~ytZhax%:1&RyXwUGVtܳW.0 :2ʸkxYrEDRwiF*n͛axȟNiKe/ќqW1Q瓔~ṹ&%}A";*T=$˧iŒ1+iW7r)_Sq@tMQkzKP `,RrM-/Kl]wCa׽(=qly6J\QI_"65/QI)+!zE (R϶$Ek:M{ԪmU0K(ąn2CE)煊$+ #A81  /I`QqVkʗpdO{Bz^un 0D/lno`f8t!kC~C[ₓP !ުp޽70i0 , v>oL t 'z{&i8R{Ҝ ۜgkT`L-{BE(~J}lpVnI <&CڼDm0DW,s/޻+pu}8Y\ܟq哩LBqS QqڨOaNyn}$8K':>\N9*ߙu :%jP[+v ^Fϐ[7[J'{M= ],*]0WN1A?`r:ʁ>_qUBZGPCW&]§s*M =M$n\|O8>60 D Kt[ k~}ɋcFR % X)(Pzdr潦݋%ku;Py>_ x;M[dWQɕܕ8mlEw1c)udmt9 zlnFܵXdroׁgޑX0e DX LMkES'5ݔ\*Eg Zy^h$:_*W'-])E|D ~7JT b+\|Hd)k ykMŜL5 MhE|`Il<mu!yvŭJ&Qwˤ ޓGx0\EY\x޿,{"`|)Le^u42μes?OZDEr8nMFJ895;24{ hdul^k1(PQZw%RĂK˵"ƕyx!jC]l)$`CP h7c՟RB+u"hW,J^dca5)Dk|۲g`;JQQ{EG }0vQvߚusA9R"i?ViMMU*oy^G%'bt-Fś̮'<* [55]>hfy~ CVmK8|"]X\/3zxQUhn+`˽&Oy>VSE֤ L)$Ffx=yPS9&XvLeҸ xJ%␄!k5/]h,Y7zYd t2+ʭlG鋴rQB v+ʴ08B4˺-? 6Tϗ4'sx\V¬Ϣ{ȴ/ǬV[ ]8T,x} xGW#;oY-ɲ$KitK>uYvdٲ%;Q.5Ӓ:333vIIar6 #yڅ $@Y{Us=]իw{~KyTpxCCG:1%j1EWc/b*BEWP_WWWS_$ F* {c %$rL+AxD:Rԅ IY=cQQ.j?zg@06 m^XڛZkꚌRK_ ED=υwUT3$v/]*ϜQgDjxɕ8&*%C'"kxZ,ј:&I.gT[J? DSZ?:-0zH_AL(*Fo 4U"@{*8xGHjD셮3㎕]RU51s&9SU~`ZzȥIAJ$QWs >L( qyL[% ,Gdpu0)%E0}jL8*ߧb|$EI0uHHL~~:RQdE'"0Z@:~ ͜9 C"qty椬SHQaLRa0P Ja=|v┨3=-4 F8##İo|=3'%UHf~pBSzI$cFPl椚bPb' an]hܟ_u?ve/KwfZtxTc!ATq7 K'$Zz¸eπry9ą;8u\0qpIb !řǷS9:N{-i: pڰa#dMH!@6aEX* gđ1URDHFlɺrYB\aoR>o,h-UGI^ GDEɱpzO?xƚeFl g$zV&% =!$5*kS,A\fz,X|C_sсy'9qqk>)ɂC϶fY,s(+3"@ y]_HJE͉2)p) P zw a&%%S g>W#5X9Dtjk|J) p[@TSUe,8f\z}hct+3zB"9)B:B߈cj.4TSC.BccK @P,L&pN[]sjuf5x=>h׸o\J?C? 5a? ,NB1KcD.4bmUR9NӜ T7K7n[3$i7`>.l4 M?пBHJahH$[Ѱz\LQEQ1$"J@ D}JX_ET_7~&@rH(9 k:THbL)t]HOz MH m1U " c(ZUz :W/Xl|iF]SFDDoʡIy_ʓQ@#Ġ.GFH & DC*墪'^p[CuBy̅ M#RJL$)*-S 3,2dLՅaFE3 u1 x^9$7dp_!/הbKrp QS-*PO|B;0 !4}I`lkpƦD5 SpbRL()KzUFMfʗ.9r@Oaz;-ņA i{딾Tl)[`e>l~i׆D]4vvSM!TUt1`2v5#i޳x ngXg 3$%7Gd^a&{P 2+RLI\G쫇6U ^8Ņ7l[zدоo`KC6م"ߤ |RcI__ 5k.2p\ #E)]DeT꧱Y r~=50tK ǰ x+iP[F}w8O?EABVܗZnEЦa`tR_=LIWFʌr~G VL A92N-7h47+"f98}* @²cR:TDe=BS״;|2> !$/yuB+VM*.ӧD8hXநD/͇=Q;oMweYQW5s0L6sWn.A]eb1RtƍWm?}qR eΚ:Щ†X \aF9BFqs3uuϤBfįi.pNMn^ۃ-9^[㽄βRoXz(L 8c>O_W޳ܱ ݻ׉5%UX$th2Fcnɑ o,TfCehbq7HebXҲЭ/TX!fB%^U]I ā1V[V7?KR.w6P?2 ԸJ6ErvOOw JY!5"۝$ōf|G+2gUΡlFc$cwǢwu]t9x]/e_9PPdg+׌Ht!4gו˥؞UܱNomY9}䤎^t p^om`jn\ӛh p"&4VLʉV6 La9<8hӠ|-[Y8X\sr_ґxdB1Z[M[N["6DӶ\2GD!iJԙp ] Ж8)4w,Q1*O -v%" vwÇO6Z OE/v솭]$P qTye9Zg6iMbRo|+EAז +𭃝mL->e]u﹃sG <1\rO bt͍Yfe[g_zFynp5txܹOa6g%+μ$70IΩm>ɹrL.厴PT"u]IN>c| zl& 潫oUhlP1*F4BI{p~""TD݃ۅD5[Ύs2f7#5;t?,z坱s =**N>EKDEWvirڦHSo8&lK <"Nﯦ>֩1vW+(M6Nt Q9)@h5"*:hNN(,qEerO%)@wwuwhlDW{H;vWJ4Ijh85,cQO.MrCyX>F9uRȣ㽞NSHPزOәxq%{*0jôǍ=#kyAAo,F^{7ܽ`Qy$Dov 8+n"wX_(פ!A|IL#Z`톃- c=@sw#pjĢ}:Av%#h a />o GF^/0Ϊ;jkWCgabg?qu1tQ'tneWdX4=-Spuv\ &PѐDTXXEZ[:T+N^Gs肊iI5 S7^;jaRVa"4yj. cBʷWUx:q^4ȔbL6y[p$pCʧ5aaer:2N\D=N!"O@5^0t vd`J,؍goק؄o> x2Q.{kjst:g vϝыڸ"N-"fN+4uT5uT 7Hխ.+c0 8j9h48KU$+X z 䍈,^:4VbrҹAFGd0%xÔk&i'⊘:sY8ޡ G]!Y یR,&MdP +Nt)$,]YCZWb̙ 掙Z+l `ˉ(Nq4Dh(01WXba/ĊqQn &J4iDNE7%eף ֦lz_FIvrV. IIWB:6T](yx!8sf| ,>i)4dLe'e67IAx $T[ߡ[q]\'QLaU"T%o[DM1jG7C~l_q`!E@/„z{{+U:uSnև深4p|F&ZUF6oTdɱ#F>~E7,LAv 1feLљ&aOyϹ2Ro+/# xañPz\,ޠ,@;"_Z%18ysuBk*yj Z Ţ;va /)9W` )s@X p4Xݥ|+{z0oƺ:cjl8 GIJң =H"oҴvݴ4K7;]Ƌ__mp c;b-"Z-UM7DBJJ2E]Pp#(":CFh4翮QAXIުo7|V5֙/!ی_ǖbpe48AhV:@+@C U:;fk?8գ(kuLbmƶzIywׄYebյ>k6̘ɸꫛ?h0r'aаBltiN] Шkj! M4NQH%$|}chE :RT>2@cgX)Ɵ''fsA?t9TșA7ߩ7_Xk;+7f*Kێ&qU@D%f0]\R*ZcwKEؘh򘜭xAّ`,A1I "c̑\eR(PDNBH lHo Ât0WE|є0YX c[]I,[]tOR+0K01A+i|+jwg'+I]-فt*)`NS#cZUJ(f?h j X (j(̚j{k› r 4\ߛpA+I.{' 4:%eِ\]Wk-"kx 1J+?p[Jc p$!ۄ>N9::tUcQ@FaK>9:t>i3GװVP|[m% f|R1ƇEU&tX6[ECXu,=Vq:\ &3+JeCmz ,M/X| 찕IveB ;$i'kK5gjtBvg%!oSCioLArbeXU;,fx,a LpD0H3OJ XTWmmI {-h Jv>7q oYԓ: nM9W1P5iٝ#1]ԥab'4z* ek.|؛/1hwOU 6b4{ vNE6Cj. MP%`u gȝ1%+O+`꠨հ /XblL' 6I)5Gb@JL$ro&4 2.:*%:ے}YzIֳ>]إ yoX2eKoprA)+97zCs .{*E{$ {:B7˟#fuq{\ 11?˒GSԡeRp>~sp^~ 2?8taJ>\ {9Ʀ.P#=hQ'$12s X0؉]V:*E+]ՠi-[@yu-  V. 0^B֚{bjK.%kzyZ>~Ip6r~tkiAD_kyrRkmn6_ZAzd}^OX3jrRK[IFwX{cujB@bXE6GTz0ҹ6Up%uFV._[YM,FԮzjR[fcm[ty\#3ԟ&W5-m]/_' !s`솯M)6o [5.͑5d_^Saɋ@\3n kI kv;Z"mQ 4 Tqb@v)"x6 7s'q-`[c{Eub2GQo,hQplfudAb;k7`[Iq~Ҝռw=)]:d17 ެ@C&7tbڪ)m3 *!;TL^In ᕭ*?P< XFRZ>l +@J {YLq tCE7[EсJdDi0ƅ}(u9(oj! 5 Ib*~l!̦ͤ}cq 0\Btz3iA_y2tn&۲*ڝWZ_}yGiOR f@8,*wd I8)31%Iu^ be%E@ʨZ5*&UkU7;ƴQ*4غ$1$AmO&T DM%t%X}b(*pZ5JIhl\Yי.%[VsqY yt4L']&$2_S9nj0B?i ڵB2i ػekm|)(n{oU! XDE[ɒhE^i6/e񞭤CQJ2f]!A'n02Khմ:u\dc9Y~(d efKYQ}¼PMoMf[edUszxf'kB'P} NZRo{hgWE֯d#,X}c)Y&Zv( #6?,ޘ9Cڸ,"Ҟ 3_c* [g_v֥\\Mu.r6p5txpH[:sti YH9mnƫ[jHAy([Y|?Y3 qٺ4t/iȚܻwA1['k6`#%K;;xԛp,<*|cd9 TST2ZI pn9Eovle kW_ǝ ;ɶ (1Q.l2G8:ʇv}.RJ9` _Pm^C]k+lGcûO".a6ѼIb3֭5~M54WEM3{T ,nCj*}%GPQVVeȯ1] X<( yl"{!9ų0*a;#rQ)*Nkhi6!8Vvۃ1ڷ\ ͳ]7X/6º*9ÝdYMޖdj"?x>\[Cᬈ\` ?0QfYm+ To~|/)^å>|󰯡Fdk4,"e  4)P}Wx`%q \0oG*҅z,ձվԴEf4YeO.Q]`[ x0<2R+4T.}Ä{I~Gqpp-HeE/|ۗl%@ncUi? "}g+,ܶ,6}lk^?Dn^0!r}^# CbuBcnUb!yv# 6&kIjL>/5490-Ȍ&"20cXZc(0|&c*7:NbH1=6a0s a^7HRe0#qߑEhN4u sL]7}*V:zC7Z]{tؾA{_?$ ;:H i8;| L9FS.^V9ROgh@LBH\Gqx 5 xQ~`^ 6??LCWp F$%J&IêxtYVbBA< @ IH yԗzDg/e&Sjak"A#` GU$*^;:,27ov@IjrsjL}G`]r-I.N e-Vd6DK*jY hq[H4u25bɞk ˕"7HyC ̿@I,+A;#8찤1vdݚ8hVv2--)D`  BdFܹ.هw*a 8xhG6-($iRH]<&jX!\)~L5Ӆ!nzknm) :Jg'5Q0^Ơ,wqzM FF)`| )t']U_fj9؟N'>i>}c3 -TvmkϜjH쿵c쎬 k:=8ntBO3%K_o3Wvfc!q&g}"(0+oz\~zwWIwq kыi_8f-媨\vh{:NxQd+F. _d|Ч)$W`c פHm CQNy6_,3 S$a^ ,xہޛ _T]%)yo#%J Vn&?)\3js[2$l6}JThS<{Iw߭[Mƒemv Qˆ`&#̙dLޚ5]30P1&r{xe\#VgYa AZvp_&Gau>Z?}7\# pRάݢ lXk]?썘!sߑvνS@ƒ? t |wljlOz2HEϭdo;n%f݆>}?=R%<7<{ӫ}᰽dN [M~y17:Mػj ]"(7NMN+n2.f5Dupds'yUd1Sv+нaK?] 7]#f.\vwQcrvc[:7E6tgR4K5!OIy+qt =_aY3ΓB4X9J|PkGWtwf*:(,axz7ǔ Z'W"{' Ydg(A"O4o l&k(drʦzv>~&9АH“` H_ ҁZ-*>Ӫ3uh. c\Stɏf^k@:Yv uE+`m'ѹk wxqz)VؘDKIۘĉCoD ﺉ/,?=p:уkHtv+]&?v'Z(N.Eq`] x VRP2sVB%>S]=349ouoZ> uKNQbYIr$'Isr*IBԻ(J/~|ԛ~tg&䐨J5R, $0b^NS<,ehz6~sd9L!R!J Zҋ=Uo|r/NF6כI}9\ ޴? }4l>;Ɠ#l4Vr88+[gCӼCd͂D<$ꒆjQwW Agɷʇ3g3VԚa*B@OYY?@ݽ}=) * `aiGm2Җ챇Uys#,Rk8mskl6l@[QЈz w1s U}AO%lrѼ_Iek.ɝ1# )_Wr QD ΁f;y w[H>.rQ׶Z?G6U2bHoi~]N!ֵ9whfOQAa_ +"lN4I(Hz 0lT(Fc c!EfYRZ$OUXDLfYRm`αa,Y{QiWiY"siΒrW5#- Cgl >7>O6!ַ׎ %#s"hj6?FnUm@\؅oa$,0YlzyqȶZӨIK^fAXnȺzSn<}}d9y"Tָ&x>TYHuRApmu ;z`y:ݛ>F'+j]8{V8-l'uv v*}3 nC|ѭ澆RD+իAk0i^CCsdAP8rk|YzÚȰXl/vDX#\ֲ1-TsVB`}Qگ_Y~vgqcO"X_<i@@4ZK` lzPfbPkOJ^ 'YX^afL]gf4!τ}R$9p%Q{q_6^㝐Џos"3fyl|,nw#},%R /Be2pjS>u˱Rq{:"0Dl/'5V .a%XN^זK@PHQqhi)"{e`?MumfȎ:^^Fj{b";΃%M=oe55fRy}g.]RfIJ Ηw"3 ?ˠQ,dOaY7jž0j =f=`Tvw1},6?ERmnaIQy6݀wfKdOR+{ZDn/FR:wW_&5V>?e\iQ>CkXZnXV/_&]^JٗBhaFڍ_,i # })I> d5M|dBO-ç /S>VEdx *͍%0 Roz{rNw 0ȯ 1 1ċz/x:wAE=; O߽M :1?xN9`5?M5oC:>=ŮɸO(X|?W;^7Ǝ%Ehʜ!7Xk˷I|yߥj TV.)6+C^`Vexmn[9E$sH?o`LG%!w9 ~5|lxJ5"D%3\s# { ufPӟeUܑǕ^YpoONal"QwA{,2{Sbm VY7-#YD\:KO?IGVw^gpS`h|e2URKot[ C6|$7#.ҟE WcX"` E3`?˩;17Tۍ4p\ ;oy[['id6԰gxmzŋBry,T`+9AM$Mxؾsw*33S@ @cuxh dKM|lרXp9Åt:G5M*hkd٨kS. AV +pzduuHXqM$݅BY۔X>Å.}C_n7`_[;8n웒;֔1=8.7Y'r2go7so${Ω杌=uRy*L۝#n`</'(xK NH?I"uiOdy}bPʚj5CZIXBѩIn $#/=՘B]y+S0Ua(ֺ'{P2d.MwDŽUMHI|#+v澢cgsS+ݓ.O[~4=teБ1=bESf<⦫[X;;`>vQ٬?XfGp*8BE;5;/pEl@/֎tj{ahDn]hN12D޹AtF5G!'.fAg3 ;憷{v;\{Aǟ:܏ |#cGg‰pp688!@G+ᯎOB^=; 2T!3Ye0<$VlxNyhesbF($#\y_oOb/϶תUmw3XPefNmﲠ\,_:% QP(@U7^YzHsU@%)eڜ rdЛ->-,Ez\՟AUʑr>*%<-n!u|;Oa2u=KAݫgNQ%t,li L)c*tuPbңZtĜ77BeQɾ n%XS~o]377WڭN? &0 PNS\DE51D(ةj!:M4bHBA 6{h7? ǡ!y Bcܜi;3Wa~\CҜ~LܚCvf..OPt֙dDvnW̥̽3$`NW%C=,O "K+Wo'%aq}V{]۳foE?&NN(JʏImq'GF%W.-\k-5wZofc㞲3;Ua=}ݔ^[BS%4eϬhu6Y_&ihQϛiY2ٺigr5Ok_Te8|MNF%sɎNkks™_ݾs=K B-NZmܷw/KKk VKjb_4*Hl3U۽"<<)왏ךJ.Lce>%S12}}{I)u7ȟdCDX6P0"xOȖM3IZX?!h,r2ԏ#vŔQ)<@J9i-4TY0X{ŮitWTu+b5][e>$ޗ_} I~!/PŇ(~[́TXv^j!n-IZoEoڌc>_kudWddq|3N/(6ͺK|Ōgb^+mO0X;ؓ6 kcO6mGh4 fem=OYspLvLVjxѲyo[]jIX0VC2|CqNѿ%s}2_]m·+stR_-WU\ ߷Č O*_wWZnu<_I1Rtbu(#{|ky}X]\l?ՌqnE0A퐑b\tHMHNh Hs +_y/y8 Pl椚pP#=yַܽU?>޹l-:{_+ Z\+- muէ_DO[uxWUo#X_|C( i8WԘWC9`19}ǧ,!1 ` ٙs=HI嚱9iOd ϖ|oպi1*\-񾿐˥+_eS`%)ƴк}{XJj%a`^ߐ&oˁA4ʞXt )Z<>9 U6o  5RIhg7t)"j晸}fƎETuJia`7`^G~Z% 278g`~u/3SRstl IT`7ޅIˊ93I5PB~Fv\ߤzFݯ?' WtG ̝>yA׉>,/TIoT'xoN{-1>x9'pl]C#`l͛6y\A F\@xϒ W3Z],Xkwf8?Yţϒj8YAE\6Öu\iW=cJϒlIa>G_)^6цYk꣤{9u012_]~h1R)#c\/sE9C#*X^u`h\}- Su*4WvrDqO;n>2)2,*͝#C4utPu̞Mb;l> aηy-t-%l; #QJ"Gx} x\ő#|HId=,Kь4m7Kc[Xa'!@;@d[˖AHS ݄c$$wW{1# KhstP$joF^(޳z垖֨UC h)ɰ6WE-ᲆh-\O7-[t 5p /pꢭۚoWꊕ ׯl[B- *u7ܲfm뗯B;nP{4nPʂǒhCy4OіPSdQ)ZƊ/m"6ek`S Z)u%k6z0QQpуMʂі=M-Kt!bre_YY=,]鸉CkM_?[ [acom G@{^f-ziǓCj2p&(ȳ9$hC ~HԄ>S` 6\ JGgJpnT\:*WgnW.A_B zJ8~a{ 1N63V' y`S 7* |ewBH0%4rxךGM-]_2|Qt p{81CT3{BbHS0j/`R>&2m,s8mxE0#fR35 ?QZM`N_*=0s_mIǡ%> 31 fB{fIQ[2|7/\?7֤2~@Ag&tJf0_L99f̹,02<>e}xŤUIq8$ 3pA M?JQ l?m V#䒓I;Sr  v 9NY:=ד+E E"_l>Xo{W7Y{_798d)n EPa j2tu: K'gW ^?nfR_Z;jt0kG͈k;.7ih!'6U z<Q=&DU<)lg!ۥfl]f<$G?E 8SMs++MH#&fCJ`h{\I=Ռӟu]^|jd`,w5{a+ +0 վ `;߲:Ƀ.`L[fYt0;a)s.QBG`$g~Yx*J$ͿAAVmi-K,I ]nf[7ɣ ej?/w S῝kPo^?߼~3?iA~;_(o)lExݜ`&$e+0  ".$v[oF@@'} `0t~_o)}o>MdHw6k<˞!Fh$\X6*CxP&Ya\JFJHq0Kj#5c$(2t(؅i+~ca1]5ck9@)`;5crA1~dH'n81tԙ]5LmuNX'Gؤ'FwW~@Hjn` 2^vFy[ԗG7J>&N7UOH YIJ8-Cq ׍{Gƒ?MC[hI}Vkƕk8r:C,'}:VMѝf];9g/X>4]j(:Q[>kR!6J Āw#~bBZk>lCF~Jj%ߡMtBL?jYΚс֨ :-@]-ӰϙrT]8t<{޸"8|K:"UGWLB"44N2>Ak$-.qz@|Lf3Wn),_w/< T6 (.ar5+iz-whA d6v馿IRTKz1lǖ1po)4=.}hC1kPG1d]7=g`ƀ{m^D2%*- ΑR}=mtLu%h(A;Zym0~ˏ5JiNt w{'`\o+沀ďwcUJ}UjbރHt0P[XvV j'p卡ް5aK ]K xS(in90 TpjVw֚ٗac ZKs7&!Wj5qZ$7!`WփW9s 0 QL||[&R }EAڰ8ׁ=!Hp4؟ URLâS;/#٭"B`&Y"|'댭A K֯oW; jE{5b&$00_ RNEOT9eᖯ]Z[(f,IG4~>cFW}8j#M^n7nr%~ϱtr|k"㚒=V1p'm5>q)7+-}M{uS)ύyTxTKI!]}x"~󟧭pjć+WW%KrmMs:|sf퟇̊ "&|yv@YHjx)#[NK;])EV7.MsŜ?mFL67Ǎ3)Rm#B8TJ UmkZr]1h-ݺ?|ݕc6gM1Lq8Cx9A)Ӷ6wd_^#!Si7WN%F$| i3Yl`gqWeoOʱ׆:uC1w6TTrl($/4-MϨ:`C2 ҭa(nΤ&qvXR0M{wU}Uc47BuS8.wqoIP2q',n~l^S3w!/sa ~b$G9!G֧;,-bz R.KشJ뮞$dfJ?'Y>g7wi ̄1d(<K[S&is Cʉ-x t&'nM9 ?mTqͼxʱlk,f<@2Á%u*vg`|Atޘi>Ww:Q5+⃡Qdٽ6FR1Q>8_pQJg;\J䉫1D9>`fZCqWfq'cEuіPQĔ YvpRTM &p4!1)%84 i熘iLՄ.1FN(kU>,׸m$I8u~eNݦ;yzƷ,P<3 MVIG.oRuN(w\=@ ٕ psUl%.vd>HA㎼R^Cte\SҖU)9H;2 ̶)a ~Vwm*eec"fmۂ"l>+2ՓV6@7,1)>T3華wď߹Ar4rwj~hd;OcNoy XT!="W*QO= S&s^`vGa&cȩ`d߻E x]]ZQ媦MJ^!XXPަB)#pQ ELCE2^.6^& >,oy$ę1YT/4 vڕU˝rC wUBC> jd'A?4:(H%3N4:]!9ζm}3e2e^ң1qo6^vHvN0C22ߗf/fxDžk'1l73K}ir_ܭ\xXz!! DK~l3Cf'~\,f]ۙ&D:xMKOd5Sw.y 9K9c>̾Cc<PYHrr-&n֜>sAFdNtrQNjn_᪺[_hEwr%f,fg?=:U UhlNͱuÕ.nev 9K;C:ŗ'*i(spV0_&9̵jz/:)z[dЁx~ @o2riS~iJgd`$V3aL3.F$@Wb ֠fգOX;,M\'f'5k+O}…lC 4$vG2GT-1\*'!yWA0=K\9~zp$O J7|_<=?Om 7 i؁~ܥ}CēIL:v;(e0Pɼ&ua)Jm8HwC,">tl}5X{Yhm cJ=joj_{^2;2aq-tvoڕ>(VMU\><9]xSF?A&ttiSBA ϧ>>_f:(~cb?v~H筆}htC1? oR\Te$5KOr vLӭٙrwUTS^B}e z}ߴIh:y\*J/8<{ZQ:v",6ɤ k]-a Z5&=b*}/*܏]6 RFHElf2&[B[{jZBqG\-/^oLeGI rU2q~%U>okF*{Kɾ: _Œ oS)sZe0et1!An_!q;([t**9ds,xNv|4P-5Z 9 vo h{Euɇ?T7]e4Bn>_q~eyB0rTtM(2&e7ц@xv)ZN HCKej8d[T9p}#xo=t  R#LzLpɴQdJ! *ZI*ZEVm)4écQ/P,"+qF@RwOMNqɒRRkP[@flU=fcNOxZ~)=Ѷ}J 8 vAzTP T$-3U`*"]3gBTlK\&>IS>E'6Cl;r'3w®' O>Y"G~xǖPqD+xHtV5 W F l"cj is L8P״87.\mӨн*EuHȚN-*U<ىRU%I1#({9xsd{%<%VwmL-\oIqcsWͥܦCymߞ˝9Ho:˜g`cS5]Q b"ܳvw :^8y>M#fP"P׳{7zXƙ4&l&a;n*j|9( hpIVKL/s_[p!fìi]xӅRqT w9.DU٧+7BD8)eRp1}#/(˝NU<<0[1ٍP:xפ FiYMHBo}OW{wнYhwglI YFU bt.o ~6'X)H= )KmnOVP Bzaa{ :Bܪ-ic!=XYu*cxqz h(ٺioRm.E[& ~fe k$.MMwU%D)@yoEk,YJ65i@LGUWV׿pf [{ sh$.oh(Ҕ%nEnr {-}Ou XY ;E%0LX iJ?{vk&HRrLm&u%Foϫ Vw=:pdw&-D:%譖Wq{SÁæu|g RS{i( U)lcW/}({n>W/Ԅ\O$QU"B`zJ#M` ȵk⠓ 7u n :9],c^Ny";Ej^/5pBP& bc̖KDk7H,CF~S?kߚF5uRQ16ym.t48;#\Vc)S[8*:aFt|ߏ=ۡv$mMX| Nb\s&ܦ;fyXLWZe !;0ح`tec-~_P툴+ͭ6Kp2*oـS K/ͣBԀ񀅩zgsi8ŕݤ;&`Aog:NBEa |(I^e0o\[>=P ix _yeI b VS*_>lC0T~=?l@PQV8%8չ-}Avgynİ;TMb@3.x1%-ٶlKQ#uKsRzyָn9BR ̑^~9V"eP8/#4"#Яz;H3a=XKjbnX|?^@L7 z٬B G9)2Knng<'0/=`=%v^9+_h]_:oN0E|)/w*iX: SN=c\<>}os< iJem=b@wKi 㤹&TS3ފ \ῧ ZPWмĥ][vDyǽsqSf3o {tiӆj3Lͅ (n9J6J}Di .bA>l*k7 ׾2CIj,;RHUWr N+g$ Or8-P _FJxе?+55)9+?TcPwJ|tG r{e??iAo6nZ;9u2H䫋Ҽ~Fyx #qk 63WM% ="WmX{&t~5j*""WKOlcg}k` 57>ۜ0p~ksǾH=Unoj 7FN D#pP)i6754E?ǭk/Jon cR@?I,>e1D7bxԘu@}eܿAS' ƽyl*5O%j*6&yW<}< .i>ڻr:C4O Uz5cݷC[Ws2.9zءy0&k']JW]Yyof1\<9ՖM5k֟ahEJ]hy,<7}gC1~Ӷds:Ͳaq%dȝ>jX]ҳ@o9#/hjx))uY[L6!GJ8,HcJɁ|+bAV ](#)Օr(+G٨G4-{aL'2~/S eZOpI[>  T,^c-Mo!J'FäaʛZOMBX7GtY&K($$F,q%ɍe4Rr͝R[ύFTe",h2=A{ъp 舵1V:t4:4-`ppg AR ӯL!c7kU[0<`h^ x #N@cɮIh Y4c-f-ݠ)K Ш90p_BN@›)׿ы2kcdx;ũk"ў(* 40%3=@BnI'Gu%yf2g.ə2( _&ASi}LA9D_NhB ehaxYS"40]SiVUQ7yk*:>gkInDg3 {pe`upcFt)vN _B[{C7ݝ(4I%:'sɤi(;9,X:z8zHAq: LQYҋ.ptɪ(Ex묞ibۓSQAGF7~ͦchqģ32 ,7cXP^Z*H:ՖK|u'*O/3Qeޟƺ5d/DeOĜ3|fˍ B0\ Bc&(WnʕSռaLABNylOb 4U ϱiR>9hu 'J5٨v @|ZԂ@k6?9Wh"yg6.vR~WsQ\M!'aև~Ȥj睊$n*ŃK 3{3-yC.)htxǥ˨lk wRC_3B8W3|3e(q:̤:[/4~/aizʍ9Y{vQjrCvatK=Gsm։8(neA3'ރ}h~AF/!&&[18N]ھ_ T?j PL X%+\f2vKWMYE<d'* ԋGduبa0WP Ӈ2+ B"U0D@S+F(,bw5k-F^@avrzWVޟ+AeCm%2MH9#~X0H_*K~4G1kI(]dg*t'kl%,#?Byv*dw .ѽ4wt}dqc%Al$GbkH8jp{5M/)Ñh3hNSsB`=M@ϰ`i:4rB6; gjƐiXmzZX9Bwhjsr@C%LZ&6pOFtq5zU+_2XtaH#c S|ZU'5 /ӰFGVb6KѼR["Gך& WQdT m М$vm-y( ,De+Uqj:t:7;5?'$Yu}B*Weh^Z%FTB IPyO2(B_^<3|-iՕķq^#vO.Fiiw"@x{FtNSy=3p+y&>&@-E\c*^G4g) 7wTm(J'(~6q%LChE80|ZL9b*VUFٓ4:0d9GBROKc8Z2<}PauЂb6!DGD7RP՜A(/mh2\$o!]=V vK(Fa/HpxnFVnjhmcC7f8d7!bLso f0g@TvQ2E.w4J{;?!A^ٌm#p6JQ <޽+uksl`/ӈwj\;Auk.e3=Z&U8 A3a=7Q$p DB@3EB..4 FN4_"}OÞ 9CJ4|~y~ǒ8W )~ApރUUIn4YͮL7:1z(B0*w޺8(pk\׌Q ӂ*rl*LfBLvf!& 2pSBj@xrÒ,Qpo{'Cet4߫'TH6RPB+G-ԫ/#PH[56k G= -"5dQȇB)zE>A/R{Z0LתMIQ([fm_`,Ki~;j7N¹^URe hc+2mYa+)ۇ3z:l4C}K}Ԓ2-@M[t@gpR!݀ UHA2d!)]+A}0$f]cg&8("JՎ ?kފfGLB 2s8*%jFWRL5G~נ#|srH6F=-eBr&=8PUwr uuEݕ[lYK_CWQHA=.\䇁 S(No(]6cl$2fjEjdg+*!*KMKp&$Պj)0?C+R 2GFRK *t.<r >r׍hsF1drAJ^$s#]imU-m( _:P24sdc \яi!Pſ) zښ}P͉5z϶h!c8q ;݁nO (gvNZzLݨ$ ]ԠY#V>+mF*hɃ@rnAs̳j4@"D3E('@33v(q|'UnSt `n߁H/B2]NB3\>O2LȦUȼ[ Y}'+JҭZuw߉BOR(3GZݹ 1>_0n4m1rGfhtH%^zU~}L=h=I'М䃟_s]IYUꫩ&=f^dW@6݇!oF9S:c6mj7E#1.o9cbuIzԬ&~*aZ޶e*=&%mߧ3r(9< 64RɜБt<ZI6?nD {swHݷ7@;v$=F[D(~yYQ9˺otoBLL]ICv(.`GC:,`? ͇6ɇoM&s ~n42ڥb=Džu\Լ)Ԓh*zUKd.g,BTjAxIf T8CJ~u&|HO^4Z}9i4fUI؜%9aFo51w!;EA#B܇i7$oٸh_3A:fXe!KӪ+!21K2XIFC |  BcJG+ZhWP[XakmPQEֶhKk!%J>9+wr1ԁPIhrJKP"!~W1IML)j02#nS557JFJS$V{CSۀy}δ=IQer}rXg}s^:-7tڕƨd:QFIH-n06@wn*maʊvVЩ-|cGS[co}U"/YɗlS)@ .xl05TM%[xF*3/Iϰ'1*ӳf1@΢E|"''aƩf{IUmd?0QA1- J z)mѾQ%EUT@Sk+=2Ėj)3/\kG"F%xOԄ^+8"DI֬VyaJۣ3p;kz f[jB "r1q(FN5x@+PlHdB1mPÁ>HߓsEU/@96ОpTpOʧ_ s,-g^؆nW}7_\\K|ߟT:o`%A|*Emlcd%o5ao9)sZ[ +B+ye z-KVWU(}|[ *KC -֑9ZDWDC X"ZIX\o*R p qHsu@yi8z;u<#.Osgԙ-Cͅdַ)Do-q *Phmh ]rnm~SnA#lK]qkqw[9˪*kۨu"L_ؙ.b?~p8BJ;l6=R<)H_>i$T RgѪTCfDa3dV* !r3"78_.Hա!=iõ*P*!-ߥ={{hWmo g}ՔCm,k4rQE䕂%Y&tFy[-ě+Fu3f9@d+<ޣ́nr(?jCK"~e܍[J!` ǹ5C$)F C}zc?ЇXu޶gLܱp8  l83ΤSEp'뇁EV4uWǻJ3zd`kIyLa:݃jlrC=sM>9U4btqJvESnj E% Lq+:75q' 3K&+sUShcgVfכ8hP#WUxHZnAlƏ~If,沼%egPME1:usVc8hYIKsߋ"}j,WG=QV4/UQc/c5lrb 4<*/ʼn ,Icգl;hGMV,,C "l­^ɴ!/ =|X߳M)wQY^SiI&][&ho('ܱ0 .fv{VS]u^?ꙥqҕRj*7gU"R{hB O^o=vcsp[Vb7ywh r ;Ow^AENWQ!#w6E۱ GՇw'ߣsqI;4'鸔sHдL\$l,y=OPƺ-4+],7Fݤx+?^W~PKP˄0^cS[=vX.rc{W>=i~joZ,1ht?Բ׵u ptrWn p8oW񮴶$54@/h^cA5Sʉ1oc:fyx1r|׷+ᛚb mDUvx9lnLh&lpa'e/9i/Մpcў}q5 B&FJꖯ:i ̏'|@]^^1q]"!'QႹbf$ۙ/l(XIT*P#~*" b؛$$&JP钺 ary`laػhN.JM;J-hZEremk7.(oZdBTO۳/dlQm]j)3=͇m 7l%,9\&ѣПItp3bHO(g *t;7&ϦVQb> zۨXm7T#i_'D//\7[hQRdIU1n7u_ቇ>y5@w)TZOi;Gm>aԙgJs]AC+mɋo-VqTԔׯ 3G-u +kEy- UO?x} |UolIB$dO^ aBB EGx k}Uj^* "nԏ ZlVkVV^9g;-!~/̜9s̙sΜ9}Iz#豺z.k[~yyꎥr#tzrz,r7w>"VW7Y =yGwʝgOl[CC KVbU@ g.ijj*5t:nnu6Z!Xܻd\k4Ty#3< BW8].u;,^t7߹CB,OVqE^=pEͼU5՝Et>Y8Vmص@U*)d|Cmem\3UֱJ֠QQWV5 s˫*]$WY=!kau7S`r}~{C@lFy?tXZ$K9JTL+ߑҼeV[Zjw5yF9<ɝSAuac"lZ,I9rQ~v[d{zٓw{ WӚ+(G>A/gO(oPoȗK"ߤmc]^`ew8Y?qx FSذvxdeܻ+Iɚ|SD`9mòn;@[uDv壢W R{|I?9szkzXkE7MeMy=TtirhrmɻKQyu- 'rfpN?$[lN͘F5yċ{d7@LP6\uJXKSr;(B>y+ȍȉ>#V쬳.YI.Έ{֐}:jFeVE3{ПId5P,RBْ-#@D\BI RQzM*@?s GQ P<~PZ僲J *2+gMUR*7+_iE'X|`T?y! ~v8ؾ̭UَRKLcf{ 0Kk/*g x扐ѥs!9`Em@VlJfRx!!N |jz-Iʡ%Lh[  ,gB)q0}ב>&SM^Ԏ yuG-g-,76Mlo#Ξwra>uKiq u<>aP8wmLVΩFS#BlJVz)srz7k|MXT;@I{J eeӠb[kA ǛkZkPЦagD!ȓ]um5[٦50dnƴnЛ@P>C =5kMh#dgx Xڗ.7P?s-A I뛕m i0) 7F$)7me [!5>Aҏ% #ЭFb[^9ڐAFI~XC- 1a8Gp>Hyuda:ĊL١b"Y&lG)Ϟ|fL Uw= ع4Q K8z&I q'Z{ڠ$>Զމ+_|rxea3GB Y9lFws ض hlP~eoo!އ#]R@e`:,F8N/6k˔=c%k4S8JJADA0=}΁A`l4a mM ee6pf?l=r.좂pzxujg>8Luz23ڙ*65X@ EV֞R_I 0^W$Ѣ#G6Sz)_7]ā]_~R ~+WL(pAtʄx~X0k8($'sQ{ץSeu"T"X{z=tP zEumuR )%e1}6!IxN&]Z4+`Ptt[U׀Ӎsjq2#@P˪$Ik#H[{_* .X?]/,.IQ6dP~!)s}<v0~EFuYID `B؆Qk51M944>/-2eSӻ3M91qڮ<'(6Ɋך>=PR޲ZpCTMվ)=ܠ8־EI|y䝋 7 $8Yy6=5W; \Q?vKlCм1'vu T.-Zk[ck5 ?;'[D፭sb7aOho v=.mW``}[}/P,cf[4Sn Y<NZ%3hTy]P{.0o+̄ a`?J`rUpG}~"U; f׎8ɃUC 7b9^K⽲unxET՘yb^y.|\墩=!f}mR_`0Q>N,PJ|e^`U5 (㪙cy\^XŏטםF-ƫf>WYe:#Kĺ>'Q}jz^J2t;*x>iF-`@ 7wTō: +3 y &Q8U򵳊M8tNZ&^{YBl S ؆>G4彫3ƊC`:=+Cy y:j } {-|Bݑ1%r,hR]u#_{"sg( a7%_?2q|Ff!C6Yy:8WggjG|[}6<]c3 ioBXNtdcj9sGKzb$*(DM5X-7tyVun- '2p-Nd( rzq C di:f~Nʙ]ል-GS-R^ݗ˦2}Xڝ&.zuX=ӆnIgwwh-MA`D+Ga?;cuA$7tVw&hQTyFp Қy԰ԣv_?wFið=a/.Xpm^a@V.>QlcE-Gz﨩@:9& :3Qtg L8WйqPbr05 fucA.GC%-?n啣 t ʸ{^i!pO6{nA_6P!1sޭ^ܫc<$kwLWn7a1!2"'t}_D2`x }(Ǟ^9ƴ"*iG;|-6R# Z]W-OvA>֘) RPmu,'+)nyh0zpnyh;MQ&I`ckAxg&D2X8hF 5 Ǻ ^3~ʩ6|Q+bBe6@Wf>o Xp;{ŵc(&c1T||~U@{P vs=YYk"@c{H{";?ӠĀ9()ƅDY,̙{<ҙ'kBYtsD,YYH(R1 ?o^ \tҙxo*&jbUi 1R`Gf;!MY0(yK)Xc7.R%] 6\,N@Agl(MV胚KǤop ;F]ʰ4Ńց%ܫMA\l[GbpD)&NtcJ7H5}O~ D10 z^;)&<1קŸBp2I'D7R!¥(n\x?i/`8=~aC%Tc/߶fQƢe H5sEt*սȩ~4%"jRmt ݈ \}7< hJo ج.ZQb{!p 6< vAD ^4ji-ut7>e7`sϡ斉J͉G.s'GC2*\pighvgȽ!H!yK\"\<koe#@c|&us(b]LԃzJ˛t7WG)?IXӊ`QƛD]\mthKA|]pr$#ZxGYCjwOsh A,+raǫU%ƶĄk)6yVMӚ%0 @B%OϒS *(=x[/TJ`>f nxpƜI UZX.&* *E7YЌOC.G/K(Ǿ{8>Dy̗c ;u'>^ű;:cYpEpXDJ{-nc\pzMF4e7uw0@o3ĝ-xA%t2^}!W)|~m^q B~Sи (ObzqD/^<~+ϼ2Y/wL x@_$}3ȴ{v+Sn~P"2.~XH( B+|4[~~^IU;mZ#CW_a 8U" խ̙,W~L׊,'+.p ~m2$r%oʾTaEKfAέ(UTfB>`'tSc$]Ǔ(<;{MJ2N$?0!Ņ()oGo4$wMFT}$+%1V2b`l mc~+lD6J4"egu5ؔ|2gMI--OYmUV.'x65eʞ~1i,Fuq#r/(b^AK+ ~rngbV]VyN8 dvm,T ߚu|pHUf:GEDbrY b{5aC@I/]5YKQ=bh\SCg ϦE nd<)8>ԔGxt}"}|\(Ϝ@Zn hGtSf07B61l╘+~aQ#r#7,TaH]pܱ,D$ww +~odS]-0c1(8W7ҰHiE쉧}2\*YMCRw>5ްh7fk(?Rxwb}vVf Zw߹$ T"3İk<- Dp0herπC;9m>Rf_vp+m,7X3ov5Nu ~ٻExC }`@;UYA-e5?*K>JU$=\W#|&+䷺| !3m[U1CLОWx# `D=Ξ[L\xĈTr[Kԥ{YJ'i8[=Kj|z31 f_(?AMsᇹʦ2RVOyʑM4O?C=x kJԇINf*WQRi(|j%;e22NuhHU1p1SnX<'ԾU6-7qA #:Oyoy=_{gL  itBM5YySL94̮& :Crw ce~qOW|f.L=䀈o hpkkB ` *dLc,jF7$=8A^giN86y~zf47Ky߳c(aI#OaOWʯ]\hv|:Z.5G9Sl 1{no}~;h˟Bӿ^$U7uc-iou苺Q3Ň &~`i-nz Ʒg|4:C i/ƷȀ(PYDF6N4sfD9/NT)8:\=KHڿ$OԱsɤֺvXq#A\@1 ax1#R;*l /C>x F%["!G6"1}MsS5IQ$5䭲rJ$a@pb&Uc] oXM;HW6[?|0\0MV]؍>_ꨋ?#Q9jj$]j'œ:*~pƁT[H4g:Ag9_{^h ~BGEykE3O-B Lz؉<5]=wol!5s{VwQS:^ Nt( (ՉN# j-ɍRWt9奞ɗgx%Bߔ!ݴX,mlT8Hʊ :a9ȃ@9L֪E( ڀT0zvdm0Eijvj2CDTpy^=#cXP/[I3OXt dK$ O33Va[,uA܂ hjQ? h^v[˩}ཆVFAA#|bhImXFz`}g*sG' ed;YCd8 k6o"{sc1͋9|Z̡SuUdMۘЅfV(Oܰ=5 z^dLSctN_IM<SzOJZ̰Ømבg6 lU‚!nUu.[Q(xj.Ҕ󭐱wxwy&@(Wi  bMz *(n:1?꺾6e|~|V- ?gѮq6:@A{HDݿX.[|TJT?OmUS[[.xKscՈ]}C(ĆiOϢå}} OQ˛G90Ʃ3m96nw~?HO?^{?"&aM uv$JjԔ&k,ó aj2in'ѐ<+ɒdu#ft] Q>H&Le$<˧)զ^ Bs0ijäGyOi-:?_#g3{2 0h؄r;pY /FbFGrUQR["OzGa`z@0GãnҠ^s+s,D'Ctujcb!*pcNg#GUf8d;:ђ'0['-pqrTנ!{=9-;Mgf: R;EVT|vQ$e$"KsAOW_=FR7>ino-V$wr )ԪqTxaY8f>~<1fp| $TD W-m>/{z摺 x5:/fu /QJ!^263b+k^%O_&WFfyM>8Э#͋L@}k,Dhbdߐh+kgS&\ 35G7@2LK;8{ZNOeB;˪GOkV? u6u%֗V}ԫrƦx$褻rj_NnfFfi73IRiċ}믑.v6 n,H;F[PGDjrPsV^zfZL Ek lmU2 ^2K@`:TS=AvnmSO?ya3|g"۝AJ7jYmDӅpdyo\8qmNo(pcաd9;͙4mE-)aԯT6ߒ6F*MX>kfS;I]NO!V;+t3;Rro6uٿ[5'iz͸9񪋹KfCXn.W6E\coeƻ50e(>+wܞ- kuQ5SL?LgK>Աߓ7.龨f` hwdMbڳZ\m%b&% {!<_Kkd2RtvqĘq @C["$ŧr ȼS6)چ9$~&&KM 'uAߎ4{Ї? 9 ]*ZM8wH#(3¦)dwzVӊ;gsBK5ߡ z;$u0m;siaȪajw|abLB|Ty Sbmn=2z,EA+TҽM=2uFwW.}xb=qg~'k>YtQ KTcv~@VX w/?7&^okzEvfd:C2l]]e-g~::c\? ч9챠뉛y\-&]aSku( SWSLrV \1DNn[UI~ڦQ hN{9$6YY3g962x(\;f Eh#otoD035`IYX`"5Uzp0+1 YBL\p;9e!ϣg? _C=GBk?=ЄlpWKX1׎Nmk F * X3B~LXdg&ѣ6E-]Y`6X-D܋ pEkO \$[Gy]P5~{1o|BZmR@?% y!щ ~Mɿ _s)ВC}ev0 Obɷ:ojjω3渀AV02GN|sݖNxvoZa# f_="WCq% CpC-?[Id3n;آIjyy3/R+I uH̖~LjN 9؏K{Oŗ1YPyΘ 1t޵Cuaj'$,8M-C` >%UyYiiִ.f9WBNڲ`va zC\j;*R#i>pz1o^ V|6X¢uMvΦwiAHI+6GAz=Z:p- g]`Q].΋wLmmwTC5fwr݆m£:(W c mAp lsqH@1ƲmQkڥ_WJ3s@ChTIt(xlFLuoxp?^47RmX OS笒r`X5!N5E+K$HƧYͻŬyz}4!y0֔JE bRd.1Z$5 ժ)9զ2]epWIG ީ2)j,M MDD=R SqɴhΈ)djvtHyLo%[e*) 4K TKsK6AUiΞhv4մ7>«85%,(5RYa(hiFiWtPS萞xAnE>v8ܐiBmB8ӭf>J2')g†Ijz 4l'.|k CzT]"d!a{'aw3(>,٨,S|(Y#B[.p1+Zi%zgT;s9YHA-/& "O9RmFhY3/iPܱmhhVd2(N`2Vo[-"Sc6o!ٳ.nS_˓n׾aGxPwSwlTgoQRb΢:zžT5cuϴi)d7i]P@Ud7^7 :jijyUl( Pjky\iMqfHLo N-ݘy3c yCpjw Ѝ.PEޠ.;5wc#; `LGiq 3כ_%*hQF@fp`<`0Ԍ8|\ k`x} 4¬Zڊyl qLm6~(324>y|Gt9y 5dM5XQt~\ +̭W/yU+ΐCU5 OfҮBA(y+շ+u@TnbuFEbbB\#"= J .fE5U*i3SslQ *3[SszX WLAkP#Zlɺ;bV(M%JPX$xx]>x]rG8EAL&OwH$ry?앸aҬjEXeTd0l2p2g?~;{EWy4'x |6T#0: *-0c6)QpGN8h$eC^ί1lL=vGiTgcyL#Svi"7[ zRjyv[]<"r8pbq*L?}l ji{{ 1{r+DV_O|/amo>Y*hP?UHR^5e%SSGXS45mˇ֊q/ɃJ҂Qw_KrB1A*n1@&Hey A]VhT[4\w;Y3Lj֍c'J [p$b8Nh7I*OB׭f%V=I]xwFU7P8&KSGQ݋i Xah'KUݡDT,91*WJ%=cHL/VqOw2UEFg?KN'SṬBD]5EqO LwMsu_T9 5Qp,_sbtŊvqDSrT֧Ky_$&>T=kf1GPV."D7]" .km(qbT_M R {0q!>.ըu3Y=! yMB.kavʧJ 13_"5#$|޴+'mYggJ/Ʌ@P*n5F Z"IO(Sc/cRenQ=d:r w0W,-_/Nf&wC *q]A}Ksx׊4HcOXTa o4nLuRn>nYnX&mӫa 2ܱ.\YTv _^ Mm?@*le(w7h0vÎmqZhv=@{Y~k:jj0R݀gw[GS=КRVE\7Zu-x"sT0ގ;+^H*Y 3^lItW z|T[<"hZ;"1.F,s(pFY?s.dҦ,/h{K-Hg,z/co2Q(/^"`d\)ZՂ%]%UJywD1_,#7ɢU;.o}cCdq"y5r}>6Pi]fuB;u2\FaӃc H^H) @ᗭpW1M, V=3@|1G:IPkAb(A%Baubh {5J"?%aw=}x9࿳Zeǎo$Mɦ.v~&)'*=] qM]GN<]ϰ,y饕o^/'[^ wӝg$:OMqF'ggN?9xӵpC8.ym\"3L ";uo̞9ף42;uܩ?0G׾ѝ&8-NYq`mYdZ߱(8^kI<0AK/]+23M@9!4 od/ {A4YNğu합%Za5L. :q [Z2"Ho 9J3l0ďOgџ?}qt?ԫTH㍠6,?6=R7Ȃ Ӎ,}[?3#97޼t]xfkӝ;~tӝ;O_<ݽtg`T 0L!l^:v~0}uF .K׃ :4<¿9h/r{C̬8rO@ؾ}lzIW/lL$ EVNx}lې'& l?CsH*R=ǰhv-tHOwoGp2}eOw"!{ܔD{_]NW/RPC?\kӝo9 Ow>yӝ|>=G1\;dĆ{}lzG- {OԽa|z>fx-|-@ /0>~x9S<{޿ajD5dyNr( Vţ0 Ǚg=U# /% G \a޿ _|ڮoUx`^xփ!g0'H?2[炪uqz[l=wT3iVmeLdwT_ ?W]nqxbk|]{$K Ws aqp$%HpW^[t-֥ '?h.Ò*mS׫_\!Tc8/cX?:H6 3N q ”Z*RH"MoDh_yُ:X\ZjIJ <k@fT+! M i[8[#6hr'kcYMgB!؎:lJ=񃈳B&р#)a'8[ɅْawkYjl, s`6IlHqϒ!%S݉E%NO8 a`=Nw5QCw0ZO澸uߓ {5H~I8-]rfݑܴ OOg҅>9Ԕ w_o5̀9_'h@.睠#\,7p86ga0%+ #^<8ǯ7 R0Jc#9hܙCa>^Է1)uRe-Ҏw.ro4PgNLg}'!PHv3mzI7 +xx %.<ʸS0e{qƃ!FX#q# HYƳa7 ⢍f2mb7|Zծo]A5w}ǖ*MTgl3&"= >NϺ"5چǣ=p]iѮixK[5T*v>J,+wBW,w>i2Q%r!娻D|-0+?au7`'2y+egٓa,pٵ+9Œ -K0JϪKJK)9>Lr4|Thoc䀈_huBTbBGY{˪2T 1Y}^5A]H~ pnF) VҸ75wB&GJ?&=X@J)Z2/irLv3sH~G/Z93kkke-hA'SÌK*9bfGܘ9ɶf0tc9+2"1^Z)z<֎gk5y~s1Gv2ӡ]sB:ίF{*YIcnh۱|*TP\&sWCɭ&Oiu<ʆawb1/xTt,0G%%Y[R̈́e2/hxMш"/8?Ɏw6J|uõ$D!u=3K(w<7#ZRϰ_b@HYWr_v%q,1+w$e$bN[#S!z!K12*"i!QA6JtЁ{2%5 |`SFB+L E=UUU|}&3(X e LRs. J)Σc"=< )sC=լECHAUzٶLZ!?iVA4xu J򴵘cA^%9^(- b:y{_ʝ(T%[լ pynCᩊ]GEx@j#n]f]9Ku$bIn&Qio{IϿ0QKJ<'>Lh# Ց2L0CZy_Ȃ r_l+INē$)I7W]nvJk@(e׋-yiIlO˜-*()4hm<^br!UBJ4'r32NN/4%4ă+Kvv"J,Z߲U1-k=ս'x`!Le|{RKFoQ2EnZ^pt^~=5E5hWA.*S`ʮvQkKL[/幒ڋ^)ኽ٥r&hXsr&(tp-IAH͝YEÓm Y좏oTTAe2Pp'ZP@k%J]o" W+lަ:<$hp BV٬eHTY5Hт>* 0>[ejZXaJ(Y;n2k A@# I፽9ICR ?M-@d#l"AÂŷ7 ѱa=7=/T{2|18hqRhF;$%LUr=YucUevSgIynUo "ڰߚG'l\8Xv#N/xLՂcﲛ>A{8Q\f0p匟`+e*u@D["6Nu`Ht+㭢sʵycmm! ¤!`$MT4;Ht`"*/R"Xg Et)H*rzz\Vg}W=hU;ێw MmH\;RAʞ+7a_kAs Us#eF?*J엀b3lUm2rI @Ѝ'o= phS"};FqLB/[B֩w}th{*À,D(Zخܲ Brb]-_}YӮrʥlͽH +uF|_lԻ +meHT{ɕ?dU,ts5$0-bC8?/ 瓜Egp)ʧXMY.=s0RTv5'Vez>a9 lE=Yd*:)D_;)g^Yhh${̛}c,H2+u?We=8WQT̽sG4,\ei1[{uu& ? ?Jk+ݛ6 ::#ke"-6Rq]YQlÖ^A/#<0pn7)u/&W1CwY,{ԃ.ޣDЙ8o-/=x=;;czq^d+jCl 6NZѪ<ǀ'wgp¾j}%vz$LCK(>슂&&bڂ+oTXl2qKl66Ӆ@C^8Rs@Z11D<Ktn}߻FzuH YU'z}{ H+]C \P3z~̾5swFx#y.;h[i F45`EۂUY{l-p9El+1.>ahn%/@q]<!-"xKatEIOt%mS0@- bkkD(m[vDY]k4T`7 w$ ;WEt{A@O~Pn#0 ͔p9 G0s2ɓh֧ȓhhf*9t1!49?ȀA}M7|mߢ5rN(գ#7Z"ˮe1W 鬛}<*avg|ºϙx^5e]r5%ʙÝaOޞ y sEx#Fl|o'G@= ^ilY1*k%@}TFureDs&ΚG'ZA E0c_PuV4>2C/n3\ܦ[V J4Pp ~{?)jdӇc++8ǂ7α_ҕՒ~Xժ89Mq^tBLGN~^ILonz vL.;KS1`($TN?<ӥ^ư "wZ)B\xՓF qM{\s[;)$FJ8fǧRtC-N;1uN<Ȓ jjeUGP;u0:hj}/=4UbzrIVqg0SVEpB\N'NkYvgad`Aܮݓ_ŜQ"WKdQ o}KnSa^5';j?QW)!I=phV*w:=jCg~=pq6 0=qšzv0К7^މ3Ӥd5h&una ف|Ij4R4ط'vh-|DH -{=mٛT[%U4>?Q?qjܹ~§k驷p%!;ioR}%KG0+Db/rW66 \Q-Iv~l+^rv$S:d=e>ltH[ H${͛Jc rdAya= wþ>tp 6B~ժ) 8UEbqb:585.;qZq= IR\[*fdr1 tƞ}`0F ~bMKu#4䒳6=kfƔ_B"~ G%OD2#Vl=UhMUvyUky>%m-vJ#iQWr&[?s^UArUgՌ=J<bXs[Jؕ`=t80)TeL y.xo-¬V-R4u$p [b ^{`z0X XMݓbC?b @>߼2n*Asm] n5hm_;J/,/=À]bbMaP཭Eݮzrt`I`~)ݠ.Tt` +[sjͫr+KLEb\D=ŏXЌYV(U=T !?9˻0Cn{D@iv` (QhFʶ?@l{5<Zd^[@)iM-C :qhCGY !GC~aXц-x&pv + =$ʎc;)M#"q`jU`Fիpb6z-'_얛rQ Y9ݰ'3s'Y /`tkdz,hDӀZlF,j{(wRSk\zRV <$V=u@%1l$Վj W鱝&0uVh[Vghm<U@f%BM|vn5߾K ~&w {qD!NK3 [S$8s=lt6iYqcN=h3R G~tdďYQo̍;j_兕jNsD=8PHqr!Sc)2Uq|tzv"xK})g^rɠrLB/mȟdUG~F `q x%tL9 smqg8Ev5!#[aHZ)+ mmhɃbUO hQk#wrJնP]][-0'fqڴѬp/H3R6a2,YӂMA_ucL7 /[K)u*d]JaY? o$F2[ujΧy,l/kgZ[^o)M.XCD!~oZ* G7q,`hpS>u ;$HYrzb-DcBlRNh'(0 ? o\܉3qo[l??:Zjp53'YяShwkòɘU(a*p 5SNV"Q=RױϞj~D^Dx1Ñd޳:HP(6'( 4"?,d$S7JNC:E*1n>W"='ukB1ϕxٔP@ WFg)abK̵+5s4ŗJ~+am-~EН ً 遼 16 ;[yNyJ>* i/q#.gSS02Af)JX8[ RBG̸\ }\'0z'HRWPWʙFCʒU^U&YdK_iFTNѡFm: Zzr5X=ؔs:HP $.j~t:´G9c5U' e|Y܂Ӡ60R<|^9:5 ($_Q.ւ8`DIZkl':Q}|⭭:l XBaZK;JQ THX!mmp|b8OAjT`ZEnpȃ67S\]#UrqO ^ od+J7`8bDh7ƠO*bq^ 4 n8 M[ۈ +\8+,7Ɖyǥ0{qW(NKc"ji&iẃ]=M]ߝlI0 lt*!8E@>QB% 'R(t ;Cuٞg_\>_Wz9 8J`n. ;zZUqE H&C~Q#H:o``vtC=xgXݐ?[/gY ug&{h i.(~0[ÐhdsY&T<ȸ69N|1@/a>݈ݻNqMFW< ?Ekio| Q_|ۏ[,uuR* EW'Bс{avoSr e-*.ŭe0*vZ|RļQ}NUhUF2\PU<ŞO+k;4xՈw 6]y\wns 0Y)>s0 >Zr{%XRHB}Mp5;9NxpXke-2NťC?{WDLFur%h91^@nBheᶋɮҐ@_1 DSVYë6ܕp؃1Z Ό/] J.Z*׈!䖃υiajA_ _;s r>.V N(섘x)ٚCO!? AzP8s]}|[kLl Y?V`P =1 T?kajY*to1Sv&_%.9t1xߦO|P{ۓL߅($gBruKSuj:ЦQl_GS_BKDv-ZX$~Ź_HE+؊"]Y%U?JWL%r="6L0UmMzwPDC/C nm̞ZXlpϯ 0`$.;‰-:tՐbDrc N MhlKWS4Atx O#d oԩJSr"-.Tbm@5eZ(I ; RnS^Q~u=|i=ꆌn)cfy`C_Q@y{ۊN%>O_ [tI代~h+mR}l"_QGY_Fp@ӀttB..Y^^7y~) *Ǒ5^H>L-ԶY;P0)˧"^ጺFP(v{['0|TƆ3@0B˥l+WXf[29#Kt;E%OJǡphDݑ9Rh|$e>6ٶUH; j\Xan{ ew̹{ݴo zaiHGܼ0ɎsR oF.߀i6Z]e/!ٖ}U.j`G7`7eqvUL^2vunٛ9V>jHӧ 53tFЏb+ V@*V*[]=jxm3>*s۬  x9Xl \VP|<8hVh%&r;l(e=fw24<݃&:IzexƶɾnLϥZ$;۞#5$,\m>,9Vhlt]/Eͮva1ϸ&G&2𚿉YDzd$NMXR3Tz2?P?o`kejy_3np6:A[Ua2`ۨ2Jr, i~b6(iw=v4-BDwt!+H:j}'j4kjW 'ݺbIj5YrEu˃8CSEٺn&87㠝ֆ)j>VIT}ߕp8*ϧE8Ar5Q⒙KJˏ 79(HvِTljETz9s0!L-*wz`u;;kBSn܁Od?p,4g$ YtA\WmH%V{҃CgUĺAe}Y؍<ɩF[9\%6#R+e[kPb5#VGG_0F-@~?Տn4|On#^_Łqo]-S*:AU Cz~%2DYdSr'˚n˃9Qg}5{ [ /p܃ z].8jZ}=TRI:4[4B{1ԛV j8~AY}REa/.87=S/yӖT5m1$a;/qU))r7'uBZ.! 54#3ZaEouW5#q`,ZΆpt'U]NGS kG,ͩw%܏|D7|T$r깰5T"^|e0"(0֣Iw] v0LhKQZEu4:Grȓ? rS1W,_b>MxQ40WR@f |AGdGyS]&']#[2u#LaDmizOt0$~ Zk|>o!=6 JD>ˌCXo:Ǖ}݆ pQy5|_zonӱSXIm e=I~[ =5YsD7 &H{K E>#}(LK6qJ0JV`0^۩¬יc0En6ȰDo닲Fuw1tY#ɺ)`{J]RaЉj!0.:}a |zQY:s?Ш5W?N9瀔nz!Am϶ 2V>FIqr.lHkkE{^,2նUMxS6[|QFkЩ1aq JȆa8# ~ s1crK{,gD>SA5;%,qջ꩕%2"-hm\޺|Ee#,Ϭ?Q ;Zz4b'=鐜"i\GCZ $ï=;X-u>^;][CFu)sFcj|c3pmt[˷B@j`c4gˏ{G7fK ,jQp9mä xyV=509z$]^ẓIJC,WpiKi2 k<@_:BhպK?{n9}JFRA"n4j 80{n}D]OR(V<˒/ܫ[-͜"%˜~CgqT dE y LԪQ{ ԾԺeؐ26+5|t(.TT$d܉:Y!G԰l+l}yv\(Xzcbػ~xٰ5Gb1+MjokK[BDY~WI1E&CKJfnkLR\7njR{o֘Zu`+S)Dl1dA5!AZҥpHpɢE+0D'{4?+l1p˝kdb)]e/}dUĸ\1Gjz cw-»7}N-X'ƔK:sY??OoiwQڊ9۲G{ΜÚhlٝ<3_xkcTX+ 1bMjYG\ qAQ ǁm~֩7^pu1cbܭ, gG u;YsY;59N.WNZ0k 6 7gi^)6x0nXlUA9an]3ڦvyqpsQe͢fѪg*N_Pf~׾x1ߏDtϝ\Z'CStJM3&(a:&lyvEyp0sZ)}+vo] lACoQM">Nc^[bVG4Ƞu``-T#mV6ATzRuo|u75 @|hGlp5V2JyV$и \(xm+КvĨ9V#y2Bv<ϺZCh6x7Xe od' A>5Ձ |E΁? /W諂Pk8 N(ҍ1Rm+HT pjy0M1cUMp>5>;2j*p PK4wZxtTFuQ k] F E5dK"USNqHWIuߙIEuԭ~:Y*W {/Cy֝Zr\f O1w*7 .k W ƒ skK"gm"|N3b>R*/[FW@a(vV@"[na߈7!TU۞^84'ؗz(Id֋I P;` ekUHd=/zgTYR<'}#٘l!˖/Ck$CtZs]l&<]^^Ur"Y :1\/U9Ivgč2{`]4R%p8ںFX6 Ks 8a~V9g#VfLON4YŇE\k3 \8Y.$s| ~%[W1_0wѪ\zqAg1R!}11aǖ+ 4+qƪT[*'2N}Q£P,W;ȍVcxZ ףN*nRaPa*|ϐSfuȲGA>~L:jhYйig fvu#뱜wx27>s(; ŷ}ƈ1zϻӉx@#9lΧ\"CYv~l,p$TmїēOӳCap6C&D8SN ZŲ o $`k.U(Vc~E/ҊZY_5E#[PS*].`^NQ -겔_йh\GxkBg9x <ћ}D?UQFApߓ1-s+*b![9&Uo0L9̵7b" 5 (])D\>A^*t!s+\a+l"|6thlwQlȜoW#:^ap?Sb/뵲8Lډނ+_¢V[Ok._0AĮu|Jk;#`P]Ýϓqz'QcHE=a5wOdW뉩ao#a"ZG'݇GH=" չ B+jO p#<&ţ^a<=ㅳӋS/. kW<,Z839IpνoJ*~[8_# 1`p~y4:Yt=aEHB~/e9t78daFե<ЀyAS(_VeɴNBx{ܢg-GTW~I\p+ |6]l~Y!a^Aa4`IӢ`-ΐF/Z[, 4^OnBWq4^EiYlTu-WީRNk"NIr.rm1EOp[B{6k,Ww6lz}?c:HSRnL{/ TXD0NA `'pvj67a ˏo)yz #m ,/e]l>L]"3're=Mlo6?N03=m z;s|kyƒu.mfg5NHw-FsG9 liw֍pXͿ7ABj#[ۺ6TZi?5765jq6S<%VP ̩|M#a.8sN/brCG.լïLfן4x4臐\ Ę):4F@ٜ>{e"邽XĤJmE2BmDd JpJ#Sɣ7G XDxȞ&b @ gIeR8WϭO@qÃȰqy"6'udh͹C0 8fSRzU7f䵰="m&g=3'hw/cjI?>(<}ksK,wA3O$"%\C_=:ER5~8I_h *J $dY{, -y]ϿU/>@lx8CH%rEܕCesfϕm>ĩtHMת}n.ϊ*ه(t[~ܥ2n2<io;/T˩ƭanuio1X).35u#Pɥ[n>{@V>g&ioum_al{ؔ tfioy2.] u.QֺGj>/"άڭg]gB6`%\_ӰlB tE+ qy=MrAfygR?Q}S 44 `\ݠ<*7xECB0U򅸁f+_\.i_n 1RT<{R;!\jxY 9 ڡ¬ ۸/k-D-rP֔}\ ާ LK3 nJdv:x~c=?&_͟U]6[LŃ\sOC}kҖ ?Î.'J$`x$sR\|\a!43^kKqe[?9]}u$~j= q(^: Q -df}][`T"?ASځJq'т/=cjUݱS#JՃ+F:pj=(fOa2-ߔ{WFhbx->^8gQe_Ep̆&'>H۞_^r  sX4XV"0K<KR4N1bf3P"bLydn K-rݔ> }'T?HNtQO$$' ?KGC:7!Wxt7i)JO&\ݥbr4iRӯ^eiy#C\e2R 87跦 wI 6gE,5 $;y \\1KG`6NsdW2\g\n*'?wStGdE{ط MsXZ^8^1M_Iƽ;u^ZA5~AYG=8p#gN )|ȝz9VO~h_Ƹ.z<䈎@l4o LmskX@h!{VBAܳ,!<]cbQr(NE]T6Q-ԡy`_*Y W-%謁:g U nOu= >\k+eQ̕_ɸW1t` L{st(۽U@fHս\JB5 nr}#nb9dz(oa7BRSR(@ZPCT ݟb%\ oÜ*'pe)庮}or$u.4;((>;ܫߪ;_Wk9/h-1JbU7,*nmvЯa5ư`rne/q)zТLZP[Y+ifVҦ!1r*n8}ToZ~|f_ȅ{ʯ5ij`27Ex #,ApRrq\J `ZQVSVA5oQ8֐~]=P.|@vs y gsT RAǯ \LD:JHf&O-Wss!=7anv1fxמۆu,(:sGܠn54RAoR=FMu.[ &RaGtpUP~AQgcBbUU ީOQ3GQˑ᭛WxQbY]qqFY2}膅݇] V3U@s8*/[9ؤ@ⶄHr c u>]ۿ Uݓ\{<!Ɵ{TD(5TKgCWs)F%04׃RNǃFL:`%hŇ DXZI [/ L"VwȚSS0 zĦ\lM싚T_  AeI,X/6\ ?84e]TudTFlI_i )lG7VR{wTd"6R)}89Rꙸb.8U]W&@k1hRNA7L8 'NkqI\/ .[3":.9jśg%#TL=GK @J jYtRbKlLŞd4{%If~c<,:hx=@(w_o˓R7@[6P Q`"d KΓ jY /tY;Pp4l_hZQ:aFw*OOR?X?zpϻ#HX I#oHSg`f xvKEw_U >?BnQ̗P\B1Yc%d42}z~mU+A<:_/h]]nZX|:vRAŅQf7AT,B"U$v]o&*\45s Q&dC0-p̀ſ(0@ Kx !)K޸m.?~[̨~٧{j GęSfx"~ʑ$J{zxS{`\"wueuZ<}aZeJ{YFl^K 6 [(\y+aMPfgm"&j#\݌z2 kiA2((n ҕ[ºd(s^60s7Km(b2e;"XWzN1= ,) r_/x=2j{^_ѠoP4f/nd.έ}# pnVSr1\oϒx#tJ "Q߁!c4Bt`}9-^ {ьyK*F8T2P$c Cd6 DRf %ACDbc a(>_q#!LؘA/m,YBz*^Wkl!}Jh1*w;pX;>CqtDOV`6)ăusNOPx*GAZAj28%'eO"{unKVߜO+\zr37 eM uwtotWU5Mʄ]*TUB E++cyPAl4-U|'qFwU"38|Xd_yGCUUJj_M杊YW-Qݚ83ߘ+>6gdd4@Cp ft@KO1 :?PNC#5mG%V.ܙ^vE;KEs_]VI2d_])R7!wB {%ʍqYtz(/ JٽL2x+7J|*$[Mp[Fn(glRcN{HS Z  XXTx)=bVjo wi UUdX/jJ{A9?Ÿ4HCt<ny?T.~ap஧O$<g7LET7s>9Q~6Vr̓9xOS86P ߇)2#Hx6b s*`ul.Aw2 F8 ~V,O-\"({Z{O}N拏`ڙ;|=($YgќD5 2NًWQ9R-WSkUx-G(E.W@vq!%Lً/#Eo_ǤLȫؑ I)m,h#YŁ dgU/DB"э'M}[SyJq1"oT죀5E28skOT2$τ,㳀J((k\T;4>;t&+?T91,L6",Q t+ ^f-r~oTFM7D:t6rs?jz>foXŕC|0oU| yEE'"~P-_-8RJwP bȉ#7iQ7ٹ='`2ڬ'y]T:G6:%S"-M 9IS#S&ic o6=eX|1;Lau=H#OU&u]E=pOda.N=/Ju uMѨ4\ŝ hwk3B?u:'OjO͎(sPSWþTy[E&)3%#HWٻj7?~.ivIkK,!Tu@*jl"tiu]YΑdoD ;MdGFO׽ovbǾ ~QtUnN[\Ld8#c<$L30IYj]`uAhu%pA$?qFgZ81{O7j=r&H^a({BE1yݬG 湞0`+A 4̹w )GiA ܯqN &CL+a'd' ^t;-Gj{'Mٷb򲭊H)O> 0H/W"H1g݀aMm?H8-nr0ƗEׁ6*Bs+L*LtՅ{!,쟕A [`x@;k ub^Lkxr5ٱmP&7(CCSg3>=΍Vɟ{D=98w\ANk_NՕDzɭ炪"bPJ'跿Qg^|!=gr=E괮>g6% k+0 +_j#)NؙM x];Ӕ~ *=R2Y!8V$VG* blB&Ue6Hyz+¯I"WG9F:~F)UOw/olz:U\f„}RvOJF(`mWM0˝Xׅ@. A M_ A0]7f+)M8dh5(W&&f1{>2,s_9&sM8EQrX%v3ĸlˬٟz8͵T fU(vF8 yR1N#.N5㾓BTUgdj:_EjR#dj1+ˌK$y%6 {.,Jv,k(&6ym 1^?2*6FIFD¯$F# 8*|d8u=Aί)P4bƶ - |yḀܿ@w@>G}E Ӌ=iä28U5% ޣ@[CP?ru8T˲h0ڹIx#@RVe-T>V1Q@ˢa> {CL̨]i@v[Y,v/_09:_a)4 nQcp=LD%)]Fأ'a-qJQ:qSs`2ܤ<Ījcz!̻R8!t<-!ip_ EQ') iPpZJ(#1-%Ӫ b |UO>QY)ME<ʍGbJt)Dz1hS\1҅r9qmwswNU;c+i>M`2!W)=ja baaa 4eV͖h5Μ FU dﻏfNԍdr{0 kBp:=EH{wMkn~m< ̍?txJS̩QiIۜgc\yגQh3@5ۓb4i:Y{ zX'謻 $1wJC[Xc){DhK'ّx;DN_÷di3?ՉXK;cΗ{FJ+lZ(Po[&{5ǡֵHTt!]tY<4rJim؀)%YH/hbT:wYmmu4rbP~b NAu`ZWWғ?K;v_%y`aO}',HD2H2OgGK6K!媎lۙ DC,6"S&%tERXsMb:l\j>"NFA~". ܌ƩOQyX^nS6"ښX"w]EC:Z%Vf( @eHЃ%i |$V|nPXBtpՙxCgW!wO 4|lNxͯ~=zZ WYPQCB=i3 J)GO AHB*O7;;7М$μٙٙ0n_('S0Y*b"bXcf?!hpz^b|<53@R$>|ĴU<pNU  3(JpK3C*NӄÄplo59|;1}ߢLVZ +YB\aIpW0f7IO6alݣ'Z>E &Fva]G9SoTyUEI!?mDwIBylIdzbvaVӵ0lk-0rm41E짉帀J(_`$!䧟NxB)N,5ņʥ?Aف2, bT-Um0?Gt1 kYjufifyNyO4yyt]<6"CBm' ? 4}i.nd꽀$C7=X z{5ruY+?.d|\^0@>Z_dPr{2x!W,im Syb aT|MRWd@6;9aK-@\Ӥꤲ%r&{e I'wAM*H|`'` ,YH;(rO@hZRq#( ӞN̔iᮊЬb̆O$0k}Goh6.~/Ǯ:ȴ,[+SoCrpAAK=ܚ+H 8fΓ$˱H!Ӣf̀(3+c/ jl&m]_ж̘1uIC[WfɳhM9}{+{35UuEZ֤N_Bj,]kGgGPD x}c n}kQ#Usv`z } +Ro*K'q&MI"bR>(s cU.Z̀ke5k4,kl\V+V0N'{Lw mSztzmLܿ~mvFCұc5$ ;kZFO{DCSwqW{nxdnFB2#HmGZV#-M Rw-: װ3Z>fkf9ߐN8nF"]9x:u\m&ӵV?PB[g^eË5fS8зFni{39m:Db˴ڽF9y%uOk5X;kaDI'tL,'toʰ4 ~H%7w=ŖY=nuu;iznoMh)zmsKQ.?WП+l-=2q~#IunҶ%rYJvFv,<6u n" ) 0 qʣ?Un1E?%"OZMȿpRx岆e+kW4ԪϕZW/. :-_*vvo~>CO v,"%`^vs8H}{{[~-z ۀkmY{hk+ .i*r55ͩin Rq8T`a¿VxjÊS 7-?9](|ɤ9xtK;3Y9ldǘ myɅͷyYXF֟tѵcG白9xkڎm}NMk0ʳZNH cWXGs<۰,Ns}&.my閙.0I[ 5 :Njɜnhv2'0υV!MTUV.X%KAPKhXjxz2k`d\/6݀u*Yo)=e@ҲqI3N dLR%cE*7sRzg< ʠEßFTL(<=(1!ĥ HL3kWS6Og @ e $i` eu}N*ʋ+ ,Y4$n |bDw`tf`rfa{m)\)4R)^2cAzvܔQ `ǜ7ƞMHGʀ?=RQ|XT ?ϦYŖeLI8)f;qI]CV=ſRgLj.\q_(lo]xlI֟@Sq=  UNLvޱf!"L.\CV6(C}Ǒ & 8kѶ0=)鲩3 TH~ !R(M]5oR&(HU6$㭃XQԴ铮Nw~846O_1W(9;h"nӖYCZl5t28g4j'`.5D\B& ʂf2"{{fH9 g6,#Ip󕅮Y{n̤HV !L#S?RzF'\1 H@ ַ8iZ" 2ALф2$ 9pH$,r;>ЌF2m ,v-8ބvZٶك VAW.lD cĞH{ K$ _Y?iቃϼLf<)`1` o( ٺjjjXxҥ_iߛϡqpgV?JE0mH|^N=_B]t&4HZP E=a7qD= 3.i#@mpKcc.M^8L'x@i:4[!@+)iSEb}$"8ѵ{%NX!f~O[w&^o]i{h=@`,c"Iĕ3ĦKa%tLQ@~r R t/vZ"=|4κp,tLa`8kI'8ʒM>Jv]Q@k@`8.t8 LԬ3fRFqS vNZ զwٸw)Lض*"Xb1K69l}0QQ|eY{ܜbVv}3Bz4!00#i!'D;h ⿴S:4~g4d=WmVv$HI\槻W۴CMǖeM/9zֳa'hec*^[ap(c4ygEᑫ^C6CyP.IӔA𛖅P7EĂ ybyg|$PL +j|0uT tћ:ї+j.lкGyc!L.aivd [>Bqb[{ٴcdF,nJ̵BGk z3qK߁yѤ= '[ -@"e=m39#EƉ۫¸kփ43=TlϋI6)#.&tgib#P'a #h7dsxǻ8?\1^zu3ֆri*5, S3U0uv Foa)6*[“w\ӆ*%X.흀W!ZM[/\=B76>LyB! 0?.qe pEZ1`\QƓHY-`mrg] (m\6Ȱpht&]N苆=0UATΒ]0,R%Mp9#$%^I ƇV{cTg=lm1 Q.i}8O"CU4!^+*f }oyʹSfJ8<F+/ Kjc29lc=t{fo0*~F%wRzcN8TPfUݴן82sm ]8uGGAY&)ћݐ5en`DR9<] |=gGV*1`$_~pjδKnh>78vݫ* cTVhp04x& =* WTm+f@.xJ"x7mQ9K2+ SƷnM1* eE{7چa-H ItI3mLF#Ӏ#r$n:cu6--͕G~}l(nb=і|̨,|:91*hP؎4 ̨HͤV j`\m/|u@]Z}s*h n\;ڇpA;AdͤsκF;C_hA&L$'w0?psMU ("G~\Qpn+L#7?ww4/0QJચr'R_-]t룔6czYPcΕq[%oU}3d'0O-Em(K~F sLhF`?uK+c2S C`̦be+?/朢=[Z,.A3n~|Zkی\S֩ձC."BT1}f1"rt!lKǜn38 =9ȋc' rOB &廕Eh<,Bd{:斎l|]E _U.j TD)t;/ExPϡ7FDޘ 0:<<^q1x&cWK샳~LiQ tR[7ٮ9ZKk{3/D9:aduvo; HûX;i?iPScŒo K1Awh)M9]A_Ag@'q&T DLPc[vhJ[t)?ւ kI%-[uut[CTtxuLyyBa7n}syrcWXn&8&nq#sHWB:x#矝/`qL@g.G$^O[7sY"YiCǸ?kC兼cKxN{LW_mc1B@7=RR5_.ZL# +MX)ޙ<סE$Sb6}N85ܣR?h6 (nLǗ˯z Zq:=voC;PguO0š-]P0LI)=ɵg-17N.%;xF沞4\[W )qo(_!W!qɡ23\f: /A4&쳏9;} ,ޘNpJ1u¬;3:Ͽ:HhJcBg?4nf$p}GRdKl(ǭ7r$ZeGwlj9B C&;hWvaQs>!K1|{_ky;7v,\xJS&L zuCD%~n,o^&~`@ &d;#qS@ESQt r&Q볏.E^7Đ2 <\ퟗo cӃֹ@gGe!.Ck#T2R?=EL(]0͈ÿ0."E1T_^˵x.uٟPqgbI*4 ~Jf eR~np}ہL)jw 1ayT6OO2w XCۃiLeXx@B( ;y[/}S̤l_Ձ3 +DG^`gQ.P~  U ADAӦE7,-x QE""]°u6wc K&5gR:[&((A7)?,( yC2yhlR @FޙoQrl%v'6ރq,qz({IS*L9TE}G= ,DRg}az'Sxdr{u,IQ[f0mc#ҞŅjicGk qH_t`1^ȌIoo#_D822{Y1\a<0qgrRpi_5 XOβ c־25<6>Ydu|XSEa-~ f0~fC9T#Y =v#Ӳ.RE҆c !R, b{^+tܮsa,"R`9 u^7Xk'rV ·nZ0p~ Fȶ,҃gR9d׶};`(5Xrr1~o|ue]Pj#>M='Фm- 0fQ,#Rj^HSZ;ABp9)5"ˣ 9ͪS|Do?4Z;9 zmZ< 4`s ,m46]Rzџ=NϛzZC=ل53@pS>oN^ ӝNigm؃3pVK;Cfij>hHC"Îd .{ғimH 6'bV[W')TU^Џ4Fp`Ds_m50JL9N) $ %VVOMU&OUF KV [MJ5(3ol%WInƈD1 vc\f~hIZN W9bFt2Cy||:xB> 1G6[,7:ԝq-cB #9%"cySseS+9Ժpյ NBmԕ|Gsc;ЬJs]ss1\d2\gD HGqU?>O2)XY}:M=xAMO4XR VpL.I9h5NԖ`r+ڎ?\|t .><@yxSAaUBb_7HvfR2TVaЮA~X50 (3.oiYr[Gj4 YJoQъB s5;kSbL@A-W/*#QuJռ6d=6MCuXWK)9XE7RE_s{yR-pgàgȬFE"HX\n4;K"l)%iFRrd׿eD.U+TeJڸ2{R[1U&eȶ:.ޤtLܯ8{A~qvE7*cUM˕ֶNRP"IspQ ɮ߱Bi&҄nJ|C &.]HъsBo,&HN?s2ub*&Ɨa yGP-C({*I?ml?"k⹄.0(A(crvq`Z&yo* v 7lRj0y2urR.@c4NGj+d)c 7ZO8^8,Z0È8$Av4:dmB۷yw}{= 6^f峳1G ڦ*٢9Pf[lQ⎤8' DMӎVeN7lfPϷ*_Q "߹}M*)sX]ЪsZ 5mQQb@H~b2ݷTL]YIxz;*e?RA ¿|:LlP,PGbzsje4ɂ.v*sgFwu|2cZ6Ǧy__KoK?ve~4$75UͶI:cJe?QV{c 5n:*q s0_vE1cY#f2|PKJ hO$'6u:Y;i- |,e84ӟtrPY[W)&ub9ml7 ^EWW߫L >+ukVjgZF'?珮Vf++L2W xEI0ufAza js@Io i-c%v2v-a xeBCR_©p8硏ǴHE9tEb+(xb^j^(U6O۟r2\VYqZwQV1n`c͵2a&)brP.7zfPpH71$ !]\9~GŸ)2pc2uJ m̵+3E飄eKY1D?[#st  ~LW~_A6ou+:[tסA/OdXEO ^pGY`K|4%}9ܪ/}-)fS4~A~zT63'7V:'G+GʎQ[W#ʑp`(牖Oܝ;wR:X-v7ٟVKhҧie𻈈mmǓE| s'Q1X|"su{K&GgbD;ZxsLI6ў/G-OWVl#K?~U@PX̚Ncbc >&vKc?~Bzl]cƕިaaX&nT| WKiS:&vƕg!0XK|&f%qENfeu~J l:SAZ"^UޢM}޹+y[E5_)YBЄVe]`x ^FdOnU%*%MjxR_[!&r$۔7IbNe՚1J1٣<w)=3, 64r^[]cYvE'Dy5K+󫆀L9m %IJV̻Bw-Mk?Neay9mSEE:r9GY+"tbKYTDs >B* f@~뽰 `huVѾqoc%f# =ʒjb5x#RNޫ$j/߾Wm,f^*}7~ Kי)3+[WkVjxEѺ.P<2RY4gWX]KeVhD=* L,M1ZDU*凖o;QeDӹUnKsKM OPCϗo U.HzC^QȐB(cl:eJr×wd=UkySR!*wfo,dc6/w/_|dHw QBCT2\{#a%jN^mg[l"L0G(Xmg$Ex[͑^ o0 ea)P4,D>qy7S׾\Uo)gz<0X>̷r?z 742TnxGO}DLvX)XˍX #" &Q_?}e|axH*:e ^4@qJ(McNbה춲_u2#GQNTO (pD9Lx|T/IB~L`8Lk c:ߢi8Yo'K)*/SذY~l=89yصEa*WC%o* 7 o?ʦťۂ 4/jI)U4P2J@p %!atc䓘` ";YЏa,%ǴnX ,,}J3z3l wX"ԖJN6T֔jd 2{<}В#lX0d:?T(XN$ 4]7DϻD]0!2ru%I o ̞Lob0#1YjaE1:"YWC)jVPOU3F!pgƲJi:p)QGڬh }Gn1. :Ńm)^=wwb#j\"dǏU6Ă1o^6>XgB{!B] -Bc)6{].6whO(X`&O.Uݬy0)'8(>7,NN_oRkͭa XHl4rXqJj?Y3$9iɏ$EC-sV^z%|F+uVQhϴn(!?oiSm{ |lHgE#}[I#K)5[ՍsDWBm^ԙԩoݡV].Τ% 5쳚߼] 3j{ᄐrl0||vP[MA5( PW/TrJ`~xj )ZFYK]S%')uOR-XyqdhWםiE hgPqJ̎u=jb GWn051M@y {ʫԦ,x6[*#vr^u6-B/yة.w@>-'SWo" %">u*,@KKu,mW[+29k4ƫUAX|Sypr@]sYQڌm՚1ܯ esTΠ%kw[IM)Fh >B_֐C۰tWT-x|})QN+r a"5V>]M?NM8,~ɐӂ7vk=0.aNWfO# k]U-擱ʋ ˠ݃AX0`$M/nPw.L_K0)p ݺ:5({N*(Ř!%w;5$Q6T4AR6zI% {km{)97Ⱦ=5w ֈu`_E3m x~Vp$>zչkbF G !E-(PТ]ׯheW溝P~uɵ}9f G_Bwo)h; , {d]aFEŴ TWiTz2j z&`[SQwQe_˽菲ԕzsWŸa:T n~Y|/O{@ eC j禮^s^OFtW# 6\ԏlɊ:hg?=9[F,lѲcNq#ΝLcf0z|D%òYAJd1n4ZXC%ƃ~bjb^W'ItnQ..[ԪT ܬz/^I-|uw,og)tOx,,NSZi*."^I?2`^]u b~-%a»M˨oHR`+&RZ> RO{eӘ#]:;4|7?dQ{iGq= RX$QK1GMLxjҰ\ CiL zڮu7{^ߞ Y҃jms̶=p ki3%ᪧc7r!c @x_uM mDG-)cS%:x&.`=q?ȽўȁdI1ɳ\`HT NՂXR59 SrO(&ԥ1Ûj{=@r~6uۚ7:j=B +~6EM f%yEgZ]j^~Ûs_ImDK)}ozk< .c>#y7yOsN uۑ>8y BB/G|E*gKm1p0 0) w֔} S>pè'g1Y%ptxN3iT$,rYL8qJ-ƻRz]T~=j >NnfY}xҬzvlS@#z1o% e: 8z6 XHYtj>(]dډ;= PmxH\M{7(Vzpj". ':NXb {/'48^Z[te|C:F𨈃 VМ4ئ! IDHyٮ0j>i$sXt RF+{\pBX yühjwn ohbjn{09\>=@n`=:4ӫ<)r=tXa9 T(G`cd` u`%-  F>|/kء ri?hy)`p<4mƊ;f,np‡}ZPK]?M*B_+e\ER*2xf I6/06Z dL(CYu!TGj@ro=?&7vgdq'/;5˅u1841G"َAƫFX$6nde#o௭ ݞcCLVY=ᕰ!?Bө~\,z񈞋 iS7~%^ZFS\xTxLWee4烧@3Nl:8y3H,ۡe|FO%[!Qb37iGf.k^/5~VƀT. Me:X%ʔ9LR4L|@:г}Q!2&'#28Lҩ-hj }$\nJIv/@N Q#휫]0x؆l?$~"w<y&^ N,]6P3Ƈdpj 0(%f0Q;2i k:'GjSut]z41f"R6ɑ{Lw|A`#&Tp)+u_SPj^A$ hd/楻|QʐzԊ=ԜZ;H6J;e}.ZBe>;5XBXBG ;=B:0H+F 1j̈́=Ae^ʫYmF|?GOћ,xSё`^Ny:y<Xg<1Dc'{3ec;"& d^ag"ҧ(*J .7wYIe iq )`哲m6N]:_.xkt%5g_h5HcB_B1ԓI ,˱D.ѠKv: p򼀖{g\PzS:Ʃ,̔=Ѐe%Z'.VAV#:őf^fH`LVڜM!Y5>x eGkY)5]?xUp}t8CA 5K3Tb<8жgL85&wЇ?};рlȄRCKf*t(!$:y"C wAj[h'Bs%8a%MgɭJ3GIP&jt-[D?`hD Ma+|B>۳ %4d. i e8!ԳG`L G1AC(yP3V{H7zLzFˁlXxXs[Jxhp/K^øm.#nakԯCGeA@NAxؾ>#HP- D 8?IO3g8  pp݋ѡjǼHC#i4/ Qp&"L4 $H̗ sL]ܲMPeҶM Q]dҡK <u, PHrp?h6=Q:Aj5ryz)V'YQgj͡o09:@?uoѳֻ>]RuOkݏsme`:|?u׏RT4Np.št_:}4|zC_K@SETgA<`?CL9J3Ol4<r>qZ>|nN:gtoZ?i_)u2'HNWzQ5qWq fU{1X;룞+ʶA[MQ,Rfz/Oz,bpEq jq憷^L\kg Pm=O}-#>V_6K"tFmJz)>hpx$NKbX~ *ܧt0]6 I*_~F{f4.Hyp}!uqb}+y]4}N`.{6AtEZFJ>΢]Tw@PsZ9--f+aB\1P#I%bpv`0)2!A=" ]/(+oǛDYBezmK3 E 3n9%v[Ȱ33e0WЫl,~Fѫ*x~UnQtIi0D aS?oĐձW$b03oXuv"<KRD#s,x;cXbײ"p8z3[k7â8}^Z,D:요i"/:%ŋO^rp4ɾTC9UeDy4 z `4;^1%| 7QLi6d\q~?Z"LVeAM,6E&=WO?ڈ.]vbH5rwi Ukt\=!ZPҡfG{jbFUOyV ^}u\C7El_:wk74v43KGZy_}_%,jaH=?PWuIc5ykj Xk %_W Eؙ_Ǵa'Sj=r2" TxpFݵurX67qX'gEY [ȴ Jb #f@,{# X0xXOiSdS~K;L"/l i$zhtaƍH}|.:U]-d$#>BnX| A`F)dX$i&sꢁn bakM7|D* `[pIX/$0lz$afl >s nyAsOh Շʿ};,ٳ$ٴ3gw 5#"qDWzf"'({?:vo9YLgQ)tErLq߾imD,â 𤢑f'2K 7K鰝)sn^m%f4$A*GW~+/#!ajv%y.%ʤXnfO1bKq(I3'_<’W FO`rZBG/wˋrzÄbٸ=qA+$ m{ :`iah[XT"kN>&`<ӧjmK`yXsN~XTS-%cM&10*vGef4"- 9 x} UwkXIzߪyݝ,l,Iw ׯQ hQExEE\@ ࠎ?(舣:ν$g>Яs=s=[zG9oS޹=s:jRU3fVUv4YWUCSFJWu;l^*Yٱm(ffesBUG˦lyH4f,-vm=u+ٿa?./TU5'㊥ʗn6Hɻdf7V ciUޙ537ejQ-@Su~U\Ka%ghY[ XZ)-o{U599s78&>4\|Z+<1B`QFXC-o?i0w4ا[J*+o( MaK*hFS|1֑&qVr߼/. JmXxV `\\ثdS.HLU2u}^VK}KIK "QU( BU,g\(g4UMycjz0Nlhrr\[mꎬUst=}0~{1o WwmGq0n)Jz´~LߘTX9&3ZV퉃}>s<Զf+ ܤlg(I>[&;Z.YP&?ʳ$Ji I7} - Ԕm%ǐu3,8 `s$234U6c1\a a A/68= Bx,o0S8QD;Q"01d[ c$ ? v6]2.qk )O9#JP8L(qu-<GjN<*`T^I3gNY4KՍS9MBsA G]ʉvLMem## rEaɅxhǒsf&0:VKz#%ǯQk٦0-t3(\aq.높ˊa(07 I`^I($F쿯3s.hm^rUWrF .IsTTepݱRRT;m|l;ܱLM2fk(œa3 񲆞aֹ5qsf\3[3Ru`H`*B5vۊfތI %˛.4 6тj[y&Bq]V07OYq8AO7X6l.?`l_I9Fca|&dD& oIG "U0.n ~1VPHm*G V.00iعeᦴ"+U1P/cW@ 0׹T4 1x`W7;`d0<0X6 إƘʵ1,TuӲT_KK C Z~iMTWxu``*8`k(^ Ȅ`A"M793vi83 z ZMd4'fqeB9 6neE][z,9 ӅxB#}h48xsSSx\>_96~<&w1Iⴻ5ωO=6QbEM8h* Ya%2P/4V$5naVj)U =G3F45<@H Oa]eu%|qxdE/5/Hwt6P%s;,5'6j,Bo7X}0t=;.k 9ȑiakIT!m]p! 0H(Â=Oo] 2L8p+>7gOR6H{;*[,{^<|սIPfqXРgtxҾUO_D:aQ-P8u _86<!a=@X!ҹC>6 xdnWB))&[`}7J!BwM~f 97 q=ћW( q"Nݴ 1!,9xgyc.f6@[e:`0 BN/v\F:|i{r}Nlw WB!ΆǷ]Tmfq vȵES9%okeQs3c,rc GX*Y-mKǽ(iG޹o3Cy"yHTEg㉆-M4*39G^N!^ql=oe6E㨥U\d5$r#[izh! `QW>>|S̍ QKt0`&4YZX WYptn(];s& S2Hά;BVl!z؁`= q r4c洮{4țFB4̜" \UMj 0%C2D_luF7ozt./C&v ?\//akVa zTC,㮀$GnX.]| X;4u̧ɩD0!=)tCw8R*D/鍈|R H;TlBE iz"?޸wM`IjMkBMmaŀE=Uk<c)x[k' {Y+; Ru½%˳WV}CKkOFG sRM&># 젏,vE '"mom6O>6aGbk#!&O .0f.ZG;z wlJc7*#_R;[WJj Ǥy(.aٸϧ9ꔴxc 7҂ ]=~ɩ~m8\98+M/T2j`=W\vm"g9O4\0:wW_'71/Lp15HfOX(JBV4_,Fa%nArEb<ˇt7 40 5d0Kxi33ԅ\R3yo?gkC\ج.|Oo>7vu})>/#!tb$f4|g`%jbx## a֞T* g*= =:-\ĿLW3 Rg։P2T^Q3S eXx°^~2K7m2(`w?aZ[Uҝϭo81 ~j䨊L?1vIWl |[쬑ZQ]unoQd;J%bk)4 C얷>0yR5mA,Mױ g wvG62=u$.;"'f2;v#T ^ l]:+[C˘ 4R@fpCn#.J݇۶bU_|%CRpE(8 . ]g[j)hՙW_o,Zh% @jn@y㦹tyKQ*x7Yu +QYTB3Ԙ\{0NRGKc…ߚ_髟>kV!wxq 6Ȗrŷ3[vV^XU̬aEjX!M:;*E3*H5xM_:6F2hi(y@x=Um~V"a X’I8D8WV7sl&EI0iʫ܃߼la +g@z&Y1ŞUz}2G`(#%G9cr93f`؀ 6+3nXZAghJ|ﹱݯYY!tr ?Vl=T_;~u 2/04[~ &Kxؖ k oω*ghK{6MVagBY/ B~a4ǁ:;(Xh_~إQC!kcă'Prd[Lpexcgfj!^ފ{zc̽_c,sFZ0-L1m+}]Yp+xKSx)jpփU'TUM?)Q4:5w";J76sޞ9HXrk:`M< 234{,Mp[Mz%OY/ um=YɘW{eP~zb̞X1 YIR7$d CM'[96DA /|L30RnScAV!iD,=&6|*,>Q2p.xN μ^5e)%_ӦؚAa([[ȡ6&~u^łbXtvE*?צ\ cQs&4- :%q=QJxPپ 8<ϚNBXP +O_aZ~w>t dajqP#`B[hCYGS M[D.4@[ȿa͂);sztir5^'kQQ|˅ ;"z#e)S8xt0d%0V8^X5ڷR A imhPAfb^PT\]Ê^4Z]a3}r9e"0, xKV5jMpmO]HZ+ppn -oUX9| 8-8-+K*XxՍrM³09d`Ea/bA:݁Jn.n5sH`E&wȊΊ8)HK&u;^M n]`L`Ւ9MC*84&~tUPZ. yey`zT$&Fڄ#@Qe勽kK{"]=RnvԀ Erenq ]=F1 \;BVRKMZDe5N/p6'`՝LLD7Ģِd) ֻ+Kߧ4-GKy:S"lPoȏnD=@"d铧֒Z2Z˰9fTĕ-^V.Po -FPꈅJp 1(yPAUo@ ee=q+i&9\9KOt hg*dʡ2ђ"ɡVLÕg<ڪ) HVZ ⷎ@*8Z.aҖV2o^ 魭PC CLô"3-atLk$X8֒Ehtp#d!}LWe゠ 7Ec~t"z4~,c..;%!p%hJDz~9d(v^{NJ.ghQSsy& .0_"j%TŲd)&C'7cpy7:f2SZBA#MZQ;tc5Z P0\ 9ì8 ..Z35b͜NiSbjztzH)"{{I Et`Eodc:}$F_&ȯ(̶^p%fki=">9ۄ?" 1"F#us۫IBXr&qR|v YN EyLj%ג%4q,/iɚ/%+Jy# U1R߄ *00eY^v 8BlTG$UB-y^?I<~p7'IK=0(,ft|S>']uJ6 Lb&Hcxz=?L7N @:Oч~iobjB0L$ @MW0=KPԱI2otVy;ݟNyUvءp8^N玩@w Ȱ4A{VD$m,)[-}Iƽ-dނ ]{IMy Nx0Q@`0=!.Qbҟt.BM{ɼ9̅:w](!6txՆKLvR(z7 vR_(⁁,E͢w-e@tVpE15~"D,t4/A^ FeCe nYvCak۟>]ޓdw;V( մvdu#oojpt7 LBB⿀A:Efy&8ޯ̦<깇ՀxÍ';KIe>rM&܇ҹgb|![]DW҅'IADgœd B::pxg0~@ZLyϣ!gmȈmz(GIgkĨ]ܟ%=gkl~Lc2!=Nj:gaE]q1[MZ鿜"me&ۖ'=x1"N:$OO| R^4+˷S&3gP0/I7ocXª7Y>ЈLi %ٺS~_DB9mgJbiW}8[V[)Aq=&\W Rf9P/&})]]5GHsWG?{6#g>s*"yd#gxE "v qeGD?6$6qCzV$6\b7mu~Mݎ|\hvC}_|LMV<qv=םꮽ/Kou QV: ^S-\XjP8_(~,ޏ. ! >n{l^Ldq8s9+G~$w@8Y' x4+amtxg /yLҨ]%pɻ x*;WB[+nW\^"sXZlNcҳ/6*LEe/32k/y#0,%}B3':7 JZ V`4@LS? Zy)9)7Ҝ0Bv{=@ј"u1NWה䈿#X*?"KL3ZE8DWҼ cD1i[0B.XY~$A4oXQlJ>(?!;?%}#Eg@̄4+?rƹ]3ұ<16GH:N{2@{A(w̏ ?IڗM]+ i._KGGFV-+Kv0DΌ\# z/Qŋ qV#hIs[NZn<(g٠r\34 I1@= q_v'XVk.4YMhZ"MQ1$o4venj` γ Dce帲HA+|RucXgʡ $h !M$*z*/aod[=)%k Ce'MԶCjqϤj_Et?f?b `G@Kh<+zf{8Z_ u ɶ4ͻfйB utvb2efrmgIK?Awϖ?ϖ .*i-}J詣L_Ц9R'I^È5̑7>>W z/G'u-/n/h|)6B#m\û0~G|>_XZWTW@TB%[Hkd#NEJJV, (r&ܧ]+UcU/;? ЄW-XI̛HRY ,~ )gk{v:I1N7J@4+ā``tM+$Kjҁm;G Xn9K E%/tH;װzfs%g \v)R۔W,턹N+x$DþNqR&$k>D5󏧇K_xYZcr}90_P .c7Aއe }~6k`^4Q}$&u,zdMke;[vK+Y4rW=^ijЄALЋi=d>g^cW\oORu :s#ٝC].tOZLx¶Tři']RomHYP/3ć4B4wIu,uڸ@@^\;﷮=xf4,꼙)a{CAŵ"; ]G Jk[oB7(8(4Rڲp%^Eߤ([CRK*}|4lFkrJ_vq!pD-/WKKG,3g޴5Rܽ vv'O7JuA:CQl\'-qʙ\,ҷ,K`\E넊|)olgä^'tKGKaE(Kwmg ɦ *2x lx\ob:k n͈ey-tNoZ鳛c)KE-Goz%!~et"F5ELECG p;0xbH=RsRMnx'~ &!*lho!btyM= =` @ ;j7fLv}]*- 6R.]R~xq80 ox=KT >`UTAW2B{yi/POvԵ"o}(R~{3J|_sy ;7lHKpa~uD_z+&G嵗IM };L꽛>~H(Vb{wlLj(~ԹZ9+ xK^`h#lWIkCJxv/Er5 ط@PӬ|6 L\\=mxi@kvv g30kƣc k 5x$8[NdOE)vŨVbIKlO=OiqK=t M-7S:z–[X"[*GU MjfqEGj/0YFBAKu@y[nN'p=.նE.#O HzN. |EA$yiYЭP#࿙;˂_#v-q\ƒ#oZov FHrÞH[M|E_yURXE8Ug)@x}y|U՝D} $$}WP@d! #m8р@b0&v֩:]N̴ug{[BЙv绝s'4*rJʋr* KK|,Ԩ(5Tl/<6 ysrJ[e99EmųҌq#59%yy;5rsv3srT8O!N ?YY [{dY㧍gmCt ƌ✜祗xWJ fm,IO\j+ oQlnx4! VCC`C(nC`zy~#oEaqF{X} y=l&ׅBޞ oϐG.'ȳA󷲇ڬGnjVҲmyE*6&`CO`2Tas=lO- GSJk$cg ¿vL"549ج0O U_ɘJ͋`hY' JDG<@1<"}LfqŦ+7CLFSa wOj (+pA>CD#U֮k=WÎS?zeq2s,1J^3Y- *2bcCݭqn&Q]>xG(m,s@&le X CFxiH+,FZKPgwYwߖQ% X0(6#t3!*zJ4S0=qՋGE afEylÕ[no4P7 K0yg3m{0eteB D5^L6 ɺşe#Ԩh]>vSmXH NF=l.};/X~9ZrnܓS+ce;Zǖ~bϘ>&KрFfGt ]N|Oϼd+NOB؋C!j$G HH4 &f%-ƋAxlRr dbiڤÖas,8+nqcMqZG17UUxm xbGC'yw,woknIN} 3L9q:ߙݫ"*}̳ rJ3fώn5gxY"F'[{X?YjȜnQ}X&ؘ$"ob{Ac/3Э׳[d9kjWf.)ha RF+loɶ_ĝ2"τv~gdK.)-KN3͚I=(e iIm)ON#L^Ȩ$.,l4yvk ;Hayus]_MdL5(kL'pF?_#~[a͟9vZdZ9ߗ3⫓ ˡR߱XfE AgSECqٚ5uGQĴpܝ@F`& wEDXi,^-QfG5MU.I#16ӈ8U&C ##Aï\mGj '&[ƮdyZiJV><È JqI}Ӗ:Sbljǵ{U,{dST`;{]0LA"G bǙࢇ2ðSԫE [5FVs+͗iK> k9Z4672KYpɷKО:ns8pZ0У2u6IkC' xN~#I? fhEhZ2~m_ԒV_c^iqZEIwE<^W uf3.Ա8pyƓjq۔dlD'RV߮o]:ŀ*ww~*%865OY+H(#[Dvu_pFR:r#f*6ɳtC"șF&\Xoի(,"4֟ ֻr ho=[1vS4 R-}ýPڕ2Q`$$eXRi[) |/Z.o2ROo=kg+g)R(bopϠl')m' R90i86IDXӤo8=4bFt@T8ב2͐2ؐ{}*R^Wý{-w'IFe<έ^OWZ;>JM̀kQ֕V9"sRE[+Gfwhk߫S'|]"bX-Hxkw*c穞G>G]ǨO?z=nF4xŵ&H3xhŌ بSd\M 'cX7q7p\ft^niJ'S%2xdyhs "nho54HT ˺1ў Aާ]JiJx^VӥxYKnaRyh vZiBA~2 U2 XJGϫCHMytc_$aEbsVxqtiӚ70m ˁBrGٓBBRkD3Mܱ6qB0af;?߽ѪkI7LKǯ;é%>ߥUIWI;d'\n+?*Ί0?Oa0JoK^9N\sB~5m,dH}T6WL k {}UNLo?%Ӝ UPmvq*s"޲C6_ȘhC{-`Wr[{mɼ,ԃczO!r[/D4FIK8"aן5]6ȆDEe|*~ ؍!"XI%HyC3ZHNK%{N}k)'Zu,c9 i?r&Z!sx[.qygDqH'uIqec~U>+OqЉC_Yarҹ̭ tNUtl$є ~S!v%b4\XFEFʑPv<)—[Q:)\U?㾲`?$oV6}Wy^zuk${ zk(6jX4ݟEkK:"d޷z %0kM2g,#!wnJe=ʯ_~A׆ؙ.WG3NcRbe;mm/3Հu*20]GR.R#Ѭhב"z)&_q;#MUz\֍FuU/{LV6s#BM_5/[hn~yCtdg֤V+}7"3[8<>4i}k0dr3rWDxfS^5*ҩxx 'q?h2~Uʍv)P0 =i]Es`"M1{{*\ ]4K,:]p/XZ St]5b_rZ %sĔw?^Qc<uPXʧǬ k$ $WI/өtpIXsJ" \;"R$ekڤF_'ӶIb\EV`N5w͔vvSv?fz"QV޹ W{ۯ%Y  _A7ZXѩGюtGaG[O~y#ˍe-5x!T)&.!ݥw.p4(''8k(#Cѳд4j"IJ[yܰ@~f|Tqs%>dV]2?ɻ#jYsgM,I Q= 7 +ȿ˒<ߋj$f# Yp;M'\5d_[~ZulTpMEŧ2( r$F2yu#$sI7L =,~h9#? LuH2<1b)ui34xI3|EUo 򠩃{쪘nnn='(op웦!Yϊ-Z[/Zvym:rGu@8\8Ê_bJ'ެ DWR[80PyY9SM=4#9tێdΫmJxu>Ҋ%ɱeT Н1Om϶F) ӫ>ONip{Ghr|A%5xQІF _-9N6#;:yu!H)#9twzQan2$VG)l(c=| Ȗ=0:Xsu9ہ.r/%9_bL "$3\; E”8 6 cC|ǝX5A^=:3ؘ'ߐVP|[NQ:]|iyԳD 3ℬ1`k=%!FeF1D> "EnlǦ+jةˮT`pT>NWY!s?~ZV!7HԨ`{!Ou**wN̨>hƮ.)~穾>FY4¢J4F_4J27S@SLk0~;l;sCwq3)7?nB\h޵h:+@{>s쾊,Ky\mJ(!&hӂ-:zSd(DS{=ʿs풱zHcVr-w0p'Zt9Cdf=u8lJ!y gU˶d෵85E]&ޯ =A(1& k"WQytY22}zjd^|Kݭ!DmcdC~_hIrъV!|Ɬnn;K[?ȓB4=\lyJ{Ixr⬝oϭUU#&wTWQ;dBhn_0uk%iTWpTpo)Ӣ+4gap3`f&z;F16b54xt>k@3ŒL2v5jyX06r^Bs#-'^ j^ iޖ>]:}7ZJZ%dCQԌr! [wO/./((35~nc~ O= zMK &ƣ>VSf&2a$`akp:pBhXEM[$%Y~RajA+1rع<8bM{3fB'KDV%#e¼Z`Uw@4JWt8_aZ3 _&Yzq{˫Ͱ:udsו3lځ鶾ac$ƣwYp0*#I#@pPlW!$x4X=/LyE;ZWd>$oO!Dxkw6XrɸTrץ[nG/$Ma ~';j+#Ax;Es޷wl=I`훺D(x}F$k;95W}WӥѶ4 p}8\}M¶VPj#3&U=X ͠Pw0 AUsƂLARy܂18.F/lyI(1,l*f oA=nDHi=zdؘTNr)e \J~aB%lB&/n5˷1Cym`ּ"N::_$Pg.ƚ cN#=4J/(4wYcAo3 GLX p1qSg="1 ;cw'^՝EPX0 dʢϒ(aȄSщL0lp$zìIhh<=xy=VnR֣'r >#7ыjI`P'neCOq#~{=x~aϖ+Z0 !2dǩ*j󭜺atNM; Zx;Oqi]M7M]Y-^-RCG9Lс"acv?j5qPť]U= ;=NDͲSQKxycVR1cKxg7/5#*^t3@sVJ[K㌍\]\=f-ؓS\X*9Vz pe6Ha ljytb.1"(5R'?mR ?B$266Јrޭu8]εIg;w}Ь{HJc+_Aű!k5=d£`(9#952bu瓼9Wns @'J4=2dltyPXh| @0,M>dS05iP'X_}(?ф)QB0*A89Pw.+`4N^šBb,N hb0j{sp#YN z_,Wq~YN]e%ƊKDxoC@K,N^SM?[fLgCZ9:Ѻ/KcR CievAle`G˳ڻ ̥ /Ck}pZ{ 0dHIwЧɎjwmV΋=L!{G4dő*[CNIHZŻ ]+ ]`EN5D q>dur_^ FoRyqNy#on:~7:twkG = Oj=C'NLüFaQT;_<z- upmN]m|lHҡS)ʉT{3(lkѕ1V)Pu`p$[ Jmus#Tr2 i%r;?E2MWSyuzGkn6G 0m=Au3Fm#vlF` ,2εr(=vX䯩$S7B#L*x|Vp&pGBE;pe}`0}N<$Af01= V('nߘ53yul7dhwFIVpL' ^|iI+?NyO?GYv;6L#^N>z{L4caCIJs8ЛzfP_9`N);ˊ>*Jy ڱW .@_K+֤Xgln*ڻlMa&σZ6l;;cBF (H >|!)~cGѝOOvRyKk"(/y_k@pY*ۅHupm͏yZ17wfh'x} mt Ѣ·@֒ؕǟcGewZ }Ā*Gx7LFIUعPZĔAv`W1T:z1܃;Awg@r3 ubD f{AwKPvp$:pQ" 'YpUA!̨ɑF¡aɳAS 9! q]*> &5{X9N !2:>i$W+|U~n)\QJH"FOι]+Vs</c|7Qh?N(.9ƺǒye5_ʸYKdhT%M\%VdTqKy+/@7iȝK *%31?[Th[ tB[g%:KKW/h=(GV",N$ P ɵh^1qMM ^xQͺ.CNԥ@W1?y5].|[_Í↶IO)7TE[R["xu׋~3̯ Xɷ=+G4#yיAi3l8䓷7=MܥjcfX\mn>8P~|"͛jX^:q=86hji ֊d NZ$!L^'uo7#~w\.ɕ!T"vij?)vM?F&I/vc8%/mlwGtQG|o{?/UFŪZu.MhyMѶm{u'l\+x4` .고k6vN3Kӟ7VqI0}C0fӐZ$Wb2Dz4Q%m-h`Ԅ ލH_ΜjT #~&ʅ^s@DNNTc0#3,P| A #6ЊWm~2@__њӟ(V(t늛(rjh6b6QGBpjbp-,DٺAquJ:fС 1Vrob r vhIMMLrpOIb|Kێ1x8ݠA}\fw3{dܜ(n秸ɑq첟[?cׄR+ꬔԎɧHD?s=>UOԽrYN^IId3(@Oy;矃#n?>ř wB3Aj="7 Ȝ߂ۿQbFTAz-A~zn`?8'u5/`?7\RZR ScK@ y6w]&xe?F?Qc^#? ~&Ucpe( aDNB%N2AC\n[ q4?Q&j7 mbMQ¨ Z!E?#"YZaMaX0O#32`yg|Fw"erJʋЯ1O8B1]*|iB&U  @tF;mSZY 3+DN3ph]Ysׅ5bՊ  HBy("9MnFGM ~y~f5$H.7 5'Wo M@{"I̛𔫴++oe1 w܇NJ:.%FݤqT.3,+1k*ubu;ЗK%{.#|Eah~wHF KBCn—=`R :/p1=d,>P[ٝxcQ>L>׷3M"#p{z•pԠʟ6#>0xa{y^yyaiIKeQWtbrּzѲp),ޞ&d2uUFf{i[tq5S7A~93g$:zRs? 1U/P.+R,^y+S,;V hh?xǵNl{ ukZeݶ4ٸ'l .U#hH86Q8,ulSTB2|^iT5i8N#U=c 8bbtd>5Vbl*i4Dz`8j+U<+v6dHH꣓Q[R.6SsruhwnSBt'־C7`Rh+٣FrޜGaە 3,x9/ im(jV׋,ak=F׸K+Ssg9matNR^e8KV \y@+# W݆$GvAB"3/9A~rE BoMWn krCfUQokw'\D)/m[-rnpfJ*ʁm8iqQe1h脳ln{8R{ zFyƞ<#V<8.Z (t{ṅ+L"r45lMᚱܱޜ3O/W\PXlK|״`R{N>yNn5ʣ-kvVlێnG8:$\f!% k;\kz edLyey2 aT]f4jUgIbycTDپzx'RMM7cK\Cu|6Z4/<Y RiG/e{׌G*pJ A3jRrzw̉!Ul̏0}",mOͶ3PGw|fUsEpzX(F ϊA/"F,~ʩ ET&XEDGE1,E`¬)Pfp7IүYRؖK=e2f<*J~~p5ƃC"DCeZ)\t; "vKr*e;8M0JXy~1VhNwT񃢌vZhkFvB|?jH?6˵^NdKMv\;|4w_!s=ܢ79ճ7Z0e0u"o;1Ym8 Y;)I38YW8 ^v^-NE 7;a*?CɅ1WciԦ3ʃ0;FڟVy YE`Y[ذFnaAaENs{iEiyG-U<ޢ5Mּ"LE~n &B |lmg܍Sjm)L./ͯ؝c%y%yFE5 NUQZSQ-hQ^SV9I8W]5\1 TXbbWv8ˌR2s3(7*cP5F9DNRqDe[qaVp}{MsovHe pw3X▒B +Nݓq&k*64fsSU~匈򍓇񶷿Q_+ף_by?b0943SZ֠83+Kwz,$aTʔ[?H)2GJqSڋN[^t)p"QV R,O {^` ?4 W1d'vM-\lcxsB("{"&jrrQY J#č "!V&Lhu x|W}\Z-bWImټ _* S953 vdVlӈBG4L~p 8֙09YyuriɃ_Zobe])/5sps6Mi QDylɅ>L3P,(!V 5Z![tm86"lq?i'7Ev֝=ZԚ]G'{SغN͇3s!a\ͱZeƖrlS¢v4,]l"ZyEgx4uﮆk凜D|H&\#6wb}Lmڧɯy6k/0a#K"V!Ykf=)uN[,?0w^N#ytC}8xζu :TܮabKiFI}ƞg`? i2;+2ν8a5ưQє?74%X`SZ? eG4g.r_m%dݑ>#0C58e7d3!E[縩a9C3(r <#,0> g02.^E;r }5.`^ 8Od%FWGߌ}[N}3Pt9)LE2P~6N(KX 㥥%xkB(/)ؖSˀ>SsElsSzkYg xW$))=ѕWPAQVlşڣŕԲ^Er5W`֋]%FyN΢nMY?J'VQ;B;cf3h&z ܀嗂nȸ[8F&<}r*uQ 6`R<H<[ 묡+&whm)XQYda-[93Wya+[_;|BWG,i^ 9w*5ei-ٌX4ՠ+|A3\6Fq%>E:½>. 9U~.p՟<6 ŶgڜoooF˾6 RLNONuLƫ/O~ +`X庣94,@m}R.M!~FA9~\Oh}HGC:9I6Q Yq`u$geFPpdNghzN#EI?7cPxE5}lz лp{,cz$~6?7 .Uq߁zW{UU$2 ȁjl&#|֌Jخt?Pcd/;l"pVj[?wH]MmK^~4s/XJ٘T;y\:~N{t=< ۂT18->ohn%JI*O5HJVԈ8Mb/jҽO&{P,_x_*׿acwpWv$!~|vwxdciIy^$fldN AKňAx&`ff3m &oم7DۮR =4ݔ>_5Q$Rex} xב6 q$$$A#@]@`4F>pK8c;Y{{ⴓ8}܄$:7؛lMͽ٪z98/5Uի^U;35^\Vê =4bmcVL1.jdXNJ\nHM]{6ŏu# e,2hzQj,5䁀EbYC>Vtys=DR'=Su njQZ}@PR 9EMxSrH$0ɞθcF|k+ʤX֒t#xӓ1UN\>']m]kt:::Ύ;:rT_t? {=l퇑hqQN^^]IN̤ۢoҹM7zcgώe[@x-][C~+y+hfЬku~-AK ǀ8\4蚜H$"'zQ"_J-krj*s\>zZ*˽ҚeBB %uU*ɴ6f#?4Ri%UYW@ ]sJK+>RcIUݤE̳'FA [d-!ฑSۀ64'ZH(XDCԖ^ 䝽]G&kS*UB6ي [AqG$ 1$yPʣfHE +϶mSd2BZDVFc*≁N9sZ.-ˌ$]CЉ d- 9\t-} [X(ޣKC*ky$L!%a9&}tyVnu3l1zA!c2DlT`t:AJH2QhG%m#;4a` sA4=},w`U۵$uTϝy9ăB aY9^$O6 0򪜁N7I i)|tRڠz$U] ӮHh&?6M55=&mA?BT[g{[rhUpX 2u|/h1ŹӔF<{; 4Ȩr&u :y)P5#'Cgrw}p\d5%4*xrzT0w0tr:fZ7Uƴ ZU& | ILKk)|Cr_VU@R f"gZ]gns@SjCJܙΕn-˽oQ`R ˸Ժzm> XtT5Qn[3nƐ_`<0B闎>Wf:VۊKBM=ș3 CPSVuS#C=} < c#;lJ{EJ* dDi :ި|Q!QZ3I TI=gAh5LB'4&wOƔI>!EIZ$Is9 ]$ag)RKj·#C-k=r≧Ju4,4|4PzZjo\^F-Jb@=$p(bwN*!MOEaw{r?n^^Q+twA$ (b@(KȄ"dr F: v3"&QCJ[vІF7 b2bF& m.˕m;ٵr1pI1DURO "Q ][14&SNk6ovTTXg|.K6 > Ziy{Nk+kP2!sGZp Y^|o0DIЛ~T"_|2eU4_ \Y9iC&[kV>vw_@:d;=zߌ6[0=-;׻MibNWiX ;s75U2IzM;ԇprL (2t\ӎ-d$Z/w)_]0yXuN뷳-L<.ݹm%!V2%z z2ow qCș7"(V;P:܀AWgT=d$[k{W&$nS퍵I1>3Gʶ?8TBEH7A`Cʦ`xr5.q$v|bhw0O [lVj.G Nゥ,7qwsX} Wgs"@}aF'r=W6QAF_Ǡo#{R ӞbBW%@?,u 4@?fuv޼55_yl~~0߈j:_m{g< td'b}ƕdO7V ă5ڿz8%51,GkMEnoeE;<NX7?W!aaK@Ǝl|oDAl"ZrF9jðfFŭ0 \\4܋2 3%gܘ RBwmFYkH=bbߥqviYYn&egc@w*1Ӂ30<Wb@>WvׯjUBAXME,yVw?+96ˣH @2"R&P L| #):.M8Eo@̀<""0ZS[n&1$ㄲZN}kSMGKB iaPȌcZ\6Hv|`Si@"Ќh@ `ԍ*\i:\W8Tlmvoh@AߐuHΨ1 0'VFH- ;@(޹45 N#DzhS3oy>W'^>D,``3 Q NgG\>Đ x`x4aHk| D D* *!ܩۃ9lF.[Q,6N}a&[UA* .(׶!_ܱ:c^g}XZјm-DzHbnQ0x)#&'֕p\ً]40i@G0[w_fJ-1a >t:l92huI rY%*sӕ5Ci_b`4Ǖl>*AT{szUQG|pdƌYvׂE xU.Yq 0djz<7p:8y51p\Y{>5E}>o_f״Գ<]Mۛ }KLHf3V,7z#l8T~2fYr~{m7-u6T'T7ۚjZaA-MudNA?NU?ͭ) "ѧj3S뗔[Ӽ΋~ۆS^} :@~y]t`2*I:<5 ʔc?0Ĺ3<5 1od|91?O' 'qa$lS F)]6#6{%;̗U;]k:-WЛyݻ`ȣ2 K V˭zx:-t%a-1*( 2y(LޜFRQ#2 "GgLyC`pTN6n$=icEnl51M&6&C6[=UoAC)Σ#Ƀsr/s?Q{[.L @6Cjο<ȿ`6\yuWibUpMF :w}Nc( yrW3smisZB-e%a+1pfӵxr-Ofݼ))_GNĀgQpY: &k80/θyl_P*, Wta#TS_\OI c.J%jSjWfmijq2BH"@K)c<~XòCQ ID I;TxJˆ{k48Q>!-Fq%e #d,\g֎bw֔PV{*Vh`$ L h&CG:QCZeŔӮ>z^ mU}wD,v%[{aUBhc(!N[*#>nyUuN<ޟ=af'' 7`vzvn ^Ų)l( Wf-6M"zN\WZwQpqfͿeц*EHaŶS48jlM&( )dj%FzWe}{G6 :ڌdD ʏ 9}Z/93kկq-l# t&Xbd3u!P kMƀL.i4s4Γ 8H?W`$F#d[TX,sMߺ;Kf|*@Wc鉢2KO񰨌;SNv$0Ŏ TC ^6U8mH.dxTyGxƘhJ+9Kۻk845\K(}.'Dḑ㮟R-_-|۶m.'^S=n8/z=]gA1-<4g͸*ךn.-YE{iX WTeI,e`M c0{-)]꽔aӬ+/~(V+yG`<[Mc\_|9e?0`GBc jоfgc˟GIOI`nA36 @v42?D _J$ jIPOM2#G5D{RwX7UYcxח[[n=VZ/T$ZcjØ~i^nۦ+Vj{W ӋLZFH3ZTH|!հO / {L˹XKM!B6z8S jQ S1QeU׳.7Iep=jr%3Osgb*ǮdˬֳRR=jݹ-Tأ6>m>XkERV9ƀeEŚ-A4. Q.buCy}2A8 'Ձs'n%6pCDLqwi;z[{sGO-gvyyhocxj40hTT NY55SXM Xʹ~*jobơ}۞R(x`|W/hb_nI'Wzn%)%j}k%[wL3TL(uX5pi6ݚRO%>aN-lu4ݚ9vffJ g(Dۯ1eBŊ0?5x1 0?7v xHvQ5} /ne*1N 2zݐ je. +5Yv \%kY:6Xo`uv:Yݰ=nd9S&BS$Eʪn+#[gmf} ړQ:h_]l#*NdװΕEѠx+<ͪײ1kNiхBnu5ALj]PɊQ X\5 O|54M;>|f7@#`yOOQ{T,J^iAih@9bVJ|0Of1F3jxXyP\ ;͝hCLBj"qoSU4UiZ-jXL[&(jْ?ˡ=`g5MZo]&UCnep{ TS0-"! ,s1Iw- rZ>F#:vPQ%0v-*ig1!Z@):x]r0wAv5;n6XYڙQ3_l-bV*taN4-uܴ8h_v~xS5kEӆ _ְJ^i RpG^Wj*RZF< $AJk.gK+fD(e!dub?[`5|JAH}a ֽXk=@%s#J&q7m\Ӿ\YuYeK &Nz!+_pA8_wl)E𯽞s1NR. E۾n!DG_ݘ2I`p}XdeFl9ΧF$VOAnaAO4lk٠Pm41+^v腜q} W-dX?=HZV1l4ʢwiExA)s#4 ]1vhڀRcZg%澙n?Ţ`Ү[g (!CQ?Ye}hp1-}->kY՗+ e /QyӐ`;+T@O&X㒠 8QA?}kڥHT`pH(~!-j,)dx@jt_;@YĪo :fSv]8 Y!;0?Jv; ݙm>2Y~NeP֏RlاN  }=׊ykrivbϵo7"kÿ?vr|&Kɾ6^8d 6r9 kwx]w ; 8;{cɷEG؎Y!Nw8mYA-<ȼ$YK_ɚ+8ގkBIZ;]g^ɚ*ms EwL&x2obM ޥF:U&bβUN`ݫIk4ʹeͬ}ŔR3j:/8':uh@Yne-k{7>kޫٺ)ۀg}29ke+CJ9amlہOƖ--91 n?%?5q{Y!z^,gW;a#G^V/6Ny֛d+|o}ú.rVub`+ 43Vulٯw@M1nn\u$[U[OO=:=cqQEo*#8ŀ4M{=[9W,~R}=[5C}l7ۭyo`Mw X<{/ZuˊY2ُä}i=zL:g9,*`\&6Y{>Q/>;dquIã!cTe&dz1:W<;+)k2P&e:~xb8a@N9G& punFD3:U( 8v6k 3ztk=oM+ - 'rRfaNfE=R=]o:鷝b{Y٠ߴz;bޒw; >\_ɂt((<lX{Yu;V !.vhzEfJQ>aǂJw{v/1AML¯&aѤXz/kt R{iqzpoZ^٧^w0EGpY; ^tZS"_Kwzaė| 7/tXGn|y<:(۵R,膓0U[c/Ȟ7㬧Sȶo[)9e2Y/o zyD:s:mwϷ.=fw'Vi#[6p5ޙNãjXE=lj" c?o?ldi&'GaCH*!# 4Ivx8$MOEwJb7JJ{Yo~}J7ϟafʅTnn t76P NjH1݁,9"lDrW0#=pE2XMy$JqJ\t~ݙ-3emgs=4➽#ҕϳ۳S0Epx)T?7\kmgpÜcks,?w2(; rfLu67n0QssV^opn41E9쐆ofM'(/~(nOTX=*-} s{w6. vH«Nf&Q6p%ʃi},7-K6(W1(\zphH٠ [IjpLJHJ|ꚿG?^g-R41J-iaq"*`nvLJ|A4?jO d?\usl]xmLzQHY:p~hUV HE~YwYy7]Kv&/{ȷ9˭}/}tO7ݽ-3inu[TPηs \g=)(cͭ俱kQJ$vu3cZ#ewi=u?~Ki`ſR̓&zxs''DXn:~ .8V-mֹ?3[8Eo3!ǽL.ӿ KY_%[ȭ gAnmyV Yo\竂=Ǭ߰-EGCH @pض悑:_;Ym_YC1uRwY-۾(kSGwݙ2Ũ\i+wi%]Ͳz[%zeL/hHPRҁVZj)TRmlz;@S|@?|^Ud"k ^T{81q%|Y4ʭ[.vYe>ͧK啾N)iR% ʝ; tR71h9oc5@O7OnX䇂#YN.Xuho-1 y!-Zʤˤ8rnM'ӓʁڙRzLIq/{,fJjF4žpliv vFiH+&Q՜^9RM3M oo]S%'Ὀ8ΡyR{pT f HO.I{ a*#~O†VETqݍ?{4dgm ,zKL:jQ- DQ@즫vԸ<8:1i˼,tk.?MEs.i>ZN5אUǮVZoBg i̽j,aiuܺJbq9fOd[HWxOn\ δ-uW !5>`/E(Hk\T9]~\FӼWڰCCyyc#J4w_\$;8 mn)l'Ai3࠴xg]7$uT6rY֏+޷梠i}#(]a$)m+:ۭ_%5mPC/?퓮rA45D'NE:,mqf 4 ҩsE(i\_d+wgL +BȺqDniyeD|2z^|ք B}M>.e-rP6ZXD] d5;p ̑ ; $=Vd-.F?YRaBR5%-OEM cFı5wo{'e$6)9$ u)! 亸e1`3}R *q]sSŨ^nQVHl]PR3AZ41BN1M Y !=]?zR[,=ªK;?8h/+L&K!ޮD^<)I۵+3R74GDaR?r!1&5U"*1͹|*%5u1Qhm A PEim-YhhXQ`%Bcӊ tUۆuP)/*!J sQ9cWM+&W}𚦕B<'*ejaP/5 e%6d,)RX!lK;G$)EFEU53j*W PDP:UH!H GzV1 !IH#D &{9Pf4 u O,/gq1$φO"9L.7w=SC= iM5C}@t|tO!}bTքRjJJjR9 <]_]ԝu&jAaqIMH_HGEY*H0HHPQT# EE+.${&-.+RvђfP1idhU!+m:Py9IQapԦQ)4)ék*WK)Ӓ3$+*O\" [-jmJZ@imJ"&0Yp}5 $>ԘVT۶c5$Lχ9⌞'K׶һ&͞xQˇ$ *L`ȋS^,)VLg8CP jF8IQ!AHjrNt4|^ZdzOVgoT" ڍ;:N>j K] ÌIt9z r?}Jh|Ԉ&%@3b\?H&^RG:s{4Fyv?g 2aUhab`L'5UcqdļHQ;wrwbX@eEW-m'xӣG+WIK]HI04igu%TkYIIv&ђD)] ճJI53IH!2q涁,5˛0q \ohtkhk;5&X)x+Q|8# ƑP`2*/[B&`0@HZB7/e]t E+B +p0Xuo) Bb fzp[ )LNٮ8qv"8K0x 0!I'8vL.#>ӁʪjjVPatx^lc/y36BaKW"0.~H0LJ2潰1Z֪Hj0B}Hwz1Bk%k7ϔ=\;6 {_ ]2Ic 314#hADewZD6ϰ9JnI@4ݑݪ@Cvƭ %A\fZ:ʭ( DQ04PA0P}2Gi%!p`>>X$;=.Nm7^"1) y{m/+'!ݳqEa5Cʣ e 5nr`].pu0؃eMpza&`K-ۏ;~Pwx=M 5Yi@ @wPqL]֭ VUR¦ȿ2@ i +J6Z^_(gK =H!=|t$Ι쬱! ^b>y%;]1 3O5%d39$3w !`f```Uу2(AE_Ź9*_X+0LI4ҽla UlLpafl>Y hީ.9[xK1 TX\"7 &mhXV8qXCbB2#/%Cem[Գ6ďqpЃ&UZ+h5:)*R)} / 8:Q3z sէڈ.K nj]/auࢵ v3o9\rU81ݸ lY` F!\C[w]0:ceeg-cb7[t蒷/fXB68wz b4 ABu/t,b|#- !A72DL?=KZ/agBb7>O9 ?ǘ[ˤ@Rv=ҭ ={6,2@eX2Ɨ.Ҿ&OcWI.ؠdnO^ }=nHclhd6_q=f͖CP}|gjM?F) wv-(u^x^"H:0!ǸA&{!Aŷg||?4&-vWD\477SDžN1$ukC 6a|r< j *rDzɨeHFq[+-!OW搖1dzҥ$pS~a)` Z 7rF$Vc{o ,1ac"!zn*Zꝲ"LИO6;`105ȍ{Mi<~ImI^=_UǭdL>ZS`8qw^C耙_9`ڷʅ|b[>Xp C $;=BDFt&"h8G#Tt.=\p5I3G}r e\P՜wvw0ͮWx(ڽphӿ4v_u߸Ѝ$/Xl5@.5;zR0mS= mpwŖkgCc.7>o,fX0/k| vr^wh"z䑁e~;å 715ỤiixM9Ǖ\㚴# ϯLܲo,\^G0ħWt醵.`۸1+rJ{Beہl;}Lڠ 6*q6SMHfvv22|*ELI3'  ajKujбUX}7CI=6jr|;c:<ѽ b !sn yY` F xa &b&]MAλ*) 2Cфа']gv2?wF3dk#2w`#!A C$_yvqбyNA6l -KJI.F U^խN)'bQܚ[_UK%2n&RO\^!¢%.VPdͷx+!"$AO;GQ7M1!疀eUE4YU0m mÅ6L<3rWaRYj{'?^YSLZO1 ;Se;v(t171 OH΀[9#u7;ú Vl6u" q4l ۣjlt`?%00;ұ1lD-`pLPCGzdH|pA^)e).8\(m͕;Fszs>c|c')xgsso"r*?+ @a4_sS_n !T_PC0qOc&.Hq< njL=*Zg|yF䙋2R8]$ѫ[S ?ÄO]*q` o̦z\`Hj@ڟghmCwigwҺX|0!`JiS=;3@ N L39YZ;{f+,?;_Ud<6]Fz!#:袶g0[/L=|^8I1%dg₪{H-J+DQd&P1C@,}Gfvk+*'xNn#>0BvoMjQvz O-Ynat QLTl#{Qkf^>/"Cs xK1',= .D3{Wlf`Gϥ f\?r2Oty,XXx9_FTBװ\hĥY`-dnT)suAOC5XxLèƴ5CF:?D]>6.L`lb0QuҌ53j6, 8>&˶l_M.j#3Zv{3רqLBik[Ċ[+lI-"*mA/?/,ܻmjfߜI[ˢ'zB&; c5 loeY.VǩNrD Qx|aN6Fp.׷1 נfL'R"å-j~3},IfsTu.5UO KtkO6kDGfQc[̶Xd45B xH\6~o>i~rƄ}`$_^XL}Y̯M|T:Q4N,&[B?^誤gR]XfO{,!A-^%$&B)CeX&wAAՀmX@qe6Ћ T>#QdEذs P2G: ,]0g Wz^'x@fmfAkpͅz^Ac^xh,,҆'-7\ffb[,De,$#.NСb;[Ja^LN~,+2f&+#Yv,Y|,15c[LYJ)6Ū2hxPX#H5Z0cIU5ARbƿ(?<#xMUfZ_/j"N 6پؒ;&M|,_܎,Y.4[d]mlOf ]>$Iyq`6l|o&?x5Ӕ)X}hPbuR$1bG#i1?XDcUӬ2i2n7Gk淉<a"NKZ=p~/DbY:(/ @U RXXōVg5}RzƺU0m߱哧Mk}TfFP9Ev24E "ϳ"\a-Nl r\lg`SY6ۻsqV}w25'ǘW'0_1Eq厉ΫR\zp]=Ϟ/}Z9\]]dVH7ȼ]D`7j.߀w{?EX^FT״T 3y=9ð[/x \zk?vFgƗa)gVr+C6o(isaxNʏhq,UiySh iksfre[vUb"E{\(V3L_*q.S4 #[B'}S!M1" 9M|v}sew5.̓yn6 43d&-$:뻟],yFtc^i-f {o/^Gج"H~o_rV50]2ja~?5wI0߈ {.mq0?l.%g̶_mnavYN_SD+ U<*u4)6aZ2)UNY8Q!Gw4^y?:?9R }ǷfZ7`W ~. ,~%vNù<`l"7-@4~R蝼^䷗u61Q'k>,QP)yw*=ɬ(j9u[=O7]m7 ̬D{o]rjJV1: mϚv /0yEܪdi)Ve=ؘ<ci[]Xd?[F3V~!쟾5oPQh9U[9aũ?MC=lzXTrN}o7.üb֫-_{󾙾b"&Gj@U@]3?^/\n)qWa f/@X~}B)}(% ciyeWkfSoj0"fjwYU55X-NJ%{A jPh5ؤ&N|-RljByL).mMKl:D%06*Ck;\LſM !IuwfB5Qu,\:ݎ#N\b/}~1B(x9X:x(uvH5AV!Ja|$L``E<0at2^zhiӾ7wUHoI!UpJ&z/%+JZjmgW*R2)uucuRlٷ猳Rм*o]AeN88'G)X;ZOARkzق_..spiTMY=C,(77).%o$Q MKwv+Y{r4%1#"LةII;!z?NB;iWo|wƠE+-6w8EmuԝlsFrx f5,||"PXB]iL &Ӝo{jn%"MS0Ԍd,KSHm1;TX€Ֆ)l 1.eDTR1AW4-1S)m㞗4-Ӛ.u[o&~ۘ!'se3Hx['^YgB}2-l&aUۺw_8ţg?|w,r&vr 5_s:yMN`GIe6yWDCvz H+9K țf|l3N,gKܞc*%>c\PబjeUa7jvl10,,fj4\W H, 0*tɮW瑲Q5F|`\6"bI*!. %ӺTMG$nblCdi8z/ 'DdQ  t@s.@JATjxu5N HL7$iOϪrҒ J![Ng!%$F#Z1NsKxtY;>m0T; da^07k P2毗CPEd$fEzTL7^n0H% ƊjR5ӵ0'\ojH 7Dn!r#G߯;>R?1ef )Itk~R5xV a2s)h|TKzx8`0x f Rkk$&Hڠn?HJH zzڵDq=2%dtgxߝ[%䋕C}bjc5SU(Ѭ`j_A,%Vk^].hM gKj@]𻺾پ p)hfBǨ?wc2BN.nS= `1Adzmv-}$4Aen͍}͸qi۸ YS OLDaž\I1&!"t:r\8c(x7on^MJsEGP))@"e8#.`V28T1Me)`wjchr:[>7z~7yzk9?C>GmMVVVF+!h ^4UXIv,XGnGnt5X&8Cn}55Qa[L{+6vC~k6ϹHCpг<]m$q[@_H>D>wX+ cnRhЗtKdsn)qh#~~m * H'ڰž߫k NKFO)C$b3vӌϾul("`l;cloѸ- e-o߫```\a+<{apnb(.̦[aޏˤj k߳+ӁTJڸM"|ZVsjX7i@Q^ k<2c\9ر=TcL%<4tngU yꂳJEp7)5v9p$t9XX2yz -,F]{5߈BO}%A6=Ώd#7i}}ah]yOxT셖B6 j7n&<:`ӭH+u7ò,ynT]uk34[շNf!å[?} p'EM*c֭Tu3O=y+)IQ|1n'_>FAb83=q"g"{RFpƇ ,~ڏ{x׶W|s9ו> MƖ;}qb4E:+58wN>ӻKbF]d@2buuI1݊_0 x ZigL T %PoA@8O | ;ySB6JɈDQMgHr`v@_^:ΛwmwumngD G#*`ŻI[yK]_ti·yΒmuC@8FaigxO> VY=f͠~WwCc3rT̵Wy Q_tYx:V֮\K&{Iq~y/I1W<JeVG0G~5f=a10|u2NB\]Gv".cpd!O.Xzs=S(|t~ԧW%W-YӼ%UMKzҤ~Ͼdvs$j}$m_.߸umtd*F.sޭ^  _i^:=8&7 l^XRxGr^hRW#tؼ*ȸ}7ad yA-8.Ard~Q.E컨xp^m{q6悗y͋z7x"QEV"Y%>"~qR噌Lx@ȥ &<7JoitA%F?mły(:OڂFcHŤzvZSo1 dcR˼567~4-wdIlkws`$[ 6'I*"uwW-sR6Sömt]8ƘD0x dfihRv.Fx(hl64 zRFPK& Y[ҀL4h`4>C0gȹfC}4YyfqXiܷsmgavHJwFtNH,k2Eruz~)/}Gxe khXބlCPWI0 DNfQ̩:Jw{ӆќ{UCꩫii抴q aɔ]cN O5@64.3^ |V>6h0t|jz\pISN>"O@,Yb5VO!I+}`sٺ5/#=^ϕsK4#憰nu7ė"O9%~+xϿFfO `PG^"uƖW^FWbJ< K]aq$5#v6%$&=h$=YZ:96*.(<8ƃsJCklXǡ :ZCYYw%-}ƟFfm:u4^_' 3hyآ|edZ4럼LzuxdoSz_Lb%_&7ɐIV tz{n. [.:-T[' 5z#1اLc+`e{T^Nc `*AHFf5Ceޢo|5r[\ os{4nz({s6iu 5_o ~aAG@U<1}dxMeȼL)S=3b% E%}鸈LGM1?|bayD Z5USK"Be$ՌǿO>PGʼlYY1v+)-)U^#Oixsu({^Jh;1EJbQ⊔T6f@3ӓpJ")HUild $ "a$(Tϯa=vOѩW)ss=|yiQϋ3я4~ڟ}kE4:㭠1R2]qzg.M={v iqymXѻ-~xoG^pKZT/[kA׏2&xv#(x4;&cKgn$J@y/\ïx^ n0X}D'R%Ҡz鳗 (ް0=׃Ny)z <x+6?=7(1I{}"ANg``a/%djt[M7X*t E7H LV¿ =h?a$HS@"oA7׵`c=ߙ\x/ޝ<E  zA3߿:~!H_s?;5>5 _2 q?;{nϾ'U!_#O!X2 0~5 [(r_z[z&' bAƯn\FFㇽ{xv? rkEm䜷L:zSDUO&??L~M}z? ,Sc?WҍH(Gs 72?4O=s?ǽfڃAsxv݃o`h PY@AWݒtN+]?N[~܆k]J-dJ^<؞L?9\ H= _l" P?n )}O9tXt2@AT~ԉZkH@\`DSgoNdTՠ/ DjQmePvA{C_`HpxHLɛ'r>:?b@'`9|GSۇg#< ܅W|}\ ہ xOl.݋fO4r/A{Z[v%_7PoŒo]$: Ed3"ǀ.<~xNr)/j3l|eonU̻ f gAΆ;;e`=8 -XI"<1z?Y($}q n/yQEËBᑼv~F:-V2,Jc̛]OHV$2Z`3#J̚#R/Fd,^vC[ ZTR}ce05wn[! {mB5!zVԳH/vi$ߐ7mVa#oj͑^ic-`ըcJ"{;Ԧ=G9ԔR.~gWuXiX8v_I2'FdTA,&n OnMD&נC^`؅:z_DdT/vXB _J Ev;^% ;_QZZdWU 5<_d"2Q5©TU##q٭i؅5oۏ߼ ٙ `CM7>RҌzߘ6&)qc ~!_,HJT:+X>(bGnT  G i<>4;Ҁ.["-]toinjEy)iOX9͵V2G0P$_i3L0= Fylo*G׈@ N뉍g60iA+o+;QדN>ʊ%cIIQJiLe?=n{zV|ѹ0 U̟O.H|z[/GLQkTP`%v9&>DD_~cX~ŨW1!#H!*@ȷ~zi~+yˁbSCK%c3dQD ~Bl9;+NڞSR yPبݾR!آR'B: @xRb;Sw YE;+:U0=O>FxEcP&h8k^*)}@V4p.U/5NIӛQap?3'MgDbE#U;r͜.sl8,^R1.ƢZE_ޥAB-E;8*hCw~tScꟿD.x"IᛯC_R5($ܳH|r##J/U2T_o]lK'ӱ91u#Rk(?Pd`LeԠe#JDPaCMӜsb 끝'Cx}*IĆ7{jҹ"oˤ;q; e( 7vT#l`*sL.^ zё+4lƆ-YN'-K841>Z2Jfx W%6Qѐb",5Nef06OLeHx5"+ s.#jI]"\<"ykZ lB9_E(B'ӐBx Y{SF%y$zPgĦ#g"̀0Q%1WV3dpKV ׃?H=dq q.\nc, ,ӦMA? 60|)Y쾡\/^wbE%\.։ΌuDÈp2 gV-hEDujE۔ ղ=Ky3&.z]&3 }vT7+1IOQerJBCNz1cLKM jV4kUABW^BIu3fQoD{ ,ֈS>ɌG@Di6gq; r7.&wrH<C&aGgFo?nC=q=qdhZ׾jMKF*( Ȍ~f1 2|#QSHn)fm>p\+9Fc&Lw$-35?%IsEE}om+ɦΖV_ (aȯOϓRfH ` nMOm9UeP4w}KIS:##Ga 0tDYӻyHir OxۨxZm5mTVy&֫,Kft!kœTԛ6qΡ4Nu~(Z\@u](ljI2~o&e7_ΊNbRDzO {*NHNJQFQGLq[Qy~ȭS DSjx>h7S)1[FLi5vdv~##h5&;*\G1~}cr9&9 /\ϖ-o gn y7wE9g2\zߎ=ɠECM4W|ޑԆH X& +;I8bx:4A2EX*L$K4U77j+BcSK>U\vt(sogh\.OA-Ϥ/aE)\&te7ד?|=od#r L {BN"@ZAV[#蘊x! -ܪ' %!LKpr϶^>R`_HAG[7| + ݙ߿`)]H.p"&VH}­7J^/6Dr3[gFt͔wQ ˻z}= F$_-y+]мD'ˉ$K-16~J9íya?w 8lul{iHmR{ G/{k[RiCu 0ɴpZ =*MG,j|}gb3Tq ^LX\ַAqP8$2C^D3N%:m8Iq;0TZ痬ǚiEiBxT)TϬ,6|/֚=AӜPF?nd-{ $ny%O7 %5N\u]inṀB=2U.l\ZLnþ^=%Qh62L 7z= wFFav݃Tt'Dhed(und[8"^WPHv=(8ahmuվ`~frUfWowݮxwLjt'C 5~Ozyi\ qT6N!o`q\>092Q2(tPN>k5wvj2>k9H6HP{*ƌL:6rUʪ0)?k%Dߋ½S@h־( \P#e* uģ-7n|zَm#~oF18IF7r9Z4ꂿ7llNا2@`EHq5!劤m9^zԅV)naF` #fz4b8|Wd-ߦp-;OϬө]KMĝ5ZPF_af#2*IZM':ΫT!}NHG9<-ٮ͞ER)PԏOulG|s `T'80ʌ=>'bf[޸@RvJ(ٛKuQwA>z0;! dO.zRmSڴ?RBQcQSŠ'9 V8\x;h|eoNt=q('x``jЎ&xs<yؑW%xfcI9\h .m) 7.|-rVX/쏝R'|.ޠ uw!W7{~הTRa_8ePE-Rpr<r7 t7wnL_8b,B])xӶ6o7Gy\ϱ0Isє@MJvb\2шkVBnzI v#l@T`#p 6"n2Xɼ~U!jt,c.r"8mne1Vs}}i2E%Ֆ7\5#߬ž I{s ׃&Zݘ#U=#rhҚjYUS(R#]ډ00tܳr ^Ǔ3Ͳa=z'ƳWg1r^\e bBqC# :[Koг5Gѱr9u&x;&ǴᎱ#%ȘFvB.v [-ќ6uJx7lc ?F\{+>Ф-|_;_ɶV+ أtgH< 1j|Gp`Dř-SdLw]n{J;J|zOAB`몕PH Lt[&VbŇ{ampƕ\Nh[Yj>vGߊgln,D͟eo#xk=X~Ղz(:C 8{r]>.Y̊L3Oo`$]'8 fb',Q `0eՇx7Z>~{ }ȠVz!X(FK9w8D2ƁI%hTDwo7P:'ޏ\1m.^:OyAkZfI=T#ssfcxd 871 `0Ubrz_.+ p*.wM%-\,\m=LAXHP Ե>{[}u%j=۲hJe1Qx o6:O.;[Q(6I%ShP;("\0P 5!! ]5bgj}A֌?&?sn@ BӮ 4n΍4}oAoڱjv栊ŦwYG=yNzÿ|䖀SwȬ-={Wl1:9 gQV'A\?v!;&.=Oh5O>+M"dˑ~F)x*Mf=ũj 0)~`t= X 9o ՠ7ߒBh&VQÆhzLu؜Hynf7 c+=21} g=sHT\b>VaۛL3ej:쉼&BctӳT&ߣylj`ldfIʗ:&UG_J:72U&I%LAVYb*k5?l|kM>+es;i$_JlH̢T=Ji9DDy`8;G1Tn~ɞ^p=70dvԡhBc+v2aCkGlo֫X쉙C?w X&QuZ_uG[-TNhQw[ 'LmkN2N=~kb2>|}8#11f&4χg%ǺŅz([\DC7 = ?D*Q|ʴlfcؒTp ;fLL8$$īAFB~/cR)̦::T{(G lP eu{JWZ'kV!R TUtܯ#|n6Nqw%ޚoݾk">7+H,71#(KHEU2Ur\"#3H!*nRJc=URy͂8jkI hYn6z~lC+ 0oO3V[14mika߃2yнcg~\4~ .Ȭ>ulS]6%lG'ߟ Wup#@-SHۯn/VfC0XLf(f4Uc[9.N2rNm0x3s`pY CEUǴwubr T 9A^ ΍7FiFl@MRf'"/SyQÑD {|9z&8q 2 +5EnTÙ@Gaũ~8㠕F%缮+ wmص?"Gٽ&Sq;2βrK B Gl]=ݚYU#Pم0e5s^q8B #%.Ɣ CVCi̗E;4󡻏TϛP`݈A3 ,HY䨧O>U>pKj(eW!wX1n_ <& uhM$`O:ikȗf:o! Sj8~ޘC  K9+A`RHN{8L `gKHTV _fiS8`21"aYeZEcHt&p@2SO&qpKmZ#L .|?KLJyUs4͟X@Y~}say qkhpGxS^BdZn9QE@ڸ %1z5]9GS >/Ɋ6S+H =>&)^/&=q1ňѠHrGpY:"S`).Rj)fFPJSJ zNa̲۶6z5H8ꀘ:Um }nYԍ:ݎZk;z2 ':Qq@BH3!fJgik5%.u~L i9BnOМ^$Pj8d 1>pO0`<RvǙ8@.IAguZ ӾN#S(| '|*YlSc47xg #$UM*"9gn|-Hs+ zAt8ȼJtu+&|F,I7u[mQNU(;uKM`i'|%;9dCL#ǐRpؿ["˹bmy,=|hRYwe-zF[t\%&ˋ Sa=qsryde\ >KC: .E\+ܴZ# 9t#x9Jh9GnNqGd8}tj%7ߑ=kqS;ʮN+K`:6g޽pQ6/HoiCÊC%U,E:I{*7 eAL3::#> 3A! r:w8[?!C1>)gر&V)ũ(ʮW%֑8oNsz˾q,+錮PyɖC'3W-N*2¡I/X c WVS=\k7i  z mZ[F1ٷA'7~T9ψ=?Y|ܦbO؆15tpKd{{2>V;#&3IAxN#L E44k飫fz΅7\&z92N|~|ܿ¼gzx)Z ;|,N&yM`9S% HJ{9ji%ģ"`;,QF|bmEm^`y;Hwg0 TV>G| @GpmpYL*z(Jvd] e].\$xN S ~|WԠcN(C{ R)WoQo.( o+H<܌fWXebďݬdh;םU\ǾE˲L0Ιo M82WbϸuXm.dcLf>[PB?EȂ 8ຣjŵۦUL%[g6ͻ%+wukǮn.]FUZV 6;HғxRO* O vySc.{ig3;hӫ"4XYj!hQg .kOBdڭ"Q䃠 &t'%c [dNUo\r\ s#Z[ ߊۏsU\"j1*n>y0g rrc\q`_WyZǰ?σJ8vEPdRh rC(*ª6F pa>z%E7]Ȏ ǭwI3g1p#y zW}â5Y i ԋ&xŲtԱ+!2㸠 UdB:Q,xo*|?ā//op#lػ#{|E(V(uE zȔvU۔f%kǜ'HG|9[4bhS#ph#wljd<5>i%q{?UfvTNB<Տo xPfFBb \;ЖWT XҬx+iZۨ~il_~KVFf ι28vurl}͒:J c WAfe#i.AwL-)D"Ϝ ʟ=8/#ܪ:8Z`RPBY- U[2>m&x⻦s:![Nu-g1POcTپe~t{ja4ǔ4h$_XF_p{2qhqR*6~2X]U5փŽ|W]$rVۡztyq+@)m;HZqG A~і$ro/{FRp4xQ `Fr0+4qFhú/P,}e5Zc5lP`h)4K,GIx-_4x"ܤ%%9eh {41'MyGTէ l[ ˁ͵ ۉs<Y .)n]+G^K>:eNO9 DeDzP6șu@,:k UzF,4#.('6O7d(GR /y@2u 86uinNH08TkdmCO_0 W1s7EF0y=aRGfz swIwd_sLG8V^=I\Iz}j:S4ŬH-pďrUΓPLSBy8N4rX$v6?x7&Q*߲Y1Dw| {v˷T Y83Ӫ@-:y6x;F0K: .c+ 6QF{?VbK91J k"EWWΏЕZKH)n+uX Mך=K!U$5lQ9&XT_䝠wٿѻ*S^2""21 ^g &,-DM+,LWfBvxai'|qĭͷ(yw͆O{X O%uG;ߚpZ]/p.8~bqřٌ">*['At+OV5wzT0.ý.^?ֆZ0٤mt S&7L=E]f^Ćj_(~/e r&:DQ$Utjz^+Ȼ19>.픝D aqKf{X_ ~tGD ƚʴdA  Z};̮t%I.w}`{&;G|lv)ܚ{_ [q_FISCtW'[[U{az?_; | ǮI/F~1~Vp!iF3}ogbbɨ&=#H%a,s\r뮒Oe kou\Y9İ,(W;/yȣ=[7S$cz@ѧ2k*텹"ϼ{/ao O.2ق$ pƲKVDU<9_Q)m}ψ&Ř9i(ԴOWm5 NƌWx7AX8xopGnp& SwޕNS%KÚji`}%k/k,gK%H9yΕ_d17롇PNS;yYZP;KުtF8 #zp͞-k4YUdBvuz)!wd bBhqAM5=V K2rB{mex2[/5 ufP)QÐxaj@սq&Bvh+#8ݠkX7GröJI0;g{ +rvѷr؆A-{TgY%Y3[J /5>r ݈vph.R17.{͓jV[\g]]XMxLQo3IB"{Zڊ]SBiME / 8y\/p\QI+tloY6 AW'UZ(hsmen+2ѧ%{[gL>+~_4$Qt굩M$4 ?^/9dzE܄Hm ++E<d3i6uZv3s u8y@YV~( KLh4h*b!9ا+޼9QqVz3Oag]ZrRU=ѩWgm [KtQm#ڄ[M0ƪ,ĚYԻy Q<>"D_Bƴݗ 2ldKJVaiye84#کN5wP&T1H!1U,Ɉ2NQo=z7ҊDxU| N☒J S"Hãq9ts<65/]>W* aXv‚v3X!6?\/1CC0z!̒?WE1u'I&H,HLoZͳ_퉺 O ;M4` Pƈ&J(]x8=W6 آze5qCM>M΁q,-t UPJς^;aKnɂ${圡bu`JNԬl^ Zl;)z[. A3|U^|s!9`b$RDO&svpcw}כͻyC ݳYBC[xTBAgj`QnNߘ(m?IktPL5&:)/}V~(sTvwt!-DVZD!+1&WBF(jp2^Ux[-$ٙaOi ͋?=[a" j!HOk=#vvf=w]D*yKA?ʀsx"@F4D;3U1sd3=LB8SK C ꦻJea!FLZ6r/g`7W#0K3UOup°s^!x/G5w&Q m,39ZQϻ%U;f扻J \o󌔯&o{D_s^E5o{Z(P$ s@A Gkuԛ3༴^9Q".^ap/QXF(Z̖GCxs?MȦsy`;bH\3Dk\쟸 YA{2{Zq(h].,``x ~spEWiZ]ʒGt6sL8dѰ1sTcKA ̊?4l.pc/xDDZ[5WX/  J/m89 SS"IBd8H2dqG{ͽFWQ~i1RJh=.S7fs`( .0QdsRRr68.N#LJ 1ngXyН{PP ip| /Ǵ 98FҖW`!m͘{ @̢..~cųsncɳnP]7E=Hܱ9 1A뎥:4GaXfauzԼC{oQg8Y r1A+fע$%WuI ;Fi@kv,י 2c8 9XwEA&Pn,o~_ v7=Y_([ZHްO'秳SI{~Me'_< 2#wܦmJJN щg_`]+}4@=-BdMl- WA⼲F:f`j4$|Vlce_pJעhPa#'\/hiz4o:>Ec.+5lfX8Z./r )KmNU ɸ%qk M Ã$VEj Jk)}MDA_:uQdk?u4vFCaS4$+yxf-_3>ӿz_'r@[gJAP%4 ]'9.ԧgrJUBtRk!v]٢q<-g`fּu ~/O S;^{%)DL@_+`G2̿u46Bs$B}0˗n9^ik2Rr}.vesZfF.\UxV+W;v&$f NAg7 ]sոK 3Us`g-Y[@* r@2nRҚNKG㨅#~}{LU$$ka̍_hjŊ(2:fe.`" [*oecDNM %` YckLyF)vf:'1&=yͮң.XWn =;wD.1_YgRF38dc]eG&PJl%a+V=a6S2{pXRU݃!')&Us'۱t,f:9QK/jгꔖR_1V>O1BdV? ^P)VΌ( .UX|ȕDt܃"fv2^DP]yb7f+#ѹD|=\4455TU?(EZlrJ+=pw]i ԹI'NT"kgu:Aa؜+GVի kGVSȘƂ#oa›=da>F@ {~+ >gPXCf<ӛ/.X_дKeku_Ya=vX"P f\4Ey{K$f8| ~տ9C UGlSw"] yVzV x'DJ lZ'\Yn? Ip2(^ UAl#NژFg;\`xEZz)BMu=QrWsvBs;\*-dln%eA+#<T*ɇGITF8ӎ)S[Pp}a -{IIh缟4ÕN v_yx4?:nH0xUj4͎b=:PF 揝5*_a@uNxe&&L}GGVoJɾk eYei9YƋZucRemˑv&w@\?0{BN 83ދ28{^Kqσ11̢&;s›6=cfdZ;-([h;N7+wSe㍴|3KOGZfrf޾[;)$\ԫ0sÞ:"ZnQnHHLk*7-b-T2DN}·ȁhupq6DۦR!OEq´,P^В]`|}T\zAC4v@M#¼;1h-it;!V,絢6.d` ."@rkۦHUؓM)zpGŤԣ!Bmz2#`qH>JFV*B37wEN+tg+ՉکbIV; ù5Pllmk&9Hx#!&[dOcU^Dс㈎;zYCq[r/G=W- C*;PaHՉ63>bXq\r*'tV|BX gx=+i: |nnQ6^b=:3Ք>3ی+%ˮ ӫ-8mUגY&FA_-2W_ %{Yo$(Xi$:*ÔIBōJRUx_:eMG/nծXH B Db!TIMęVD߬+_)bC|tM/"Y.FVЎ/]!5y_=dٽuV92=#ud9gsŘp^lL'(uxt 8IGQ?vQRN‘,#eyX~_2ـb]Be8^e+mYCYdTҴ32Vޜ IS`]a;iq)óh 8襝 e@VT- _RdVk5c\6B(|7б:A7+%R=YQ< `2mm++@h/jL&Hz)yF @O~-3,kˆ0CTl&K|6)2u Xhޝɷamf3 4Yiٳgvy/t#׌+ [^+4׺krƤMB֪KQ6\~KȼPXo|$8'H DAa8 =G<8 xyN5"N+p݆/erf5Ou?cG(!ߜ (Y6p8vZ!~|uι4@o`p9nG.s89\9"8L7~8y67]oղ&߳Ի+u8^URj9]dDzu9jx;L1EJ>9c|kճv=R 4v yb$l@S;hxԣDRK8pc& .m'нhK˸ff&m('t@ &:舘gކ[ oc0rWåQNJ~<!{yrX2hMXUM)m7zW&i ?aGhÝ6Hm% n1m*yU},1r0v+v>ALJpw+/ ZaܠӖѭw_֯=8'&gNO*rCIN,JFn~E^2i\&s}M@q e׶m/:/>s[~)+79jZpaA-k:oO2%3 w}.Ɔ9 JP~O[#=)غT%޸eѺР|;U.Ȧ$? [&S jg SF,^WA9D頷iEɕndyIXx{gb5X~gS'1FjS2XQ2y+A.X(Jޕ亏=&h+>Tp=3dWI0]8pX`帽NuS>*XOa2D~%~b; *`ׁ/ y-[<=Vc9z㦳\:QbxV BvFА/Lnmj},^Ny)#C,;mZeR9r'u(ـCPlӹJC0w̜\Q֟y˟2`x_nP=ʷ &0TCY/ = 4aZC$#rDZ ׅxroI@nJ=o ڌ;9|ŝdCrmYaMޠA/sֱ{A$]=E$!Wr<[X{gջʒ'~픑Շd+~k_ T;A; C6`3|&W Oi "vosVdmGVr>V>>(/ɞq t|i}PS%6aA*+@NVlA'Sœִ%Ьͤڐwxy^heȴ%Y1Kaj)SoQa7mw57qM{"̏eYG@blXA- R4Ho8-0YIZ (;x#sFqK78RԖW\) d OLLE=@&ajrMr 1pC/_21Dpp`8"'*_)ٚzeNʅDyǗ+(W*3UKcyQu!Zɩ_պ.)[X *9dЁH9 *Q+Xa~ÜksQe8mqZuN^넿(< VdZ6BYEPu~)!!r%oP,d "?0\nzfLù4*iJAb[ok+=9Ñ1Z}޼q$2׌e+a!O!Ei] OqѢ!L"J4n>tGhhȃT֠%8Ւ! ZSE}""մr[D`&*ř*f~#+A/3Ȕ1`xFDwjv%fk%6$w$𩸈v~9ugk:i'Vfxa|P>X%NǓWu`a,:Tڄ&L%%bҠO$£8&Y)VB嘝w;Ej:c0vzMeh(#7^s\i(@Ɣ7H9 cv'GƏăZa)e,])巉 W&٫' b0xBxo0~[J(Zԧ!L;nF(Zjv߰vzGq؇QMkY%eY4v,L ?썱:"sfdQQ^q$bE,k*`8-n.4LT>4!J=`&z=G̓*FyiP7NdiQda.y۪ѱh!:ܙ zX~6|d6ɹU.آUIa Umۮ 390Ts޿"ϕK܊mNk ;\_Ք P#uѐFДΙɝ įniQdq&0wI@fy4>y:&b$Ϫ,>G?s:`+/~VB>Sm)t (J-yۂ. ZMiBsDm? M?CU Όx} Ğ(7CY?F*-_ĥ,9+}9]q=v2`Ȳ>n[jp]vm ~uRYp-Hb @`›ԔeX+aZ_xySW-k JrP V;OU#͟Z:KG+(\h@EV꼏hxK`_ӟZ`O~&Մ9 Ec1œ !ԛZgƹI[6Ջ#{1bLxu\ KKQ/LٟQgmZ|}ު"G?;azuhsDɣjPܲ vs\zaJ@_nJ9q<{XnLU$-//l؍0W4`p S%.&VhiQ/vKjV7 7b1t#H/]1(V ZOȂ''ʝmBJeU4m9T]VRNjo@kBu?V|dz?Qc1!?T2j9r X4ѥ6I\;r!18M,kgPR (k" MvJ(! »R׎a+J˸`N/op=њORTYîNVqu"/ʅg4]@˒g.ȗwչ<քO~k`ϊ?8Srh~r%>o.ޯ@6Owqne2qRՏX>W6ƌқfz+yï{+]=ekke;]ey`X\*U.TpW3`|_&RGYyNfMuhߣ"ysůD] QM)mg_v$0ߛ%`c)1޵?lE}% ۰/&l)csfsٮ ʹ} K1hݦm+VkC1s {<( iV)lj_#Ii柪W]ŽR?*\tb s:Ir]I4Kmi8 M? qHgOw7\I^`_}%lx QKQnB\)܁PeO=4 y D =>z6Ҳ ,}$Xgތy,kHJx+YR_#"M֟uޤMUҦM@^K)V"ODh%=k\װYAAAE@Hnze()='D%dǦ:?H.-7TP[H%wtHTݞa mt]cObsYgoHW5BF$sJJ>VcaovkD88>$k{rd#Sm|f{/Tq?#)&Bd. DRnS9S`V =Vdh`,(KQ:?hwb]n%R(9~}үDTQ,T_j Ob}yx-2KP>[ {mU=KˆumYНG'pIϦPhx>~rȾg,Qhk[)&_za5UB  >NduDvMar}jny+ ZI.^4+j@]=#DM2P[2T7^iy@inmqF?:ǁ.@f O 0Wa*ljntaE,TsXN1V?O'dg:+לP%Cp*yzgk7lZ[xat/?>SI?SQ8":\{ "lJͣCF'{gyv^ -G*p9t0zљ0 'IwϿ^Np ZktȪJq4e?I>Mu@b }(X}LG~v=^fn,O|Iu蕪t Wͮ8NɆ;xEuoeGuv}Nxd3L& ub[m _#fV-##G8vK1W>-Wr,w8ьͫ"&$[.w*W 2nT* b׭R|j/n#16٭I@gVnLytlPdH;8>6^P?_D.xo:It;c4 {S0Hoۚ84W}z54y[43.5HYX qw8 L` sɬn$̓sw{ z,Qi >-HCȩ[Ԉ!1~L._w1tTC@hԪWh1Ӏ% 'aNeMq3&s]F9KRmRC>@+džCIkœ 3X$`\M>-&CD]btDwj`bB*Sk !}?݂2 b *!k>Wt53Sg RO. ~ygVpPBcUb&X:'\կZ@ {*[l9L>n*@ Jyx.h V~#u0wv (ku$D]:Rsר#IڴR-cyUNw~&eˬygM]HҚeiȸ3 U7we^*̷8&SfԠ@(  ƅQ8a@:PJp*Ȃǹ6[7ktM:we:/)6ڮoʮ_ںx^:y![tԔ1:{TcZGrm tI%ݟh JM$WBu M=:c21^)G.ȕ|D-+%o꬟v׸Ti#Oֲ>&ufF 9PR*Cky3u5l}I7ǭʉ<"\=R!GTݼ='&b?3:  2"vC6昻Z e/Ow%lԿ!O}/_W2nDM^.@ɲwxhQrmxB/`mƷNL~\;Swcr7^z{Y|lM_[IP'(8-_9'_pA! pq* Ɂ/ŵ}29ƉX. p |ag3@PqQuQ;QSu1m_Qbg |@D#۠.r?ogTόj9vs.@/8@H SLAseۜ2'}YAӞ2у;MIc&*v;Tg *w Ui)] e"wr2MK*hʜ皜 ||z̰za2l{@6&(vȫyx ]/zϝai\>}Cn_qqj>1Lcᴅ9 =x##3U/@@vwe 8h%.,k/v.p7z@QcD|lւj~Dꔟ_te7w|O.}*t1( u?Hص^ AkG@HJXzjuAC#V7M{8KKAD@B95qubl*u2⑚qX#8FSd;ʨxHtOd5Gq| V&ryՏwBg(PZL\?Ȁ̦zDXG?&{qWHLb%~tMǺT*__KO޹4-n$ߨve} kCw$$NB_MyF,AuK4,ln{j&HE:pqruAb]Gh:I_:Z6UW(. C})ոWPuLjD>&*r/yvs']Z*ɘ5WdFokh2k@QgW7c `lha5Gh<8@g\40W^$@!1ihvF8Nr'vL&C;WGUϱ.!ݴMHW=r4䟞Ȧs|e?1Mُ - OLZ<϶1G40xM'wdq5F\PW'#ȻQ@a2b$¼Fl/A6&{'.rt lٙGU+Q} HRT~g<1 as'pyeW׏S8Ҏ.!ם򣔏GNoIΚ# =:?- :D~҈>7@.|›HUue-FekGLD>23C@mlj2ߚ83[e> @#Qb c3u|WT4܇Pk؂FƊ%a{=[&QC!2G'G.fy\UMC^5k=ˤwiLJ5v9+r?Q=Y<jǶN'ڑβiKh`~K;y/}qԾ_) sذ9;ug j"sO=fABmݣq8R v+ֈzy#a #=y1^sX #pOς3iis{Z pmWdP c"55#K(_ G~D?Evd_v a2rjC~M$9J9e-P#i-_|n uTi5k_X됽i=PʏГxb֑zFwaR4k6S~GYҞЬ%qϗdqGW:M`gXZ#twk,gkν46~3>Z*|!.R@^l>T[.~I[h`l$ h,iy4n*JJJl4:6H_&A֟/GK`s;Qul؝8uNb$fLQViS1%Z hDGר7g$CV]TpiT[Qd뛶<qER##پ3#㶰U=1.C]K̂~8֥0t1qa#>qx3!"Tӥ3n!) ᴦq(jwUwN|0UO87;3iWx-vrDϯeB^cI؈%4Z6>F}N2pĻIo/qN"lS2x|nAeh]gFyorb?{lhFnͦ-d e#Q-NxX)ԇ^=w̟9; RV!>3)-ǕLxx"d=h7삵E9TS_͐vX_mgkPgoC:ڀwV'%En可70Ǟ֯<Ķ ;yts he De 6#_Ny&t0½'yf27U`I0|u%[6bն^ $QYgj)ybx^cTkre5޷qaSTǹ xE`vEC7vPuØq1kEr1͙d2&/zve`9`rbGj:}󍉳Q yiw"&{~'m.`gV Kuu*:~]63u%b.֛[ԚI]Zh)G6Da6ybئ4CSw!2MbjL8ޱ']/+༢uGn7*-&hz4=q^P[wK5 bn\K_ΒJd>dQOlofs|ǦKOIM%?8~h^!Sg*P>X1?ݵuԜ3~w`#\b57V \ُLsTX_j`.Ԡo$0C4PلRTqDcf18+9Zǝ;_-h㳉>4c\Im/cxoR :sx=p۳ypGɞ=l4y2 pl5GmV!cQA8z,((,iW~'kbDe˟b%Y[X;X^x2DWJ\4Q& 6 皎DQmL%Nho.¬L$X}JV i(BA|jE$7{d^xA 6-9 eXG40Us՘O+'-o%O~SjvF)> tӂk?AR7_y TZWm]ua*A^'`>q %L)S0wCZ6Xְl,&@6eگ]OŚd}ؑ۲NbK>|A ] U:F2vRD}w;"8ɕyG ԧ͐SveA)1a.ƿ#AC"'ROstE l i˱%뛌EP5HŪeiҠ+k@HZ,m}zBlnA#t4s dOF~FtG{uA|Sq3{=ۀ*Bo%b =`uzY5 $ogf`eW-z_{W!#RU/ﶼy 8Crjޱv Km2B` lB%%<-6`V7ф U`m\s-f͡O2M5)/׮\|!"#tKfdJSe[cۙ{ߌ!,$]slr (M̉Wp)*+!&;MzRgw/ZT-蕄R|SFtA(%xHO"S~"Jb9)k=Nx8Ҝ/`L7*cN`(Fb*吕>DZ.M! ZUu @2EvT٦lck;g&Y\nfu#{FK`Q҃ Y_:˪r_Y!ɯ-Q㌢Y,TIS-|-MX*{lGAk*^1vy=IZ%ס (}S |4Ɇ4ed GjcxfPYv:,Pv FyME젨7ak`! i{8C#Sfz^FOʪk5u<x[ -WUCx=>p#pXtf2HOxK5|c2qFke H>]Ss8qcD?Q:wP[@^rN+WU XחK})Pwr»^Y=E8^L^,d1Jsh@YpB0' Ƥ:㘴a zߟ5v͔/y^7<=R\,ҵb|)2ygc3كm>zmI._|Q6Wex֏ {5a uǰU\"(E]sP!9L*iK:%CwyeAO5GYs7Fur+j\W C'Þ@q?pȇ%\I_~!́z:՟ivC'42"4]b[" (!{W.t$e^}_P!E0wk!_!W^ΞJٍ>VRr_#Σ̣/[Cc7:6xv_oa%4v^ap{YUT/N{3#Ocm>ᮿS {?C/ޅz| \%O^܃(9T4rBiCuy_ɤՈ Eoi~ZOg.ׯOg-^]LF.{07Kjn7Sj^2Q ʕ\T[c`a2=ʩzS-Iʩ:_n~9$KEގ[^V8tDސ`5(2cRN[_cOu).aEgq9ekJ l/ӵ۔+cTg)&?aU޴-$9MN2sʳS4,4Qk`!6EsD{fm(Y⦕"a9"YHr PSk1!VකDSZz(QGpBOۄzw,pʁuVvo9{4{'f(98o^<;StڪH5碓OO }ȡ2)w0tSQ$Ux68JLWO$]] .oƢ)+zk%ĘӒüX_I44TkΦ*Blo>d6L j3/1n|;开-D#}-cg5'/ evc@+΁&]'h@KCk*EGz`ލ51*55UK7A(\]) ?vKmRy39Z;Kuh1YV u;KtȋG s[_4n6Q ?0N]Npu]mՠΒxwvH5 A8)%g3xڄV>'e/˟E4]J5GZUK@ N-Eno45ׇXum""e5 }nr6w <Ă`gJ v0(s=CSoU8y&x/ځ3A9\ufn]ErS:z|gߨZچYuz`:P'mD)q+$.F\Cr.:a)X{"~Nڍ#hQ3ΓKeɔ0t&i[o5Ƽlx0~ MG{rJeOgblZ [͓|i |CiPsJ̙D ]7uCGa3B'oͅMecDi/eqdmy9 ,p9XJ `AJ*@ls:aSAK}g,%XLՠQ"v5o @ř5͕.wj7wycf!Sӷ/LAh˭c#K/, Y҈3YYF-ȚHgNڼ5Kⷤ4>Q]zk(>]E2l؅W/)((}: $`5š0 Y7(L N#ՋS^Py/{cavO9H{KmhDbxx\ao1!}'%L]ZGfI1L-F2Wgu]KNUe6qԅ68RVՐG3uڵɁdpf:N>lC4i!zp|AﴸZ;ɉBW1|]7.쀔"U۽jg_{je>b.t]o7u2ԠI[^! Tla#udTBG<&7@G8gyr['C0꿯FY_ۺ)PƻLC2PxDUn;YO{A9l(lżC QN.gzv&zy._6SCGkCk’H s.%wH9+K ]BX 7 [b 2T0~O8VGrPi㰢)Ӻ;~ؙSp~!⪰7--DBԷxrtlc5}HUͺ9T$sS(Nbgˆ%d H5}>:wYrk\?:>mAQ4_kl7'n@n&֚ki_NF1\=O18T +'*ͱY3W!19?_HA$G"nt8;6r8&=Հaw\-cBPFQ_؅HN0GɟypORxIGܞ#yѧO>gN+G*W?Qf[QxXB)@N(:j`|}!>ra!1Nc?a'$\ %'fΤ<}ʭi?X*QjpwNUW~1)OjHغouv+>&5'l^R^e:g͋"&4HIYP%R4y_~3'nث~99tp7U`YXa,t,)S HY^Z*XTBZކ6$ytD0Vyp8v%jO#hg~&[U'L`5ȱh@lr'WݞS9CI2I|m5!ZJ@0)gHti"opPlΰUvb#5bO !ߟ|?lvqjpyarf<5]+'DĎſ#*shykXrt)( qPS|IM< lӆ,3DP F#[C8d.7~l ȁSYK Bo&'B2R E_Ṛ%y g>1qlw]jm{Q8wAg.]vڅ k䷌xM# P$MFa/jCDsm_"bܰ8?lh=E.%wQFoyL>KΑRV^+jeA--z~ W住5pSk[<i頕a]#U6ecITP/4r:J9 ZQȧWsE5??!3 6r #4BP rS.U@/%+ˎVzX"1KLq2OGajJT(ƇtCc#da\3ETe_+!ĩ4L5@c",Z<ET; buBRKu:KmR*@G[SnX|^'~qEg 4M"O`*">;Js%i5#~T;"!$U'|R4k)~1j_}lu;P oEu)qcjڙPKpT+iP8 mH qĘkqT{/]\)c4J4pjXnk˻dVBdmӼbBI1HTW&<Եn~??.`%ix}y|U՝\7Av児CXBYv(*reEޢ,Հ@cK.LO\ڞLw[R|_I]--+,X[\Xi[QU-Gޕ~RoߌW-Ǎ7uᄱzĭ3V'o~'(|l6in<Ѫ 7ic9|~z~ErgboarW]ӣN-?'ڍYLhZC]!}NѤx\+ I+1Cw`څ8'C^oe3pq'z[1Z~&ȋXz`.G1,*n|Cx֊b؞rg|pmwix+d+%EcM x0=݅yQ04a|c!9$oUW0 .r2|.huÝtc%BE"*ǮZ9M# AFs\׋(Y89BJ 4ʽ]U}\pjgHw4|74$P`2jvIViO@qǵAa"-%Τ=x,C!a>T2kS$czƙtd= 5$ca%S!;U;iLhׅy@/ hj l:b$37r ~8A;Շ#t%jB\c"CCG~sUD_'226KMII-V,JKڝ7ix:2 |^uj !z G g죘;C66ua&}aU\w='i_uQZ͏ŭ.uM.r daN8kH C"AHQ_P+ʥ#3jձLGeQ2hS:eYd#AfnW`Ձ9Жh]|W0po߉s*^SIZ2FhuvE赓4KgID˯,brG+kM>^IY@aElK )+&/n̩b;,^CIO@=v(R_/؈h */."mô$bJGf@m#詭w!8T8T܌f6׋& - 0@~svz{Od4GFt&fq.Q`[ŷ1ǣn#R[&{y7J6Q;BHں0}A.%QT}ʮsIg'H{_\d<4{fHp:vDH!!86]Mxzn7[<]g'aYYLVDڕ,yIv$8zn>9No,_ݛNg: ƕFOIq !m&6a7$$OAw[[ W;1jy+ezb X? ,b!sƹ@F\ݎo2u@}XרpmXOVUH1bWe16f8YuZ|0>I{Oi|ǁ8(+2"c}83c<|Xi3=DsH{QTvOgS >Ea|,nI7>yɍ7bV{7mA6'WdVHDce-) f 0p˂*?AM &mfdKaް*n 3ܿvb)37[=R ̀nDXnXAqe̛}Hv'ɴ'c$n>P&WA9glלl4aD+mh:ۇ$r|ӵt甐abv^&hZz֭[[Y:KAdѓ%0fƁ,|7Eb؅~v1V MYx؋oզ 8) YS-9p qj +A` >V5ս=eުb_YWz’C`Y[]Y+U{}Ԇ T(.+Rlʪr\vH @L3찺NX^_E_߹dhp`MjOP׎ nbY48FȚNd=$b#JY؋\5 :3KLƗq#(xաa%{X]ljHnn*ZIئpL$r A3݁Ek_HCyΘehR)~Gc)wnՄ:lq!FkhlWUvO F/ilp>AAflfj,z'\aP t<׿hW66iz׈xن(=%t9 <(f(ftxKzxbspdr $ y߉[uVh9LƁr4"hE#s}w܆`tN6ˬf{xPwϬ*ԨYέcB<}Y*F+#,Ja6l6T W&/#s$ȭ/'>PcܐU8uSqcDQ{hnI%éDֿ_\lE~ޑA'`X4q>lކ7 slv+k3HWH}cm5gZcmue&HqFǻLqY-^BwANE 0EAW`u;L6%sɍ9^Ýwbөb{v 8p$ Ǵ90Tc06ڊ Y(+[]#uswLjut衸L7h,!R>Fہx}iG`5MO`t3^z.`ਜ਼f΍GyM]ƆI>;#ha/Ǽ/8v+X}XC_:żF)YȣGcś/>قb#m qU2!_MwlamM77ܮ9bG.>tؠ?$~0Uw=X*NW>%U ,G&8x ބp dfqH]3||L#VH3crXv2qVqL1fS뉄,!sV=o7Umȓ p8(+) &~7=@&qӀ@)_g敺a{pd+ gD !G8._lJ[<@. Nʰhϥ%( ۏno48ȿ٘ās+m AyӡdtwvIc) ն&M8Mx}"[-OΫBP!3V/YW7OĢXHwhՋ)aȪ00y"WRjb#Wi[3%~rIvZ\_=غ݁IB3۬u"洏{ KJ3,͓O?,#.@ԫ·w*7N81 RPh`%Izk#{!Rt4_rQl2d*$̸h ?՝S1:[,- X5tkM@rɄ;%6q+?c }Z0LI*ф҄`]Z]:oO](09/qIg+Uz9s6U~L+S:wgn/K/\B`9qm,хhJnd}p2X+kG`5'hh+ۙf hB8+uR YX-4#A0D8N yxfә'mRXlK0<`(I,$'Nyc'qXT+=?Lok9pư( rީTI\eL@b?RF3+1đz=,oM+ɉKE4ΫsTENrECkwn^:3\,,rkL3~/?t5Acs5wVPOYeĶ#߈5uؓ-<:*KE@adX 6$UUjɰfn%@uHŦ!(D4蠍{TFf{45ki_r (&/!;5NJTv &jVK ϺߩX K/}t'KRAd3ܲmnO3MJ@[ ̉0'’tvA<̋J4|RBg_ܿĶ1`/M@^cxꢫfkЕcN϶\hl#iؕ[L(+~ivMY "SvgO~фCFkO~L%4b3\WʜHlRm$kTr~)-ZDQ`!LǾ>'\á5RkHqeXb_O}7r!Fj5@Жy"K+**TO+qkc{yJu3cdb%CobaqFD G҄Z_$?Op;bq "-7Mۧ?{l<.UW~:  + Oxi >7չ_  1Ohj50W y )jB+xGuoa*Qm .ΰA 9%[G=J>tfՅ U"ūB. ١YIv. 0w4*l/vXq@z\o+5+Sa D7^%wRvS+80EHf!%25;-f !^1쑩ȗ=h}B=0s,IZY:2(;T~IigO`gTuMM  ͦhNc+=l֑ʣ$69*" GCy]]1ǻxƖ{)BKغů_]t2k[뤻f`HX˜ECrP놛%=z#_߾}~ G{ {+T ϨFHXԭ5 M Y]@Cе$5㰁"(}sEͪ&dtn؋LD+f]IS QH{|4k95'ZίX6Δ`dãn6 6?&1CQW3 !B|}F<7i,&ؙBlXP&`=ެȥxeBX) q 3`Q7Kϕ{nc_PZL@w\ jmp+ֵnrl.N?DXDͤC;K1Q$B|s+RZГdr}Nb\NdgKX$"f2- <u!z iw{n ?! ~=h\,n0ө[0DFƦq? Ar3,7sk1%Ic3kZMKwf^఑ VŶneR= Zh g2Il|,vGD"v1QBc=.|ȍD>ͧ3'<3xo}bw5L QzGyh4S@R-WaFi0z Gja'{:|y xL;FN,bWt25oܳ83<=9}EV`3:7$܆`9rqH 6&^0; gsٰw@ěK`LiHؔXWX< 2sXXFO1c 2KJ 9~0$ 3L㦰D,j_CtpMRY*&KIͽ޽ `޹6 fs:᣼2hTv4 *j{v1e`4I}Ynq|)Nr &/Hgi\ l&i\e\H= iAkn9!svd03rL;Yp@> i1$|߁~ܸjPB%M[IɠQÿcwQPE%|U!oIuxWW** _|XSʪ*/P ߤX;YFħ38[T/qORpY28D40!ѭ+)RvȚQyic5O:DZB5KK417WWyy`}:hGu;C)it05 րC |7yeh)0mTUXb7$G6xWK 0,2m:!9m.C]E 0e{$L:*=n,r͖rq€P6A:YSQY` 0,*LIY0+=ec=e",ᢗ]3mV`oEe(Ow!yc38n:LfʬL`.vkqAOͫ0 -bh 0~:$R)+={{ +<7LgK&Np\0[VYޏR=J =jiZ^]UތGj0 uS+Q$СƏ=e*CVՕeZHJ' hP23y`(a'ZΏɜF[fX$L1bb/vny(y&|t>qh5E'k!p26)Y`ա͙X Q/g@g81K ÙmX;;iC6~D'/jDWE 0o'0 &2Ę=rY8Ic-hib P`a7Q;LK ֨#Y{٦ykM[2z vī©9q"L!z[m0eŗvቄb&FYd5`Lj4 3 s84{<N`m6+X#].0og K\lKg) [GW0[o70+}F _eq/Í񠔙 s n^eǏC/|L0N S7s* nG Iй5h0A\r2;_9c- f x*{x@Gw{|X2K'piW8[n!*G䃱`N1H0&Jb7}ҷ,xc1(S^hf$Ň{ ` l&MIS75]ꢱ*&mN@x#=hb-1GƯCq@p׋6ɣDuN{j Oo= Jp)A\PV̭ط#x:ظ͡(; %1{UD(Ki&ڃcm[vN2d!wolpH[4m~2t"֟IǷg YӳtGz 0 i8pl}QPl}؛a?KF%1w9%0o5 mQm)xv]a>m_ډUCv.ih$f7! *q@8raKB V3wOKTnT%ylGEsqzھeml#;t(&,Hv`vy;h4[=ɗd\/H 37߽9Z(J߼27 =hal޽ ckHO 2 @Ҝ&}KG y@Mx$c[JB>$=pnQ";sKpf`\i@l>QdO(F nŅ 9@bK.OJrYYA0-68и2xc _8$`s 6PZ#`JA|jxk:7}3冼f28^/D\V<.{5ڼRf,pB^ {7H^(7åVbqtTetgɇ`ِĉy h4p}=XT r0&j$>y'|G sCY[ xZ}adŋ2֐Ksxz`Y,  > # .1hl;6JƲbP*/f w߱2@ zk 1u $jB\JھDԻ>x+sw:T;1ع1A5Cn!Nw0$-8KO-Ǐ%K;>`$;6n0=)T( !wm 7`6ÇŎ}™ޠ$x{ ;'bɒmvDw<n`lh0i0-l @.7!iLׁK9IU7r4ONlY[#M8f͏UFRٕ ǒo#a`ڜY3.o)F)ZJ4~: 1 \ek-vf!X 4z)BD˦P_mC3T_OBæTvI*|6f`~~ SN /7NDh3,˗:Aj?;IшZOu$,T*C%}4+`[xJ;nWXʅ1`ٲ=9(;ٷo_v'a 9u: N !d2pF<_8j0*)6A4Ƌ; {*r FTcA%poTݢ01F9b wBeN"M8oK9©v#K\航GSkƮ1Wt% 3Q@ 5391&ĪZe_  h4ow ݱny0oЉUo7:35G%n|YJjm 6I}ok3^7~yL/+ Q'7Ȼ2ҌGè>.9gߚy' ! _0\!d3KLx;r+!/ZU2œvf0xEnHP؄)~R/|,ET9+eFC >`ibnfߠj:aM b6~3v]X!н? O?ƙ}oB߈oٰĄ03.zIPn¹MeQ^:~0^GLjotvǠb?`4zᰋSdž[G ,ОZZwL+1 38 X)@\ M“𝟂%[ܧЪ-Ed̩wP]nlt[eA ^xw4pXet$m).e+0d 6;X1}_ VnN3yz$$]آtJcĝ q8|A%K40H ȥ+ρD+_U_d>.CUwBHFUtCS T&+|$r AB|0s,]ɝ)s?P 7gO4CPI<ϡ6mfR4?)qFؙF/w?R|d8ZDŷpϺ}Ĕ;1W2'3tVTOH2bUA>r,rH;9+ Ԡhnrps(}ƎN'*!06fFsf,MMV6YK<@]vNj~Lx?MTC8LiY+<:BosKWCfj:~cfQ6j8 ALPl&x_Աfn 96G>GkFM621^M(&-a⧨#=y*wM^o$GmD:elƒ')x?FO 𬟡g+Co^{7c#0anc%) 8ZcƯYͶL܁~DlgL0BC8euVgίB1ZDHab(1JFB96 e2g\2V9:0FVy NJr_XӾg^NmʼYd̄Q,7~z0ʠdF&|-Jkbb/p!b+WryR'( GG'(gy0a2ڨe{nߙܕ;7\qXyJ]WX{Jq$e2w|} JSoMgh4ײKˆ->ԡҼjacՕCd2'\w NVV+)ʽ!+__<cgF0ѻ?ah32f#j_X CYPP~3|ZUV^Xe̙DB0UIR) Pٳ'Sc,a,de7Sۋ=XwգN䕮ֈ=\P9*qn4V9|G,p_z^+(Tc]k6;'&t2r2+)xcg¼8)&X[ߏële}8['OX0ӕ٩! =]لixe4LW"%Zt'S]Ze=%*ʘi"[y.NA5ͽ0IJ*<,ȶUk ya}1TF$)0k`H "*8_d/9)B X6 tN"I]Jaw&9EI/g N*qxFږam1ʽʊeŷ9xgDS4eaRxv%'O*tOqjqYyuZ髮[聯)sHvq6@ <)']ste,жyJUp=y;?ÎjpK~)<` '&d4CyDvc3g5.6CDd`]8ߜVf;x/GO1JVGBv3] C0ͥ^a3"CgvҴP-wǟ% D#*}Zy;#BQXaN\찰Y(o7U{`Be[Dkgr[9siGHjQ[l,Rfdž1v" Пc8xLp$1nOY[ly6v௩<7 AC59U#L X;QYS\<TVhN3wJI:{*-T/6GFQ֔9IoQ?0}`)t, ,;>XI[Ւʘ1+YNbiMRNXY@HFvBC5%Ii ' .=l#/l_U8\'}3du Xefa ^Ye`][hsnr*r\2y2/WFtɋ#yXgYəPFL@ u3\ǹGg2gs?#=CrT6mbPjo"|SתrXɄ'<,Mڸ*XlhF^kLphdW&xO_1je=4O0ku&4Ur |HY2^~D_bMI:zzc®Ն RP:q1D>7M)#F$p#u'a e`גhK4~m?R/Lu_07߮,D/Nu6;VhiЃ~H蹯pZj#4 ++IKG\1PF҇-N`T;+bKhQ 3žpc:R6!޺_BNQ k`sEڵq>/xlu(|k5ɃLL~,FAYY׼CAUfY5<Q1*7()wf<|wE땨;M†<7yʈm,TyJtAy b|cUlN@d+#M \ӨÚH CnP%4I̅AtU2 `F%*(}m1/7*њe.3=rzt^ti |c(@zt) n:ˡ6nUᛕ}VX8^ţ +e eg;UG1m)cܹ.M:솯g( 51Je'lut {4c# NY|ʣ8Fҝʝ YײKXdb w`4Խ!'d1g90A@pz<ZY41Ͱ+;fަY nY݀]pvEhav3## %޿]6 /!I'Pe`.e>|`2L (`$vBn%+f +j8&}`0V1?(Q&Bţ c;.NKSX+ˀDzķn 5?EbMqT\o,NܭNYŮce4AeP]'r~b~'y} mCnmgvIR%`奃\VR ^~Z5KTy,L+ MUo {wHHV_Jd!p(@BY%S}CtGxz zMr MŨpq$~˨!PG!}HU%uAB| nIġ d aJFhiW܄Wb`mSxOʕۖ nd<؅0n%.Lke7/q%M rk v2PX!߁c]lrV˄.5(T*KNjҒ>MtJ@X;=et%nYJ Y鹥Zoi*8bi'GǔKg|xWOR$u_}n񯇕;x "xm(*027R-(([8RW5FZb<>14GL<*x}!:كy,]0>>c S{q۱C XkẋmEtG5( \ f|MGYZ⹂a|f#vh5y_)cw!Mp&֧y–)2%ܦ0Oyp#L2-46 u[LMؼI] vT8!me-+P U*,Z3qM<?!x}ksǑw>:x0 EHW"%-C/Itq@4fz0p?L"Dbe([&EIh) '\eUe={gBf2UY?wm 4v$pS? ~;a4:~tz7ٟܹbs:g.,͝w MQbsF^%D!Qt{ z? L!||o?/~͇~[@lAC,]Z79j s{~!bB̏zTވqqj>uD (7!<}o8GuQ X r .2InCL}`0ܩ%$FRo[7v;]Rp[F: \'8ih% 8 )񚶃44 g_$;iE -ʚSA!Z 犲%ES~ 0Kdֹm$޿fd7 KlGAF;k@1SJ~0ifؚl8>Ch0rV.͋Nr pm[SnGa]#,?OБp>+(Y5Sj[q"BRd0YHb]g իt@m._^oqٗcF3?q"e`}I&E$#8{9{dd(?I2X;Il &xE[jez9Wh)cAj&T,߃Q`6w~N8&Kmwb<-oo1MJ<7נ=CF%$ﮮs>tރ\tã)hq%]}޴. ݍ0–N b[*>OHOQ's,YFK¿TX|>kjtȃ~tlG.bx$u X-Uc5G;2Cj&ƏZZj^wQ=V}m`RQBlp5?<Hx[ې[l=DMW@[8W[\Yth?w8UېC6Ox/f4KRoЦL#s%bhx|meSCgO=OMG#{qNNmSfBe||+fK[yަG.1ةp[MQQk( mZ;vdJ'b+Nz)6[4/>g}NɦQm+l sBy,tyq*s82imt" h&L}ΑC#9͗ Hh4ظ p8Eǂ0Zp[NuE+hV  ]fmJSð$-vDVCWAlGX xo ]5x][.9U0-@&ӻ0I8%?XgNF 3 0&I-Dń 2*lESP-Q-%eF2gWiňpI I{U"ƛ -F zs2M/+v܋vtAe==bAun!>z  h<- ny GUQv+$^rA 8f5]#n؋r=fAtofB^b$=ι(N=Ѯ 绨!U~˩!S`)$A\q '~!z~xvJ#qUvtg{n_> 3"NddD9; DOϢg}^Ξ7X: aYF?~M?gghg >mea s64ɄDK|0}'p·Dz M0"7 UDD!OCOݔGa^XpUp " @IEw k|[pO@Fku"AlҬg9-I@x4oDn S3jS,y!Mf29/J'@d'Kz@pQƜ>3Hydcsa>ՠ>O7[DzFC9=<D_5HA=ReN3< B![e)cN@l+yj6)kYB&qμ8t'`X{#R|Dٓ(oOJh>tBPpJ@"8oWL@JxCji[E1kɁdxʍX t\w7 gMeޒpO GX8z5FBc~~!c5 H P R)k(&`G|eC'ߺ炲 ;+(Ȩ[ؑm/PN1oP>(KηQ.`PxLPCg<YOjidIٍ\7h P(2zzrN}V ˒h(Xcd་J51]DѭFMi#n^u|$I=G|o'd/,=#rBvb5ʾ]()!OKy#J F3 [9D|˜040ZhP9btbRuAV>E &(g0ݓ:|>&vSkȆaDf!5e:\? ݥta3̉#E%Tcß>4yavbSekDW߼p-BO k4kS|AmZU+LoQÈ<՝AE hJc񙀋ld[e|m vk@ 粇>l٣Zh|9ۥ>NaҽGyE#R񞓅$p/@EPs.O^>" JwlE"N{Rp`vR}\rd1uT-r ao̟s,eP<>@ßd]"Lj,%"^eyx pB-xMV7bc+l( V^t9r]j"*HL ( [ YFJúnq6raQ5ϤT 4eHD @Z 9z 2Qjw47Xq*6h?1nbDB6f5m#c4ZXsҝ'@xQ2\D DفU AJ(wY>5\?),A<{BA5+ОTv7!Կe,`GdQ\Rݮ߃\"W)Unx6+Mgiٜ?cz3 eSG MS0s4N Ti_ժ!`YKą,8_hdž@7#22}j<=,p=m{\Oܑ cFK$.Wcdt43;=Dú[ .b\BaAl'W⌅m=e/bdJڕE4 IF1c ޛUs>. Qh_ u`ђ}w3Fr0Q!|Y2Okvl3x⌲ ""7nˣ U/ճ;|YLөW#{nZrX ( `́\n `s Ah b}txlFG05i)5X,M?t'ae,q,.Z/u(\WaJkEi~p h3Fߍ19Mp Ks|TIːp mKijFgEB< fs)ؙڮ x!Q,MĖǹח @JfUi-kLX9k3PTE- 86]뛹ǰw^cIc~3?qP>,l{fS!,JxX*\BQ%ƽӧ&^ioeG~ ?ɈL#ɞ^6}s`I DgF$ǀjr7COk#ZyJv4 (?sħk!6u U;43btS;[z8)& TNh^4 }jMjI P8kDp(ҵ8)tx.-QKܮx0Xu!O V3}m0"1>9A #DR?-BlB2vs7BFlۮY)Q \Ԯ5[.<6BTӱOuxRaDԋMp~>7qhlC$'qvO 1@".479(kZ4bw"Rt et!7F}!3!eIxt]pXt\Sz\1A>SsR,MJ 3㧣ɋ/.OJ4Bt EUL)^tEߥE/l{}/Bb:M "3I^trv--)Ѐua(7G*Y.hǹ((xǒnpt(&$ t:֒@녳XKve U5rp_OK ⽰hKHƘ^V^Px ʒ-l .^{n>dHݐtWhXvߞ\^yG>#} !҆qllE"WmMd%?)y&}oeI!1z3n xf+YjE#9mo_{0nMƥl塭ErJql]RW(X =g6Dq['VsЎ=0qp)1 X3{ʏ߮>|\q\6QfCXYzZuL`,b;/6`+ƳJas [e١K*JglsQO4zgҷr=xnrR&@B _—RvR{sپ^|@:qTjhdw~ 9l@AS41B7Q7m4SMx&PMde֮Yv V/9 G|J yJ3-e yor֝렦-`^)6t;6/3 _C^UfntVb:'vv;*?b` 4xA7593!oru"ە]#v#fbO꒔|̎m7zVIX6!sB(mNYi sSb= Ry$$q$$,Iac5r4:)hd*QE(%EEb?Õ{ݔbRD.L:J/qo:|xbzbUUoXlmyeй4*gO1f_it՞:7h>sq'~wYH`櫶JIACJjDʉiZZ1cA{EՉ]muXQ{]Dlʱ*qEɬ`ClNm&/F(®鴀,-MNDY[j%1i܊,C!Jm3[XYΣF'n^1uht-&l%-ւWĈ`46Xߣ<Zx;;tqS' \ s1<&N\$HjQh.ng rzD_ ،|^u?z)bݵuC3_ao{q :zsyЎw>A"fMA eBz7 %nDqbl2rs=,ߨ{Kw9VSc!-BNоz zn*\ (+G P3YD7Łr&GJ -HXA.S,Q.a&g&C猰M1sy{i;mƐ7 <q'c‡n+Ryq7-*=Qi^r`Hԫ%'N*2N/p!*McvI}g \η}u\&mEL1/ڃEfbwS{)v5)ŋ!DH\ڼeHr̒o[%xBK:+cM0x?1^PmM{\uw1mE~̥';|m(AO./zչ2C'Y !K$ut/:\lA 8 /1΄Ą= bbK{MҬw ݶG, ?]2E`m%єeW7A.1dĵ+xR]w}ޑFl8Ie8L46 v4+w}9 ?qxetx1%Fx)lD:.eL24+S{ٍg{S*X6j0=$p(NTĬv՞w_BE"3(`ss!ʛkNIb9^Elwmv0Siᤶ.(@f( W-LEcGs)']fKNJdP'"Efz+Ec~*nCgջr|1_f#j-9!S (뚀Yaݪyk JU%]R04yi9 eHm7͠#a~V5j;ayz5|vR`V0(Fϴyy-X{\YH!#^[FAM>*~n@F);?csDAqQ2j=88eg*ak$#j8eVANCqڨZ]Y/ф &q,_#q -v6Rk^鸰S>z }3#dK)Uw4BOCKmbI l#]9 mȲ!nW|#~mFk(A8è7tGNBevuLFPJNAX>Ȯ!v\'Br5"zؿ!j O3:ՠ YMj^!p{I`ɫg7~|Ko0(B͘&-*5*}` \g^a:*iyI)h (#2-C IsCZKH '2`v_>Joަl n.  g>/]_R(%[(\Kν\W<+|4 UaEOMIyyPd#sgƫJƻ|YtǏr\ϼW,.cL4@-K7,-s.Ξ#{÷[!Tڎ@Q̶]*@B==>$TLƺԇ(>@gĦ:b'3C(sE~Zp[^ǁ4rcSaNvc/si(ҥCR_|Հl"XDzLfDomqRQ<Θ$ RQGof eC?R^+58B ;s5(fjr[rR77`S4p4z~WN|BNIvwhWfy^/R 0nx 6"|F,Mfsqxdv:s>3bb"HBgM?ΥwϾxf[}u)N9B;!6:੢Ln~}Nr\iU y/uO[6WEZ+^ѨĒE/`ԏ>L\o^RXwrkg^_d%Mi'O{7P_T,,޿f>A֡_;pW$NR7hgbfٰYc&ugT[ $8BF>B#D"3UtenF<[o Oځtْ]9~;:DZX^c)/C<Ϋn5l$iTfD'bO-:D^ {و#vd餛nimCcDz/p [Eİ|m4"|tMC2^"RL DDrZ$>A$t͜EZ0psh:!8VE@u+(88NF5vG_}>pk ].*( N5]Dȣtr\.VJ[^H1Q $LXL+!RŲr]@\v$_O409Fd2jG .syCWXNw8h{d _'Dz*.FCa{6d2A`-xL.LL ZvVV*DƲٜD!nV.`m@~g5]Y_TSbyYɐkDW-cWNB{"s]ЋsmcdJ0/Zi ϶ _:C@3 c#7pJWVzJ E@ S?S͖TK5˥1&36?0YH L"PR:"h"Y肁yvO#Le+Nid#WkTA+]j Z"s1.Zga|_6Y;eH0f2 3 ⮻m=Zu[sJmngi붮nnZ;wB??;c=sy/I oh8;&h\qugkˊ.bJNdODP.pto0@ 8"O<vR,O$/`;U-tzH7U _!h)kDKh~JUWNt:+1Z@xI>@q;^3Yg+ Մj2CO:5Y]d]̑ݬV;F]E^[8G$KԲ. XϠ|% rNǡyT@hu4"7ĂR6J"?-Ǻ(St/y͆qlK H0.뀔% KZw"au(D~p]7IK0vN%> $)/"CpcrO9@^epY9$OeQ#|:. SzfL"c <.hZ-]CJQfB*|''g96)@feORwYaeX`tOZ,*$/)=RSB1WE iBKaoc3\j}yf  rLӓ~?|sS%o1`[Mk'iZXckQX}g!\cKò^*GV!Q!z\Iˍ1 ͺQs&*`#?S-gXߚ$X֎6x$#kB jv[""2Ь2Y-OV1{T"[=Sះ5rX_r0vvlģ٠؍P1SlLs|lc:ljs%գż'=rUa~ZxW-4u+$#YGfR'ϙ ]Yb2D#.`*t|* `٭nnz,$h߇"ѩd(0hپ:5R3<,6bKi#hY>xȗr1 ?Y"-}FX-*> dc؀^ ѪQbaؠL 6p~(AY:$ ɠxpspϰU^l"؝6x}K NC#%9ZuH]~!96Ao[1д@(l[qn5VcJ2ķh)>]8xˇGUp/b~*xW ZFTV—T%^f+6^V緥Xy{n> pWg.HJ\ReH gyւZHTyOҝ0}*>283ݛN; yQ?] VԂuȖGYM̍*x!}n䉱[1ET䉱{Dv?a 0mztǚVž1 @ 9Zad wq談՘~{>UObZLQƦ9;J?̕=IG7nH^c<'5 NqV_+(dH7R9cމi3GSh@"97"o2GĐk%3)=&9?ި;||~O*I{&f]$V<٧/^BT|׊}D}h%dMɢp%ucET J0Cu7nQ.bbFxUS\$Lۅᠭ@DQ43[i'3i SD&ڐ9dwZVb gkzʛ -'P+)c*!m*v\Yt(-/V^&1Z)|s(zAE!DpS_ %aٰH!$Gd}\!]sj*dASW$FesVC7u͑`j1B,GWCtr%:lnG w:[dip}T95"F_q%dKRDGh黆B{xV4^AG90>(Wt3>D0t&l;EXgW35nrpo~- :L9< ObpҚ^&QaN5Vd)mZ(foY#1Hh5xf3(^Hyf0QAx 7f~ Y,&~_ULdV/鑔Rt3Fc2A Sk Ǥ 㗸A`"uƬ[%@_\^(.\E8E0`fs1(DYDg!x-x2-O{\2Wa.YFagN"‡1'"|eRD)򠜊"HH #X _ճGU^d L,NKpQ0Hϳj2ͪa&[ZȂ$"ZU8i"e/pXw'9.4)0 e?aiV(7{{{>y@ҟG1uHIH8"~KO Bҟg9O,y1]/@۽yIh @#?>;B4xR٣}~4EXG4`ppp>::=M ΆqI?!:$po`$^Pp'I0Q xsj Ġ-0 /CΆ$H0(qt-\3I"|x71 C̲^ <"A4&+ ڃ"]|IArIF%Z%|6w"С"E\C8XʬM!ϙzDHY/a@ v&p<}Y/Sz؎V0w> qpU4\`g(^ PӘ$Kյhጹ0@e$h,n?t(1Diph$+kNXY^4 uDU+/h0s'{"CT0ɐ}Q2m H w!Ϗ *1qVڃ(- zPt鍨Z])%z̲%+(hZ¾;s(Zڇ@3eT{ *ឈ@Ҷcm־&e1Ro _Nky@Iězͽ){v4h f;i0 p[e'7 ƵL*ojaSFФ2Ф`@j -uÀwVZ|3X Zl<T4Q7l5~}(QC:`qߣ4 b BU+eVVve7A0ɣZN3*qrd.0x4(/E~sUHLA@0yKUáHh &^t" 0X'.(K{ *DhFbӺE0k;opT/IKlũBÌHD">a %B_S )P OaWq%莁 Ϋ$tgp3Y$xo[b((U uؔ)(b 0, 7=9`0q+TiP:--E2 9xMV,T7@zӁ>k<IJDR8F\T3`UfsxaƏZQ*屨ct(I  QՀŬ?@bl \Z%]EdHÓwl R@Vos)O&UJ]P(B 0x~Qbw; 2@HuV S&p0PCLQ"̄ 3@ofa1hq8{Yn]^PҬұr(zs~V{X8TňvcVy&Zx U`+/C鯸kᨯ}qؼ;vwkӾ?wwn:P}quPkIG7t'?auAT WnI77O Wh7XuRA8,*YK{?3D:h/`]o%J!JF6F<`cNh/gΩi Ѐf|\n}1z^AATe%E;A9&z`嘴4N-Rf5=K:~wWz}aLv$:3*.<ɘv8"=y>*#1Z]}h!'yDpx¾)1^@`H~i8w,z~xEXV%ފٸJg5 yhuZd)E9C, KpKR_4oz7ۧ?xg;h 4KP C2^_X Pt 9 td S,]m;w}vGqa97􎏡};ŋ ;0T\:! ^U١@9ᯂEYáZJ;Kno{ c n Cxº՜!xhMS("2{tRT)D-T,P'y#NZlr>G3K&=2m^X\逜[:m X<&B,%Ty<6"@6̏$;*o *)\Sq[CP-YriRPW= =/XHgxdPm^Ұ$-F+ i5Ops_dyrW:zVPsQ:$bIVýpq:uCPN&#VMN᜵ ELc*aK#52sC+Tއh'omU9P[`vt8\b# O'*C/C8)=qA^snXׄǴs]b_[ ѧ 890Ljԗ|"1(ɴ=RtN)l;ҩ!hw@wZB7{)t1k>_e2(n.@%_ۓm!fB5>P)AsjWAr"h@oKoXʧ}` Upb@ F*xn·/ ;-| ?-(Ǹ"YqqWaN(d ^)O}`0ʳEZ-~0O뫴vz M*qa]*X~%ָb$OU:4ądCِ1qŴiK4\ ZkfBwB xv,8fXqS9 žVmc4AW#XX. /%( $ydO!CÖ#t0wsX,pC(~rGq#JwxݫjuG?=!BQ#ጟgz(iF6 u9y1@̕Sx>R br'G[W \eu.4 mRʇc> φyk8]940+lWi,e"0Bg!GdcJU|!q2(Mwgލ+ʣI0$8N%OGz^v T4y4r X2_َ*KրRIsQ**e yI=o.vPh "b'%vYv%,ɇqc6XmpfC?LAg%sZ83قQm̜Cߠ^5oܘKrT$`gWh駛/j{A~jR6s FAcdcgAA6}OzPnq X!8e5uNckCC8;` R݆\@kZ|NDLo\,n}$9H7հE48)zL-H{ǑoCG Z[R[-'۠ƴDt/"\zjn^wxOaIu{<}S`U$Q*ڇ=֫vb'uQt͗tɧ*"`贆yUQר}OS:q(* BpA,>;!Z; <ؙ|tsp%(v 3I':8빨ah:\&.x eWQADnQٻ mP;}=^޴ 2ko|ǁ VZ}@`bX(gW[BItQKKQ2Z Z 6.w$F:!ǾIU+ق7q6[NI;c{;aÅm+1\ymφ͗;8zahAj][;6$Xc)Ck롙R8kb ov$Y!9>!M% #Vzqjj jh;-Kew wPi[ZP%yp!x%Ss1띚's$MPnp-NL%_(Bn1;"ciTa(s @bXQK0&dɰNr_XM, t}8R'V,v9p!=ɠIHmD}Rh]A|sYuߢ6ըs`kAևnGLT*]FBjϠ U``ֈ$K36y- ?"+Rh.O0Zo۠Z =ImFrV +c2 P C<u{uIMsMmľRd?H1+dF@YNuCȯ1p `+J㷪 LbuȒxDaR Ͳ 9cQVeϸg+&Gjw*FG[ps:KweXWFYWlQF;< [&o.]Fy3oʺi&k [т/U Q%f!'kzE̵l{VW:1]{s rگ2g[%^:R +F[r-|#% bӔUZ>o{.Gvɻ:\*:Y _r= /Vw Ό`)[5YHN{6ݺNΡFY>d|ElXuKYv`5Ayj+xj\gՑP( {QJTVDLr0TE/|6ХEйCsDIXjA$c"q[DC>~-} !TjGcƭ(4*xu &(*|E cьؿyMxC#&@`ՀBY,|xJs`Tb yn84Tb^ǯph%G$UqXH4dv&@iYyRU2&?w㷷 \GE/ }e}lϷ C h Kp5j<[b^#J46ã̱ D'QMK8i3lvx`A '@Y8i1s iJp 4I(û=|{eiYyl6Z13VP"Ʊ,o)݌?)uaC!CJ m7M/$WZKh%NEy3qY m ڽ5=0`hԻ"8s[~X$n)evӛ\$ ;4Ϝd5Qqpσ:PN$pyyx`LՇwҘ 7L~9TCJ>#ޡ_mZ Iv㷹&oH+#;T\Q*贪1e5*'^@k3֟"QqPEC^aU`Q9wV@N AAL8eDuF@ [^ TԾP,A^ @n}Xï !ϋV( EH*&"\,9Q\2TEmv.M QfwaĹ^ig-XQd5tݓֲ̹u? i٤JI!U~+A\u4}ҫvHު=S >EDNhpʔ;겶+\W+a/ThPV({XeTiv *׭.H24; sEz6 ZxJS Sť[ӞY^;]wb#xIp+d-v4$sa)' #=2Ε*z9kNаed8Ÿ}w`WPխas0zEs5o|v i5ݔ-tbf@Pxǔq{ .:iȳkԀry ЕBX-j9ۭ _4̷{$ZcJsdX\=J}>-7B K)҇vd+ ߁-Bk:.I/NGI?zёy8BFs78 cDytG?s,.1{]}]e<YmM, N`{k]Z JZz\_{AC{)n4cHq=pâQ<;.YeU|'081FAs<"h(P-!GƸ+fkJ֟S[%@2 uTRcْ0kɔ%"j$ʠ4 \@ֽ{(dHZAwJɂ]YQT6##A_XZR5}M5*avER?sL)'whK*g%v331࢜I1%e!V5s&SK-WL=4n P9xOg_s72|U#aĉO(mh >n=S/4A_rde3V_d}$5YRL\"BDaqG a dL g *<Q-01{z`i.0}'8tJT*wĚZ{P`W& ֱ]:ӾihV3 JL+45ygĬ֚LIJ_o$ƶf.ctaKXGNPFUMGjk紵Ej;Hi1)bJ]gZ R҇Ug;* y,+0XH dfvm(_t}u!-O{HXoO6f`ǝC tn<̦xeq! ddCI~@``+Pb/ J®z(>B04v1,A&I>ܣՀZem+.bθQq"WBrZnߩu_d'F)(3;aUR=jU 5sWsq}:?T'Ҹ{mS7KH1>qP@͊"Fnwt1( ҧLy ɜR ڮQWU-+ >'P}T g66_>P%z)WƶoE38@ U ^|n7ڂg7z v' DWCIȑfIU:+ 21P۪{צcE`#: ?Ϫ U<\#).! 򴔏Y#5j.S q$f8|a1{H0cP}OͼXŪS;`R5h|NY-!||L9qꙊ[ր?DNpa6,8oVՎw?=yTd~chf aQrK$bNwYFp#gʙ϶CPPXXdw: h2AwLNr #_' p >#+KѲsU'$"CG$=lI5nPͷHEuS%z>du&3`n .$kYfʖ"Gq|uQnO AuRfomg?F)-sjKpVVnVr|Tj Je9]j$XjNP طS2cpD:AB,y2yf5z^Q*߇QzaI"79-w{H F _i7=4yR 4APA,1j=%BraB8"+9+ZNgѵM&u1e',KL-w|1z cI^1߿vkp'ɴE6pNa/?SlR _[qC}*}ni9; I _0 4ztxvw FXjF嘋) !l@(ogXY`"1 ]+K ;5{gkj8_&2@r87v]58A% o- ?\ xt[vx~U PD% H_Ncb׋b$jw7yͦ`gREҗ!cU.Tp<?c2͆ j> A`Fn1:Ss f'Vѓ0'5d3V|?e6;؞NNk3ak W1˂+`o:XdJqw%$AV^%)/hix dmwMV z=YOMG}zvoISx~᳉;8;Z/ Suۨߓsrt ~r,d}t0ȱ@fBK 9JF:ΘN)j͚$nz-hxWrt1- cY4ƫ.z!+O;S\SQ<)Up$eWpkF].oԁq1@b\DMiYsK+X6jʆ{%Y0Dk4[WN#uKœ ^ޅ1PLIo rCtDoQ0cHiA22, ђ{K(PQ֕9zԃMƍҺDz1n>**^8gjܔU>/ b 6Md!X1N1ڂJ`3!S>R*uHQCS+Vpw.ؑ}˫$fa4I<^Qᵟ-+hʨa+- G}N܇a4bG`q&YΜȡ*b=s^x`-eiz>o|;a=߿#P_2^ƩNOQI$`Wqm Tp`joL:&m]-GnI #}5u&EUNO:96jZA='|- ;c{em'PɃ ?[X@tU*9?eԼ~=9q(ڛ ہwA(΂}~0WT }hG}_ Q[@.~IMőhr[3c%Igod`-8t ȴpl'YyTw!@ZC$?fe~!~3894+[rk6x@دc3r(Ufe \p,lΙqc6fVpt.`Sa5ԇxD votVxRgE,*&RH v4fP.;bw#4s? &|Epئ-EiQ8:l0$k|j8TS.9Juo; MPISRp~@W&Ifr's*Vǀ1Ɏų1tyWU9!>%+kG#J/tzTJkT% "D$>>j$XTt yϴ3-#Vc#㯬[?Vyc<~k+gl_qiӴq^ W0J;ZzLk>M)SY`jrt Yf;#N)>_Ig6K6؋9&B? 6z˗߿yw~\*>|c =~jW8a=3֦5Zɀf>@cL#w7jpPzVg"s/e:#Z.W)R.y9^ ޚӂs0ۭ Y ֦hzp޺OL?o^=^R쀷v&Q741EìY, S (rjrcQԨ|cI {%T< ӍS! ٤֎RAU5H7mݠΠmN;BgB,`B(Vp$+{U_2|=/=LDh}T*\PJz# ^L[fI5W,iv&hz7ġ`$"ҧT^b(U ^Nkjy\[K9PJT8i<&O{XW|dH%,Ǣ11UkDWyM@el)CC;/PBvs;Lh膄nH8;nJ# H,ER6˯a f JTނwq#u]TOKBf.+; 5\u-gyZiy̎d82Un!嬐 3BtVIX TApedqj 1c>6:::|w9;#?φyCQ09҂7 )C/|#6v;HKhoT9N!{'f~L8^.&x b2I: h{ V麮X7_g^Ojq%eU+~L~,/L .)(16fD毭ׯ(\_7p `)`Ot;л adV?[m`^v6Φٱ"o:W"%c-=TC]R^9`ͨ,jÀ K][qۧ?⫎9S‹ͨ.^ms@_|+q-p݊deY>f)UnS͌Rʸ)*|h^ݏe6( .r rsATaG~П7IgU&?oxLog+!u~l1a& 6e<~vJQ,./ت5ʈ+^wLV56GS,Nv78d>QT޼}F!H" i^OxP$gu^k5 ZmJ5_ 蔹ì{__#%t0K< U9O=5WRS|qAZt9 ш^_^x5to nDm:ˎE'a ^%Nȼj |+7 @\B0TQD5>Bʫu{@D-vɚW,bUǛtɣzK8e GaaO ^]2:aY!_-j7VmsfCvdVOSIs+#=rXp`ߑfN!՟ɝH|V {S1۞`V㐲6k7FYn1W(DH./AAߋ4͒lrmC"f[샣) BY@8݌/:_@v3˸qi߉oF62v\&Mp7Pc_dä>z/-w ,a5XfxY5U`K"dH|.Q=+\GNg6KSH~rsn&q37IV(( $Vɦ7LާUc{<ȽM/F`cK3R+tlMu,1Kj s;|ߖs([HMQVAR4VfGʽ`=ɛ~ Xy<A'S#jVmUӸ1y¿q0CY|Z 0 `ȍP[pu8)^ ? TRY U5ǔsRPXHY&e$jb~eBeOqR6؏xMxvnd: π&_$CSpq"vwwh&~:7uIk0OܥBPJI^e Χ$`8 D9jM hp&|"59rUٚN6iWb-ޤA[^' EP+I ЍO29.'ov'|KI3)>,ԃf>k,5ϨGh $f:ΊZB'-RQz~'׫]jMZ> 9ɿf~5Yr޹j(N4&7LPuo?o^b:zlNxt=mL0V-YO`I%X@E?.)؇~b NJ-1)Wյv_P͂z9^/*z% n ObgNW%m j{oV3PWoU-R$aB+=0ٞҿ3D/ {Eיx~6y ڮkL.[S6joSڂpX+xKx4D%5uO6]5v;~ǷMt3>ׁ^b[_xfn`mt@O|@X^=I0mPf&,=gg&o/9B{zgGP'68;M^kڻ>ۄУ087wVsBێ~䋺PO ¹)Q?\-MZeS Mr"G,g,b` IO5'O`Lw@}^_O{㒰gQ.Io ĿhGy;. K"4n懬7+*S,/㒣gr,nUEoTr):r=е,e)9+oTICʼn`EY)0q>WPP<*8_ho*Xv%S *͈e\ĥCm^jp%DX z"T>.dUU,#z2q0' "scc@5Z}蓿@ޥqf+`2T ;oX 1hJu٨ֈGUWBKpJP VO䜍>ה7W"]U`11\cS!7$[qqUfK6&`M6T؆Mۺ)+J[GꚗNۿ|W@eLi~o>1_J%ٕ s h~$vey/iJdLn68 D5rxWo{b%w}/y9_PRR1/xxwo|JW ^7{zbe"wb%c_9wn.&4nVI:Rr Yʳ=aqQ#G/d8:*]p޴UDw pJq"IӿoJڟu,6rE7_[ADJe8f5J&v<@M>&]k k=mKf`+KsklƊ÷'Dԩr)I|$@D˵Ƃ՚Ѿ?t"};2Hy~Vy-% \&ya7J0Tz%/^yx0{ຘW+i)_GI.ҒW(y<>U:t*\սm^+esPR3^Th4Ne"2M/]HZkMvHmu65LY*<1t%6LB'6zQf:v"ǵwzQ.mם޴Eב s1S  @惜#';Jf`1om}ybA27 KbP+ 2- %JZzy͗~+/$?$Qs.u}wGE4bAN'jF@ʾW qʴ*#̫'> b%$]*< h!~oD~Ӫs^&>GnxuU(0_Ѥ}܄ܫ ޿v7X3)ngsUh h)hY4 @oDc7u]r.A [`†UJu0Ӊ))\{ݪrӮw'Ne˧Yv:P$ lN(?ls+àD%v@,[⻆lo%k+0L8]3_N&uw@w_۫Xz(>ěg^ Bj=Eۨ)cb=^yͱ ѽ8N:D,4z36L 5G# xyufb "\*mtCȒjA"kNN  #8gӯ\;OAdx3blE"12WNc8l_I -r|7ym $cIV[2_y-qP105%-ld@7L=8+]UzQo\>{۳wyeR1HH!Qrz5IBԌ hRuifh3ɵOMM>!N$Qn8OIrsoN6NФ jYmջA {n'F'൓snLH;ٵǷ±ͅ+j[=ۭ={?S=N<88E]'2#uop{O@15JbP@1(:׬gyIwB'B2N3QPƠ`1Un+Ý}b.!v5/=݋J +hh%eU3Y YyVW) lI};;qyt";%d5?( l7][O8aWg?D,<.&zWeE"Y^yA'5im{(s|z9 `KKRSB({ [W8~$VmPjlƏ l/XrɍcH ,@jዋI'F,w]pҀ|ަ@.M%QVоu/B0n#Yu:z(<#͂(|VsrwNFV5qLַ5KjqA-$Kp:<@rϨ"Lv$1yi^ 0sJ^^:J(ہqr^; UfĬ,oLAI}*F* v}SQZ)V.zKQ}iQDQ< ښNeKx>VeF[Zw5B I412MP!5-&)JJssc%gex8qiw*}xn9l W&HF[N5C6(6H䓿9&lME0?.DKZck$L(pZQjͲ~9Qk.]zRjT6'hoe@0@oq~5eT礪08X0ZZcPvᢇs Eb!ћO똮c>CȦZ̓Ń:h>&p~yRn~7#@M8NWX U0:tXGL(RjiC5@%I#<BJU9 ;nQC+ [0 sG G1O b鮻*%P__~7 4U<}5CoRӊ;4Jg,V_v5Z-{!+gm#2eqXbcc+k=Wʺɂ* ?6Lms;#xuR8L| Ab`xDV=@d *"Qd߸raKιkÆ9(ZlR,/!EvwL=ӈ\(s5_<}YGǍQ[AO4B`jgKdo]Q_q;1Ga:I_\||b5+曗І?ִK{UEIj/|}ɣ&`'Ec;(O{? qX + Ac7nxi?h_9%9o5scK{Ѻګkנ'=x<0{ʌb(qaio^/PzTWNv~5wx)",v5|cyD@Ab$`GR,ՂYF,& `ցݖX$H@d `$|I0ēcePUb0B]%xi\aՖՠTlD[=YPT1weן@%c %7_ 'p%iۀ|u6$n!4T2 n NMUX$p֒`)E0p: X3Pd"ؚsegNH]\ y]MA6랛C^Ye~e<ƞ \<2'PE *O 2Sö mLCl51p[x|j8QX >EU I2M ݽ*N Řl }F720(AI- 7_asmN~`)92T;ag"JH!kW+:굠7}06}`Z?x%0Wna,lsZ΅ظz֍ _o\hފa#Cxgz?j;Z\ɉK.[V&fjAjN̠( ܱ99^/o$0]Dtt)ⲣa(VG:.|:‡Q$Y%Z+[ORv KuEjU؎ؖŜn JZi qP:Ą mfD|*?Xԓ6 i$3(>T5,e1^HLت8|%9w1UOفxRH;+QE@M|i\L~+`?z+[xGM<Gd1v㋍ "xmXͮb2cL5-j#5s%#[djMcدlx{Ϗy^x']=(Pܪ9'i3^q+]^!y*~_ \IHx feFSt,-ռ5f~k_^Zo9 Y~~ *hj%lg!+,2&- ހ ] Z]1Bvś`gn8 8.k:nЅ%qD''Y j6ӭAo>x<6Cw\d^$^7w)E dD㟩#yl֌uo.FﵪDsF8˃$ bGEPP[E iULZ,5lϘ[ P*" $ܣ2g;6%T˪$(2hﲆmu/`K;FTz3+}iOu$:1ŕ/Px[=o~*P]by>Oݦ;ТjV}?!+R VPɟSKF&l?멹%wH8{\pZKe'RP*Ʉf#/aܮ' w+4z[KGN\%o@!!xתɆF6r;n_T^[rܻ*N%pyQ.k*LeA ĢH"XY<Bdk1Nr78<負ŚD"ҭRA֓4 t-=£3;jHmVX`[fP%*Y<03/˼Dӫm~ޏ~pF~/eO;}M;Ï+ٽz|fgVNu!a`%8+ @قjŽv5<p$dbF, e y[%))/B0jTEc*WJ#l"DBu4Ԥ WxDwhA_eXO_`j.t;[e"#(Qnv1l/qA) /$9v0wOȰf*tFӳʎWE-W%Ll('=y*JMYm;.r1HGcc@KiʍA`s `lߊ'1jt͢*r8(BtHӺGCm*t #*Ub MuqN@u~(ZXA=dO9eq@ 7D[A-;iLv#8x|[8BPY`V#_Zi+Jv+.LD>Srd-mgG] dKW{4ti%`?~`*9\aQl,"-ʛ`F K~vH2%PW㧁q:Lb)RRJXE/#uu`Yuř7ZNjX։Ӂף_*ujP!!#ԪD1:܎n> Y<-!U0Ӏ`EqYE\r,Sp\_BSo%pQGRH9tg3R,c}RğDT3T#@GKOV@8eafo5q^wڭ\겨ɋ/^rlmDs#l"Y"K D녝;[6?~*$L/!47_ ~o&\ѻ@v~s`)aDmp6GՒNe$L2vv#n&6 Шv|5]\\!r4dHl1IQj:Z^sC(w#fiRZ,O-5}A藍w 0V֜Q W )PΊVA\ %'`l0ˆ.oc4a{8R{v=Z;;j{w c Ë ϗ`9Teą=o9+}I_fiu{Q,ŹvzF \9:r:Ļ}Eq]+Ҍ/)Aޖ},F^|t71a-;J"aWawٕZn$j,G+[[0@I.Ay1t+ASD @˚i<:%Gm&~.3J\gpQSyX/Qm|kW`ۄ>ě$0)ecƈyuR>~aGY‘"v&&a8n6S )˦M<g/j>*}mS[v ߩS#*A(s=wbOFB3E2Mn4fBGx8W؆U 5?jD:oqcH&WZ]G[]+28tb 8HRk=11*gnMZTHͪ'gR`G̳g%bL~FúzT_Ɏ UN wϬeřz9ŝY2c| Ŷ߀)v!#&S<*r iiC~c9yXS>^8W` fR$cj9jtk<6\?%5#he:00oto<)n0r-hsXR`$ (oTa߇{u8'#JXIK@ѴVd-@eѭJ)t/2}}B*6ؼ gн&gIk+@0#&1-LӎNjN2bD%mF=n$4}h+|qcg< LpÄ%s=+9(bm5@Qգh@]kQ|fG-02j DtZ|ϕ 48(>*6' 1O#4NfB'fAL$upWo'ˋ*u6kNrh2KT  ١w 蹻1sȱ`;,+ "`_igOXM0q::p5Фk~:6 ZA26Y"Ό7 b~n'Rsi NAm^?}g|bnWܼ\w"I9}伆ES) %jI?im`F1/"Kh]33YS+q\'M( W8 E}@ޓg4T_mC5[-tE1$H,K 3Ub c۬ܔלJ]trw$3(ke3[ehY%)K>/u/aI(rj}zXKY5V Y375Nt}n(*yh@~nr${yR9~4$lu_~{1E͢5W;5I;P ykZs\6)?SV-1A(c^gg06ɋyHeL10!U|zIcq)'PD ~X51M>԰L:@@~uuqiL'&uI˰sENP1 <ƎE3&>ISRTsp_H lXjͷ"WQOi}ڧ1NڇC+& <õy\47p:;r~QMa3N)+skꔬ(j>B=]"O@cp#FqwZWOX79} VɃxT?Tpn1 n1heMAXƨYTՄ.M雦27Έx~PG5VS0Hv/3)X+CQ*닆9z.F|{ɱ~tt\vU8T(yI` -;mRDc>2^3TJTssaÊ-hJu%,ÅFǖ;R2S;}wT"3VHT _M =ԧɯ{x4ؑqxp ,Q4'|h7QNJ+Nϩpth ,J8{X-dEBp)+Ǽo;E ,`kS4#8dG.0sR2DѭJ34f2OD/Kl]HxRh:P#=.iP62Fge)U)[fVHULEK` }-5gىߋ \P<^bVk)F5/X"킟׏њuY]lNJhH'6ZrxO=өgWpDw"ޤ߭Yg~M5? :a>BM,Lk0L%*052sE.v,R `Giϙ\@Nΐqs"TrhecYtVu#?K(5\o> sXc֯^ $9ueѳTq?Ş8ryT5wum>O*lV)RER AvUXk,vQ JU.|^!O`*/$Ogvgf ?Jb篧kkgخq82Tt\CV H޵y~ ^d.mYWfӬey{c{O;;\`)Wry]i={wF6[lڂay(>lVIl=B;VWUNb'PM7eW!L Z{y7'M2?8?vmչ촤lӻ1RVVi ;}}j ]_"N}O7DKZ lQF[p>%WrU.;l{_,HZNg gc\0?KQMJDP3xq#j9pG鼼ju+b^}ݏ@ӄMz@ppzxD* Lln'!"r/5P.3!  ҵ4!GF:jpcϙo>}ुa97)i*gpVC5[5֜[,fk]w‡9?Oş*Nx m3GPO^"_b6t̬ I_tD "Dx)6^)Swޠ]:Uzj.0Hj+姳\ gkXM^ H,, ><{%s4*-9椚S%¯$õKY[J_pdes~lx-7ЉZG ]Y\$xc섻&_$~&swbe58kR8G[z%jl @n $;"-698W?9W^K.'#kLj}g%jbhhp!ņGn"bFE)4@ FI!5?oG,g_ ᖷIڭ`o[Ă2PT aT;3S=&d?5Ȝ Kx;>*鷑g>L`*/~ą^<;*iaYU 6E*rD)GX>J%B ~ii s<‹un ˸FhJOsXFcHG$EMJ0F Dr{]WW[jG#H)OPNKuhmr9{NӀ{Wlc.gMZz3}٬i,6>ğ]CH)}/+Ҏ~?ɰ9רqPnÜZBK0Džތ{ E=kòρDH+zQ&[Bȶ\Bxe6gv?:~fBVA͉ Vz%iZ4{Hχ%s6v1Rki<Ń7o?Kk{fqt.e#tY7;p%Cɜ&n8\ڃs zHSnmelP ^*^f:$s{io܌ vdH *ZIj[¤C BJ8R70.'->Gu8ʪ.m<دO'kI|^ȡt]ykf}?eL˵p^P2X(7$Ƌ\%Wt&q 2rZ%~M^wgq- ̷V3nH;$X} Ўyx֟p̭lf8SjvVTjZ6U^Ty]E?P'ZM3bkd]{mp?m3 ؜_NsG֌%*pV]TpjL<86=;$ii>&{vՁL NJx)`@1M/%wfQ S^]GV=LMVe`,Z ְ o^!λ(V\i tV(xౢA*SՂw:/7+q7ٺ\M2D-W\{p1Rpdf ln]q!Lh(ȘZ{@'$Q5>jA_2O8JzRZu{o*r}ɤa|<)9+ G,;W_Zv5WzH^^Z3j|ǟO'yEBT )uI{ε Z{wTW A"ndox9f-}E  ^@퉣W~ٌ]3|qy5>]=_ZS7čKcPKSeaL3Ŗ 29{Ve2mz XF; Ugi#G̋'P}y,5))䮅q W!*^ՂKن8K ٟOXpj%tːL(0F{q3`p)됱U4tiVD/kTP&S Hn/AӞ"GǾ-fo4 ZiWRA\1Q%C3&&%SXd+61YUl(ZCu)Ɯ!Cw'_83jY'"bc RXRr S͵+r :Y?nUʨM-e~cpkJ;810t#բPc^ ȳX4t3.~q*ka\`6mAOi]yK[\Ϳ]k.FQrr? [бT>AۣڰpT,cj.!ڛE0}}Y벭j;p?ZHǘn۹%t;̓:$LQ78P|U s1 9îZ{)i]kSp8u&atـkH 7Tqb PJS3Z}WŊAE֔tO 2$}+J])-ܼܞ8b-s/Mm^yF*2|K\;G-:Ϊ%X+5>7xl2[#5n{0K%U~Ґqj Ӓ#3D0Ji,TN>غZ'1!y[wF8b"[x H-LlbfXh3hiԟaQP!_:3č%WtdZn^ GZ͛SJ'{H"qd,-yŽO_Ռ#vX/pցk`1 CX-ZAcRd~iOf5T=&'Gta5PlpUYkؔR7i0&4@^d4\rl%=0tE˪'IQN8 mT}@9ۭ'6?S7YZj#cxU~л0Y(As.$xeim+Ib`hߋPK^ IA)_yqio`͔A]J'.W@y Eo[b3y}t_˵8IR 21ߑ6ÔqDzRRD 6:ui 7<)ϞU#}m^9Z'b_ޭC*z.O^^E|͞LNL'}+0X~ju }awHİI6j;0K-t7)MU.%~#X`-4(Q_]:,hpv{oQ^{x|1vׇO# 0?e{ROBH'dށS 7chA2ZH!te--wzf|+ x^mb78UYn_ؘ5]u?ܢ  1Ɂj Xv#ѕ+=Cx]`Y/Dn*hZc|0fJ=|@>Ilߪ>Kpg/M,/@u1)׍lڦ}̜3c0x4Xu`Tv8&rI&>|Yqyćּƞ'\x-$}7bi*e.G"A6SeٲUȀ7綑ϧ6JJwխ9RH`2q&pg/ -d +5#%5G(b&`"UmmԸ!} ;&)2STNh-}u*/_إH^f' ToUϫ*J7Lzi'fj6O܁Gey8]SjDi&vr&I; KDz[NgChtj;gq7@>BP3?5$̣e2n|ku?;}+mW|')vŦ8FZAV'P74T)͏?Zn>HOQy?TS+\.]*UÏt# !6Dy1لrF)?}zK?O?@91Ψ$_졪ZAK̦e^B-W1|wʋKNѲLx{[V-<=2 :݃; 2ȃq8[]$ PHsB'T β{&C!*i**6CCccм'FFzzpwTБޛ'r7R Uߒ^<0)C3EVuBl8g{7SVyd34^z(>^R5[H[NoIh c m6 ^xٌv[<#{q%˼tl%Ҕ QI@$ [oek蠎<ؠkqt-Qvbg9@nkY$8C ,(|}>zg1Ri"]*7N+|&+MfDs,AvaA΂RB %a &|҄-ΐ@JQ_R91EW¢(N*PCE7ioc)L8~\.n&0*¶؍$ 2Cs sœI $/XX><2*z }%h9M82q#zҬLg:}rnymDPǗo޽:g?E?t..:g?}+#B! (c ZN?>9 3}t|yvFG.Nt޹<>xҹ_FQ7f!b@I`61H+ i>i9{j$ae,:wgQi{`|u/4QJn>X+URiԽśKNn~;=?9~/G7y!-]FÃÓ淳WӛHaUd H 5vh !HjbݭqrMHH4sz8F@B|;X${!aolTRedDmy^lGiꛯj|v ϣ<@ V]%q yf~ѻ)@Fhp~jt7B?F?ӹk|G7_}~D| GM=Oa/fs *xix[q0RvLZW("  b틵QE6D^0A@ɴSC%MK7u[8nء$REZiu4͛IiqNs~Eg3g̜9/~X6i275'OMMvה˧.MM ¹sM]H8M;ŭcaW})[SCnMbP PtYk8X3hC[5H Z5c54H `traֺ(d7˒x{"kLb& ]}sy!.vͱm C'\C}4(ƢaC(,43 GҠ~)Mf\6V.CEJeͱ3A|bBP_oYSk(qQz.[q҅E:pX&+>p bGxcYK#T<h<)=ʕKPӇl2H:t++">ⱖX{C8*ڠ٠8P"&6V1 yuQD /JۥySd[meÑHa1+EX(!&hS!$Ƣ[ĎCxCbzOpsF{| k[,JY$Fx(rov۲be\ %ñhUXPU*Qtă4<ڪ2Oz;oJ$"CѦPXC c#t9P_3;4R tEB[udII^#̟/9K<N-K~Z{-|Ӭm.<'SIk) a*%\~ިn W>7sJ\U(+u)JO(2ya-VKc#ʖ*w{T9O}h^y Ys~O8BGVPtR^0s~J?ތҥWN[*qQ^}tko6bE$kO^s v!XB9>A1L 8Ϡ =m}kd?\O*= ]y:S_Sa^JsJQЯ '%4@y\NJD Hic`Ծ =/ضs503LE4Oc+0)8RS(e: 8(q mT@ \aIn]/}@:r[2F^ 9J.`4輓`nC VN^X@m Sҏp+)1sPw(l*H K ʣ@@ŭ4H3Lz)'l{4YefC8 tУVڈZlBnXMjo+]W@2C18AWnbk*}<˕.z¬ݸp4,.: >UQ,&o4bd: 0H ONA~I).tB=R:&M/(NeL3K#u@tblA},!OE ܹzif4 wpŨB6>)s jp>#0N:LK[ʹz&vcB$P\ AP6B"_S[=i>kO9|E:WBNq}\ aH`9S?όc:eR[ŭUX9U9Sz8,>TXx0bիP D-pvZ(p%qSZT(Ҩ +ȅ|։{KUUJu>T>*4Uy Q Jt[R*+U鮰أ*CtM9Za6v^ۢ>-U՗/ $ b0`@)^y{wQJx' yXն |2"(â9h,71D]=]X xv\#?H,B[@FJVo;mfF5xE1jLc~=\?|{fTZ߃Kkf`?̶5PptZ5.S;L0N+fS7 n :LgSӦM '"(4q=]hXqTq(Ίt=p/2uadvpA(N$m7U 5P$;$6_"P`2į"㑦S8Zl;{ TR<1'36O 3oMl1I h.a5$0Eck(B?(u5HlLNpBE#PEpxbɡWAۏهMz 7rV@7j cZjR)48KF_q<ݒB67#W=\wKt!Ӂ^~3:[0l*#19-Vx&D{gϑ[Qap{ZљFw Wt_]-8.e^@ֿGemv&םl+zz˜Q q~])N<:[ 5WU 7_0 ǙsMbD\9r'@$UgR7<_9⍚#U5UE]i=ȯ ڭy 1~ ʍϩl< c@0^ڋf<0ݼ0}yЈ;E7Nfy=]#@bBvmn1\^zCp`VO⬼=і )mvn8 r<(KU~9J:CFو[;DS@zllbgvsT:@뫷I7s?[Wvwm饊xr]1*m沺ܭeMsC3;ԧ^2n`~-xRAqmA 3ucFSGOm2EMy#9xXUD ;/]mw:ASs,,xEIm_p-+h f/^#0 o2̫~;YҖ+JWwLũ#]]ӳo8>0^,⻇4=Ho:Sj0_: rf[pąx`:LfHf&Jwڪx FV+1:,y)U)G_]̒~(7֨1cB)gL2j@!͎ n VFIguS) lttBp'9 x8blM Q']w.Fœ+%T͹eRQh;Q3Py~yֿPtR6[Sy*w8+Wqpump,߱ob1UT"'5^D bEڏF7$Zx\*^@_F^_A^?mOn6<0hqUbCx|X4Ї V%4W\+W _dvProL<بwґy_& M}!0Ą!( rW8:Q0Y~*2-zԬJ?bK+]1O=*fܠ.I5.Y=4fd 6i鮛U[/65/ِV!p+ 6tKw5*厚K7][ K횖}T~Mi͞Tg cWEfIl^n Нl q.N4։m"O`og0G{nzmdң:)y7- <%Zt4sR|':ީ~ictp<~дQ Ezmx`5rz @ã\ XFV9\~0^\sNȸ# Wc_Mn2-Bx*I pDҠ6;lF%-DA^P?ۧ=lf' 6CK.7@̜-u% '%tG%dS20#pK`A J/=Z(`f ,ZꇜΞ h~Ӟ pXW"{<)/KG*{FCZMljiJ(% B]UNk4BSCr[>}|xdpn"6(UH=|pe"Vt_U<=<DS+7&w8oJ 1! Z0%+),gm6#*g:]Ҳy(ysZdXIm/::7٠ YGI1$Szadkd`rZ˔&e'mG nEOvSg1ZՎN$ӶQ#R^Ƙ/\ 72!zF =4m Eb9G^SE4^+٧_{ W\SW##ǘC#/Kϧx8|b*Ch.@Gf]zly4] {/OÕojL7C"_O=R7jY_yU @Z{9leF,\qSƒf `a BΥߜވm'nt04-XT瘤n\i9 vnى>'-4S5ha ,Q,HbY{׉ITlpDch<+>]ZxF̔²O5U2B"5;82e(֒-}W cRq)b,X4*bF `7żև#LܸjA\.KUe;j} L(li%uݣe*cc^- ڔ5U 3:6툟,l0R`- qdV J?]]SɽάeJ vD5hfQ&k֝%r18:IۥGx'e4(yfS8>7[x,řL͠1ٙ Ke1^ƣWކ܎Hpv*dFv`VcDvkJuQIP-SưHǸZ~zfr Wcc/=2cj)sM”Q~1dN xpC!% ,[ǩ=xWz nV `6}w%v-{V;0U%Û.eg|RpB}yr(znTZx \I? ^OL$b+5\PÀ||b} mTaYҬ_M42V#zaz[Kd.'(J?iN}~+RrG s19K(Ac=?H!׾SIE69,:Ԓf 2TӘM@K˥e҉=7D*9)g ϝ V(/QzLZn \xoTwHJbvpfAɐe $9AUFAZh ~ko.Ī;By/TT;B|)|Rݜ d@VthlnhA(Iـ/1)X'ӥT.dBG- qU ~V9#-{ .]CR`a lA0494xINj.)x@+q^}b/ǘ\(y<|K鶤y]ZC]rFYᩛ0%Jzk*\f$,CRs zLU;1^-߉/zWTR4yiYPatwc/͈#T~xL3FO˯,SlZQV`xg3⡎D}(vNnjPoOO1FǾUMHoGDkWB0 AWT y .uI=VpETumhuI ҫW7cJD[V,d>UR,Q" ? VxDcz@v 0A9ew4Pbu 5Qtg2PXI_Ƴ{nq^4p']5]H3Exr/+>J?*|NLP˚ceZu?ϫet))ҏNY^faMq=:68qvDOcHv8.(ϾZ1kO b* $ݱ u㣣:ax+;6J7cIԨ3װ٤XePm#xy1Kz@[=o0h(oKAsܛWf>nh-I~kSU>΂r{<5Їjn@&EB"O;T{xH9"EU-5->HN݅QfwVJa*.Qb=fh@_igK?utDvsscU s PXEgJ??Gy\|@2ڧː-}n4ŁkoGAW3a<|bڪF}r`JO*_‡t,Po;yAMU Ƥ4%Alh[6?-ejX0OkQ8nAu}~.}Gqޚt׏gJx4x-nӯa1D-Jʖ&e۩+ttجj7\i/ ٞ5R2<ņwʏ̉?I"J=vMe~wGH~vj,Ѫaҫ?[Ms$Kcpc?mo '+bH$|X4 Ū&à>8MWjd,CO2McK ]`Lnb~ P#}?%Q069g23kD Jm/ܙ_MߕT*_1JF -#=]y^yKKFJ2EH8qOa@'T\$/{h2#L6((UW[C&J?}u]?yFJUWK|8.҄^wu-1X+'>J鏖ke͑0f7F߀t|UIpX^#D*qYej? A z͙ȾU/@[YOO^,.mqJʰ _ԟЮc)0;Tn+#6afx%`VLz0Agr}є,fXaU@oid f-P>)J?O}'f~?| 1.AӏJo ?VgV 3 `P{S_Q!BtuF#\LȖ w&dF)B`b{]^6{:vr1"-tL"$); 7 :LPP9)"]gbA8n8g|64g73e=.vKͱ"mhtT{*AK dd*tm&>TLM መ(ǟQ폵'HNPh~ 9L^M5M}^}cZ3G{ܸ,]jE7$؜v?/3 "#gbyt2^(x~??v(/<]*y5:6;Girh2\1d\H**#RMxU]X=$\A߽QNhKCg/cH)WLdDmx9šǟZ߯4گԔiGG80pǐ#!peO~«KD!jW!/$&BkZRmp(d" S3PFX+U Md^%HrX2C~f k:X_Ih ?$+cd<RUmIXoaȆYFO%kWQM\njdot7\q:˄>p8ZFg3|4Z{f{G") chZ~We0l{OAV}2By)c gǖ*wANXXjcd"N$]͵55ڍK-45ELHܺDyeqdҦp}<¦u:֠{0i -ǒ5ъ5}JL߭gm=O1Y*E'8ψ bLҞ4 ^yxe|xrl<3dzhc}/'n̜wlȆ HE^G%T;=K!UF/J ],^k勊`oK6ny\2sIsR'?Ⰷ70{d#Kuw5&"VɧBaTWYR΂ b6+ɜLx1Gd<m72Wum,fY +51BU25.n]r7q J Yf$;m|+[@+P-\@L0:eZF|Em=>BArM AO 0EH[--MS;֤]D>:n,\w%G\VJjSʳ}]`{(r/W灩+ɩW\Gi gL/$).7inʫ4|$c3Z^vh zҎmY^HjjjrybW^+&v]T2$hQSES,lto9<~rEʮ/Zo_yX_ _#yI1^3 hКzk'xSNn2J~BB%VҫG9EͯG٫n2gkO!% / L<׬c:2^'e`L +>ehʣDM&1aa~pڍBȏ{ s~*tt>C4-VE敁j1 &Mee/?ZE&pUVx._%̝Sf 5_Xj~?Ukd:ݱ^q]M򑉁!D$K3vTVd\7"'|CuYy[)TJd(d%D4y @Ƭ9R<.Ta`hCLryEU)kjr-=AY!s&Ж^j 7̼+FbnltMAVJ1~# @w2E vuuZTuW ;ɧN2QS8\m ];,]l 4" &7C̩u:qCC {TE# $(/`1#8/#%%s"dM."RJ9y9 )s vw|rjy:TAH܇59fI{S5Hg/x_>GH<[%#<>jn0N"}F.R(!ae~ P^h"I 7$'tCY# rVp~ԇX=u:|z~x1KMf=!?Ql SN /rR"0tYgN/{`/jn`&ә3ez#̻G${'xP͍z[ߜ>Eshv $#ۛr)nL)ކ0ܥI$FO-{(JP"$p[G=$LR7MJ]RV`}V4h9Uq,ol0iIaB[\EP SiKqeK=hY3 SȨE 3;H@EMA 5X\ľ!9BQ**\Ytu;]V@4J׃X.exgYy;5P{>Fگq%ux+!4Hz07śNo\1p'q8j @H& N'=gLidIJ !tzYy]m\fG_lX?{|]fԪŕr3(fkVtH]IɲC~ )wߢiyBJwJTY Vt5"RpU^RSޠLjJ;ȶzT^ MuӤNAj zN_ -@}-7~VZ_5,VCw?A&㠌vj0 B:EN׬^%A{~n*X8׽TAjE}ir*#}J$ xv{8QR<LE] CE(oilzCPhY'ۓ1j>H)fJTd~ / X8]8X;{&EaJʣC L" GCLM8a|yc,]|/QSǷ1bͻ|\ [Rd&ziU @ _dXU}QdSH RPL6q!pC}](V7AEnژiYzj9*#=3P3IW/,v2׷7g5KX?&NJiY2pK7)elֿ:B fuʿy*Gɖ`G>r 0 VV@bc( k!nB2e*R"C<m<[~) 8g`!#f:ؽ &cw~f61ҞW'K*xNDPMO1}˳[FxS:[UTo/q2mRm |~yLW<CMF,JwDŸ %S7 M}x7$oyOa^dGF5ϐYAR'*_}<+M>~GރeC8K''ATêbmi&8x,|d#~Y>I斘FEY-13giRS^ CsaI6J3d<4iQu6P!Sz z_GbOU- 0Wb.zoO'9 tzy)g u3nSdH"2IHьdG9m]H|jt&ί{ߜ"s (Hlեs3dP8J^Y2{ENAvڀ0vi)Tys&U*1 6ui[<M?2My(,#9K<%'aQ/IKC@-uOe<֗H92g;.;eيܙwĶMT^ \;O>y2ap-Ja)aʇc LWĞtCR WivIQ!flWغx8+`JȗnT~W˯p}s{@ !;^||lʫΒ)5ViuϒWڼ ;p(EG~^Jn|U2iJpP @ڳCt]s `@:aUEߨv$xlΫʑȼNVwمHW'E2m/4(r '{O3wUXu`yuA1^oTD+JWU'MWS4&vN ПWdM026Xe#hV"!&XWn(0֧y_yF,yc|>tASxA,Bt>u*_!UyӒf|sZ bi.-nTX-qSEF o)zd. ,X5Sb0 }#G(9Nc|Y<t?7IV QJku~ҖЯ~vr$Hg~&YbWzxN#"v/`,oP7_Bܚh œ? [:9`):!=(kJnݎƐ //O0XK8|o&@"c7Ryӗ8WBcKy;#+Y-']8U@_|4OEtm5 ]S!y'v_@W qhtּ` &Ɂ3CAeеC<~ãTaF-gVyEtnP[la^]-:ӅAVٗ%!=ûN'#PֱJ769vTxUa"b#&V&ʎyfu0m0eT?Uhc!-"&V;BB[\<'XmJ=aʣA/pDEvwa2poeB-&ą(R4ءh$AUd3TBm<ƠJIy9Pvq:$QmәIO IV ,7~Y&jc`#YUpOX<.'#-ħsZ5._8WӭM^>\ LGT\A6i(N!RcW 8ؔSBٞl1:ҼCE,FibV(*R P5)6 +x)IJ|hɍTND5>و'uX(b.vO/2Me1/ =mGo@BIuMtN)u銴\^V>u_T678lM78X9u cZ*B1 V&vVłbwآ(԰/{lO N9xk4wgpcDDl2@φxIl~y15!owh>aO3&1*C@C2%[x|⡕tW?td, '>7TOpT.T[nxWbG:_5{7]m*DAcq!ѦZʸpN;ST|.6XŪzosdcdbz n4Шfh( ](t`kE"zƄV*zB8hmm[j!q8цr6lS,D) %zhp^ځ9j v$#RXHc,!l,0P4Y`BH\7d^İYE0ʧ+=pfdj(ͪk$<9Ay/yHnDW."˙Q篽En}Q]RٕʍĻI؛kh9PZ X?\!%KU2.yk ,DJ,9a>t+n|>8E.A+_~ Sl8 |/#sVĕuIS*!!z6= 'dFOCMp! `3NP-]$M2c\ vJ2[NkdZ|*x4j7=eNOǣl5&aUa=;>25+ںamMrfHafnozfڞy!qUv~˿%EԨ[ƖL5UU7iP-kڤ3=j٧t 4vZ^Xl(s+rvI BL7Z)L:-+qKVrJm@*exQ E JS𱈇PC(T]jX tޯ \w&-a eyRF'[+Gpc>$IPQz5ٲdǾF]ɗ!;=̮odzoW4N95h8S#UxzSn@())YqWkFF0궙|:<fpORy<(>,7d|İKfra1BwnqCѽA0cxk|rO01xkpƸNq)6;΅x O#i۶]>r35!F)J> -tCfGx8N6Imm^_L!SKsɲUUs}Ln9t8ua.6ĆY{ت/2[9蓵O/L1R86h8ϥkk(}8}-{W>P5̵ά"hzS T4.F7WY!IWT#kX awLZ()[,HX'Fڲ*B&mLbCd}) '-5Y{P>Pib1Z3M_Ѥ!Ije׷Y Ge3 KX͹C(2x .78C//@[A_X#4@ٲꋬ|FP:G۾ג5c{ Rj^lx*Qȝ{2 PR度aBL Ųx< shE0XR Q/[eV>I$ƔIj !$t{ӈo]c۳?ܶ?܌ޠ#eU3lQ%q wrĻƹܬH4 O E IXN{Zl=p7S=`Y˰*+H`㴺ѩvfjs\qûi"ZHc&| CGJ1&\ sW HNTx+"NNG7g!wB}8!ؙ !=o!= MQ'={/^yMFϹy47ӈ &.I-iJ7Ԝ3 je-ǖֱ~**tcx}ixWw;myE]-K$ǻXG%˖lNRwUNWl HLHH P!'D&0H0,<K3,9Z[c{?{{9s}_⇦k$(kFN6U]A)7,蒩KdsD5RFJsJ̢kN)AUIBztQ RF U(R>htniinES5cE`H{4yDȦ^4;*#PS^QsƞL^VsɔOܠ!uˣVZ-!ִ:Au[sThCok.6%܈\)hꜾnZhۺrB=$f11czqG呕t,kK(9Û@i@s-ڞgrJ[cQi@K?"JjZ5z74W4ȑ;g:H+ ݺt}l [yKJ;y]3'v9lt\UYh*Nܭ'ʚlHi80>6 ;]AULi.Y҉ZMהMWNOe8D4" VkJi2c>DDT4YSne~MYpjVQVB yY3ulN  }Ac3׵Fnɘ?ST$ɚ T0ԵNέ3GT(7l񱉳VipnrHG ;͏;EpK Uu3v: }LNjg=!|} H"-Ɵ-Ӫ qiK*Ȉ6 WL=D2Pw'l\?Ӓl#g6p0kæ.j(*CP@42y{W>)r(9h Қph_Me8#x+M 46Pc?KU><%"w45s^h=۽x%>SkwZ:޶-}6^h?`"'!ϜKnYQzT [j 7E 6]AY^9Zs<=v\?r`Ins $m':(`At:p`dU%pxpsi](p !Ǩ mS$0acC%9Y6@6hXNUѝ_*۽Y98e(tՎ}]kk zCNFMLct3Os5\8UDtX-_4nIJ7- Q2$tʙݵxe49؅BwWTKw7Ӏ8*Üؖ9oy~ ďvi Sv/)? |J7>yՍ+܀54wԲ'}cI'AeCEJ Tn>@D"=֞r\t|E[v.;ʠsRI47YSW9w/rwί|Q2w\*_u=MFc_r6\S1f<iSh*+m3CކlD@>޿1yLH`-38Ts}v9{ 3yakӕUk^+卌j*A${Av+Y@A#~0r kt9\h0EE(M w: F.\|;NU9 ~TG+t4Aj KQBcj)t@!UݭuPiRjVRp>+A i]33H UAc;)J=ahR%A q5&uW+a"ârTP'ZySJHuD58 ȅ-Ya]P]Ęa:, ˃0TQŒI9.yudV0`2F271U8C;Aupf7L1کBU7('`UU#+{xA.F .\<̲Ufon=`ȣsd%(˵6I`bFtф{:_WЄwu=\'Vf:Ӗfh#^}vsah$~nm9}DA6x&2/j7HeOoOF۫wl3.ZglXjiƳU=srnu65W䬥Ӻ,P[-6ӫY M29ZCW>3pdyk$0'nuv㤺r^k*#ョu*_xwݱ2-hݲ2JO1<Ν͓#ozg[A FEhDulS.^QjSQ5A=tܡD_Na瞿9R+4(vgq0n8[ LŽENp`G ٲ/5čwl:@?8p!Xe76- 8'tg+*-S< xsbL.*"_K[ {_5ʵP߲nI Q ya?yeȢ H_8^EZo[a"auk2|T*#vՔi܃Ag{J+W>xRxG2*.}Dz^_|6ϯ|#_.&.2K.6';#{5R/׫T[σaڷ?aUF\2"\]MxM܉UFE7>x<=j .R2'"`P^F=~EcXe\ӣ*Gֲ{Vs9pZ7T84% @pRW9e: IRn" m&8F@bP{+@s3CA|rhwG,1m=Y }oo:d`5ԋ~0i4rZ1΀>LgAޫ0~fjR?'_ b⬢ U1?( O3d"c]~jc?sjN io8G^1|[?DÁj#t{P+ )d,F*[o g]hx`!!iP#0G> .;8ars1b{_ &0i)mI+KN5_@N*7- w;NO隦mWe(tzEuA5l͏a9se{J-*}7*niN%7g `T 2":lbQ, _NLFj60Le2 ƴl:=wJ 'ɟ LW Kp@t&6HڏV;?0ACC;r./ 24t FijQ pIrb%=*U~s/ N&4f=jR?96F,M`YxWRg'݂hD_Q jɈyjQyvٮB>@!S.AB=_G*7K "&Ί#m$>蝨`W ?>eWݚoQ2}q;A$NV OEPx φG?SrC|lQkjnAmh,:|E# b٦hz #!xC4 Kvض1 MU)x;XWBF ƀ*GT.p/G_ũ MBE˸<.|\K3eiƞX c{Ss1MeDOQ?Q͑R*$MTĺ-aPa)Tӆ~+= QN[T?]8.7+9Lvpsmѩ5(Ymt{esKCf8ogKWʧ,*X[d%yC㎆ޅRh(Se4\eLa 8 Rߐ:hH" PM(͊Aua;<|@2[|F1,qV\XoxIB_ݻ:McHF*Cw^5KY|~7WkU ހv+նC\fJ7KFe!uiyoV W򉀕 rMQǥh_!w=xrυq+!ʍGE7с  /]ipVlMʨ93mXiId3tUTXSWo?nt/8V_8 o_/?zOph_$dg98wW(0/)s*-<'G7OR}Q/ߐnlXby_k5}?G6TL(yNs?`+A$2*Ï #m&ohs>x q"@*K6wlڣ$kmĵZ0QeHKYrV1 wej[-bsKQd/I63NԆjz9߾nTtg^Ns:#+$[{3m-Q*O7*{/zrͭHgn+'Vem 뜽DR':V(IU2c1Wq@aѾw6-cOWG4}n9gv'7`  0X◩F,m%N8+S&^^ {O-sQc3i[C[|u9]+ѻ/EP敭--!1=Ɂ[u?XV S!8i-|Z\p Zvn-ˊ?/Yڲ%q=gLݱLdjj}D"Wqq [U6THk˶ҮM!~9b-_W8T;#1׬q\˖TwsNiulv cc)WǖAȈ*Lah>{ٽ-uuəմPWd8`0zJֽTSwmuֱ-ns#&si}#>ȪK.iȖRͷW=_VXʼn__ZL?fZ7oF\inv~LT4b؜p}3l?ĪC.{EO0:0TxZB!ϠC,Ҡmif -y 1eGjv$٭jd+B*U4$u#r64dhEŞj-l\STtma/A &[Uc?L(`=P~.POham"ٴV&Մyu5(;lic]["¤UP7& _Kg&5iYoñ}Jve+Ұ,>pk=Hn$x9YJGj,H.O ;o'[t,X ~n U+jٌ K#5dE=me>AOURM;0*T 8375W 6 ?ͮ}ąO_:fv3jַrzȼjvꨟd: i: vܾh& `];aZ7OĿ<_zz|}zvpaWJg;SԔq/so_zHe5U䝛u8=ptAq3[d0HpnVDX #2\X^>& "0z0rWPT*)lx6{~v -5;\ WRlhu}m7_}vںotct``lr6۝:$.s4& :&e{s ӘO//ʣinHEd: _uD0"?ʖ^~ s!y[UZ̝s]X(VŴoOs?Nx =eߩϲ;cm?5PW{݇5kZdzu}ڙ zcFjFﻁ !NnÍlIDQ|y/TEM%xWΛY=/_[{W"s9pgT!w P5ZahA,{oeWJϏ=nzRI~ C^_YY#RˠG+e//WG]bRjqbMR9.]i|<(qeQL? X|Y\u }^WYc2lPp?3&RZ7TuC ~h;tU+TSj0LpI~x}R^E˲׭ l(/v. ~[Nea_Ƥ&_?̓Ӷ$5gWQl4#yvC42L$TI 3ҀƚP⣨h KE}2ޞJ=0TPB*t $>kYvqQG XyayClF\([X*VH 춆M;=r ^y$[>b1{a0>vBI uV߆>>k롳 r;Ok(~JGwSvf/ԇ %wvϜZP'^> z{쪵@?ulkܸ|Dgw{u^Ϯ0VZ΂:7[z=qһϿ\tAz>֮uW.ǵ{+zv[.b4~p+J$1n <_z~=ᨫ:>fPaҸŏ;$W(̅Bt^v(V^Bݻc Ts+esaNiS 'q QvVVh}><'$*l Rx=E09 {Ύ="MtM%@$(FeggOV hN_'cL/; r |])sw7\@OBOIy1矔5IvwK lcau~\V8}>c(#7̕pQ=ϟi8_B Cq4&o ;Qv;=l`=mif9aƁ݄I$J)d`Q}{1ՠR' ,c&D{4>(3yf.^ F_>\ q s~ 8op+M53 u§:zgGMO禩g[x;qP)y|gFw@p{~q D@Ij z^4.ٲ)tJ-3`+C.Kk`c#~CmIN>BFVgTr)qKJϾjxddކ1V$m*~e_X;MlS:vcL?!jq ZuIBusVtc&]r" @k?<+{KܕQY21ՠrST՚ ?|-Zk? bˇk4//u M7J ӘLdEOK [z(ϼ;8KfX%ٯT '0 p^7Y+=朓>v!\-O^^}@,ػWjr}nv$Ψ8.6seXkٽl마X ٝqʝ9VߟpWq?f"y,˞b;G {^ Ùq{SL–\J?G{<џ' ΛvGa%Y :Y<>*f;ci>nzu m%lh%[$Lg__+#hyEŌ/A5gz- 93#eC1AWOO|]<-B*/1&Uķ?|d"Yn4x[^|Rl/5V/\sEPzߵhe>/g9+7lp F[_`-՟Rr&mGRgf1Pk&o}kbIN<*_н͋ l^{7ؗD͋# APv-aлuu GN-<2L5^*d=堔^3{Ÿ@A\ @⡰e 3+{p[[~;#ki)_4mvŐ)cǟ34tct* 0ȮoΤfC|gG私|;AY+N'N.;O5}a]/, ՌBXڦd\?Rw=KNl݌qLXļ9eÉ{M-t/I1US%$n 5NJ% yw;㏂\3F-pI'yľ5^7^4k4"[AXxyKl݆|D=Yɤ KY{AOl{剔MO$>bHFb-C?RMF\}ަx'Z#UR\'Zې9,ıV_X)8Ãkq ,wD631r^$ ;KڴɗĪ\(p)<\ػ|VACʅQVud!Vg&_m@v:+Q>23qH RM騪e$ԥ}e/ Wa(cR>;MJlZ|?/"g'VݳkuE0ZY0ܾ9>anb9 ~Ïc]>7M:=_`D!oNԹT'Ruj>G W'ʐ%޹ 1]3/1hlH,9hϓVnv}EA%|mO쬟tM󎖔aVoYh  .]hCnabv|T8DJ0VSGE֣! gc՚wsMb>|n,Hb&Ɋu_JooQW+Nfj6k[ŔR~'j(H䥙 ʼn s .nK.Ic-ޥÉqh_'b׿mK빠' 7^W%:~xyb\.P\S!W(A<)#HDP`w1=SF-+wOʾ4jq)TJV%IK`7k>Jf`4Fq@ɠ;qz77=:Ѽ = 3^LqFOծ]^^h[z%6iy,lCWҹlvI% Z2w0otmXf!7?5ĵH.6[.qp[O%n9ԐEBR,uZ.j][}U%6.PlX&HocO2H![ ezX/4$z:J^ 2DB/ Oi,E + 2Q!9/JNI(wJ"ӛzݑ"QE ʜWuR.nNGz7 xނPb^(*x5G7`1Rte{MRE.r%F)lHpFz=zyT=r`ڡYEM:<8!"x]+kѺJٺyD =6aʉ6;̙r-A R'm⩣ "_g(5h:C L}kȪQTT`red/U3ԥlꏽgOHRJ<+WJ9  =%V얳64qbF ")xǀQc2-^D,)62r&[0b^l8tM摁.H }ʞ*Čq<#iy:ӑ+# QlȕdkQ 7+R*iwB̆5`pMv9XC1PA8~"HϥuS$HP,l;ςa]|54 )uPS;~SwiR2 hx uA}^9Ņ淘g~Я;)8(p{m'%r< 6rN*xʣC$z&^9f@M % BPWdhJ_O{EHhpjt1AT(4iZ @;MɹiQ,N¨u2w[<@.pϞ N )0~uЖ \Tuz|"'8 :7Vh(a+奓C Hz${SEsH~Iď+5hvBDFHY%tAP]u{>4ƟeȲ#2 Y^S-m=wRdPU1{ɕ%<.h븀.d;Z9F_kQI gbBWK;|m~lHGvN*:>v$ ?ZGlY͑D`@L$L/,}Yc^Ϗ+i$CS M`L*:wC~A#7SU%9o@ge*0~|a@[|8*ۋmhP.;J^lOž_PN0G᫁M3O>bPz1\}pzZh 82L*žşkl/ 9Er⋖&)1wN?"ki4,g[JHJdž(b9h zB890;q 4P4tL<;v43P5=-=4^]Qa=>=NN嶢Oj!r#{%mpc7r"d#s ($"=ri_?8]Yvy;VdžW:{5P\3b\Ee@d-P 5C%b~aΔ,?}CF =%Hhsy95j x -/h&VxTDX2J$\ãcO$F05Y!,7/wq}";Gd@vRJ\P~q( 'kȕeqQ ̕MoנtZ^A/\5T\B2MR9+Moִrx6A~p#_Gbm?5jS@#O>{QдbB%b ӟQp[§lx뗒Q G]^0q1)kg|/n&/m&oLFWrT6`*Z(2{RbR6%x39==8{{k{fiƭ D ėpP5\4 +XpX3Qʚ}rFq'E$PQUQNcMF,Jv:+PiOʧ˚`JQkDG1U&\9g_gsnm$ B/$(9˸―S'+;OZZ7yQTkt96 ϲz&C|F. HK.ql¬e rϋ딘?Z/Lf^JLV`, y!R[36[wGViU< )'M9|C+.?S%>9Qȅ X;,)|7<IG< +{: wu [X|6 Dlrܫ''\@OB)ʞ/R8ehZK ]\ Y#Ӭ`ˍƻ/עpl(0IFTa>-"+<7Nk>Oʠl%{YB@AҋPg4J$6 u騇1>`[ hv>e^B]c Dy;- q^CA<-ܹH iUЅCdCT<*`7aҙCM9BM{CQLB  o+ ,+ ަÍykux,P{DJ)|FF]8AFރ{5~j iJdlQQ`aWg~c"޸X m qܵpi,bO%RlyiAf%1u06ם|6J&"ۮ{;H2NÞHdd7Y90YφapY^FEi w$0HGMtDy&!P}p]ЇBAN}^xa)zt>qɎ]wDVFxPZ/!i1짏y~ et{) Är`Pau-S޻}Q*,r?Df8LLĚʍ-6E!^tLU81J;zƢE%b)_H9;8o䄤{Jqg>+ųN48\=ICm&>ڈvA}Pd)0ʣE\yL ݠܶ):V>HJ0P1?؂)J$=QD̂7xX⿡}Dw] F 7>urɤvhx3dV4#j{ޮKJQ!U !w2 uTI)6ZRJ tYY"7lHz9h׎y*jZ-lQ{AJVv!@ˑIGux}|\EgB4M6?I_mvMӆ6iM鯔Mfsaw- @ \e|"@<'C|(zC|~93f<>(;3gΜ9s3gμ1^j"WӺPaE3Cc6^5u+;F25S>db&"ZRIhJJՔ_K4EMѷuz61uLj!(GGJewqeGخ46w(6ςVЮ_D:*F\O15 ePCf4 W@1#V;/V*mmND`_TcYM&UUǕ-f2jLCY1fDh1kO.J-'RlE@3{3:+m+4/Wۺ;[*Oyj"j;4u[ΧJOgPjf*ƣ 3d$6a-V)2ߺ씊ӕTg4'3ө)KZB2j:_U5AEmŊjiuvRi-*1 USUL߲jUUgm>0Kʈjji5ôn强ΫSOEKjkK+|c%4n45m*H˨PO T6`܈fk?IRuI(ꨪkI% giDM5@%5WJ"j}z>-Uu6#cj$*zDͤ}n5vOg +ZTW[eMneHO#ЯCP5c:bS`d  CjCgYwh@H **#FR@37O4Y.(ؒ D$ N3̏#FzR&+ !-!0!n%dSGڒg]_4Wl4<댙WpK5 )Q$C~ɨŵFJlE`!a(VВcn#>h $_!$5"=bnٚgYUL_JuL#1$ktnuG ,+.eTNf 8<#c!7mT%ˠz|ʢ Ȉ 53idF$h0>g}LŅh1㘑3ꐚ̈ I, dV`q1U !Yo-|;Ft̑!-F"Dtoq%iԦдi˛"4$JS_0V%fF4Gp7`"d}wƼ%%*(QnmX!"kzro+QQr߾S5e jLB5(ڋl-[{ ?J}q6Ӗ2\DpBl U$"Vr_.++VOC+`#;Yws KUF dѡ7`7mǚFTJ#:T6omP,a[i%ꀟ&ԀLKj2xSK |K\QRhu,pHiԒqg/P?xx;]*({- =C`q;(Pť#x|٫)4֔5?ؤlSI=ĂMInjꌨ&D})Wq+Ѷid@bF@J^P] I% {Pؚ䦅lKIʹ)&Y2%?S H!z~H9<СZGpGB)˖.^cpb}lIP,lcm ac1h@u˪1{ ̓#.DU0M`o3F;CuSث/u]%& edc.e6|+)An U`m[+rRw<ͷv/?\Tkӱ>"7>SRM_#Dig{Y}ƖA\&r @\:Mv^8,?G( q#h':h s4bMY?xNA_psGEBKO+]ɷ^Y{xnmu<~!d$Kv hK\d#jA dWdUDTh;X;l1*ailKtRc|sZ^:Bl)ژBR ` @~sl=9 =0mbKF=26yA{4Q/0 ZGΪ6ØUs݆ St/GJ{,0nٱTlM@[J\Կ15fj0`llrl"(h.:-5`|mg+% ZҊ1 Ԍ6֓7YkvͯB\`Zg:- 1*,;%\u1NUn4z C7^T[K4pnjԌa !=htIS՝._S2W*JHt;NV@e-3,I L.cB 'Ϋa*Tf7-77=J3j]hKn]xG7!TN \b S19{:,%RRutˁm*I"rO+A"{i-,I Xn\qb˛kQSuBě˅cerG: )ٛїF*|#.,a6 9F |,B7 %]oN6W{82ݴfRbԛZNte. đʆ3Km`v3fgU%:;qގCzlGƒS@M_;X_ qsa:=(a XVjee55kB/j( _LՕ6Gדf ={ࢽS6f\_l-+EԼ8A f%&2_m }6ɩ)5H¶u#<;3n|Tkxf߲ )MfJkDmkﰑ;f5){6aAo!cC&G/*P9r8B;+qW|OB5;r9C閬3_~IjBz&BPr;>rh:pŬ>iV]z力ѳj$  f<%{zz# &EԎ9 Y_;0C2۬)Fto. )d_VeQw _^aNpB}N+oϴFi[&M(ZI] <&nR<^{5vq9V8k_P<,[ܲ]2Rr,O/ n#@ᤖM z[[ׯ̈/˷Y;4]i3P޹ q{38WӬi:}qN|fU}?Swc<4tBkbi#I:@KzZ}~0_V"@7`,TH^U-!pmƨl9'2B᫐5D7 'z? {c_^+Nmk{d oC$2Y;'N<y! {*ݏd3W$01.bEgpR.`k@ڰI<`V4)'fZ~m23vYR^Dpkųŵf*٨8i[w߻2$v\ %smsvgu?t_ߗ46BX37\4] #fTȤ?6FXd J&Aj֪@`HxxL-E9HF7d$qK5#*HzD5R,i"oI5l`\ʌӽ9$8m(Nj4#>fB{CRQFޯ׭#j̚Y=.nC(R" Rdt!\+T>9V\q.x>OWΫ&ՋRaW74Gz*JM03 ,"dtHC&6x1VҼy]NHVk:$$ӚC,}]+m'C8Gx.M$Hnp28TW*(@@:n،`츴Ss_4Hv ѕax_h8Ѧ ɅA;mCNn K>Rp_A=tG9L3ۉ)SBm͚9C tԽ;LM뭛 ]FpQD8&q2*78k# m.=ȡ(;fhZU\/Vc&G:iuϋj#E@ -{ƺ'ʭuΩ!d?Q@^%Ӕok=Bhq"P/bMeԆN ;@pTy͕:@x-nd TΈs ̀ @^!$1V.!i9&6u)"8n>F"! *ǯ;R4b&t |{.E~5wT$؞x[&{}rfw[ c|wr\I \Q!="L5Q0^%BP鿮a[!V߬(n+ ӾZ ~ADM)QB]z]S& =N|/}}݋ 8Š]GPm=RO:f~cn#YK:]=3b6<f-U0d9~-?V_ W'?)R$Dxe-C}/B~+PAV ڻ7BeD:^=9d`x%"f=b*{^^X^l5s{̔_?(Wf ~*ޞ뗭<`Gc>?]4sF2խ 5mN+40k(o=aց%wL342RTIk6if)AulݙuX[Tyj8t{R~DϥVC;I`5Bn(hz {HV.k[+sTp glz99ġ+4Δ+ h7I%&e]6HPZK28i4j)-}ڂ.ՙ{)"rҚ'Fr.z]NǮs6;¦[{j:yQeK][T(;?g_Nլߟz 5&t&MU3ٙD3(_QYvJ9"N29NW 诳\  nK,>6 a>`1fb_[ĚX^=ğo0zl6U,\NŬWKh-hVX9ũ;"!uQ/TT_[@WAэ_Pɚgw ՒjQ\%[2 A6Rð){؂Z`/=-zfkȏiq`Ȩ-RƒQ8lґGUi.lr!28!$ ~0rşWٛ< ix|\ ]uiAMWgO^tr"J]@\j'ʥu}du#^yEյxdG:iaq yI)rlK-^t=U@XKaX,{4tv,YC0ў ~B-~/b*u\xᯞ ٔ o5aǢ5lҬIhص=V<9k{c J^CU xn mV{hZhryeZM0_ :Ism`kj|\c3s͛0`I)nxIy|fStKj~t#[Y3adDSI,I.|fv{}8>d`(ݺ&#b[9]=GDxF  谒](+=+sCs'a۽<77@sR e7 C bh ~R\WVIUeg;H9x$d "('pFl)8Rvճups5 >:^Fd:.b]Lv޵}wM>?t6'c*AvOTo f e=w'%+?~.&[&4T|{j!dV-Z{j9U>?e?|Oc0lI?qQS ;i^g6on0Ė{Ywd zN} z~PebJ#j~gM}Gk&ߓk)_d{bQ(A_r%KӖ-j ʗmdx2jPN7IE 7(=/L~88#N/Mf+Lp&f(iote|آJ>'Fu0}P`dS dUYYΑ'3r͘ r6{_lAWNE;UKثmxXf0E?ۼ~p⮍r2aԟK?\6),815om!Fo3|S*OR71uva%HO$q%9kBNdu; }+q C71ŏ+WK"oYf? &9l}A T>v3|ةg rguYf((G GCw5~DE: |WMыsJt]P#j|vv\qʭ.?Ȋx ;X]%E؇n *or~ѿ5vj_)bHyƿKlA5)ܖt-PKd4y+gr'{λVvz@޽°T_v7b|-[E''֯}m-u8a'vr给 ,WͰnՌ%#9FύD-"ca {_@3]!{ɓLౢ5/ϰf+ϲmYTbd8Ni/u ugV,|1Ӱ^>Ǿ:x=Wf+ #`)NrQ <5C+ {=LÎ.|LɛFțtv?~Ձd?fsUX˥P~u,ii{*zyÛZEJL59ŧBf V9/ }-dt.{Ě4_bN>>hd:silU/3 vǿn #T>j7Sg{aª UsP~m t-O}i>ىclyN Oko_rXY6 d K:O ͩ#׀_7.ro}үݣ x9PގnEr[ c~2=RAL `O q_ΖWD_l l)uVGWHq@\e%IquSHm\'b`im2&eg%aoz#L<Ě8;_ 68,/ypP|7ҪHNbYYz" p޿aLΪa6xQXz.aAe+?pAQQ>#E/ p$ke7O@7D)G.kU?~}dsCdg4TcmEH.{N ySS5tIXG1~-㳾 ]b:#ZQ2mW[5 ARΨr֙8[W_ "6;9VβIDc;YonQ*TP𚩜쓴xCHr)mTI6[]wOAB}iX;Ol'қ$G`kNK1'C䌳_Iz ^2yH JeNDu.+JNliruۻ2#?ۈ*v!M4egaϊ |m|Z<&q9]#ֿ|IJʼnM]:GM|?Wm^$,=˶h|ϳl-m?fU9:xElvZֹNM;ݻ~*u}Nɫ`u_[V.~l}k4^y=CS=ǀl;vo?fv#iNI܀x?[5ES%Nۋ[:.!ZUZstjtd%z>/:׬|[XK󥾼_"3"-xG<<AtUl=S ))>&|R4t+/`=X#?=}ݑwe+5AX lꗝ ^~ 6Q? y]RtEKەqRHG_e XhYZ;$&iD CPN[U0 &{6w;o {>wjsIKnvWB@xaۙiQ/xXإוL[Wr`?NR!Z`zX~3CW0.@],IUd8{`" O m ^qr\kGg9>ħܴt9k*RǞ*+k'*zՋc{zi[X)zrzUηUH 3b +<{=odtMQ~y-^<Xre`c ;[$J{Gm R䟐2$lZ5?e6=^;W=ϖTfwlnUve? gSN+uZd&\W ˷FM#;>O>o-gI-GG\8b韱 /_7Y.^α}`JVq -#|`3YKWbԙ/a\"k$ ˣ/N/c*E٩/ROp_bqKu}83-~W5U+(ƤUR/rQ%g?MɗYAC4 V6 N(/Xy "_07njԋd"5)/YY&TsiMįYW:#jJT7{v㍭451cBLۂ ɡu%ۏO:VRyM7luMXphڪ"ǥ!+^ 12M>41=#"mdQC U4<@vJ}rm}a.]s{CWX}~x{-Փ<Dbylޗԛm9AXhĻTT2tA:[#`ME *l\ ɔL7+J}@ Kb{Xm^(ϼ:8ib[Y!.']鼸ϿšJvMhX]a ;-=}Tqg{mbMu;Jײ9)]eݕU++ĩXx我o.3>lʜ_"a<|lmc)r lwjN?>DP 珼zs檽o,r8e!vܜF8jƌeFlIw PGhK-D` a<,.YD GU!`ֲ.Ք ` {_lf?] ) k<3د] )w @2&SއRFL(Dy[Z/v[IzSwE%~AO* 9o7(Ю쐀^[X) 46MaF*:6y#1yCѲ6l=s $a kFq`u/. Yh@v/7*&>H.*[{V#Z4r"OZ/Σ B?::\SΟs*GggY%@kbSrcEo_bszXn:فE+u_O2@~ṇ*^11]a|ΛjX^<$Wx}yxUյ0a!@!!ac S\I TOB)m!"nBHCPm"֡Ukkg[ymS}>}s={5Z{zE’=9EZ.-wooVZ-[Nu8mi4/8_]r`7s~g^NqȌoF͟hsv?bQ4-55cֈZJJFڔISҧG"-\hZS?'?y? C,)/f韜2p΢ܹ v5{왓P8vNJ,Mr ;WK&Q||oNqi~ߤ8C[Y;gO]~-71坁s@ ttAˌ#{]=h k;U:st݂_97RcdL/cuO.ZO2:8h36**៼(hXlAx A9QFQh)pLtahzkgS;B_63z %O23ЪyE?3p5Ùk&u)sgJLksSOPsNC_dVX(1Q>`_Ol}y(aVOcH&NU淺9 TeDxNLyЇ ;vha0oذHsѹ~6l2[#/JlEZ1@-˘N] -Ҫ#_Dnٜ񌆙uNP\4e5a 0mx$`N97 oƆ-Fh [ 2''"'mPFrIEwC/cN KGXY:(f}vu$:j5&cc0Xۋ.3N>X6-gjQ1$5 >C)ROJιzy.n/WGNRr6;dOKvt3ìr!(JIѹH~E $Y u/\O3MTkيC[Ê4ʰdPI%G]/62r\%4̏qLOAREr=qsr@FP.⹪0u*9TV<,sK'a=‚ q6uӻ-2 Lڌ}ƽn7Q&#]D8gs '‘Si 46Ym ѵDUzNa[(}Vg˹)rI5k)@hX,h(Iڐ 0m'Th4s#ѱ8)0\;`h,*`:|u?ti4݃ !)i++*5*w{uJΛilzFǾj.ԔQL';˶%:i̭keX! tk-zRcLZG-'V¢C,W/yq8x^cQٮVqMdg0>|p?"f@ ☼A4XFr$+kW-o5Jk{CfIs]^LV f6qq66 R*΂,ܝoE&Fq`kcMbѥ,\Q~0v##ab`{t¢  us zcDBN*D,"82Aè5fd?191iÖKu▬PY_z;R;SuTTuD9@R1Ne4$5R'LReg?Yi1^KOY+lgd:yĂvB6(*P=S覢EgBߋu)x礸IJlYaH2|>s wHT3GhQt2E$-~ǁx*$-e U|>/g.IR mͱI[i lQʓrsOפ%g)MP6u ƙ5+iɺRC)TtZW/>AҸّ5Ʃ$7JW؆5z:-¬fKŴdB_gY&!̭Go|{VIfAJ{J_M 6UUsk $TcOl4gLJӂL_cH:FF拍,(-)-bm\U煣9,mYQ'e7aeT8ה ;ۘj-jʎsU炫P٩4PsHH;w*]k/˰n`Jsr& b\,R[ $eb< dYk6 w#'] 1-:5Ʒ=S-b_ߓߙ+#s6#s&4ޟg&ULЯ.Q[|[h3cRt!]C0<_rT+xQyKpIʲ? F yi<\ }wAN+dӆXɽ1j.IP܏e 5*6Zg:Q4m`2tڔSJ.9mA?㚬Mn]gGxq㉬̱ (mV5ױp`^oM5*!)P"-{Qj}$7!s˾*s!iӓSlcK*H$d5MҖ\۲4*xpcGG5f2]3sf)5D̈́0Ԟ@s o^e(Q%5X"* ҊۼPkgi>E֌S0EԲ% Q\h$ef6hxoyNy 9*;@wǤhX]tL]ʮT4ۤ [|FV8 ֎8`^A&IjXRM 8|Z9K 5.WL&3Uwʙ< ; Ycn烂H]_=bE qhYy GbbCNqna,ljվJ-Zv>}Mܾ|?(Fdef%12rWw[.k^G!UGuVi`>Fl}JEOCg!sl7 [yyq-BՑka4[y I$C̸j8I ðˏ57a#  U6^a 2ޥDPgenXWuwb5J=FfY @d+6Բ G=lc[WcfX& gj*v֘h%K1$&lZeFԆ}C;Ӻ1!Ϗw6fon_m12143ؔQ9Z >#rsDZ)ޑ'H!{Z&6$uwqzfn1v0&_H=#);i2|8ۉe"&|[M`k&Z1w:D9eۄ&-g^q-h`F4^Q52rweCN t;*W S/Ź"QZ$1nRVZHTzwdΕ'A3+oqvV]H~rw6 `[.hjxT-3W&F1 $.tF}*ㅂe; #t@KBs|:E޳GuJ\B^B:4˘W\j l"1x鮙]6nދٌ}nyrMt=#U}==Cxd=QQ@忾 3K=yڀ){ͦ 9>u9֑1 ҚtD/V('BQhOHM ugSnP P_\_jhO;5TBەįQn`ѩ,aKbQlArc_`AѨr[~o\hFC:uR IZf̕9+)/ [}*P_؃*7nj^kJ\*L0`{XT)R ~k Ω K}[y īphJcY;4d Fi~[)6UTKf- F>ciHc~,vvO7E!؅^DPs)S6uAjG@?>BҐZKXqJo#)[c+:YC݁0ĝUiз;jšD눷0+hH;HX7 ;JDRv| ];`e^*sa2m54D\g=i~cCB944gn;w,nI7Q`c1q)Zbw#wyJؖSS!y=ŢfQv.(slW޾kW۔1G'¶|DD?dtiv,?aʩx3f4]XC~ec1fU%ViօY21/tHΧ #wuv m YB=N ӷJ`3wU1<>x9iʨ4h(t[ɻn&"ͷm* ['Xп);EJEoMaDόJ>ϰUpESܽ([Jn`}6Xk,ʠTszvB-Q[(+bq0Q=5΃6/HyV%/BtpH!. ޓ-.ʹ4S&ހ!x鍇,WCi9~ǍsҬf]q ڂYDQ6c +oю< w{5d4#3\. +t.yƖ7vOfWq}' UXs]\Ba5EY]eJ C=Dr}o`nh|?@lZ۲}2R(d>S"o\}̈ BiO.zWu=9tіS^ `[ Mnh#F--"b<;K S7hN7\UTY@Չ$1[ss.9[PĚ-J[OP!IIVnJ6|k&gx6He|~js/m֍tm5]:䯹]LJG^ 'k֖,~TՙJ#1ůOkSiWgD>v;%_e|ˈiاw]ffAnI _o4܍81+&Jy#kvig ).3laf`Z g40xM|A}"+8ջ\\24utE M; L>@ƿ4㟗\NXM$Eŗ*"'^a3AMe!XǶ>mA9vCKnc[rJ\ncBnNMF BQ|Q0cnk!͠T9oo2qG8V^̈́1X l?dO؆Hsߏ~^^ۡi֏h$˭K*b<*fZ4%Ʒau,,S$'͌{X d )gnynG8jQe H/h(*_ oPdVW/XA-ep?͈qMhB>+9-tUgdybڏ,9DdH*G<BgJvQ!Ҳ)KPy&cujʳR'ޝ >^(]'y\J{R^fmd| O֗5_5NBwb#^k:.%):(1#W_ ӊW^8Rf6s"VӦpΠSfw_+e֮A#b8 /"+׸O,^J" Be%N io\mf+ ִ`E i\7OwI#e؍v%Ly#јf/ 12h#"?v**ZIb^ނ.,%i#RXx7g΢Ȭw>|scޜbԾ9#csl\ NJp%UmXw :t(@vߣԪ P\I(,VpX:ׇ=Tv 'Yb X?bM7KT+~%;\dIWz]/ro3),Y^~?GʜESn_8qf",Hޢ /bDsᅤ'Mp7NLLh[L6fPNOf47kxL󆿏5k\zwcU7ڻMOJKRUArK_rΔ ^ٱ\fCɮ(,KڴIdJ_T`y[> V FMOClaK`Kl"dVVrAU:ccD2{T*KG* *ԯ""I 91N^WIՋHCJTY{oŲ8;xuzfU, %te {eyLSZt<ȎΧzmy5a "pbkχc%c`2Lx[W">ⅳU'♧/n3!g0=e:)NQ+:(5M:\Hq)#,ɽp00~tem^6ܪź?ؖ9q>/yf)e`;5l^_pnғ @AF0(Fݗ)P~0sLyWUܸ dl)5Hďʏ .2 \.RG$4zdK(<1?@.38L1nx1!)LwjۛS[kɶfmsctl33<.JP"*iN\es1=+*|5#V &g2z+̡ )#)'VحQKUu?DK w|:bmKZC_a؉EDFaNc39CTccjyF |`;T.Sf0.fەI:4ŧAmZ=~Xo~_Z_y~H+A$i|byZ^vqaN_+*J4\I2VoCā i2H5Vo@KIӦ2▲ID`4b9X`#ꓨIL5BQeJ'F'c3^$4'-FC1}:mVWhUE?ǃ~ƆO~nW nhVśPsY%%l@Fv,L4~XSVQ2V (`cDm(7T}8_X:m F Tc?Lj?(~`qYnH/rF7RzkY:Xb 5d\ӿ%д3 뷶 Ĺ>-ÇH +;J(GzCQτ4*T嚐x1kXxKO^L|A%8dOO|fJj`L?Րdt]>i]Dc5d~aQ#_$,:̈́ud"M q1}?}^z#v9ƻ .1%@s'mqgxq4"90Dz*lN1PFAnaH?4%J؜M7A60aJY >2ܶQӉ[)Κ g4l!f,Tʕr}q~$|n8X9WfH7?DųAhYEV4l}bV B0f(ԑVuS(:.`X5O- Z5$ Mig&$B#AOָ{Xs(1Y/q+D#d\x_HX|H!f< 6 m5Sco'AS )7zy'ǀI Q\gA7) ǃ a*7EYpr 0/l}pL2N+ ^Jv3$$fzN4n+;ܵLZ2ow{8ëSX7ܮNj>28קi)8jb W#0N_¢4= mzeF0IE것5!M\J- kӂ^ J}i݁+Eh:(oAجnFB2 ݽ`ؙLGWm^ǹY wXGl%ᙨş1w3AI0"j5`F_:(6 D vCga[fNڡH?.fys8aEMZBd64>Q C'=l! 'P3eo, Tw>yB!t[o-IR'P{-o=K[7ե k)t..7tm `w/2A6ak<@[}:.Y%x"  >b0/J[fsI f$@ AyiE&vAI]J ӮV]z ~,=LnB(~)"RkBTM&q+GHQ2M_Y>B"֫|هSk.|u;QɮNc="`ۗj5t(:B{;A]Naо1v$yZ*t%RUnpAӺ5SLy`|'-EV&sXP$V 'A7KwpUDʙGr.E4acY RsB:oD4zrٽy`OIҞ9`x9|>Ws]Yzu7&B`ܘÄ*hmG9\IcOh؎\ǵt|60?ƙ2|pnpn;&#ipe9 ֹ ja9K`3`Lm{Y8SACֈI-fհT843f5s2BxRWXҌ; \tk! A%|Dew;ѽ`NznA̶G÷hSB3 6Q|OzP[ ^mc.h%@7g3++)+1AoI.9v얪iՙny!ïqٶ#D35+@NavAF&0Ryw&z< b 0Hx(F|(޸;2 Ğb dcym\G$e_f- b/ >{7:Pz(i)-88PEl*`kKEtK w݋7`pOub͒|4\sޫz$) T.mBİ>K]9X|7mxB$fuИ9/}Y!IH+ې_ V;Xzr#0R8"pa^W%x~!p{7X uΙ?ql)#rO1 0-l^jÆOQ *A$#c 8kt/O[wp8V>j| 6~f+A~Tr4qp`sj'UGrtm(`xW.a}ۢ1xz26c}ydc#3\ŹD!.\h)Cj¢II~Q#YݥE{s |h<͇2L`*j[0IJ vYk,([phpCC׷+(۱zI21-YN)W[X 9TJ]x 9 U+\7b0D| ,׻1|r+ݢ`,x8i]gfGbn=aihIjÄ!/;Ζs*єe O\U55!1ZA5> A{u9ť;rw: .j#{1;e_?&6XK4,XNJM5 x ~[apMYH}0yYEqDHn UNlC[ 2;86o* ,", H1Al$| L`:gkҦπc |iSg|פNï\茩|o9 Mx  Pv^ ֗("*N Q]w;rtZ^"si A P{+ȈjvJ hqB& tK$Bp'Vޓh& ԁA U͖g&7 JPbmʛ;<Nyvm a1`5=O }z `Li< )>w=Lq([BΟ"!;-x{ U!ke/ExJ'lt ]IMP-$څ8^=39O.WJXjCO2n&+!w!o%@X+3JLJ5ɗƦU(]tv,W,11<RV9cZ46  op|#Й FNlڝZx6/5̜7Yۧl Tr,m2X?~  9վdE,gW/[2LV_ OTvocQvb0nӅK[\Dqǚ 6@r\dELXj*|HMsY1XJ ȋ6o-7y*%jIKusV;8LGWt嘹vD^n&&[t<ء{WOEyL88y7/~Ɂے=d(mXDs/,)~瘲Z `E `.\&7mFV[͡;_zNwF&ڔSh<4 SU<׼j zi/Ng C./#61_λ !4F7Llv;rgΨv` E7#55 iGbf>dc *"u:C`h/ˌ]ydGM}vl5A{'gς11M ,ȌO+bq  ~dVwq^qBN!h7}`D4+71oe_iS\upsE`]%ܼR\,SY.ϸzoe@Kp%osDސmy>@&ʹ f:ĕ_oa@AQj^p`L% L)1y0{0}^`S`a&(00%[DE} -o#ٟ[`$D[`xfsz3D k~XJ ˑ4 BsUZ.ᔩY̰b4w'‘oh_Anۘ؏Ib*ư÷Q,'UT{JA D`$rp `HϾ Xyw=1]++ +%(o?R94QtG[aq~(ԃ@ŽF9;8e-{M] +QoY0e3ƢGzs}4 OxuL,%¬w2?dk7hQ]pi{DBm};UHو<̍lu '99]tzWx"$-;,:*&aWc;OSZٮj`bC.HH#pۍJK'NC:)O*Ӣ-+ 3XJ^lw b}]!~`.[Eb><=gEtfRd7!Ԭ FTiU!Vc Clh~.MC '< K:ލPMJ~07@%N\QiY!@\„#B횴+ƱRf">ƸE};uMغ!fpɛP>a?u~Rkl&o_ٶ,O؇>u-Z=<8G)_Z?$?4WOBe'lK qSd!ɂkES;9(gk7̓ h[/.j+s,_ LY;@c+}><תœ\vΏ_\+.:SĢ0w`fUD9/gj?@FUz0}?@ ئȆOJpv?@JF%::Z)^]OnBa\/^;9)Kl|hg?/?q{^r$ўbt&8 oU ۦ7/pŲkXwaONЖNOUceO"&,M䔀οi'ΖrCF$v6aLΚ6E"wэC,,*ܥ/(-*G#] b " 2dIob)4~XƳvVfG jd1L#`&aᖸI.Ow6C$HUw3c{D#FV&Q%:éu1C3ёQGPsecrvx*gt/8n;}2s^蕞+=#}&2D?Wĸ!1ͽ"&z|>+1/7㳵GI_y+e8x8"RY}Nv!'K3 FU- Z] k*E4`'bnNj($kNj̙YS~`~߈ NZ5ܞ􍘵9dXN1`=B_}#Ne!ZmYKn$n1nz݅=GݪiPxV7EcJ f ZJu k>jmyLk}hkz~勓_TX&t GbT##JDPWDzʄuhT BźJn*wyPdҿ o#D._[G}o]$GWQIhW#~Q=xe¶9&!I15*_&RTP$!&%!$I$1 ľj`&=qW ń0EDUDWTa`xUUr2"BWrO$T@U Š#xH#{DR]=걇/V;I=ÜB LI ncv?jIC:D#rPX7H9R S fAG Mi_BKT%aE;Jt4CE9$Bc4iװEګy& a1Ԏ"1C\_',oYl:moFDHFNHiV&1&XAmCJ4臮 ]ZyPh8*b+/++"BJN{fJáP⨚8'umU$. ``pTQ>>L{EڝӊLmӄώ%!1 ի?Q"ҫW.TĤpXBJ_:{0B#C q 8+10hT )eX]A<*#JA DHT|&z@8WB). kFPe{1Y=Y1!a$q$Auc.N@Ͻ!Q8 Џ{%t6t4[{AM.9 ƣb ' E^N*qA #%CH89ZLI 'cqx ;  `R !4J'*2U/pPG˭B{’:0^`<K+**YSX\)a/a1.VNaA5&i@Ra#tA)؂cz{C8Y\Ös#lA#G0[~h'E]psÃwTnߜݝ 9 (*r.e|c} )]=IK,% ۫:!>&u|Pv<$6hM]ˏfiQ|q5Ն!a'sqCDwfjʒs^]O*ruw4lҮrBN=wG@'rTEy4AH"22)>W" Z7J sMRhTr KOD RPqs0VLP⢊× :&cVY-"܄K/+rp9?y  jQ֛8*tL ;Z}5NPXq#ծoۤ({>j[jT4 8>^Hvs,[ik4V"lbr.1ИJrhٓ}yq S響V|Oe6T "Fk$n*?ߋTЕ"&s%}+gcjаWqSȶ-M%) /&k*kA4M7U!]ak#, сN=@MiVVоᒮn%ֶ6ln)|>F&km$| !ڟ1߻#@5E1Xk8 $gҹ Q%֑qvIںZ`Fe|#$lc !|aX%v?FxAQYC0pXĂDF`aR0ꦵ9yK|9 LkL@3WۖE=RTy; B)'dF@ƍ)+S,$+Đ8^ ICu"B`ATH!> "_~ ЉI% "D=;FhskٷSP6-״H[h>Q]3-! ]۹ yFJP;n :Uoaʈ/ۈRQ"@4 a S# \yWߌSO Ɇ;V{R§f=(0 Ke-K tJ0dcgnO Xs FFP8&=u0T#t֡_ѰL/-q PsR)9Ƀ64EwmZL3&1gE%MѮ+ܡw%T{t)ķwl2P؜\aS^ZCܾԹ)gaǦh[  H,Uaj0݋Fp$7Ae(*McW&nu0umw˅䘇]QR@!DEfN`"[؇\h 6T`U|yƐMãb0 KI~hNQ m f'@f\Ey[!ESd&w(-q*Ȓ٪޶f[s|a;wUӱM0$c x6 4` ]9;9/Xv:Ys SR'wq0J.szz#0*s7cY} Je ̚܃-7֝Rn(rNvC}®,$lBăoͮeuɐi;1$ʮ靉#ppHǽV$/nw{Pt9M渇QB'ND$b|sh'wwf v(}wn_"{T^^19NY6tM*oL_&O.);v/KA:sFS̞)m` 4*'SboIUYng{s;Sk+w6⪕Y=( 15*vJQGb>&6lrKY8W28%|oN< |8\X> `RKO~`9fTMXRc Mz٘}nv4PbaFsR_Ұk7ū*|!(YjJ:a᥵c*wn< @<%HiGދ)W#@c/~l/ИB>x\ CJ[$: 0p4@5S?Mi3$*A3%ALv48]c)"n&im6y)ySDR]z{3 8!5;4E3eP rJɟƊ: _<hK#εՒKN9ջB%?]0wulybG8kG#EiԮtӻwzw8Q4n#r4L4}0<4@D=w7WCJPPQH{>u0#g2l~՜x5]=uDFa+1E4:-J2;  o.<ݔiHswɢ /jix0Fc/쒲FJ(e_o \$xń^褐!S~^ZxlCgu}^U*}9ɳt-id\JPT00AAJ;#Ǎtz̼ 4U5`ɃXj'mj86c,.U"2seoa” ^ D 5F^1e\ex)cuN|kYڽ/_l3Au2̠ ֱg!sЫ;a H0T "gu(,0}SΪ)Wv1+%қ=(?r C.- dxPі%ɹ_pڧCeڡdž$c> lF*F\:S,FA?4hKA( {n^vvC^+y~<_]"vjZzvSk~eO`&YC_{9Vh1ÖՇW0+$jw1 դ%2T۪,pJK,IMVtԠeq'stDs)eOj9Ju9<{;4&h'.dhoNTo繼੃M.F5ʴ< aTiyRfτM-"/zXgd߷NKazt<ҢvZDV||ePM–~[{e<(qkѤ=xl,]-Ӛ݀ukcIqvlYP,˘&/(PD5TevO0 y0TtAUנF .@PCFhYWrN~&( /Y?4~eCx_I ?vX`a=!I@( [nL ;8O&葉lm*tfl6j QUods2;d]9l~G&[n6"J,67kZi60S5rQ:0mk5 OY}.,l&NvM'Na;>]2uIFSSXOGeTvNY=@3`^ nCHrXGqas&wCb]!o`VLcm37Z45~s+/%3`ȱ:|V:bM&6`BU`[mdߪx_m ¤U-d|Bwω}B1<7b_VX<H- U1ƥEla CՀ[Xw$76⹾*+nS4q"tO,JƋԥRj SMU5rGkX,d4ײr^,eEӵ,@d60;c2Uula(}r|-W:vcIk`!oi:s ` @A ,e mt0OLF2u߳GV'+jֹ,hgFݱ}3u%>k-KGU ܧd[{V]hV)d}6bK }>|^6Iu={Ɠ)FM.׏,z;<&T0(bmv$3,v6WJ&OԺ$iNob;76< {Um2վ5{a|ϡ`ule/FZeYKBCS3eп>Bi߈ 79aY ~xL56=M,]3>Y*$ٍJsG`7Q|>wYI{RM c &"M>}TLS\^L.d߿dv2VU?zE猪L#"U@B( `ݐl$>Ervr) ++3qnk3:S5HG5^O+Zӂx ]rD8̋熍u*ג벀w)ոYT ciaTM^T_Evps&ir{1WMwv}>2Z7ˀFLߕ /M@g#y<$RMVl{9hAg-?[83Hǀ{Hs<{yK4 9f]Zh!cxzf#eW~V5ދV`%YDp`9j-i \){ehPj|Ȃ@B;dLd];d`洓eq"D4'ٚd 1q- <9Ȯ(L6xש`j,.)#bF5aFoaBf-o1bT51@AzsϽn}V:fx7v Vx~ 3ƂlC_U,k1_e !6wMc("׉GrAViC㳒Z# :,Jv(;Umi؉B eZȐ` scx F0+ Hj^M[˯e+vHJZf?O "EL/ryu|j4maք)Z"T&T A;cM{X\?>`::0w.W^hФgI^_}l+|;Bp{UEu1_z*;N氮cϤ I_5{!M N^ruW_\kfz,`/O>\a eNbsuRty˯TB3,F3YY>Vgt^̟a`ؾYf+gn衿¦YbsY> 98A|h'+%5ӯ Ɋ[#Lan|d6KGMVwΆnfMV6`>[(ʞFHr}vsAV9 m+_D6mhaR=V)Cnp++r$k`N0}{ ʐ#ki6ɗh1)YP?pEGܫgR!?fTmULLER\x}M6ωt$p"UKIou'ꏳ7A΢O*IڂClsѝAL%Uc xXҔ5Q-S{mM 82$SH?ZMbbyثj۹zSN{OO01,|,?/EO:{SPk)do`4Aw]TJՏGs5F>pq|Mпtά Cnxi,2"f'ocK?`jezWYMFCyKta0;˚cqVD=mƳ?d=eT4sc*bΔ&L6ouYqb2-"} TɝR M|K_\sY|}YݜmS,<@/,dV{zNQ—?ˮf?5-R~v&ԿջX#,}w Nq@N<co5食cK:^EyATW0cWBlM#ݎ%xqT^c@в}7NUFwp,^,]l=vuYԳ0VҊ{YU-v{A69G؎]V9M;R\?6;Bǩ;E3 gV@>V7;v)$ұa6l'Y> K@\ehK}m/0jdh9XRX\uWX^wm Q D~pRFUĜHTA<?<ʤ f~vzXny.s6m_b;3|Nsgk7d4^ˬQΕ誆 MKOF.kŲbԉZ.Rꄵxēocw=_a%"}.8._ak3Xߖމa'L K>f_e+'k|ݙܨ<ȖV)7R/=H^utGѻF{@g]˖Ogm%]֮s/^Lpͅa\;ί[`凘3a d# _ZެW=ŠY_g;Ɗ2(IjRqJ~-i0_ey:Zv$G5!k%gs=20V]Ho1.f˳Mj ﳻw}Jyb !,_@Z*t.Џ9^݂A}>_Y e?!2^W=dỎ:{sx_{"xmi` nΡ~:u&b9y.%(`$U~c䳪s=!  Wkn]ϲ9n"kH]N +Zp)W \ib^%kԀ1j'#k'JJA[0;"])՟ [Q;`S"hYk^mh]5 uFeO&s44ͳ?y3 {+z-l+σtl=2\wgek$Wy/{_j[~f* QgȞ9Ћ^o?e31_-q6s6_`eF&a5V~jIk}'4h{a CŸ"dkdBE dc?cNȱ QT?ٷf!I[Xmh[#dcDvoAzx6DcR2/k9v(LBٮR{"}!^dU.Y o|/0YQob:&!;%VOb 8 *QyD}KlT/L %V>GMfM/|MɿMxm[x뗼 0 ,kVy#$~llv>5hݞB}+,v/tmbMʁOٞWY^>^IWY~o?ʄdmh:*uR+,m;ZB/vEM?OӿbdsV\X# /UQG:J'PA);3RuŭU.96xҺlBz4y_B_z5[YǠ̷y~Jy}r:'F?ubH* ~$AgΚwXl6=~O7ʦlT?:?xWIupcȞtD+8fJ,r߱ڛ]w,ъA GE2d}L߳62@,cn1c@fdk{(nd "Ȗ^nAP2>ٕ5}YʟX 7UL{5~z`هRx`{npYU;:Q=vx~˟YxhE,=`J!zg|ifݧY.aY>wfșA"3!)나(5{o<э aano&GJh/㜈zkl?̾4(C<җ"}\厓؏wi'Co`^[ʲ_c7vWҿQzF.YoF (@K^u˂мXݛ9c#}ק.0ZC~j=st(OL~ᒞm6l^߃e0`B^MZ ؝ s K blL1 x1GpJ90^ Kaۀd ,3Md H V%@Dc"#TOp}J֪JhVMEnuM J*!ު^vbhh@Phjl\HWC3!q߰TIo͸3N2!Pq71az+Wc!gZƈ*bmJTT'\^=(֛U!8131>jlq:gf>,Q%k)jOXt=70t{w;DþE;N-Ga'/"?ذdk_+ۥwJ&w 7Z/rk4?{?o[lQS&B#ި*fXZo왈|8*=BD= 3F[CzYɢqg \;æ]k<;R`m}.t'.J/cWU?a)X_QW%֑ r]/8?#wե2.mCƥ}a OXLAQ&d&ḑxJnw_L()[v2^tAF<^ƢmmE(RBz"cS6eeLy^h29e^|,Y+i9@{.t*ov<%0uhl(!sPt:hgdg :2`Vs?y9q1Wۗ_0ӲUd|.4y_mjQ=_'lURA\H{ri{"<s[n>3vgؾ=eҬ!&x} |T@XAy Y!lB $IT/3/ɓyÛ ZjȳVkEjmmHmնZwi~_V[9޷LZm!ys=޳s{zu¬yRgLrXr8c5x37.ciXJjP_] Q% VcRlXrH_ INRDܦEpLlglM~.bO[p`qBjWtuDiR@e=+R@ZHkᘮk#2úiaE65*jZ>hTQUѣHNeJ5[ |j[&F@^c0*WK%G4/k~%` h-IAmTS"QUe]Ư1=k7J8~YZҲ u%C-THn5ImrT Pe!5/ñϯZxhk\ªrs{YnYrPapDthz :ĠNnT߼aA'QŠS_*ٽJq5u 몌wO{,$hј[5=; 3;7O-4[4xF@FA$k]q~ê<|J22-|ڀ34;]jA)ʼnDR+ C*BӋܛi\8ag==Y:cz) >r8*!Us T05R@q hN ƭ̀a[7ɸsbYI@@ԯ0qIۧ!LޱIFˤ}dM:tt(2#1Oc]l + Ca R5ɸ&cAmTDi*zp{$c+O:Sœ$9BKQ--řl- 2`~Lͨpy!l:MZ R%#Ck|д"I YExٮgơ32Sz[B k5,DP#*J=(19BKwd-ͱ2mSglM=͋Sa!cqdj*QO1uD%^baџ{gp6gА'&H" OFGM+x(Qdd)RK܉na$ ~$Kirnȫ"]yy0^ceƻk }\a+Irj- axz㙹F8?٧{VcDLBC0ޒZ"+&sCZyvwR20P:ؐZ(F"%e(c]*=XRXAۯå9:vPr@FmsienGa}qR NΒAo*W-kڬ{PaOCGC)aA׃+nwsgf;8PrÉz2dRȬ * rJ7I_ޖn[b<`(bP ?ĨqRw?Q$pajCt nQXdq/37L2P]r&4!ZNW+h+)$2z`%7h칤$'M8-(>p5rpP4/2O4:?:oߜJGZ<:-øgg-HՉP`RƈĐz$ zIVW\`ۖv@ye1~eg|hekXw0.pWca#s,he5"'cP|SkKtAhl+ 0T)NLK sGPѫqX 56oPCMA:w+([K֒m\߶M UqkDS|mq}-Cݼٓ/5'[ƅ9``AnȂƑ7f7uiiW-pF%dw e[ ヅUB}Z-_DS'Ӹ9Ӌj{]IlL%#Hr~HX(siiʩ3yH ݙi_rڏѳ4-cߺTj%#Y@+TZV={ m蜰݋:AV(&muE,T"n-8eIhPj,s^fo֔ ߃,3RUCYZӫKḈΐٛVt1:pZeΒkt@U#D 핗&>D@ <05BSnMGize $;J `w 5nm[GW%BZ, %Jw iJŗ9G/teArl4֓FUY)'3Po@/XGhc`:q:t07ꉊ~-f*wXlEtiCO::4ˆ#Ε' 5[ :ݭ%U>ӥcO80([mhb=D \@u|k*q2H Q!E]tmaqCk*: hrcx>TPA¥֑{'5E?Yl"Eb+K (89F̷Xp!| :ڠ:xk<o5х*bbCR/~#ń emև ,uC 5I}Ƥa3D6}b>Z-8 1KZe 9!qy=i♧np = gqzX%>m\HesG_/{8= e++9`|\ssoN w%;@i*kE)+G!!abM!]9eB Ex 4Bf{IBB|h&Ά {$<;F'}ڋ W,S>%3o9]Y?֜mfmO^s|oUu2!\Ip4a]|! cw&.u,qj y8,T{>Pt6k#ZG*̘_wcW$9TiU>S A~-s#hqP{"`\j3Q~Vf"` aTY1 6yHȗorxx7lţ`y/knbtbBp5}U08~{9sOF5^-)R[{wkun1ꎂPF"yJyJ}h${QGO/9kpc+h7ӊҿbM)\ }? ~϶qJ*@h:RAS@MK`gER BcCMDTt8 I n yiHN5XRDx6Xe20.]h6< xpu ;[9>q5\um|:r؋n*Aa֑&xs鏎{@9f.1ruY}@I~P X7ݾPM 6N$qE"bl5T(øs{' n0)0t&b{,(J h44g'.P]]eщ.'@L9 !hf{n2ԓ[cf"&[!YtŌ¥'#lyS~-D$`<Qtxc5zJ+?2mjӿd/[Vx@\XCNoDcI$M@Ƅ@2nms(CKnp]=3qde6V.d\~[H6 p(e9zh7Kæ~# R! Dcqj64Ew^'$&}H ~?z%}аwhG*W8XQA,0.Re^@]:(:k(m>6G/o <+-h\JH $1 .Ob` HZXIiz =7Al;(:d">RYi^ {@PBNEv3B$pAx(0zT9n!{@XX"؂C-CM}ToRR@OPK;T(C`8\D e!?ZoZ2Ƚ WDMo'WuiXq ijف>iڊ1AZbJ.2`"uYq-0w> ؇J6.pf5/T<~ J^ cf4n}ٳZ;Gp+a7=gţc-tʝC'l` )LQ;cZD,*f9 Ȱ"gݺUS)}7ZUA5@<.PMq$ ]4j]D V-&):,7er aQ0eQfkzU9 #1"N3~Я]W'+s*8w VrCqm2S  hEE_լYZT21KiHWT$>4 [ +䙇u0JrPaJ]mË'MbуG7EJ}N@0h&!PSHNgFXT@EgZB,W!M)9nst '" ;HD_CJ[O2HgU&Eŝn=yP5Z1A#5W %ւAL\r'$o$ץ?lb[F¡7pnQ$!R%bXŹ*;01INE"#t^:EyGgw| U5l:cZ5ԘlEى*K3߽"%/lK$mr;a{T;+.e q.lJJf՞.svSqy E>a7-,Ohx|)qPЖ&-9LJ'FY~#ƷTve55QCdCQx%,D @PHB3l@Rƪ Xe'V3ڎkd9d]|vTsJYR[@EY&(r{36Qd)0.`1zhyK PatYA:cEp4NpsKIڒ:7jqL'?fP}gya'ΫrLH1^a4ʦv𩪂^t +ÊIMnSm蒧N]rO ~+ Z<4 T|YHwI+F_~t$8*:^sv>3mBϵ5~5vSAGj*Lec⋋OkB{Z.( g_3nyqqYO8H2'6~4)ELTʢ ١Y'ʩ a͹iJͿ#aLzp5LJxA[o?:?㙗^# TkEY!C`@_kچ} l~}cSo-\8J.R\Uoe/l8Coԗ o8HOUvOV[嘄Y z=TkAp,NЪTv뺵e88ů l7uI"B--^MNM42B=9(eA o5f̈́^W~'P#OGO3!kө0-ٰdKQ!;IG#Q)Fn6ml3汉ƤBoJ6qe4wv[/cwy7/SWL pE}w>;Y4n< ]9Uʨ yeT]l%RsC?fŅ*dch΍W*r7Bs5Q[; I]n-3;'7[U:6<ЌK~]O`\JqGJF_ijYY4j#B|9vu$Sr̿eδa]Gɞ@Fߊs]1 @a8xc{NHޖe{ њ.1ߗj_ P͟oxM4SD6M~hR]׉b̉Rzn?dݗʰз#]̕YVe# Qnhrq#+n|ۭ;œXV<U-X6lXyl"+1`s&v '/Pka0Z3uВ۔}`2[wڙT?dkX䘗fY=v HWx SضqA1}SYjSX4MjTvIF` /3˲XU ig-CWܼ/Ǹͨ2UfŒ69"K9eXGVE"śNceyyD# qY(g(]=4IYev=b{~M03_ex%ޮh`5B9"Ѹ:dX f_nd=Uag.ܥL{z^] ޝj8&)|vBcfk>[ ad({qckJU~^mnJjHi=mf63Ln'fs3{U-4 =?Mƍj~ ]LW!IAI ] ^(`ٛd9\)vV>9.dhJb+WVU8cey/td&2 m6e.UOrI>35TG%PĪ: szu^_?:*cs9-i}NbV1-y͎`Z:2)a9 T3~pUViE@t]6 ؂t{gVw}G5??m10a wrz|Mrx f.؍w}nkamkYyPA)lq_7'+F˂c,TŽ}f'"E<_|@]k J^Ǐ.DwIL<[$풔=9P*̃ˢK~t^qf^FPG [fmu5fs;c襈u }r(^jhQ a2`YM8Geym3hI4=gQcS/J ;O3 RD(9TڶM048TBEȬhn;EhXf]65g.6VQe ->b^V+.)-Սvyd)kWu1NgoK+w;Vblp 83wtQ{rverqԣP߭ ~JiaI.l vFrDH?Y+Evu+[^=漬~ab<#jc9P,UykgU%L'f#_dA Zy% +Ik؊/b2 ϸv5쥊;wGZnlZ i,b1y+-\<1J*]82GoWUȍEĄ|-H1Q2 j+6&C4̫]z>3/WmY i=z<.Uͣ+|ueeUTL{NJnR`{cStjUyh7 [Xٳ}:!;]FZ/ePS"EW'!˾͢'+Y]W>昈 9,FEC> r3t}m0mfM:f}IL`51d?GߝŮLJc8max`#Fsc1,t6e!nɋb,uxfvzJѲ09G-hq'>5&Of/ (m8Ec3 -0-&/%c>t+kFT?VX:C"D51a+ѵi.hgᾏk80լa1iVeMRq$epm<6x,,ǦqadM`yP0[o^V1NXe'hQ>INi[h^< V *vS'bUmT]1],ҿS^}s 3*r# s6 !3t:QR h-tgefhs̳TȬzVznej׀e}.*QHyl^OB`,mfڈ+4_ɶMnQZ wdWm1 Cمo4B yXͦ0-678՚lY 'ި7Lsc^as7`Z4qu5V͛L6͈ΞH=/(vQkzR&}Ί̫r16gEbbA@{ܩ5Kߏw*TdsUwP7/ҹ$MX]l6y -W5v ;`N drZAsp7f o@u*t3K4A}fC -Ŗ{rlE&F xNm}zfi_~Ҝc a1X ^^ü$*dE?/l{ src^=<J_3y1[];{ m*0G>NxvhC9n`4&x·}o/0OtKHOY 1Dr0=lz q[UV]ۨFw4 u滇5^J]y2?YW>+_dw4Lx'seh.ÈS.1Af1뽥b`͐?f_Kb2չ0~lk؏g%m0֜va Եlu̕2jpFױub˟.׆;|O̷#yܟJnv  [A齺g/~Xo+<>ւZb$@jI07]Ge>y&:ƈqQ(ռzVb^Ϻ!.Kzj 0L~r='lV}egغZ3aM" ,Թ{t.VӹF*/6mjKchjh.LVaN(쳞iS.Y6۝|㳌̧?˲Ʒbz|p~?X^]7nfSK>~/EvT0aﺝnTCS6ncY-4~5o"j%D9@.?};%k6NVK3-}d-;v䓑kv6|Nv3Kk,"ayBr￧"ݗlAIWE %D] !yfqB֗YS"dalzXTYb] I0.V_sW m(*K:PEdBvDbn+be"K4GYZ&#YCKr` flUbCV$dPj-.qX lm}RSJNA8>U!cWRU T#IVaXB)zT >|^62h7ߜmDz絻56)j|}l˸/t&.yG縅_74|5I vn Ѽ~6нGzM){NBNwW9M0*q8ULo}lNx࣠Wۦ}0oek%Ӄ[l?<*~dG-_gA[A_u=nQYr9)_J<U0,ka=~I#<+i)'FNiZ*I߀=dY+2sɶ|FPzJdGzT/4Kj444!525{[& pr+FOINdNb!WO?hN6˟QQi`_ boy\6kl3g8J3nn[Ja.{>*L]]6{Fkiu3ey-?-:e}X9Pb6sc9I {x G40><81#l\sv2GWG&l=β`n =$ހrQvNn kפ.ilY;9DY`[68)Ĩ6[>8I6O]Ǟ`{/&S,ԙO|f8Mybte9)z1~ x>{J^{-D3> OOz,oj}%DzsVK9{,92TSjv鮎v'ꆺo{1ϼiv(N_ĊɲяX-?fYZIf98bتκ'&-cg7> G?#jk{K<ìKW~9 RteD-NY@zeI^!@P l^)ê3_x5;1O۟V]ߍT vOO'Ng66K,. TnO04 I\:rn7x_.'4aŹ~Z~rF;T4""[XnҴxN4(,*\և00DEĴV\lN;0swn}f%Vo׉0#/vKl~^mKl޴~O!l%V:?V2Zg% O%OI`n^ V_9x\0 ~ffџ]>lV+ @i?f/Vp&o~(RoZ7+ql/rѽAѵRIEf+/A۵?ǹFSZįVظ*=uުx0&92v7}:"%X |0j+>hK GdWSWY~ q4 *Y\ST>4yUN[#~goN~hƯRHX{ ɔ˸vj&^cճ;癿x{"~I>[i9uVYK뮯S-`uLQ?s r8.&`y&Q1 rۯ袤z[+7z͚]fΛ,oT7rs6<ӼM0>Ty -[4#Icn緘4?mS^hU0^t0O_vZ۞:ӿd;/m]X~~*dYyWp[v^SvF~!y_x6+=oyYE>iE]%=$$4x}y|ս ;$L $7 a%`"2.LRkЊZ h Z놖lՂhbZ\j[j[j__.nYonBnfnv/Ju˔cj I1n\an\KSjd!=U_?k,V)a5&d]j͘lQ($]wɆni_țd5%KcJlvmט815Uےu೮H\Vcv-.=JGԸ@L˔}cT텇z}$ŕبy7\B_Wc`D<zc/ª^@,mHTSNҢNI(&d05\˩ҩvߨHDzy<*SI=jj9%2<2נtU3.?˭j/[*,S?{֤4Q[NNDL9T*r|!fs hFWƌzHPjN A֯^raN.jB[gT/Y\+M.azQMtRûriT#-+gWr&jC jBs ŕ)Ci7*[t paQ YJkOGI|ɤ!O_Gӱҥ2R{t[q5IAJ|n=]ӥ9 wݕ;XcZ{RoO)JIj R .-< I=UE!3hXÿ0 âv 9*%&fX v9sC{`C:LCe}TrcSO4 dD~J'?=c{[Vd(jDEtRJQ9e@wJ9qDuI(Ff,: pgz<ZRZM.-`}`t.IrtW?%7<)0T@ajRReDC qAbx&*-Y(BUaِњD9Ye]M!>U6UEOx]H6eaUbJؙJ tأU`hh)yج%x$ŊГ t١L)0.un6|r!X 2I~3N[GL27oXuulub~dZږfxTtZa `Ӱ1TN(+X@* QTyfTiAK P\1YZܜ׍]ֻH3 Kht%j&¨jlt6;sMIrVmcBnHh"'0A`B;~C.7v$0%4M0ХO'؀Tv[{2K*)_BF6qeX2Zf( T!#hoyn/m4dLNQ Ap%vX]i`v6FHp$ 24:6kfv?RAb,eko ZdrLRKvumMPZѐSm7a |V@LhIzW5$XUF- &  k`GpauR#z% YVZl!Īc5>GU% @g;i9񣓫x ؎ygՐ"T5AGGI o,oWQ_+w40~B!ap8ѠɢiXo:vpdJIfkaI2T&0m6>t6Zf:*J#? 60N0;V~7əK*ਂG$3_d$M uuYMsY-%/kgDɔEo{fO88s EIͤ[Q9ךU&P_W'rSegWXTW@}$J!"Hk4ԮCQ]rl'kWBO&! % 4-* F +wۺ-bĨ\+`ZB!ѝʍ= cF7sIƲ Eת zOR\ò|lR%Y61`6zD- gaj 4 zokPiWV1uUpG} M 65F 18rEFIM'}*?13'R\'EڒSaVW&,iiŒO}kHj2w[.-V8ɋDp.V7˯B\3 s6yU]2cg.^;`= F3gm<1(/# -mnl8%_c);B=va.1UG2Qˡ|O0Zv7oXjeдp$i^xD8#A:Z$@XT/s[ դ–,^?`.,ӨmKlk9c 6+ܝRԒ]M@ZXpQ&ff~ ? k^imܚQ2认@j /ppsBꑬfpC?pr?HԇU& b2BcùL)p͌%nPvO@TG0e-e\]3@iPa=5S0IzLp|B(x2- .n^ |9@fjh@999t>Ub:{?92yE#%WV1t+\';Ύ̫za qCvw9<$u?"D L U38 2-){l!V #0 0˦'aǶ'ᷜ_8I[OG/ US9r-&7jvyC)`a\`bJ ؀.*}}- ]."aj@G0u)5GV,~ŤHD© K"U*U(j&Se1FX00l#u&=Dø]w^mSt c>מ p!֧o|`ic`KsŝRT\"$Wn̏Ģ AQnC)T!~cR;<*2Q#r"Y* 7 SO@"Oa\;$^tZ-Aٻy@ћy՚!druOUKۊauOrkoxq1n <5%G) - }pס:iX[J7kxa/m7 -AL 2egLQƕ"215DH/s βז)J+kոg ?8y,bGB 2!.}UE&8hqŐ0RQw]jqUH7bvrlE]hk xgvʯw29$mv9#C6'!8z99s;sbφWN. A2VX(FU7-׽gE?,:]3ﺾ `IA57]L:/+H։BHmLG V1XYK˹KXMjQ@ DŽ$"N@"PP*D97nX޼ZZzC Bi)YϿM;DÃrPQ iΠ#J m|-7~럁EM3ָZj~{/QR͓^My Ekm*hq7DpAdRi&'߾Kd.WZK7`BvXII,-+';ށzc8&n؂{9*1f"ѩbNL9ud~|߻\` M @I nYu1> oS:\`=ӄT(@Dņ$D"2pd@K$vܮ4uz`- ]&}*"JEBHt[?$o}t IݧBCCYNǀx jB9CJ%%]6#&J 7bv\pHU%zQ:fm:Wɧ^_Jԡ+p.g'[ecVOqI%j$YL?tp~uP¶25<Ζ o|.թB)Shi&,Drw gl@R7FrA`V/?;j eOe¶&l~Br|jv}bh$ŨMIKJRk%6(PǙBMPmRta5Q/]xRLkmss}5r;]<4ﻫ,āAQjv(E0+ݽv I2[/ol(A)rd!B5|=S(M W3 yߑu byjz^?7_s4 i۰z-ӈeh0j,,j{`e/B/Bzm4hLk{.%j]e]ƥ: h_}OQp2wܐ/.H[4rW`,Bw$ia.+e2]:P&8yza/wd \"D:6:?ݑ7|'A3Fz4$ Hh%*t|"ʗnhEfDC6p1I$wDcq96h1w6Xli C'Hq;xC{y8y7Ij 5'+M'%U>RIj5c9@#BD Ycɇa:+ڻ' ?0NN!@|~O4A`$'#.nOWߡ%. aGL_Ph_׈"M=jا`B]46Xi!񊃜cv;xҮbY5 Br% cqwy.y f=;k xXţ2ケƯme]SD=0rd0JxFhQZ7i>oUB4Kq{G XKE$%ѕU։;H\ڗ#I,t5ah0)PLiXLSS[r-yt C)?kh4T' *P*V8͞OᤩV iFν'xQۏGˡa;&iiA# W]YovN夰9:*OQH\Nn(x,B;}h;x0u&6i&*AeAXcU8c5L001Du,ga58, WWߐ452d   (L#t)sTt4|Zb8AK-3GO,A?+,ᇞI~, "f$v*Y)4 0{rSrC~rdx8bX7gA~rcA3W8Jmr9=GDUzivg+wϗ?7fZwStqG#t~Ck͝VK.˟ya_]>ZLl9'^Y`]&oCq@B.u:~և8'^Yꑳ;vv<7Cs(bq 7'ߗPE zS3;L1QҠ\İ13agB819;{noKxy9|G јvO-*_Jn58s |9x)I+q{~AgQ9ol{~2 SbFtݴ;#'E"2 J횒@qۇ/e/UI){hO)> q*O窜VQϿ]ke@]l4`WCx+1j baBkl2w/';`Ƕ6=XvtR7v_^`ѻ;^tPf7ޭ-Jʝi^&|鯓Nܫ}msgE{=SOyr_P *m!"D<  )a|`f(?<3f"Eە{dy!4+[~7IkޡcAAX|zT5ս]vhdVlC%mع3!7|h攛Y5i(4c| BIQ]Q])ZT8įڣR GўhӡZ =+ nFќ)Esf+9k׬+K*耕 ?L(JCHîj߯~ˍ?D7Usl6EÁ {j=J*8YꜦ-1EI$W#C| C2ֹ":_mSR P< nOcZ SHYuyZ2 &a&y aמ}Pp3|n)o (Wx7ZC4B">ܶVxnȾLC: o+y/۰ ܞѷ9Yé1%XbQg!c2|ZH (f:1%|AKLOm6^}^3E#+nߧAL1P9i\a$DrcM`5:gt#MͫBQ6:,|efpS0}R)6%CPlsɷo!,y簿X)*GQzrs=E:4{if[,dPq Y>!/R&J>U/F\MVleSrӄ$z<-ϡ:>yVP2Zl^ P&gnx,۾+5|x0&{LfLDwF b_֑HK7{F5 /d* ^l`X̰Ɵ Nf #Q>r,)Vj-VmA<;+m&4M`eą7`ff[5B˭)lRua[MaVl%⭗VJ]Q/.b/ vzMF;Z.f%gOMCmֶlչ6Q@ [ yɥl0u/gNöֲ xuC[< >_8]ple疳e%.,7quM_)pa: [~^aU_wAg`bK]}v nY~Tn#wٚ3)UDmkX5w K~2Za X?]\?`P: سKXhlt'ϸwXW}nqC`_.ކ7OT s̴TPrr`&Ih x7KΌl J7[ψݝxYo`O|V Zg*L.-+ U,--I+G$zMLs90Fk3!xQKs S& 6Qm^D,x Nﺑ>l5Bv6CI٘~ob7e8}g}RֲQK{vju<4I#緰wK )K;}}!`MRnx`ҙ CmK 2<(ZTնģ؃[ه^(I6qzG憖ֆe zqK/5 HVJ ^l~smog>.RD Lk[xK.cք` 5/,0= Am]y?>?T^n[d'^O"^%ٻ}{5d2f>;_`3 NJ? _jW^S)-8!b\žWqxpwc/$AOc_^VVId$qֶegBND3'ۙXlyI}Lv\ ٲt/L AǸHZ;.csseg4r Ry=v-7:7bqOZ6ޥ?@QXR &]v%L*1F(lŤϱr{cw)~x/j [nh]7E\Z}([ a95[GnfSƷ֊bVjM;.-"Қs- 1MB+XjwIEGHZ "E:o?-`¦ND EFtKDe+z =,Ŀ{2(5cPiZ]Y%~`˜^!v5쏨hl_S d8rɋn,BY𮳨W`tϖuOo)=P* s%.'脝ON5.M4䏟 <6UX[[o*Sxv[쏇=x_~@o'\2~ң\/U.ÅH]uRk~;#ls˾w*q'{wC3]a7jH]ڂTw QY# r 0aLl=*?̞7d/2Ͼaͻ~`=p^ _bp+=7εJaO~ľFNyȕ{ؕP$绉T[y/q;DecE%vj$mvAusԹ˾ʹn( %&/}A[\up^߾1U%3"ʦ7_amG^n}u}WϑZ|jd'))n¹ȯS "rٯ~6)._!#ΆX?^/m0pI@,CwAv`VCvɆ[{,OybX6Nrg8;l8>&T7vK&۲xnٲ7U|'X~H(Dlܴ3`zKփ`57| {dL -óȞ}U,IvpٓəL Ey1ЅO=ŢÔ^ -.ڧ#LLNME/4h*l![y-{' gXI#e5]txZeW·|V=-V`-y Ft 6w3!WXϰ,?Zwcc,Y6!ʌ34r0X۬Z[THidP։u7'uG7[ > kbV]=z^ 6wbO:։Vk]<5V,4vݓ#Áfu{=n  n<z<ˊţ]/%l_@FH lI}A4}謺և/BYXwtH[,T^Nbu%*_X^w`;pGl >& zQP,9=jCNһϪ~UZeX:`aMOb?SSe[ 寰g\=]&Iuƙ=a@ܛN3\Y\t>&I YRؐr>fB&W/"bklv[xקLS-*&nw.ZfJZ75?|wù+p^#m$-3 v~&UKBM4S&3FKz[`ſľ#"fJ9K~ՕT'm y/)=7lR8.z5#C>x} |\U,6MJܤMɶIߥm@ۤI f&iSTPQ^W hD|P?S ) s}&M |OK9s̙33gfK3a\_N4TVRFzb z_VyqݺuJg\I?Wӟkϵ'j\NRF۸BKۿ1=CV{rY- Tb)MIq-բFJki$SgAO#H9jԲ_dr3-F6hHm#šw҆M3MM7UeC:en1(-&, tKSVPw3VD+ٗD4^jDf?ʩKWVP}9 ICyQ; a32'3ϸzzJ&3ƺRQi\|VZH+ Miz>5KI];[M/Y=/4PL4c(V fZcWT;κce*RVϚ){ 35$>#WUb,:դ~TMʡL|(N ` X %bi@:GNOU#cZh0f\?&-Ё"~IL3`u4D%ٮU ۧU%c=I-<q=&SJf79evq5bo*3~ԏ}T2QRF3Sz֣4 z I-iMv:;7PSZHDKKWQz%KDwMy$?8SU.Pg,+.PQ4s &txR?Cjaf +'ؗNܹg$Z( `ZVu9хopAp[JK&͞ 3(aIV`kO=Ͼ+%'w~84V 2>$ko*gG$Q3=ZJM<;ԝWԔwk -'AC"I4[/,wL]#C fRR,KC6n# 4p:iVV5 .MoE6A> aŒhxoMԞ1jak*JKi!A$6kô=|CǬ֐,"EiY݄!y{KooSR=RE ˤB,M0Gi`\Hih.Ȼ .5P̂-.Dj>on 1`XG7.ϸ+/=9{P{]yԄ.e '$tT9?tMZ1^#/ @T҈!?.p>i:If79þ2+jq9Hgd&m39? D3}z~yU|.[vFŶá5'(ٻﲏW/#8_sHUBEzjRA^6wLpxa'xE&O#=O(ftÞFf}y;Q=e@ZiYU٣m]&ɜ8]_S~8jp,, szPI/9٧)kP1>t -P^PƈU{]%݋'MKk:eub`8X7>7=8L@]M ࡞]A$\ԁ|P xh\@[J?W4 ׯ>N]6 cmR?\X\3՜m4Wh\+hgD@0)J3@"Rj!:o޶\uR\5|eJenT9>ף9it^Xb˫Bcv4%aRGu[V3ZH]5:| 8RQL =M7Ҡ:1aAx8U%Y$JFV^PV}T{h$\z_ucKPPBmŝyhUsPNtXdJh+t 0T]%pe ]-<f$1۾Ջkf?Pݟ`w<5HGg%O‘`|Rkk%{.*>*`: /!/[4C([X_2ضu0w\,ռi-J6PM ; A +U'6טMAՆH) \bw4o5u3yWVv8l⬋>TQU:Y xơB#/Cܜ(vK oboa`qήA§Cǒ8_HNhn-zaq(!}% P=)ΠiYbкaS|ji.A.ip@agV[[YeΪ.]՝~SA&K/oI9vd gNs03R:IJL* ^Uڽ١{c5[5ȤTd}ýPrQq:5ˈI5Ian}%ToVSzZlj}P%1AS#je8;8ɜ8pGuKŭLI+l'̦4(\Xi#KƖ+LЖp~q]ϟ{,>ݴbXp:tK8 ()\<8zzT!M%^Xv⋐pg7H+ci@ot썂N͝Gt'B{^B戴ħB0BuWtVH8~(fMr^r)o*0ȣsuԀ2>c޿<cмevuǪ58i=eN:ؙ4~-KBKݻKK* :6[{9Ki}nlܹXKk-Ls& ABιU#8౱It-\"'w1^v8DWEYpZ9B+AgJC9}Ǣb4Eh\0yL ]~8Wj(;޾I&d,e7Y̫ۛJ$# t J[=k#W^%[voHqU%ػ7_$@7ڐjqh`np\7<ȨRZB'Y\;t>Q٤m b@D]\0PJoX)ՉK; ĥȾفfԜE :xƫ#/2>tg8?<&d+J#VLFm!M0L``laFESvbᲪvBX?rb7gMEt%:hEm禍4PWRk4Czg4 dvbiӺl_Vx*hySc9&Wí 龎/#Mq5͙\gB{g;Rjc 7PpƿE dG{ǁ.M N~P~uFFf~rǩF9bʱ%q'Gh9jF0hfCU Nv(b[8pFLd8ICkF>^ws\h4[jX->`R/JKa˾k0(maj*|&t?֎d j=HjCc@n'T|x"vxe>*P h%},^iE&8Q4銣ms̲}bC;=0AHcw-ͣmezz ?#;!Y3硎z_$:j9? ݧ|x=]Q*-ny{,sjSȅ0w664Kog|D+߽c|^jo{.7~O{TK#:q&6+%Lz0ïy,y9z(DΎvsovǫWKNvSǻv\p;ڰֶ.g:{w>hp&~t+I%MV椉&Xԍ%Bw{?,.|6 *Y(wHD2W JB3ꖝt̿a%5iC RRC;wwk7\3^wk)-;c;ɝ&<,a&[\%aN' 5a#x%AHlwg*ɤңT{k"{Fk7ovo/0_KA`I&с/=] ZX:z]!ZÿPڤkBGi;oF?6t[r_+#Mr} D`N ;wDy- 5 ̛(L~p!h|slpP0P|GO×#1Y\t-K@j5"#J:Jĭ HNptf}ǝw(:ly,GԎ`_h4 ohE)VH̯$a߀8,q(VEDukDƩ U8o`vwv)C%kQ_\8 5v|0RLG=ȥ$ӹtOn-k]4O={v^@sqK2Ѿ kE7B<\mS<2]QgXDʻޝ?xōG`d&Q*FbœbtVOKj1 ts-;niw/x_{[Ga֗ؕwJQGƖ(J{:-$\:wb<ޜAXrTyĄ!d jn(}`(*Xg)(TgCxF⨧(JՏ)J#SnԱwzRɵ614'=/.ҨF.TM_G5lHS@čϓ1]eiB>ǜ,0C] @:.4BHpc.8 \i-.o:2-4H<74{8@Rp`/5Fg-X^ab)lYvrǨWjF`-g #qíi6i(VzOt*ydPڑ<8vaI: o ^ȚjzuC"?L\ICk$k 0ٯI&&2EW!3PqboSTy*8 kԫRR,C]Y16jXWf82)7/įyPJ(ErdN W ϥls.?DFM"&iQcakr'9_'FRv4PX_;E6ēfCEϲ_&Lvɵm+a.ȦYg蘕ʥ'27 }սdR~ R)QtB F&5Y%r~:b xssDbt'亊x[\ 2z6]Ze7U/ 7hc؁)nYnvR~\j1Rtyh.o$-6D`[YQIH_tc_ltRC$rI b,( zVd veJC(Ƶxɯ( ݈GLwƸ+룣T`FS>c!\8E*?bFL7؟١:o= f*t%X* GB \5&rXʃ;A{EB@w:dIk#pI$8%4$k]mkUO7[d+nMu}O.P:\D:;{O>YqFa/?g1N̴ﭛܩa^B};\OJ+g FQM؝l}]ӵ5Vmṃ{Lfz[M1zT?#͠φ"+~ї nE, е|:S-)c)Eծ2%PAaŌ~L\ KZrԠ'Vц{&{o/x}ۏVwP6Doѧq폿~0F﫮@ zXJH!D Fyh%_hրzT*ZR?bDF\ƴK~z|R'~ihQԌfO?bi Yf+i">?3w\gvOn( 7}ճ#Ԥھ/U;畲y1L˶:cw\xU HcPGmn1dzԸxH}:+w>]6uWuNd01I^;oNd]SM$vuI둸DQLfj_ϊahulL5lj&\:# G/Oa53>c2t"hQ=L3I$ۧ2[="J׏sxXt U1Rbwrjlij!\Urܙ]LS,WՍ2:o;Mrn,̾ 13m&&@p(ɖ;Ylmuk{?kNU%<2&]S;0",BTzlaY:.ٹӳY W5xPNO*.s9f ɆбDJY'̡i̽Oբ/UF" ,4r󹹬fT}!%d/hv決prjy.~D-rYC4E+z~tVɖ*E{M$Ο+YM.ofaH,WG?d- kfK&ijp|hb-Nh\-`5;fnR YL(ݡ b| l_THYĖBö8^)>k+Y15 I-^Y"Źf)[: !cVoS]lRm!fyŚ=MBD8;Dقis5آc疱>/7XzVCYL+Fǀw؝|0U$vqW 7kU7^d.+y Q}uKH 6ywZ%bQA޳=:%z]mNF*4|+9if[Tw,𓴈G}{6#q+{f;[vSm\726ιy;{ʇOkߞml/L\ ?e@Y\؍eG nB픱δz/5TQ-fd(>l^H,ZY@ꡜ $SP}>2ޔ vhwaK_,f8og_\ 4%ޚQ!?0ՌSy&?,)M~vU}%܋Տsto!JL yAzE)"|=GXB@Κ=xXiFL̠ڇ±y]adrRGaO&G`##VCB|i:Vh5Z"٧sl>q6?i剬vq_ ?|Rd$z@NnwòM2f&,.%tQ9E| iۢދZH']ݱp gdC6-]PR/:c0e~‡|価pg]o1(GL]SY]9UX<C֧8A# pKڶ[@dlu}]ox߼1~ -Σ V;%&*0K*n<7'Y~6gXڹlhl˷B! e[([Յ!#Q>xGgj7"qI59c7DYWMHzwUEtI==ULg8uζP1<$z ?Lߘm~Avdf=@:'RAvIIZvxYr`ZFR{qVh`^_e @_Le"^#`2>4JsG(;ܐaw@R `- P @35oa:1UNd_M[8A/[MS]„"nv~eŒz^194QbW9o˱n]bux?޽ P˕lɔ.`] tFga6R̨-g*@^p9ڼRYe埇49U11"\^QK] Kq+Î:_m*υE s;,p6tf~Nׂ2Ժ J94܋05[V"rj @=$1CʀA *HsئwW) !b locqM9B.Ar=s;ֺVJ]ע>H k؁r{Ζk9YײS}S_?ze&yo^^egb-ߐ|-j:%UMP{0um0ù:'&oQpiLzJ7{Ggt0,UDAreMOGgzpvn+X W,[?>ٱ&v.F;͚@Z g.մ̅4y˃7dͬbni_O#0љ@3~rLM0kd`]Ո ehɵۣ%)L8/&݋a4]೯̮.؎վ ]QY@Mg.Hjfuv~v*_sL\u) k9kKi@8 [U" 4&O{j {x Fѡs^[WAtp}͑0J^p1RCʗ!R]Ќ.V6ѹS-^ H>k(gÝhΖOO}=] m/2zjեΉsfCgጕk:UeVM+V;Cl[YXA.ޝ6y̲OQ֠A߼jλhq$xgXW]C:7kn'7 Wm$>btV#uSp b$š'ro󒍰d1cCbDލq.ע'`Lҳcg&kl?9_MvwUɪZOȥ5y+w<[ [QB@;Wbq@ؖͭMI CcZV\%k X:WcUwM+ WQ-KOs ow]Vt٪Šfۏ@ wpc+~ `ʓa{qa;Q|$\TMd7y(Pm2 {v@fֽq%]Z7>Z]t Y6yllm0GIr'.Ͽ ;^LIOπ]xm]J֤Lk 9V1"x$,9v^d ϱ֭H tp PWKXL89rpΙV;Y+n髴M:<ZE;`E9td͑ukYSvaޯIg/%TPw9ʝnc7+ 6)N@H F!l0xXw?4miv=ys#a S~uDVp&~:~9 iֹl4/]V:ouEiy:*Y4fT _a2t}͙؉)&1mGR/qчj# @htb1C[)SlDHu LDcV'ڪ bmZl||iʰ|:CmsqPO.qs ClCIlÒeWq+2%x?AM9E_geկe3Q6 $UoFv7g(mܚ@{$lcoJ _BnSu&HGfNqDnx"LMb=tΉoz-nTM7VLc眒.oaUdi~;l.1^l|l,:7~mO61FA[Y=Au@f%xqq!6WQy^)z ãD c HZxg^ ߨb;\$Eh` U2pp [3$@nd:-aloQc+9zL _}V__TTDO~un;-EҒpHtmYySl@nf4`JNK~Yӱ[\0vކQ-+n;3IY3K G_+V)w.!dR^m ~*l'OE ^ lBgXg6$oXIУo +|eDHF$:gӏ^dAC[]#yGl?fէ2ٖvsN @'4˰tdM龧٤1قI5Wf gWⴷcߘͮ%9 k`Kǟs"F<͖w[xS'jb%qm^>:[ JɈ+a S}#!> ;[zmbTQN $ؔgY]Wd bLgY$\mOe\,[TJJ' Cϲ2H͚ |slsk˟c[Xtin!%`WKy9`M[.uʟg3Gjsycy68悶O<֎ж _ X1o٧9/9{͜?,ʾ~)uE[NuߥlN/÷߀}lVqsJGMpn%hcU}KKѶh` %fI /7XF)[(i"] RpoXxl׹7lZb>Vs&~Ojnw}xUqvs]۾'K$ǭ=@u+xم_z+Ź9ye fդvIj\&O9'6};G^ Y(3`x1 605d'>yu`oH籗تa^($m#G #jY6? OO氒|.(?eq!L C>;L=F!aÏo `B{%PI?L~'VWI{׀4C 2]C6_0yϬl8c~˰ک5b?r,熿szG~ |RHN h&;pf6(>qPS;DӂXJ<y͗-XjxQrNI@3?/z!~~X ˷JKV{J &gu|Qb-t{6c6!V-վQ]*!lM&4r (G_aM5~r+l.ک4' ̔5`FcR˽J |'|r-[og?ʅ~pB?Y\ ]0lEꦑWY㬂ұW梁/nHw-/ݻO@sj 7tugtjl]s5ּGE(_Lk9ߍp=&Y_-ģ{UBک7[zH)lynz]/,s/ AJ/ gO٬^ȜD7E?Iy { Ws|3?XvftybUMzJs{A g%=:>#C5CNObZh}B?MҰ|*PtuȢU\P'挂-je$A\GtGe2 ; gD.{*:X 6i4%9C C힪'p6g֙-lW ~SyVdռ_)gE87XL-z+8+2RvFeŘʚy#ח̪ ,@1"JFUc#*v$|ufF&8PDsY.R:S;.t" n\dX"e"ANx0Dj K"u. @wSS 71fzIIY.pn/i}2lr:=l8*locP9x[b${\-jܲ ԭ(pM41lB=6 12(6L<"GTiLzt>iFa+Bg "Us/{%1ܱUa)F-V' p8C# lR`V˩{.X7oxqvONS!Sk6qNcYDihBYo |v8^PEi犲|&toQ4*CQNe Add 鶾 1T^}Wۥ %c6,JCoga߀݅ϩ7<\#)R 5ou)A+BvW£Y'UnRw_ u}@~~bCH7XTgc`Ș}̍ty0Jt. bD P "i4ěsS#Kds:;/NLh Ivbz>+A(l*G+1ˣ ēz` aI- 7 Y[ob:AMˀ<w=G ("T-bM!]y0A:PeM^rua'K>A$5PK PYP@#f,AE;Hʇ{ɯPFPy]T\ۊN΅KPҿ:,ʦn3G/)hAF&3 Wе1yw={+Έ,: 1AȇŪS•~쓑a ]]+xx#,@<&D'd0ZfEfcǨ1TZ˽o8g};i7X3"%SXt<"¯o OX n <0|KGdo2C8j~H. cWSMUޠ#"kw:\:pWh%4b訙Dw֛Da-JN), 4ґXbԹ7 p(7ƨ{|FMFN! ".<Ij vzV&.#e>AКEv ow$tؽP\> NCHfO BBiҧ@fD,׋/WT!"&!֓IQ'\t2x!0qdY]M}\~}k/cm Dl!Їq $hUvZl/9Z2u((c"^1xd[ZQXQo {B.)Q7GK/ɖl2D5=כwҫٜsfZC*MK+Ae0]7j)*s5O )YIAI8q6 "E`aNifqIL=AIqIp^eIeW.~+uQ.SON#)ԞQ`) ,8 kt`D#QA ڎ$,#Jiz%$%pY>%2#A yI*hWDm6#@N28d8}.P7 ԰4 # P!_T&;(}hTˎyS]LJD ʩ;oP W?C-y~ڙy#^ aIʣcuu9}E>k`h$)8eVoU%aiYJ4<J=랟QӰ`GZtsDZ4I>PHf,*%KQ><%u8R%up&r:2V$4nk٭i4􄬓ܮtىymحcKmY"Bɀ@alzOf<7I@R Wށs}Hs`R;W;`{zH'RjY]bӨ尞qn :a{B@Gerga±. L2(Υ܍I-[C! -8x?g3';(Q> RVѐ$AE0:IJhcU:9B [6Z-a \Yy7`X2/(06-9IN623;Y(bZeetEtR@?F@:aG<=`yAgMzjƯxEvYjE'+5{u)fm_7ϐy;&)25E|4.nV25}QBW?-BWo؁ H覔Bkz]He $*\)O^ +<8C3 ѡӯ\1*6Dzdj jtoﻹv+lCYP]vp7~sS#ey/YC* `PM,L#BrT.]hEKA(tpd|/ ޅ^ɠ.~sԁ[Cy,"Ēنj[t@DPI(:L/!AIuPBtPݶjaQ=  #:54qB9X"ZJ?O q `8֫naȕ1[>3oL ;o`#>xȡtq өc|+#bMVR9jWb^-ޜe4h  txZdvq$N|5<}ʾ=T#$ n(M# qHHJ"2%|%5-`j u?}'%@dF;xF57̔(wH^r;?bU!‹g:jfpUDH=x 1%r_#7Q/5-̥s 21U<™+2 0`&?kR>kIB9 M@Ai`^$gkumT\Fѿ\YI3OnyC9癩`=r<8SJ6,AʨqiQ.'QIƢN í-0xyr-,@և =Xs63]Aca&zEӺt|e*(i/ˆ|rɼԬ":F"i\(+On*OCrg4%x8DxO)8Fy~-EF݌'BMN _rh6+[A]MgB󍜛~wlF>̅"܃L3 FxUPlB-HFؕ|;Pq9C 4'/uqL0_}D~!! ~ խpl4C0 8|@.ΡghBꔑ)R&_72ΌV6xK\xT_,T?T5.缤 UЋP$PgVΖ|{1>*B/jTӫa"~P/Bн@]P &^(O0ϔt`Е_7DW}u}u u,a\# ''~~2o%{ }ց^F 4E>l3cM갯« [ߌĪnp_"pvMP ZECE p,D GO 3[)OTIH&1Fcp |*5ZON<>5%)#S37 nY1#/ P-7٩ʎ6Xu6 zx} |UŹo\!*n@͊@6d-X H@H VYت"r" k]^ %!]ljo}}O}}}?}3sf9憥=3|7|| }~'8XY^ʨ),27g^_^UW^2Θ[~dyMeꚍF]yV#cS]ݶmL#;-0ޫ@Vm56TTAGYEm]MźueƎnSQ[ܨזNƶ[J73KJ+k =ewQ>0F;dwXOۑacƽ[KZDaWVT/PU^WL}ފ)J:)ٹuSO}le?3J**KQFg't# )b B0'z MǶz]uI閚mu }q3cB7oq[5Lƭ[s5Yg阧 i ‚[+j)VUlkPRS~KyٔB#oZQayeyEy.TF̀RVmAW:{e"ɷ3F%鍋ښ7 o2U)Y5sf,(2r? ܱ32r' T<3_|1-g>hL-v˿ \W_IxkاbMB(cNnC,de}Zv(vh2;퐹⺅f>7Hnmڠ]L v k(VOsTj_s'}b G5]{G߫?bd0tcX,.Rv*NQ;bOŚb{@eVWa6T׬/ϦDX ku`})(St.p"3P{Fu=%ZpgeJ'CH'Cf;,zB<訔tͣW<7|yKf̂J6XZؒ[(0Q vew.%,ֶ]9b'stoE aK7hP4?gźdL`vB=%]@ 1I/OP'ׁ?jw}pzF_Oy˝ x%Xy!6F(CW%xrt}S]YyMetHk>2yӅgp]a=5Ɗ לoonFf${ 9BNQ;(dN󳫋/J2W ${/]WY^"#lQҔQڈ=]߃|1KS(DŐyߐI~`?G2ߝ=<>8|zi_K|`]]'_-o$y.n|j`"MT9`ӤQŔi x3uL18"Oxf1f8S^f䧺 ;Q Lɾfu؛<Q 1ȼ.oVB $$ ƭ_p3+J:n AӼn6M0ʚ3o60"Hu'2{dsB*Bxk( ؃; ,uqyTM@}&VI[GS/5+-|xRsL%Cb](8*9͓yKSSrzO ̡~h0,@L7qdMɍy,u\vMcO De ~\gVpZn؉PQf>zOiSe1`ҩ7M`)dE9{RlN5$^*j-X/YvDuFVsG Z%3lS(bQ z0mWO_dK },`81-61ЀG?*ZP'v[z"ٜ|@~3{`*~!,eB1u6f]][ So.LR1;j6>1B7.=َDꐆUPjuNVZLf*ܹ !?:xlqdGQ 3Xr$mqSgޝ15 aw?x]qfDywviG֌ǃ7;TT#Lܚ{i =i7OHnd~|V(پkek.o {c˵lVVR 来ܟU<3XY^Z~SZڍu5p١Tnʒ ۙ*T>ճ)rtye&Bk5Ϛo>mYecS HWZՖȬ||J~0&\x ʤ݈SڝߐoLӘgՅ* *qoߔK_˟)oBAsڹrÆ9X13/alśsJ@o@zO6-v# R[=>aP ŢaEŷsOC)0>IN8ZօwzI =X5'l.^p&3v E~S3YӅU6؅f#`6eyr9 3Lʶ㟅| 0 qO?ݸ}fpEҫnymn_4'TtfױxNrs\uDzG; }O X޽;r`84;&ƻ CJkZ2$0)G-``SjϒGrEaLZq??<&ӿ}>t~sFp7[wCeiĄ %c b8 &k\3N6_n. vKnRfU_G?L㗅e*}sb#[c<'w³BQ;jpes3( vG{,*q۞]A+Ӽ2+%?TƓbݵ?3 d{0v-A)-v^+(!E%+a%\/v=/Zyٻb6!`.he)3(pzZ2B2YMp_ުXC7v@Ԅٲ7%J ӂLD.!/BRwۅ,ԇyMnv{E)r|".RDS/_yUkA8 LCد;ݰA ˽#-anݳ36V֖gf5bqIɈ|DYJ|՘qC@~}nα)K@M0vkxxyKnOK5'%x4W0Yhk]ry!A}nulM tafMekCɐpp L7<>i>{<L081A sk_eG3l~tj1XO>~gQhIJ92٦}>g+n*pEQMOU^[o̤)-*8(2@iv&RPmLه(Pf̂?۹NmiQsd`Um;^pHaQ_3З"ش'jڢ@o)˵)Xdp]ǖ+,q{ "HvDz&]̤F)Ke"3RZW|u lr{w )U67:goqӕIYFQ +TXl{>ib W\}BjyA72 E/ ODԤT D6xW;QZAPw-=ұ4|yq]2:&9 F.M>w0زcՀ/EՖ^8Qܐy_(uUOVid,s+%c⣐@E@S:O4{p'# !- 1j{JV&y5|L̹\o)]ܩWSYfVfs5arIT:"vYޞ;s-븫 8{-¼jbBjiz%0 -9Aq0M8%c<4Z ,퀷r3m!hE+'xEOtJT.x,k(f˿wQ/W$J~I-Y0nG{_ xn^hgygM቞;Nyõ y=OyP=>=t{"6c=q &yYI%O _Q.=9Sxwbj*{L5 E&RpJs& ᄒUVvO_:Rf|J"QD@}2|[Ǹt&b#Qlr$x!nO#{Y?i>Tn Xot6OԙYH=٧x7鐙*=]jťS' NTZpDuns[[e?Sq^4\jL#(sO_F#/85Ž.iYv_OjTz3%>6{A)o F+wRȬ j}Gؐ.Q6Pnoy;n_9CE;>oߞuvyij0Jf][&ѱўMZr/$hA7sպee4M6sP|\zjd~޸ }|fd5,e h=jE9WbcRo.5YeJ#>CрOz(9&owy)Y<%,fb\n?[BqԈ'p,GNނ$GV|K4 $D\+ mef,ZA][)ڮ(޸'(yV`Sˇmx opΛx3Ej{_8zF/%w^J$"=? 8_LM㧜+$|Qvq;cm¹z.U߫~_nFWzY?e̕8łmF5 bhWZ9<Yw*wNq:&le`6H?~: h!T`O..Y^.ߥ酅mJ J<̬pO#,G\(ɹb]yMUi]k:ũT8O@=^ ~Hb<ˆ;֖6nx։OcOV|<)o%kxǃuQıM1F'xo`]8*vXzN}ĵTjon1sq>zHL;dDƛgf,_Zf}̖nd}68 *G_#qOwOF>}M1B WơJ\ħCZW]F6K<ßizѝ8tUcX>v9%e$"#"ky> g2'ĭmCdEgZ_]d`^M_v۬5[?G!%udu/) _!zfݚB `UE| 9:7XʉIC#?r=U:T`x-5d?Y;JtQ(0ru)||8,a@V[?os ioH 9t+} Rtُ3RL1ǼM4`}}6~;অ 2:xd?a^g &'kbcitI,Yb!QOwGiאy!^izpb B Ļjs71/`UӋjea]BDas! P*4RU`ijZZqՄs .}zpɵR*Ll4vhS׊C.{n*(nB$)DK nc#6|(Y;n'(Oޟ OCZ*X2Zik7$=5BT0G[O\O63|7(ո-&V1#{J&z`)kN<$P7YĽ?x>9zi8Y<>ElEyleAƏu5m,Yqt29 {4fCv{޷y{].\?!UFs&O+i)yVv%INQfX9l[y ^{/bD5vmz]Up` ?OՖ@_${a6I- 0B$b^1\"=\:`!PwnOS ɭB?nhۛGx[Чڌw/o BX //) 4z| QWi

)b-թ/Y7&,rNFPha\6af- 4t+$}{1@>0mGkg ^>,㭖 ?b=a+iǐw$> f {VdPo= ׍(4uFo2i}gNT\Oo쿿VtTNc]tI%QN*zi湃b]ZB}oLe^kWṕHa# cr+=q~vбZ X1xJz請m_pH6%s*e[UV9%f^ voҮLՄȬ+)IMؤw9hѠ Q.S/[`/ޥMJ+~FO0/ O ƆHD}cw !=Fw! .tp{A|wY7/5N:W$eC}D!WZy\!Gw'85_)wx*A/Κ/л^j뿶 Kח20鈪Wzޖ]ѬiG EUxQSC;]DԻ 1]:fPMg[k!R`#9 ?_Ot|DF?ea8^oȱ&M  j,.c!GY]<]<_h1ʭq8?R3\x0i0I'{?8A>PUXi|N3>U%k] VBSY R$sZZ,#H%'1AUFˤdy_O;Tz~IN ݼCpșט2osپsm)kXW,H0V)O&0E}'ׂ j#_x!6]k~j/P&4Be4׍Ԧ/+`hX5 !E0lDA"Tx^wǞ=K<Κ0"ޘWp Om oxhsx)ӄ/Mߓ3`lͺ4`n{-%D&=,j,-2Pqٶ\8$ثWPVtU?qnQC*g6vQ#YiJQ"(!s}<Հ6r;ulMTÔUqP `"e"Gj9K`N!PhfAgA栬 `}˘Lշ~ma7 HzwS{Vz6쭀PYW|a}Mv0|`R>vwO4GN}gy9}+!' Ft073#x:M)k;ЋKPVXY.zfK\2B |7׹XߊͺH 0gsE)?\uYN !) ZPKc=5Zk-b^E9ffqt@CC[h#u+dH,yO٫]r/yzsReq6o,mQW:`٤k'NveXTsmhcgmD2**z$S*U`#?T<>ҝDȴ^360Wt>T-L?4-([cWOJa`<ƟG"ᢓ@8#rٜUEZT18&cT KԆloT`<* 4m R~L:"] ?g* !,/tɔW6x*0IK?DYӳQ,[iVѪ)ܐZ'+a\ʴr4ln-"jE(c_5;TƕldaY_,ղۆE-:`^˰cwFuZWSR5 [;Ta>(O{Do^ ^Q]/Zu%b-c}7A%4{:D7AC$U%oN Z*-Ȑ\W:8r*7&/Gm%bnvyuY".L.{HY$xԴbz㕘?ͻZ/eW[`Y"zHin4O!7]{F9K"Њ@^1ѰsadvW?wxjnE?}#,E2Aߣͣt\2 2N?<22EtLxu*)uqjgLe(#wtU %/|($$P UQ0J$30D2dLfA|̝#Y%ʅs6#@񌀋 ĞG+Ao2cNKol"YDϴ(jO\Vf L=CO`* 5- о3tv&zZlzF*hɻ~-mJ!E}2O[:P2{tc ᢯[g#S`Ҵ &i*!$T QHtdеwv! ك۷tc*:*>`WꏫvÀ^=jub,m]87wO`c[V':Jmy_q!!n N}Oe?P9pAi 3$9HJQI?=Sɕ|#dL~Ӆ"M=:"\K@^%%З7 7}.$Cʓk0<iu/,q;GŬYg~mDm3*Fӧ/9wr.,0H&7ӱ3RcDTW8ny8=mvk\*!8&ѣ x꜋Ȱ>歚ɀsP^]J1q*3؞es 7/A(:-UtpsX I]?W܀jLܹftQe\8fQsq΂ɋrv+ İm褱BL *c4d#k-\jnsm GE\7Z祶qA{ E似>6ks9[|"EK{Q;S0cV;HIwE:יiߟܝ'd/Ԡecb )6$H -" 7QMN1zÔp#3bJۇؔ?d!yF4s{Y)ozRb!\flcҭidpD,s!)*HW+ʆUGqNcw;vn`WN48BGpBkQ\[YU1,G,asCpv u}.2 Qq4I p<'{ 3!)E\kIm9 zohX.x₇ggj%03[30oA6WlAKFWghMd?ueu.fJz\3ٍv!dKf)L(PQj!=23-8O|y, 9V[oֱ\Q/ȼDyħT,RM֨^$.BWzl߄YpN1enE+ս$xOtгa/Ԥ ~PusJlVoьR`1^Lu z9]ܘ/駲C'F|YTqҡ _ndoU"Z2K dGř\or0=g `뱧rE)Z#๶D>q{R8fK:x:K遼U7EykiPBވd]/0(ʟ# 9;3pbgZѸࣱGN˟"h \Ztbrv6 ^-7@U={WX,хC'fRƹӔkh^atBȜ,"=Ǚ,*i+/VWmߑͮŁ+>?װ'251:0&فh/f\jkݗ갍 TxA#UYM_Bp:t컸sJ\;og(4P-_4UQbc8ٹHH}ye뒕:-T=yjTi6mԉWOQr8|AAmu^O ԙ|"ϪegWt&m,+,nc@4ԟ 4?YiU ?1SQh"!ǡhsHFxlq9%B/3k_2ELbY.v&P@IxT2!4-G+]NϾ UxT7v]S*2סB[a7X q|=V2>xG1!}y3}^YZ8m{qIf/C?&zڻ)އO5$m#XdWnmQaTH;{gUB)BIUT  \i$CI'*^G6 ~+I߽wU%U< xфH-GQ@Z@%g

Ez*п1@W2.ՔYhx3*HN,ULM/3s!+J:ݲx*iMWykŬ~_Ӆ Jr%0m9_AfHg o]ɶ{姍ɲnrZ:H`Rʧh[ޟ9(+lXZLիg٩U(md虓PJb߯q0tG#=)9<hl˱&_A~ƒ؀Ui/S~K_Xxkj~ŸfN IkȪYpE*5>^l-2\ C]zfe?X.`F0:0e݃) d&Vb3ܝ˴]e?n` vvl)j{&3gAng??`Q@%g+OM+qYc|5Lde簛hKaCK&1ŅbȁE&Ih r5/ ʡڗKa0VJJZdk͙3k4TOD&sl71 eeZ ߔƑ3jٯ6-mpãYZFP[ea 8 |B F%$4ֵSòuuC.<;F.kbn.z.oB͡vvvIIhjBkK~TU pe[{ub*5#<` [*2_A@ & R%0Ҟk8%7.+[f5r<G$M6wYl>B Mwٯɵ :kwrǀ]]ѿVN-BCb8|A$<&Ư@A$Q-< ߲~Tk//#PNCEp!ijQ*roWMBiTQb6+ ްFI$$l%S:R,EhTw\XBQYOK=Ɓ70FE^2Y!}hź(!x*VS>0:4i51CZ-Rb Q24.kd1Dp #s}$ s9@q dcH]t4jv1{qqH<^`G8k굕En Od ;=t{c+]:ukɡf k :c敢cEWtdK[o >M=rOS~ ?4s˄?v& fעhnQ5^]7fc#xg7.-T{Oqs+3F^yV.dJ -',krY;X}TnVVxxxy&udX^VѺ>[ _zV@h0 ' LK4=\?WTz"? r%^($ʌv}H Xo8MKyJ|F26uzq\؍q_e. E.Xx)Dݍ5-c-jd钫fa0 'tTs\߲~[E^!-/_Uuо|@noGs1ZUk~j5ŤeCqk{SL/)Dlpejh$ejB tBN(q7EŜg'oo Ȥ 6ZF$֮h&ʞ'E j-'7|4M@|I aSqKONZ>W$$"vANIoa%7O46t;(SysyY(EpjJ8%#;%T~$^7wq+ٿ@LKLjѩ~,Lc]Rg J]?~\iWG}|{ )VuÅFn2.r]69:AU[V6o,aC+CPudVCQF]t_ 8)T?0YqH2ٱ&O}WZy \ϸ̺f[q/N|6ټ`KweڷȥUvl&S LIxhrހ·qLV6=1%ksQ<A",WA{ W~%Őz2S ޿͑Hkx/+ѕMjSP% {PnʪﬦG#Ԕ,(gK7n߷:g Ϟ/p8odS@iv3"]>=Wis2 /u_jt!.Ox[̹z$a8NF7#alU"{7Tk[uC9_Í ;84=j E|RؤΜX$͙fCbVGP SBG N &j@!"MTUI )Ea&<{,k&яen ZНYtoU*Qz޶mdE3e;#v\v+/p3􌳮m%(Y^|^6[ߑ52C4&; KS} b x\g*܍螱v )db*}BN{ԅU4OS[Q.:XHRBD=qI\^&w<  rL_rUdXԇOAF&ȉ!fya 4dw:EEɴTyܢE/$-dԡ+~^-qjEÂj=Y%_%Q1&h_Nel&PoN|;xk^_V9-W Ch~:Ѡ>t!뽬ZxzAK$wѩ4oYUdM Ű (u٥1L` BjcF˦C @:Kөmz wEϋ*nNK\[[hL,b .I OEٞ2`BhjaTKON-A{}EO[@ΐD\{>j𱨞x)*}JWNSB6 h&G"h5vqa) @"?!މg.w;53WnNGdluQۆz]t`(j31uF>{,Nֈ=AHSxör7gxZ nFP [~9 \'|'E Өy_łFVR:ZlEfwE@ނP^|EبJ ݵϹuՉ9$P-nQfFwy7+[B-w[^:MGFm@ٸxF\I@+4U +>PFK]a2p!"FPҵV->ˈ9Iw/@k`7hE+HVa9zz_ R~qa' ˄wQ8drojY{|ުO.G4$ ]D2GczyHoچ@lj8hGn%>ځ,aR&-6<_di cPf wߗ1&EXy[Eqp!`,>vQ[:}zȇw2 nc(|dwu57ef .& ~ 8ʺG0Rkj-ȩ,OE37f;EA-q_,dgO`’Mg 0 n{7MuYؾ47m9 U]aĞ\./MXz-wpG'ѡ(oej Υ{$xoOd9$}&Q96']9 I?H&X,KdF*ɀI=bStm[(D$m!_EuL ɣ܈ Ѡ1|þQe[HXܓ߈Np.;l^L!IGɚYMfޒn)p)rZ[Ȏ#+S~:XFn?`]Ӵ)ݓ3 pdHِMq`–dvdҘ>{Ew"Py~(@l~6#u.6HC\\ Pۏd2 khy Ql Ξ4+WÁ(-ƆDT$ލ(" QuƷFפdMpz+9M؅[K5P; Sya' 4iڱ[7bL (q2ea./jSNsXS =$&T $c HL¦kInJ&.8S-z񊙡S"xs=?̝[l/UzPVzďZKAęGK1T(SLF!nV衐-Oئ%]{>nGLoIa&vLy$~+Kbd}HF .F (hPh;(L㪬B~{Ȇ^14Tq4u,PHԌ#zX_8:݁,~iEU/ kaJ)3°T'U]aDZΰHx-^yW ]mlC Gi? I$DaT%$A9ք ?na e*`_Πj/>>IKL\Z'^oI6x~átRSWM˵Ѫ4UN Cb*ǷdW>̄ G#W./g5+>̌C`*(n1oU` q'J*H&"HaP44zK^Py**i9I"p ڷ8?;afgR 0j/߶-׾)v[QpZLz䐏JhqU[f"F_pH`'.qhna ?ӢUnAJOYD: V H &ٝ1W¾ˁʭf=M* 3D]P}=qKwq/@']#U}#c ˎj}K3a'>v2FhsߘaHEZ;+*[ٻCG\G[8ߌc~/eT h3EŔC_KPqSM03-> |zB k{iRZZ.6eMDl"̩ _j-$@ G`yG`AӦ@k%_^.mn+^"JSH{TAeI6$IjVղ:a\vL2{W۶_e/A% PFC[F&Pc%BVڢ@NMs4z1 A |_ERg%ՖRHrvv;3;7(ӽU軝(HA3D;S6WR봢0^Bk9{%:MjNqNfܵ+:w45l:EWnRk֚}oZ25pSZ`w^m=̓ ~tx;M@(>V6fUԢѩ7ַGv "_MnQS 0 A6~_˪ }:!< }6Վ/-ۦ?m1XK֫㉖q$Y,!^V%ou8׫3,3: .,yug]emeG`Rc  Z]#+@V oETcy,ƾ7b/18D DJoB(%@K.ҭx!'R.sS"*|]{T`rSD>ّSۮlowA݀}y"ᴊ%XGx8I_(4I$@DH񟃑D8q ֖Vnf^9É(TM÷/zW6xZ/٫ 4ui*t[?f]~6YxՅVI %|Wtt_{W- 1HUaTXcTT|8q.JIx/$EF1b^#T*iu_pПgQ۱NyZXGwΟzO g /uᚒ}h̴[mdtA9T-?얏Zk-AfNʝrxm\[KW K]k(y,13E{f}e#YuU!<:3BUϭZ˱ڻѫ{0*TLokjELeA避1Ît`<[J5.5 C gt烑UТִ_VB@0ڬ\h؏&\ T}E ?,R-Ҽ[e1$9}l+4T:zM^sc$̅z5ƛ2dC8Bwz\Cn⿽ ;^/_"zឱƨYz&H~䦌2|XcFV;]]?i-VW=}'K`*F8u( oYH#ʸ(ʹ,>L,a^(<.^^9t]ۮ ESu[*O}.Z։|ٺOՅW/N1JTT0ȳ[M<:xA~u1Ƴg[N}8x}9*%1G~>Mj]tdK#J E' b\Vs"lN 2ֺXW@?Ag!*ʸkδ5u:]Hb3y+?9~,OC~f8 ZND8X:8u~::Ѝ@!P[ |ʰŽ< \4H0&TY{Q9dS ӇsZfl\T bJ,DY7kEV)ӟX2ʥPYVܝo3>ƭ7~=\A'Õᓍo_W;ezY\߸#ksX.ɬF|L:Ɖl-&+1wwǷφ[^@c3/ u-7yyJ: .zeJg g4@cv vt#G&iIqwtܣα#]䋂k ?pHy6|$lܬ]Pp{l4=q:"xgq8*ZNَs|A@RJ[*\A/ف}\'ħ=Ȃevw\~$L=6(W> c AU\+p (DQBp͈H~!d|P:~|ƇW"`/||J$tinUJDczK2I>< 2~qkg.Êi ڐtޜŏgcXbq??B)@ܟW14C(c{,H;$./CLT3 P{~&09\e A=+k9F\M䔎SZIy5? dBSYʦ\pg-hIWHY1xn &DxI҇N]8}h^M@ BD \ow. [UmOym1&zL9āBA\ Ne%x)Oҥ@]bGe~2(^U̷˻ yY&4F .yMחw3Hi_DKe'J#eݨ b=I-C߽5HWنZýE¥`}$5uS! zi/9 37H\/=ޞ:BE^T\ ޼R!]dY: Ij)9+q#8wk]q<n;NI y D;S|9"d>{(0\Fs PX#*4WpӠZ}Ymq &o3;Z (ٰsm!׾µ=S'na `TE]ف;dk;p'ZmX`_lu-._(+B%mdl%bGpyv ? jO&0 #M4#":$l; ϵ>lB:fRC)y`Bi+|> +LԸW5V&ߺ;B[ax9G4;^$LU=g{w ! ͂;dA\r-+P5 [w7j߽=~3hq mںxЖwklqmxrAx")2ƅO$&!2`s㯺*\YhSAs\p;2R{{ oy Pg0 |q[^~Srhe&7z{C#t1'QTy~.`i{.v|ssVYӸ&3w^!q7CwIdxlBƐ;ysss qHyJj- ŇyQ_7P5<K wq;)BbNʧG6 ٯ"z%9ڧ;l&&DHd\`6a} 1 h=v(BeY^(ޤ7/˻vwMayogq/B˘Mv ؀O$]1@~eJ[@@ @;MƊ"i_ |Ȍv9^*mH&x 0ȰW$DȡAQEm q:1r $r{wHA.36$XQ Be}s%" % W6i&S\MZÛ#$ YԤ|Bw|xNv[!/;s 1x`]ؚ`W:zGQt >D[G9/Uw6*9Q&*Xt\HS={d^8kq\aA[g[ɶ @F0iL[4Mi?r|/GN;dT&m I&'`\Ŀ$E\j)> H[446iM#YW3b(NNX](⹸N@7`~hN$.MUɍ%E-hK[7kVy0ANMF?EY-rwn!,&i(Hm(t32ʏ*`!kv7eu.q%B6%XbDI6ئOIXNO+ݱmɝ^xߌ=>;VJl@"ʱInjB*bY? > ȵ4i/wj/b`Z? niǕ6 b]37MͥM,u?6!!MO Pݦ#ɯD9tN@FSrY9nw7* vl +M?t&JA7" cג"9 XЂ1hMrYAF8|NiquP0\l~!uRb}t- nCUnm'߬jӃ_~e2d^Si$w+ffq~VKJ5Qs|a5I,0ez2I{1_Ոgj,?>nW^3V)J/֑g}zO=|.n}&s+LJodMB<}5q]{%'09c]Ԧ.cռUɷ'bŹRt帤\yD-GTd{/PH'h+wLo(,j{@؞5[6. %Qdq IZ&F4R}Y:1m xh@TEAdxWe cx*14^:cPDh0 FQ"'Ugxl^Fml `J{S!zy`QZs#yXڇ[ͯ^v.yk?@єx^41[֏̊b/&>HA`mIhX Ur5%R7t)!Mko vL @]o}1.r:}UmHpe,R[Rw@ @m_퐂tF3`֓=QGH~\a)72ƿ#BAPi5 pgք)&I-d|i2*x%>JUw!`2N_Z.{H6ON:Rr m#$7.Y}s8NMa^6Pc}Sfd*c@0nHVp\;W@t٦&ewPUvtϷ_8LN ua.I: f: &H5& 8D! GDY+MBCјh'ǜKԚ$`I8ӂ u7cc|(uw@yFDO b6 JmnÉjv)̛N?О+qzE\ͭO^~~B*8$/B'-Uss@q}/?UJr6^X%{П yOԘ,l}!/lU'w~>1h^⓶.83W&61=awAxD`RMcϓ;m4XLbC2{hl^aR-x~z.yۏkר>^86xqiyncP-Ih=No! Đ%d랇*GBA;Uc+pA*01fk„uf+Q2AMejal} MN|?ў9ξb>ßrԫSAίd2{ x"|{aIo&ùUoByC{v{L#= hKprU'09B :PqҜWeVV7D4(&eBf Z4mwca;U|,ogOY֐sj*-<11 =@=+5y/Vg`O'j+cVAc^M- ?bL*i&h*ra,@UJ%Nyј?:~]:^'҉رO^5_K iݛQUQfo6d7|Bz|ڼÏuJ%c]Bu$mCŗ\V* Z2?Swj@簁@~˴휊0ZBtm]-EYa}< [(&:ūCL&95 )ˇ/KuD뤌B`}0 KC.;LQ9S3@P(iZB[k/hg2Z3 IX@?aaV4z 3m&=EZp6KhuYkVJvA& l+s0]ƿQιtno(܇tXRb󒼋@;9t]I67'vI&}l+w M꬚]5yՠ}>~PJ`i*:D Qx- zo8:\NYyu\g_a?L5>$ͅ4X(S I(v0dY+3EHpYb;*DzHːUEhY5|H@+ 6 Qast>:y ʍ ̫ e~!ՉÔSKGw> ަjoGwѧ!)P" !!Ǖp}D`dd&t"OEmryn*)eAβ0 d`!]putBWX`ّrR 4Fm,hݸB>P"T%"5h˺罋k2je:ơǶBwlԓP/O_|vJq*PSǪ/\`>j%4Mc םKwɵ8Dc{}h_<Wh͢1:ߪ0#W2]Yoބn:6^KUCRl?]c$|VQ? Ӽh 5.y9=y1J5al"^u;`iHĪpZG"29" 8#H 0据UQ+yIūj 짃B,_a%۰ԧK$کXʸڟ5=VE$*G#x f ct5*q?GS? p"d"P#8gy;ΤhC{}.B0l>Ԏ0A4p\O! -8e;Ȃ~5`יQ)ZtUIb_|1WRԚ-*RؙTXwh ^ ~5fZ XP>>`i/jJVhLXU޹$Щ~ټDN  v{߆SI55?C4 4YIb>bttɻJ!u݋qU$11ݥ|Yj]iV!c>(< iZyCb a:=9򟇲j׳-El'p>hb)uU]<+moC }y@dXu:CI M] uCO}7 l@Rv莰d+1vpͩ+n,Bڳp52ѝ %WL(ڪH9id呷+/DT'Xy¸3kX'ɿ^ebCQ5^f6;JY-"[ p->ͥ!^h37'|rBqXb -\[m8k-!K6=,w7-Etk5"e]p\ilnE{wh{q>sEcyjn1μױܖj4ڂx݉uƞ-NRQt#^=0GMG )UDuY1g3&shQkE??gfuw & +ȪujVc塧Kq˛J%z-qO_ŹB5q `Z__K-W!]Yw'Kݦ͢0+c$,HzH-26T}۩IS޴ IӋo6 7t oeXFݪ2t3C*my>yGX4&k(r[Sï,zGo%οQ8bJWE12ct?wEt&; gٱQʄ Kt< 1[\wǦrU\E+e}d h`_rKӈM5U}a*PʵTW?ZZj7ڕXZii>Ɉ/eNiT c);؈Mc弅j ?6*MȒȨ3ldd-W[M{ڴo9L9̟h`]Gz!B"U][HU'b?U[x]$sJZ㯹lZ^hfFJLfI7o&5ב֨ҁ\U}:vq?"Ŧφ̍^.O6fF b.Q\T-ٟdDM<C!oRoLZTq0Fv KAhXqA,SRӂ(ǟ^MLlr R\X`XEms0Y&0DK/6mjEAmL蠆Zm}o]C#ZP̱t/軅Bmy]/Pbº"^%U$1*RVZ˨V6[H^ 0M9 x*awЩl+T7 qnp-Qvд\;Cw%}1-X$bT3q|".S7=av5YfacY|D"G`VRaZ1u5OF_ ='i'T1l˽}AYp-Sk,fpG_{ʖyIՓl×ⲒŔ Ϊ9HzA<âe! j_M oڨFork((lKƓc ;4(S&8 ܼX~C qPqTO^Fc$8׏379_fNO4]/ZJ[r$E*( oȟ~C5 6<:{eE{O͐HWpGIظnW8k/c [ծ(VFPkbyzah]^5mBğ1&c2=zS/hXuEȾ:.ʗ'[7^}(.$a)92WCrQO˥JKЇQ /pqy@-l; v[ S4"RdfPJ #{ZG@qi1ll5s1`Z%CnI(1JzaGZ۸a.[ QT78.trxय"NnSj`)"YؼB +1y4#Bu&7KyF}0h3Cŋ0D @ Mȉ4'NxTY(gĪ+n<D fu16!8<wA~S JֳfkV"*AboliaU 8y34P53MQL#XEonAY  ~g,c*Ŵ:b$Ҷ3|/Օ#[SL%SP+98(w[}jtDfr-LQ4I,Xx 92?6dok0L# 65 9H$AbTFXqضzJw޶/Ukj52uS]t ^&Sr\ֆޖ'F?V ԶeDCW>^XndPVp' rIȆmm.>u 4{k׺5zfB"w%Ϛ5hli=&^!4&|i.'ZX< E0Tj>r;.3DӹMF/"Snb´ `Cۨt*J ʁ8" ;0qqlXhuSEoQ]G4v/AtToSxRW ݋Ҹչ9SoRm\3qi{g{ie[Hx_!ǵ^63H&3k2|LN SCTuO^&,颵!Lg"ɪHm2:A" ^OD<hu2} lwp'jJ3YWX\p YN 7VwaUE[^*x9Kw`U ʬXHM[T{3*]0B2Sl܁ *OaM/iy8ePff'0Xrnj @Yy:﫴69?LjA-L6s#qfLŗ-1ASzO/]@ܛ_{On#ԒL!ǭ8[#f6lZ2װB^i[NQ5flw &*E]l^ KZ>,@y9<Ӱg&BTb x]6`v,wY{vd&FRZ*.EJ*zjBuOc)hfGZkqdA9W M*׵F[GRmA6\P)Ԡ@9kR\UI쏸р Jr+hk8ӸGvcG<( cP,~ryW[|waZ sA.zLMM=ް FA1DQFI#՗4hk-FUuk$&| Li[4W-BL^r uOϞk,K.u\J6ǀ;N1au [@L A2A!{Y\9aW1.*BpZxU ]mEv[IjBYhSkxK5#)L'?i,bI4G䳣# ATok M;K2P3 lDj]Ģ#y6 n2m^[Ζ[B,zډ=ɕ (" ,#w- AM7HmO#I7U+tjdЃhOA`~f=X{PvCͪP3ifmpl R i8͹>7dLuT4ordV$EujDprC9F@ l;ۇ%#:VU2j%Q_F0jĄLImEW&b`S`"Hm5126c[+52*H,-_tWXdnv!&q5qIE6FgeFw~lYTfL),Z$¡S]f${iygKVoԲE(TQ~i! K"442Rv?ԭ:FWV8UE)]Tz$`uPZ3ԨZ!Չ&@Pu&Srf'C7Ă}1T`RZiBfKDU~lLӁ Y98Cs?^:QfNUeUpla}qȂԯt*J߆t~bͺf+pp @GD\gmq~5* r?*Rfl/[ZXYK9#n<~gX">D4Ԧ4}*%XK;~w3IR!ʳɘ A왛R۬]jpAD 2%[ekaxQzvSnmo?x6qDU5b+]x±x[T>?y?#a(&T 2T"[6vkV`I7F&&s5[q?LO&:vw-P4ƒK3FA[Tծ*.;E,Zǖ5bXNy I]bHnn&W<z*.ƐL`='ŗmR[P(.oB6kEGpbE^ 0k7~g7vje FaCƽuߎr%;Ҥ(,.1Q6J:r"rI"83ÌZ>)'jLe/% z O8p`Yn2emq'[u&j`s3K9m~gش hڊŷ +њ3bv.}V^tIXr5C^ o2MdTҨd}Rp*#q'o^OTF>C(Xz&,!tt OA?xi{ <147%WPA hPRԚi5Ch&WDee.Xm$2b7 #ʽ@a#{`FTk1 TWQB|&fOٞ QXi@5aNlR$o5yA&5><l_;GT)Vbݛ?О8.-V~sp%p|~yհHլ_-AYcB kP{ <_BP+|GQk* mˁj\ 70xքXwc y)0)#-!~ GhsEEO[׆*ƀ NZp0 Y X\5лj-hvn/Gd͸Ie!3#x2HwPE;G{M&F 7dQqKם!d.SD ,%Oɪʹ[QsLUa0z6=u *f $ C`2˘idLQM$A-$'uwg ByJe _: i6W7 ŃUNۜ| ̔!z=[%|F'1Q [lK @f` )>zu @-]Te|9|BhY0WʟIΠ}z*p ,hyjҤ}J*taIxa\pdEW l1 q* +጖jTR¬!5 }ediu:VgkJt`Უ1?}3g֢BT8VQꏖc0ɶ)T ٮXtG (l3Lc2ʚ ͯS^ΧPTch#c{f"]Va?ՎۧgT$/#㗠dEQ ON4(`6"GFWDqb#w4(Fü>B]ݥ〣 )Ъ}(U7٪|I!kdQQF" OD'SWsO$l9yD)/QCrQr3T:D^\L'^ g.\xW_"ϥ67ȅ_?w >,sԤ\BKSr%}7$AqQ_oSJ՞\׼S(`s3֍^Х\hj]J-Z&sO M\ojhI='fjl.m/ꝰ,eZ5f|ٝDy8nVpsog!so/sy0gI+9>Hx>DfFo>JxCLWܯZڜ%÷jg7>uO(fs`/0#|<̓gtD6n\@`B}RWo^c*0⸒:bͦN0zjǛǵ^E'`j%Fk+09oscMGH,;pK^oroPd/[R+k^6 'Ɣqu2TND1ET.zA˂T"Z R&8."NH ݟʪ x ok%@Ϣa:,t'sfT10uF"&!g9 :J 7w^mIeΓxBj֦hbYKLB1U$Rb\Js]_N#wp/"\ Z>p(x.Oq1?7*d-Ka66Z0ig9&{6ðhݵ1 tt#{7iW}1 r*"v怶:L#>{ЏqM+Iz4 ƯZʃkmR1 +R7W+MX٢".+p ^5c4ӆ!zB#biW'3jF[2J(Q r檣HY|x] 1ᑴ&d,]*r'w N_^RzP~=q~9 R:k9jw>R8㝺Y$ \2UtA8ix./M#Z"*1(lsz"0p[4'8B#0w!%Ž6M 1_@~%לFz\,eg=Q'hMze *)%z<ÚK?=-.bWr|¼!;|],w9=3xǞ7a1gy>KXyD.28iYZ]Pު;c:gCLqe7N33H\"T-б0*,r5ŕ^8yfR<KͬzAV |hbLSFqaFz  JHDLS7aRFPZa196+Qَ^74y|o8h+A} _{7Q31Q&B+6){w|XԴ5Ro,I_e2f›};qOI2|_mv3Nċ`g=HhT1q?V3&UFHbfXיIf0QsW]2l] =8w\T0##e1P,~*BUFu6 2kTr%LXnJQnAZ!RP7W12k5W g;rXc">nY(S$u3Օݫum7l]O6n |^vn/j{8/j<8˴ }{s۷ĊvK@FLT.]Gߤ?{+sҔВiMd>8Ztcf=X,h)ִ3-ӢLJZj4sQiDF{EWQ=-e5-Bg&3G㢌2XQUQIW 9AZb|%2pн&z5z<7soZ$B)pal`9BmqN"j0YṾ?׀Yz zp B oBZUu:%ڔ帷Z6 Na]Ԋ%Qk8`!e `R*JWOj'9k)sK2`K0b౻Cyv"s(k=@Ȣa~dZvo`'8YE C$Oa1`WQ 8+aܥ=knZgXN;e ő 0Q|zĦ3F<ŢNGҸ??2Ը40/JDM{eܜ0{1|`IH+IX!CkeP{BfJ E3.DvfUWxa]QݛXt3)?jKTLh=n(K07NEUtz2[Dò8& ~3J=^T!Ym2!GaY&U+dY F|s9fssYb4/?`95F~/<.Lu jfzXu \ -QK|qØnb/5J/901 O9 !n z]Kd\M~3؅nASp,]F5%7-`/4jqC7-JLA AL˛0‹5p.֗-AޑYi7=̏-Oʨb9i j7!W v(ÅpCa@57 {RB+;[+K72Co`[0XGжʷ72민m~cB?colK6 k[Xγϕn`h$Y#SڣI@͵s#o]q .wE|h8 F7uUX7 n`ֆ/9k;ntBO8kF sb_FwSsV6j56 :Q±:[%70o,|Xc p&Y`HTwt R_B8ߙj_uC5HdE)ѷݭq$X5&zJQd2P/3`q1ӦZ߁612]]+[z9!0i8*U9h?ʋ\*j "NOlݤ2텾r'}|G'>ϟ31f%5 2,= @8WEiNp)H3s ZL Fmwo{e2mNO{`ʗ7@[dZk{6¯oH/Q=7Yւ r&ޙ3=pRkp&̫hA.qR69n?gYM|\&fÙyWb r XObjGkihi:jfhIڏOVIJ>p\X݁/Ndu1^2쌕idUHw/| Q }n]+8ڍN5 P3;><6>g'0\򣩌h_Xp&dTП 8+AnpߧpId/Gg1Q^rWStb`#j;; H=Ld3:o;Ye bCeiQ?pYEuAF2Yd] ¶H>И/gG[uFf~?2^Gֺ}Fj6*SuɛB'@ãQ[PO OlSS͠dzb e{@{$;} /d"[:܉/ .-Pw`D_6,5FJQ:VEMŒ<`a,(MP)k,AK^q-}XEaXtD_̒tDJ93[R QvuMtݚ | ɦ,P)GUDc>2&p]>ꪨ1ݐ:쏤l+J>@~Ak)Ϊ^!s#2[8̩24.4=̭&gt\nHrn'BRhݰG3725R< SupEo߾(@&x|swm2w-' <[6H?/K5i%Nfj/ֺnjwmnH_cEV#"'֦l*HJ -N!mgjlg~[';VX#69gWNX(IKpzI13Rv\aUC<|tY,Pu|67(DW71bQ<`dxkkY6oNWTkէ`ǖ n 8+}LmHZCUۙ7^a>(C&ë s |Q[ہmQ̟\1]S]Qz`KFq 3$ciC"I+jF,#87U9zRTa߶"xĔ|#a _^+H‹b(Y=MIkm ΅21]?Mogy"rMj {DƂOp)*#zu p|4W.o=QETZ̼t]a[NȫL+LZi9J38 +UdHfe}5gVr5bebu/RL>PLJTh37J*V gpPpuŏ5l_e3h_GWU$MiM_eJWbO(^i:WR.nҳmg0dYL{C%:X]6&h ˿x^c`s]fblWӢGMgƒHrE$, [߆@jn_B|Va f"/DctxocFпO.O*:zFyp6Ƴo!<{>=G!*rR~T58)_<vDm1 0ZeQH2Oyt" :6Vup2]tr椻hu>=p.rzpҽQkN@@[sŧt~j;1~nٺ 14x~a޹,tY< xu>e9 Xk/ctžO=R Q,=>uf+#=T_s!o^x<`CKڔZC+ o+IвWjjrk&wYWWgOkK76k{}HNث(0Ƒw%MQYo":Y0>(<D(KN -Z܄L,6@Ԃ5?ӵ[u^*EQ`15D-K*1m p8SHq̍v=2|)z'iM}jsGBN kiD5zl_wz{TI(*«YĪN#i%[ Rdט%i2L Ø{b(ΨȊBbEL5XcQNքaj-F@FUDRT)%"}>;1i2"VKa&"TbNY"gn#֣'|n4}l*D2x` g#_N?8z+lk7 vFc҈!dI5oūǏ=_cUKt%.0+3kWmLj*\an\MfqEy1+M(e C0r)=)m>ycZeFuV43]#KXɿ2"_II8{E]w AiX,Yޠr )ZUaH2,lĆ,*i)ķX& *\ M/PՌ> 4PEYTT%RO)Z*S_si ﺉ؉T@gCi9FIDJFoqœj4 Uք%Y^oн(4ͺ/n}F,WQ([+,$ ^׬.f0éR5`y[U7q ۭ{m$.K0Np)ؽ=jC~ę-ah͢?_ww8˃ 1OsIzi6!-'"x/NeXi|nйvcwi<~3=kZ^)R.,LmXr+z~ n ʾIx>o[GbzUz={PfuHt؜xýt0CX Ir[38lAmի?7[EE + U.GB#Z+v3mNP![ Rt Oae_ u4-JZ[q![x X`M\5Y Q&EE%UDV3̼{.ҹ1[Htr&uA&ﬥD4[rvL.-cq. 2ki o`qF"KNY>0ʢ6zi6='+L{U= y|y!\nx̿OC%U2r8f4DS 98U(إU/HU o1qX](^I@CcFJ7mb;i1ރxD HCpp7?FοJِ͋DBЩrw@* ,3N'MI%vkbS,ɚsT QQZ9Vy95DHpD/fXI ]r7^w]<;żHb55:FRAۖja<ǟFRީ9J)PWM$JFv Tn6:Fv`l&z T&av=/WRL;Įx]atu(Ri i-nD(観G42[m)'76A26hnn'P9*ތfZaR6ds(G )_w".x嘶D߬_;7TWdp&cY~n&~.R˕,m鶋̸*:@]'Q /R4 ]Amf<3sZbALo7aop:}awVwoFиaM1z:ae,,#7˦ߕ f@1?AדHWsKlƼʶ'90M klV4^-{RFs[n4Tc^Ϸ-bA^~al/ m+ś/KgqtNe'#ʄB./uH}R_DUk. 3۫놠e,VkC`x2[n k$2R2[MnA3 YKWJ G>{mwkBe.Z"ۍZO+(;MJ4‹~:gixúw-j8EM(-'gr6C7NN~b-ڈ?zK]&P 䴒hr 6PKHf)k崫G]0KţHݵjRSLEY=ǿ;I\#I!z-JPN<A\ f։[I >(ȣG~&/fŷ|Β EJβkdDΜp K$EaH7X q+[/E&+q޽8+A/Y+5[FtӷU9[%A͆5Vύ ^ENL?tZg@xԁ2{Y֧\ N6b+;O:P5ٮ@*U)ޤ$)=V0C .7vinkGvꝲRuDR.ba*ّr7 Zk;~/fǢD8uZΉ=crZuV?ֈåuHpN?MU2&A,XJq fښNltpVYEu514=nQڒ܃z4U#Ozu/=n좪X\Z=" FmLr7d7k7W‘M7M0f<ǥY!Q-<+v?q4)A)֔fͪsgVD3 ^+;DSht֫N ڥw,a ;'뺠XWAh.YQ̢ol,ۄZR j$֏g;*z92?V{wN,-ϖ{M1ITY{Cc]-=xoޣҰ)6 RfXEov_2|2\}+|=~:6"L,p&nV'Bd7few~ ς"iIz̺r:?~b6 @W.qfl2nM:CSm 1gM̎y8@GEAq%XzppH#Y;{[Ym8uFgdj|`]%Jl;V >iɚItDr32{#[vgz\}Iue[$ "TR [E}0VB8bS'E_ˇm"I%h9%S̷SzYLD,3y*ӹ*2eAXQn^mP.>~ƾ GlJ72 { <~gxy+XVt+ތ=nSeZ-(e$ʋfcųF䖣VBR=N2!fBj"[WZ鵕 e;a߈wsT q[Uu8ʉf ybH t1ʯqP9im(`>sCf8V=`w0^- 7H/=eԄK8W!\$ujLVEj)bL)NPx;iPEI"i ؕW ]Ӫ>p ^el7J+{FIɮ15Qku&9`S&2aWLaf 1ԧ*IehoDފ"jofMfL lMRrS 2@p JJD_3x7 E9CܝZ x"q قeKȨXYegj/'mIX7юsr F! X ZqJL"/B[n[:Eh(@EfJ ^Essx7 9` @қ;%y[Kn-+m_42Wk&PkoRpG$r-$xlx Ԣօ|LCnkL2DQ KAQbŌLt@ٻHa餸:ӢEC&0F1 uFVQ+wE5waܩظN '&]UJ ~GWս4-|t ^~35 ![z,#QZ)=쓍_͕؃r s.f ^N!`Q[hى_2DlT@XZ& g.(A5/Ҫ6gWٖN Lh!F3/ƗJIE:QotR IDSX B(.1pt)A1Xe]ɥn:١#zb[>GtAQϔўVbI?9`^Y(/e@ Ŭ] RF_|J$aX'e7}R(Tɋ^ ;yse??Oj?+Fvi#́Zj-5>#0N/3`MIܕzf'1!)2Wիru8~7<gRtc8Oz<{û7%j ;_ R4O /iCB `a+&ˆ*F@.Yt"`22zP7ESto+j<qơ-8ֻ6o rm5-'-q"kf}CQ1 n[i 5oi3nýL9ɛ~$Z' +hϵlk9AAEgtQ]#XVTE]2K22*rJ FAa1lv뱙g)2MPXwҭ BG8{ bK ) e(E;/7h&4⻤YҽH82!$!eWj!rJ{C gdse~J]l:i[Tfd>(PC"k =P. 0XU.A x-y!r9`)C߮r bW':XL<(8.Pepp I.s>EoqoE ,ַ/Q%v'#zlŪ&(6wwS~22Ӟߚ~k.s6v2`ÓX=`e7{IZ½5YŦysh_2U\n1oj# 1Wo@4|q0i!#W@X<p4='wpUdW{GZSAR1X_8 _mXm'6hn 0R:14ﶎyfyU6"֢R:*!XױF<[kEN>uy9c F0E/ Um5Kvx7RS߀Oi>߼uUYoev"I8RDkM- Hh=`hehkj(=0MX M{cģ%2V;w`{0 mNZ[ =;ԊwWl`;scq҄E $| ͲU' 8958wz:LvxTGWeNo޻<^:"V@G&xLĥ @5 u5.xq^Tf( ~qatq7FvB>7e{+; ]ٱM^{9n}L^Te_ o}V>MʉMRn@SտPz7~n~ӓ39G{@{[m_ʙqYƦz658X7=߻!_+smi,[W#%05ϡKȽYK R~UÅnn} T7Η CQr. Úqv"=I#[x+bnTZ .+f|[fOAHP2%CPy̠LxSy tcG5a@,a Ih RS}oh )#d`U,jhoNޖ.M>AtQұiڴ TZPJ&>" }ߢ2GgTys*GGnD_#9Co B"v ./3M>s qtDFɿ7" 8QDk3Ƃ9i^VVA.̍Ng`8ޢ 5"MG+Uwbvw^+7bЙ~`;$See# 3`m-doRc'IE@AKpr*T jyOES˕Fhsx~2,|)dPaUpb4\։])o|‹{KX2[}|m e&OC4hilRSKL^qH&[-}j'VN'hɓu qvYF}6{64}:^p͡Er}'j=Y> =xU$h?y(ΎeǑ)`gsmْ"] '.`tB].{dXX1D OHvL?il&/nW_lHc\wiWw8Q&;yT!j2:Te܇QכT20|7&z7JR1Q mt x0aS/S ^k4JŮbS OF%S 4mk!y\g2)?O<|=@bSl spG: ؞^HĥDY\'HB(љ3&&F*?,OI5"`{ނ&_`ٺE]O BTȽG1pr83R"c`VmQv/iUwQOlV7EIEl/E"C#1Sڲ5mUkp[AGlyPMH;,)VTm"V=؏R{vv&7+{\h/Ͳ#x{ `dh L1eߪ?/52o=¤3vb\H SŰx)vQ@,j]YI x5˦2\X(UoV?[cz[ܩJ̫-Ap3ðNkEf,-]Έeo)]<yad'h^@vrKF_ UmPtcaofT勓=0ΘD:|8o-i4H]cΤ_I2͖=3z5iR!B:j-"QpU7,gM)K9Wvt=/Qޗk}Y,qcN鼙cV-l&֏f;OҤg/+(7(^XaOUm Qځ~Y"3TEڀ oX]Am:COcs׼B,?qS`O+:8)-{WVy6Y*6Vx3l#r9!10{mWʀTkl"]AfDY'dzYBfq))4H^DÅ Op`"Jᔉn{0ԙIP$c~v4㚓B'e ͫ@澭NC :GrS+HϜ@p!k~1afex`It0Wl)̙u]~uc˂Znryno0`:5;T$Uc yB&1Bt5.HgP([I:Dp͢yJEːMPK H zVhItߐ%{Qt_CX:Gs1E1e*{ 鄻SDo :+Wʷ5u)?\bb)WGg(fEcV) aPP.h 8Re*8сiBQ;=b$פztT<"HF)FnA|ᇠ}{wtp Rߜ}/ވCGTu}r03JB_i+HVӴ 5RL& V*-#@\MtXJޣ D:i-AgjCuq5%<㋹R)]׈qeP)аCN(V+veq&*z +C`- Ѳ\T׬'X=]OE*`׏\}!D4` xrg8SjBpK^()WSL釱 / 0*0&g 2&"(EtbWM.Qq`d^i3TD6_E17{V*kr9P(9U]tP:*J}UiЙuj\9*UiHkd8ϴ>2TU8%nӡn{Y]#[P,`Z.Ip!;7hi Bw" E_{ } e_V.X=MQLOa@$K*!mw}#FPmjU)s~WD1*f~~t9(ӟ:$oCw5Zfʴ6j ̙ӞK3Y6~&>"j DeOJ (AHFȽ1peKböEQ\+g^ݪxyq#շ7-M"VNSXuX嘰*֗mߙʶa6CX}~ӲpezG)>/@W/-SˮmDQ(p̽߹Ŝyxw:ӌ`7G⎕ I>;v'|lnO,$T$a%w>b9nnjQ!#I@^x3v%MHq r.c>K7~1jH!qR̨!kr̨U3[Y}r)U=wU,_un 7uN)z'.1r#o 0Ӥ:u.}۔*Ї>ƇZ֨KXXͭq;D;E^`- YY;3c۔swD<9B۠wy7>u9>IK?a?O8mv }pXQJ(/S2P.x=Ypbxy򉴸m9t'Ĭ!s͸ԫNT"SӅ2HԒm1 Qx , 鬧z%W'ht`m9TꖰU'>Q]+ra+Mj^%p^yCDIN()$;W5 *̚rwv_=n`GP;G#h_'#ZRRz7oo>M7C0zzv" .vo'[1T,3_}RdV*R =(Fe6Hd SAtmˀYz*HXC>ul5;K M~kQ& O=fkghM=Գ,[A^QCuu`qQ" u;e-OC[$lhJBLCO|1xki?HEݖ srѢK93voC]3 6m!^cvX"uy "Xm&LP>OiHKn*7bSX'u'2C{Gy)[VO?9Jv:VIƸ FxP1_z!JUE$Ήre d'{D(7u|"Zn\*#ۆRN >m**F`^+.p **< }A(;~F}h-S -¨ы"/]Eܝ*ho"jjBх<8\JJ\HѩE*g5i*3W5jۈFbVw)tB@Cfdsʈql+W0Nzj>TW&2]$ѝz&l ƃ7t3bjzT'< 7 㨋,B^{i:S>^N93ƿ!wcȐ}өPm*i5ɺLJ95GvqI kZp(j łqwCIl;uM/mu;$.a٧҆psi]E7!ľ ǰVøLJNWxGh85KWf^zIضS5sFLQJbd/Khg WxoW*oE69vaU+P |b"cXZi aiKrGJ0tq aD>AvTi+nCRFeQ>e5Xq؀oyv=~ŋ $(`*GXdĺIW- oyB}**RiO2 0hk5@M3UpdA>U6!ʝRN8~mj5RMJTb4\/{D%$s?OUspEwL3Ư)ݮ˝ڪgѐ*];SD7ފQ}:,Q2QbpW@Q\^9S6;{òLyzа7’A|zFaR^[(D o/ΞEQDڸjR"%L34Oέ5xy/Zb"$kzڢ]8N~Ckgz6B[H01δ';\@aH<\lib/HKLnz g/%{J6w|CSztq LS …AyU)*¨TUqO]8>=GӂrQ$KEۈ }}e}DqUoJуm 6A` ܥl2=7bKS-3-s2{œR"i̺7ߍV h<&8=#aYgLaͬj) 4IzL]tf\m!7 ptflu/n0qed e֭f|;0O.Bptҋ4K$Gh_:#k}ɯw$c`\,UoZ)1k{b9":*i$$')Zjp=2n$6>:: a)9,\Sb^ܟK:6=բeq^GŊ*û^2ndѶFeR* W=,w2e!z {1pEv~iNr/+@CWA|!G ɄWc~wtr!?,%g~ˇE>KKJBwa/Ҩ g֠]Wy.#)"S]Ȫ3 %Ų-Q_ݼߚtm,=`}u~ͅ溽z4)Խ'U\yޥuEw@ZJ9oiwܠGF?wo$]{=<9' 59>k=i 4t/Ό?#}YGaje>OiJFU=mhNxW3Ϥj} \SNC˷?d-h9 &^d; ge*C?3萷P62+M'Py4b[E.A'놭`.-ϗ2O-DrZ/u0iIX{'u bk/N8.j ?n@V|4})E)ka')t:[#7x'(g>;/ߝɲ"hExN+=&ԩv5q؀Ql2!2RcᘼTٚ԰(r*@.)vrk䝶.y1B;BzJ%|JIs70\$@Ndϓ<D%"Z`kOݾܤDynkz595Iq0Ku'bEI5!'E{6SɌK J R[W{.|hZvO=1at~Ni)}zQ}a=ϿL(B'^1Ȧ[o86+C+fFp@NsTn!W2\cOk)Ij;g>?3 kd|۞ca2b6ꜤF3T%>fT|T?`@W kcՌv0qhL1^ 'xC>TLЍBKRbx QB3o2R ? | 9tj!jmj@$!|=لϞ+8Q' -G\zaBi+ڎfiYJ% ce--PqUtކpG84ΰv(ĕ l$aC)FoCP,&U[DT%4--7ݤA*f[|Ih-[T3e Ӻx莖G8>޾ )=9t+UYվ8o3ה|;[of'EÚĦiVkFЫīA!} }Ybh:aF2d;M5KNn 2a=ӗ?ؗۗZN{ormJO?,dpIqc.I#tA`>>T[J&2][1~AqJFEa[F. seϚZ,KUng&M+O8s_a"lU z5Mvo7އfX_=^_(yeY ԆjdpwA p,/L|Kz[ЪFnQO3|9K_% QsQMm05=&XP_C@rLQ vrh:F ZQk14i5h8 gBt|?@_jqscTU'e2Y[*]Ȝ bфIBw5"|*GJ~^3 >tKiD*ʡL QzȌcW$1a*aRmb}e@0UUA~S5`}${JM/j y)Vsy5n?3u2beW{X4[lΤb8^nm9kLhpL  lA${5II5eIj4G:b'=1|pDKӔMApaK n}H)T wj鏈|Q o%oakaBô,p|S.ip1Dyz{@uBL MkGأ8-;,qz˫Ϧ˙AۯVk|Aܖ +cŨv{XPzmeLߚ>y:쫓AWnwte&z.j%?3rh+X|YpƜiHJmXU65(@VuuX톰\Ÿ@.J[:m|/4_07SKyI=rNkޝj 27ZGZ.#SuI0bWH >!*H$sM-P֑\A-4f' ATc:|_pL^^de͸uV;^r*kF6D߸ >;%0Za:ÒdObJW3A}Kop]*?3vYjo_'۠yh#G W[2vh]3xIv1bEP̆ϦAl'xH3_ ~Y,B;AbJLzA?95Tq^P!G8'ԋ}: ps6#D5Eg:-uTVJ4[KTB`έQCQ1) 3Nlmr2F|?\) WM%9C Jkv#}-m*j2tlRSz՛v>I&YE}-nDԠuSH an\h RWaI0Z-tʭ1t =} S hbL.k'2i[ڬA&H=,^n#'"pY4}i;-p!i Ȗ.x|x=O'Sj1Fs({W5B{C~z92mqھwSیZ[G8:KV(\GAVɦF28RhO}ϳ9EOuwU ŏ\PmOc珞OT}nbIUm'(d+TQpSUEFs22T_E4/0Ԛ $(>%`a.Aד2]DT۶ *gpZ}7Xiol%f]P 6y'WZu0&iI)S'U #O)R쾣QH>;fu7&˸H,1CArc̜bdѣ~u^(Bl0yYTQv||[ZdT~rBEuܳc骙}~wM?!'QQ+jߩSA=ꚭ.#$&e_|=<8?|8$Eі(&Gr9jBG|F;0(ۮ:~rǚvb=d&ڤgsnpca,Śy72I' EFᾛM W A]i &nkC<-Ie:yْs;us׾3'a5 9>贖s Z^F4 F(!,͠(7մaۊk>t\׵b@=1˔cRr)J_ӊQ33S_#Wgnֹ,{PS4ti콲Tyt>XȰS"APN >e pZʽH'_EZΚ/O<Ásdg$lg*"ZE'(?`ܲ*ǧBx .c*ڽv=w H!;V=BUxCX .c߂V<Ďoړ@18`;MdY@S2c(fhpVF;*Ce a/UrWz+gh6n]Q_'nF`Y|'eڝGME7ܻCLB+F5)v?ڱAesn N[x\ 6`EE6l"U머-z%$jd#F@g0GF~ %X% 26r-bދ 簼pȹU=DOeiÖB%]Rժ?Y#. Hf.5щʠ}f*pϿE:蝀C;<ޥy-~TLиϦ&)}`{<&yV_T&-'|~,&l=7`ٌǞX +a0oE{c$g{p)o+xxϸ$F`)K%Tv Ro dajB>\XF}xh6vtN䚎E,()'l*>>A'{4v^AQ:UnhLw=ꄌxQUKrX.E~ tslI_{ɘ: WP. xGmPNJvsQí`ްu0f@%Wg)D`ծp8!,vl lm?Nk%oM'i0Lk-sNE奠$ snf/كR+P( 1Q37M e\/͌k× 'b3L$ bA$l\jʲ, UT L5Pc4#P|YtNA7Ճפjl8_e

r^ !vA"\krr7Jr zy0j@Gt\o^:R"}R%15rK ,! *0l?rJ8V"9kyڴYB[/g2gVz΍G*U\(XrcU>;}N9munu76n\^na5RtǟZl^"L˝N%?-Qّz/}nh?0s*p@`UIs@L{o5nB= ()ZqZ Q 26R'38J:zbC%7!}ΣY&ra^s:G?bwT]!0q6iK+\|EXe(=Z5dp콶Bs)wǃW ~Ub,l"f20o3ȰD])D}ǟAxI .`U/%SH0t14}FR|HӪ3~sDRzaژ|=\wEUPLX *%E19U;JtNw,N ?^4%I<)a 0+D3%{I/Ŏr7mO}`6"$yk(u|g$`FZ >}RwSsLO=GAs"GҺ~O3Jo-f8ˤvځPLTlɯ0lCSjrM!&l~jܯ5fUyPh sEd㺦)3-| Tn9q|`q2a+@F;Ehmɛż9(y]HjVfoUIMx`"|u-8&ot ~LO@dLBDtʀΕ .FI.i |Ͽfp0s'ź {G_Q7oHQGz뮽K7=Cſ,Z)_FۥMԨl[$R\ 4 vOz!~ߪN[sb]҃M .G /yقK ]س9_Bg<.fhcO()&ѽ>pBdͲy^,^Vuv5w2Z9W<^ԁSRZ}c^:|Y,V$wbP<vϱn̦YnH} kw#$fM|.e,eӲjHL`}@تܬgO)LO~epxa<I_u]::O뤫V&uĤt;>{Z.*7t s 6IWR>z򄹸[o&m:/__8zҷ썾6><=5~Jmzd4Wϵ_pbRU9djgqIq T=ډ!;\&{(,!VP,ʞ!PEtߎsb˃E-j og&kV`V!h1?l<\J.K|~>|!ns/4/H?ۥ@c9Ұ,(n۶dO=V#8tM˦KsiU$MaOm͡D`lh-~N\4L4 @vGkZ.0rЈn:ˠ_JZK.J{Kgi\cy%AD6Y/|9UY/…ڲ[eiizbI6P{I_e3v]%AeVG:p. `IBiǷyз !7]g^$(|^$q|Ճַh}ۋֽ^u8GZUZhgEPܣ溊6%?϶w58E2L]}A6]p#&~dvE:23eg ݆Ʋɪ;>dedVmzݯB#Rq~5D!f|SL\Yaa&u',mxap#ŸZ, &X_Y:- F06ZP]+hu7S#tJcQْtsz287Co$/ {LT邛9B2C70"цO2Mi/Om|qͺraծHjի/;509߯ s =1)Gu3h50džInqDAz/HZlI<7.HSM T1ˡn (iOx>OD_ĔX8|.:/mY SPҴhs ]˹HgПse6SnA0r wǧ{7Mcݙ䚯_,=>nAE6C+12s\/ K n=d4VdR9oټaHν)HQnc2qN#g+xALtn#߅ O>wu3pqehVߟg#.P[.lRvyU*nyYA1Q湑HxvWSfAn[" nE[cmB:xw}BBIYZ""$zq9s9taGxHa1gt(ݝ1GMc4GpbDYhM2`Ue8*%45Oˑ[V4ҜX s9my(K 9yV.tn~IeQ޹-@̭s /댦=e!z7R̝{`9I1DQ:,#G3*ݒ5%=vGpbg}(g=UoSH0h"|\x`9r1݌}ȠTBQ[ȮJ5,X¶4H{֍8ܷ"MW)J-2~ΪfT+aJ+7Pǁ:Z\繸u)32j1!=>5%WQ-J!<ܗפt`UZ!(N,(a2ozn ѫU`ajۗ9$ꢑeO\J,pMN;v[p-a̅[3hs})9㻁#ΆHW"~r lq˶D@hvH4 ?`ЛčKD[ecWTS.@ [\"Qø#{,0)09^uHYƢIxPf=RG x3"IԍADlSN;YBބYc(;wc[i ϵ7vWb+'jVkUr&+o]hIJo5 ;,/fʫ!`NA 58@bs0>F[eK҃ux.98"H֞ϱ\?+wŎaf njd_G++u\x쾹._rĔ7oB"VZT]VJM_1ѥLSL" ಴1 :˘Ln/+UJ,p2^q9ZildrۃVoZ "NF"a1_'x=rܸr(o9n,Y-q͗U4K\X!HFyWIyy[Xsj<Fe7*`2'͸+x`oeɮy*DĠ{%dd:`YcD' T*aK,4G|*wLK7&|0{Z01/u_p'or?"t' _@3Waty AG]EFp$fc{{{u$Q<`Ux \Wla|C7vv۩";>{i~Зs8#踅w.OKM_=b7S=w?8O"I;oi>Dl*#o"a 7w7w?\*7#d7.>~8cbqyvmlnm7ŕԕO69y[iS @ 5~!>a/Blj*mtB>YAr1㶉n߽?)iH9K6.!qsH~x)h$p'>{11}D?apbh Oxǎ$a 6'^ Zy> TT"c{e1J3;T oYj2@})C u ! crt\gXw,X}{ifTbP%gx~#6Jnn }V3-H0*?swkw19SS@ yx<J}qfbhC0`~N ʽ4,p~ϊoTүooY^:StMMX|m6eB޷m,&pۯ~jq:{mZJ_ 08}6 #T61|R!cLc%æt¯$Z6դ K3]@;[ sp~OJ k Ι#svEhc 02rMuj]g'54eǪWDM*Xn uuF\rZϲtNe1JW.!NO2k>֥($w*W/tfErrVʀB^a~͠lzEېnhGC<5+-O<cS!* hU0Y1Y("L`j5\ߧM%%!HJtOyR`>q gDaWD4 6L0VBdYJ@_ #1r`B!MxI2OS) cZtIqu[23Np'`gq;weOk=6fɝ>A-wfA6i{uwmIe'͕ꂰ`u?kh@AWF_"p%zyWuּ"e$LcƀR`I?_uw/Xu}o 냂5(0#(KBEl/DeׄF"IQ|XN:JbW}Z^bIƹOQ׋0[>r@?{1 wX93VSH#k6QIIW޻?ۤcUN PHAqVԕkVrdVF2ͯ@gļ K}_ wl:i*nn?,nNKB@)-&VUMW=ٶ}h +JH{1{6ƀeY;60J横lla8Z=;xbszR_m4B܇ix/>Ysb>%[/]: k֏7i1 JsHrO,r Y71ndH)vzBIpPޢyZkcH -i9In Ӈ8^~)7Lq瞰!k@Oo?{jH H1 ،GT^^Eq@30}_U{KRyRK#XN`b Ymv+jȾUK]PkZ[%vDGMhnLE&x @gvF2 *Ebip0%8S0K<8u2 Ӷwn0@sw X7-t$ްϱ@q$wZT>.7q4Q,(㧲~dQn9E:kr{ H{."xF6f|s SUi؅N܌"1HCmPBB;m·LHܩaT+g-QU>Z$ اeJRUBRQ>$ 3$'CԍFiY;YUƽQ2Q,iӋVq?U&'&Ԅ{y4pƢ!}Ho\I1]¯Z" 4ϋ.N+َn`+W6ȹZ>¸kmaQ>v'Հ6kI?(#G|n?Mlm*Wիiڅ AvUE1X2R R{H(xp/MY`>JrP.nnnV^4 :pcf&E%0TF0|?^l[eqĤ]8w[ gއ久bpICk1V'ڤ^/E*/.x)ȶ\7m6l*_:”bܱ3l?&tlƛZF*6 V/ EǖOjt&h6|c5__VF<Jx-D E1șD\ڴk^oq ߧ"ƛ.+Xp|7ɨD#A!L,O[5" fZIfHL 4ݨNT>d;_xšȬ"-`:4WI9X٤b`dDӺ 5 [J NQV0FT%(\dJ]u:bfm =Vx,.ty+P |̾&l|M "xcH͓g7U:kFҹy Rnl0k xx'sEWUa@(DVNML+CV~LWʗWh3ମ44VjmJRrLNI\P`A:Sa7h5TX)έW}lN6U@bTLDU{:VTt)(<*^K0c^RC-(h~׺ίCaFw9YFu,ѡaD'DTaTBDj酪F̒l۝|h&>.mZ>w[7qM=spY1<=D_^/w9C? ooXלWxk&UfYP7_LȦ-ږ6ٿig/`LpΔ$wcrD&6ٝ{려fMz3Z*++&LXZ/xFhaUhϓu. Yrh]Z,S+>XVcUvS`Ũ:niye7!lI+[7W,ckS{iӚ2>FiLG G昫c`JœDUpl)5`;fwLt {>9ر`z$7 2f,%@c.g..sƑr\j7Zl]Uq@v!F Fi)\늷>Fx\ֲ_ '1,ZТҢZ 6*,`E#~qwԘƀTr˟o: $Qu, 3Qg[TԠfwZO7?n e\U}.5?=YϕßYm8j5|d4@Qڼ__)jVk|'V_Xl6_=C˷٠ q>C+5vz}\hf^>67ˬQ TဖBk6B# <_ͺQVh\,A~ #am|:FZY;:/]94bc6o6@zUL/*9X+(SƢ~g#caDeQߌkuq//,lc0DYΪE3) E2^s-9F'2l& NyǨ2٧?K 2fm{%;A2.é~X!},5&ۍGb\.;iaDʧ<>ʼ+Xñl4-t "-6'm}K̄.@:U Ŕ{wd͌ha4CEʒ j-?T4"9}G\WRrg+[_b[{3[33.w8:Q ][3 Vf# M-}WZzEPƥ@C8ATCo?U7A̩: Lw[lfXvELG"u]ݙ';F9uA *4VQkhri%:_ESxG ܶaOf]2cCL$VxMϮhU2GΗ ^}XPi/x]6)8.+f5G-dYPr>WзgFܗ 籹}oD-+-{eu/]T &rك>CZumP(GxQH8U6p~:qVhXKadE gu:AEuy런*W]̳qdz-sc)kxҟ ^|m #OnW*ӵT܉SżJ+RKlgR&TiD4oD '|Xc49iK@{qdhw:+ћC޿ilbUKT ӪXFlK~24ܺ/D:E j;B836'` EkЬJߦ;Lkko e:\Nrk˥y0'nlV/ˮە%JRp>2!)ٿ=;),f{0}p%‘u\xb,N]I]z mT5xTN] nW7+ Pa5L[1W53˵c^!xMAd #e'nzo5mIK-%8`(NҁvV`Sh0NQ^g 8֣.țh=2UI^/HbD>8x!R龓S0HôU5`PaU/r/̻l=h!Ӹu"-UeՍ8CJ0'BsCԼ#Vqӓ 9X=Vke*j.{}Gf V$6(y5{RpkGZsZVBF׿&QbRfvFsµc^Y1-fn nE9hͭ[Mm)mmPuKˉc@ҽ4$8DcbCјe]/I'}}+x36oE/^0pcc1Gg:X˓' ;۫UV\amjUl׷Sl? tRq=^0i*cR/\Ճ󴚩QQAjRRٕ-ɕ>^u5^`T4AֲLhSM \NҠ͙lG=e~Ψq J5ksI\zisI"*}+t,r}f? N<=g G`Ek97Bp`xZ9!1nY'@=[u Eŕ½rYH %0XYm&  My+: p)NǑsCUcޘg[cS휗z<} RmA߬[b03Z9Մq-=-~EdupӾ:YrR.@WUJ{ kmn͠_ӀyO Z ol3V^ՒO]N}KCʾYtaVf] [l̳ JWxUKlU?q͋&q[;v|6/Iqb ynSі h%l Kl`ARHX(THH8NZ>]ys}sg}a˥N`YF2b/ːPBeG'z2͠9+$Q,[ex{uSJS2cQ?Y!.clECӦI+0YSpBULE;MUMKFHDA A*)USf#&P 8C|m2%_F?-8V5o1[~cz ՗tYӽb/{PG"F>Iuu;) L :2CX+@i[~zHPY\m66da+epi 4CR3O6?kU1XPUc %B?Lb~WDr+HdH9it>cw*\ld0 WIfF=D#1F8 ?8Q3ҷ$#dt>3<h8^c_* D `w Y"wn U FI*51Q 'F5lpPHύ/kSR[M,mvßUh%]:C(v[w%Ǧ pPm*D}Z@=yJx25wCWHBQ9V}K-D!&~Xv47Ր<|Rspq;9Q=&ڼ0: ^ pHjH%CͩI*v&}dLDym, wư1fRѯnDF=׵H(ƹpo]4LEeS7HV jNDeqPhx\xDw9K Y@>"F5By'p+昮+NbiLJSf{Su|#ET!͆8V Nt٨fm^Cduh 0 ᓙX1gdQB;w4 kN:~x4MͿ\-,]b9Z1wMFg."XIN&&0bxmsq0ݿ\C*!V2vl]HNE)`wcwg33KTDJ$mr`ޫR]%B2BV~sϙٙ ΞӧOYdQ<`2[p* ,S ǃV?H0ieak,fheE KT;.$Zf̙3$ x9[ iva&0-(eQ/d(͒hiƿ&,, !EiȂfA{5X Ofյ $^ص0O?}Oa-Xw(V*~ZuO$b?K;؏7sE|n,K#suaEG'adzw~u؉tJ2lgSt> #r~ܾ< I6uzsg,㍥ʯ^/hJ8Yy ^nĝQ;1/kqI{7g:?^ a+_S,g>Gy6}gN]'^,1Xq.n9/Go8 Lea3A\~Kt9Sc1og^{{j~޹&So q<[\2"Noĉ:vl0_ |jx}b'1HwU8!w>ϳV ~7j[=?-'-vU<.㚉{}ɽ{;/zœ^mlH8g uI4 AFj?HvtX¿x=豠 ̨|=>r6?=?m{M{/y|1bv)f8&\S'N[J\nq'pģ-.CW"r5. _Cs $ G);eX4d ;-Kl{F!>R跏4"pOnM@? Ie\a ʟ"{ s}ڽOq[b/uqs>.!7LNWW!Fx{O3?U#_gSI=%>/},bY̗Յ,l}ȗ3O)']޴"<CoψjB5 ̕K}uvXxb1ض,"Τ\)y3F/L(W\H:61@CP ag?r6|D_0W8 5Kijr8(3bsIHXK_aL\ /M:Q{#>)?{JG% x>#[*"3A#4L`^yy[kˠƛ.C#H-xEw;ąm[4ҡ\4*dHcyQ=2{.MNY4:Eg벲}AM?)aδ5 +v }4`i؎,ä+(⚛t_8S&ɥ$nܳD*9N\ٵX]CPh ]vȯ8 a^~Ag|\+BFsUl42.@&Ļp,gyX;zGwG2܃ƀ밃$r}@_-Gzd(V~ܰi_[ܩ0"@,A]8F 2,0G8`oҧ#ʕzm)w/vŤ~m: \B7B4K6|lA/)A;Y 8-N4H['M,yZ jW)Ia' EZA 㵰M&ܪ!Zkѐ?6ԍ˫Fp!?(_hgu—V0w1 av4+f55A*5#j6N8\X8]plpTpRpkJ,x$׭t*P8=p7{S(}83ysɂ/R38QbmK}i6Q'0r]6w}|F1:B`w=RُHَ{w`FW$!׉W kS>;0_ ( 13cEbs-t\-IbTrjLD#;)kè,*Z^ȧ&aȯNEUH'ivv՜sgX'\6vע4v2}>(8rwr<*B:&|6K݊M3~ƛx5ςTN" 'x08>ʬ='lyb^4:rȖ %zH9ToP_M9B"20?'M˰UkLܲ*cKP04lMg:,;*,3Ruyؼr 'Tz2i׹jʢ!d:,ROs#,E(~ >Pg_J:_Q;Q:\/<{papͪ.sEUWTT6Z( Q'NNS2Vaj~jTg~C'4dlӼvZ}sZ!/V!C>vʖ`eU}H$&i'ȿ}Y~G-i2CbID=c]ј8Ky (a z]?n"?> G` mfEY`H}4K#)J3^$ac3b^J+eȰT`c{.Ζ{oaOͻCgCO)n\F$.дM׵>7TH-R~o& Ը9:ֶr{5vY`W CD(qx<O/DqgJ6lèOx)\Ql/TD`,(D>7DHB4%@̞D)M(I;c8E#T>,qy|?C4RhPc @"VV„K!)b ;1צȈe#<"`6:TA,\h@JKePEڦkPCaSz%" #ci˄%fGڍ&_{ufGON=uNATeĶ "z[>3:{њy&EʁסyF~{O929¶duA ۑ "<*tYpi|ΏcbBrWr]Svj4@'xm{e|AdlLA+taN UнD:El[Rw+pK#^^99o^fQB9Pa\mO?Zn@g_*w|;IWJ7Y9jWu S,SH4H&e9GRȧ_*{|KNCKe!9QyѥH>Hj>>=cd13LJK)F$C~EH<:uBM2T'HַUBa}/-Nv$pQ^΁w4=S-;te]NU8ݰ/5EIG J$zt[D/E@R5atƠ L5p:V"lةNzyv?ruj,f T_*Ht Adb`>7jf:}{v4ۢf#yxC _-bBX!PiJɆ5{Ĕ* e&^._7R7;ckR {0ȺT|:Lf tE#WX,T0lG\KKY:‰\rߖ29` U$o)~/S tNSq*ZyJ80R#X v"1,/E(ە#WE @8't\f՝%]%e C:P sL##L.kǙ8/o;W4G:?>ReID۹G@c^ު9˃fA'Ң~=A[jH.8EH걂$-W:oܮ:mZ,&Vl|J'δudBhlB0Zy0mk nKq9%hU؈+b?n$^KĖ1Y5@Uef*Xh<+w`tO*|ѱh[)TIqy6 $)Ve,^ztw}|AM9N$-JW /{/.pV(&:yvNi72\^uJq 1F{M7dUw駫;Pp5Cm,IVô^QZ-9c7XL ;*X C V-|"4^&j+#u 4o ίQeT=Ⱦ4> j,^Y&fO,'' \8Jy7^?vy"Ӓ§"w|K=]J#<>ҳzӌO]ЂUݝsŹA, 4wL<_wA#98CۚܗzRa&bkN/cL vkbzn߼ڰwt:K0|j?uC]Q*(rFmV#43fa_\s#(a#_&-8eF&QvY`ѾhDثtQs6f4-ǹ9AϸJN(=}Þ|)^t{4jUtIIڍ3n"JZsNkn>xS2vbUzvf Ǯq58W ,CZ.y"ME$e\6PLvxOHIr=n-\򥫐3x*X0H+6' Z=1 _H"`rڣ|~?4H+{ݏg夵QT 㷓 t[G Ξ :pQ٣_yʹl+_Seȃ*u~!,3sOWS(zEYf3([4Uh VؕWWJJ%r>ڔ>'Rw # T=ir)<6Eb|jJ'_ojƝ"ǂ'F_jYWiǃ, VUٛNt 2xg0;,CdP._WQ̦)R_c>~iƈ]ĵ}.ʂ"F {΃oH5hI7HA̎;>ʍƍ$8c01J _ϧTOB]ay>)NJc Ҡ[%|gŵ4ϡ`廸U%!.Uؽ[Shnw=n)a@Fo<r./nqFB^oIV2hρlOӅO>k% m@XxpmhB-CSNi83d0tPMWda9-&cu`.\{I#(?(iK_ )\t^^??ɐ ok:ۈҞܒܥ6z̹dM0V9,IEiiI+ZR;N C'm}UJʋKd̳13`~sĵƷ7@JC:Q<4#ZfD-3_\0Ta'x;;o;E'A#9 Q8zA.lFX;~u{_ơ9TKDml~šعrqU5M_M>..s$.#>xpROܵVJXtM:0^Rw7*0:{n%'[s#)~$K=54߸L<&Ѵ"T娶GAoRs7.o,S&[V ek!拌([SGK(%@$Z#p ąU"鼌*ۦ TyHP-4Өތ zp(PMP! 9ql-qEK!El?qKPPܖppzd a&HŁ5DbHi&6|XS6/4*t:j`ʒ{ݣOJD$$a7vz(e@xPƕI0|6~w{xeI7k aJOl|:Iro0%}*itWwҵ۠ڦL|2E'8rL,ryAةF:tYF3Cq(4lmq4"u'FG#W r^9y^>n;AsÐ pbEv* d:DLD::/ebѝOIM:uɓm^zqOgjV潵܉e֡W#磊r =KT^S6bXԠUc[<@CsfTq|'m_՗l#sM_*N}r[^DNVf8+" ~*A0&?(7. (EA4<ɪWq=Z'Lǩ×> iWA0@aBÃW4q0w6cOPrYlx}|b% vГtAarYde)_- aφԻ/BX3ozuUP5]x{dzFKitSd Rm&!ȃ@}Iͽްљ\q_$' A/lN?m@d}rCy i%PEZ"dMu蛻omH9veܗHHh~QE!!Knc)J6dʦ;!D(XAǓ*O޼ k"M¿GTo69u + po$1d*T6&PL!S/\θÀ;37w)nYz%Y󲡮OIk~=jWK./rXmu(ΖAfA[]``fQ74%0BhMk{vj_# yog޻Ż[fnce k\x͚ ]8S7k1leʂŃ6%W`*W*2WZ54=5p&C!T@M30ǣyaKٸO\ K[mSX>[”!A>xv|BYjؕ$Ꮷϸo IR*pQ>]4~Lu+a6r 7hǽ85!zϞUm'qgzJ0V"@=굹V<4"gДDB^$jk\xTz$h r̬qL7ɻem G9up t\2)X{t/-.Wp߈gLàB4tawK9v=k'4<Og2ɼҺK>ȴFP@- {?0\DEm1 Ҙ0˖('Yf2"KrLf-wt y@.uF' p˄?57 37u톪n}=}/,N=5wܑ/{HÄB{\ : hy=W\Vuz]8`<8Ż?IuzM*MTYX7gT8ѕ3"t '\]` mGyVhg( Bj-ߺ&OaէF~&/ 3n zʻbE<Oh5@$^I>vC{=71&M8 9 pIrˮ`ynsӷTjj_E"ma$zBp3D,i8il*^oOEk~w0@WZjޭr|8[ ybu[:!UBj?1-bUd_>Q2k=6"]Z#?뜢 xM96Ơ v:VE㿐2Pt>#\}XN4D2Ygp#Lss 7U5cѲTݗiJۓT͊գPXuֈa2`yب4MI., ib09((i$w<)n 2hc %}!,[k/BA V{RޓHQ]3YcD @^/P!)|a->uZuuW71aW2yce؟PLmEO 47};钇 Ҧj!7OU`kHLQ&^L8eQ/,ռ͈A`5FKu*3B~=D=)@d7Q/ ^{xn`#tY|!1ߙ7ux ;tא|IH!'c a4nBN5~J|b&69fx^3ʮV,y kvfzэ0~I܃^]/UTEAt,(m0>fD7#hL8Lo^U$TآY%%b*IA+;?Azܑ7x%<\ ]eWH-G@0o3Ǧd@+YqU7m )Ń06W Ԭ>!_{[Wd\\d){b]#1F+_V8p^VcyugӸܡaاDпx{% %`Lʵn4X2/=os^Zv.0k^HEyZ?:a J 7X 90"t? i<4 h(bB FpnTLrEVwԎJd5LaAMiKz*6O[V.;q?2a.HIp<Ù% xeh (t_d(^u0otrFՕ:_*A5t$MJZTR5:m9J5ߢǛ 3˽jD|O$Pc.+p}m\=P plnJ0及RC>)!Xê;fO,0s{2 t4SWN)r82,{!| #˔5Wqw9YdWjYXEv۱oexRMKOYYAM ?@c}锊 hW% hBa>kܲ-ܐ=fF_# SῇqQ&:")32 a &z 2,s2.Pf+fz9æ>Z ͖fCBHmrSGva5]E`u-̢~peXs[^-y-'l*Q+?p<'ILOmCv.P@+,j!t{-e @ԫI_] {;J/ߞO2a',P7cB<+_1,$c_?n<ˍ7vH/%' O7pstx[:!( |mJ-8+c<9fu$uwV@h޾[#`;>a_T|r*ayRJ &Z inhj.4͖kœAZr֧e0|! bi+0? `>5 D'F 87S1p6{hqaTt)i(}1 Q(`yj!~(-zc1)jlNyLЋ]j3x,紺v%;vvT~-w̡KEC?JS!,[ةp"K1v4=kw}hvFDHmp~aבԝ:+;lB̚ gs+& _6veA;. +QxQK_~ASbܰTK!;y,DWi>?oE)A@rZR4e|:qr>O(նDž^v f तFQ4wr=X< a;{ʺ#T+1FC4L"np)* `Us!M9Ɲ('eXǂ6gWJúpƾTf! mujLιb! *uz,f?cn,D YW8A/4gH'8aЎ*0c_yՌM 's+FQ%{}t'PߔbPRmiqd!Wr:!#RTS.cjAq߲yʊzэU,{Wz9i)0*䐡'A:3~$'HzBINy#n TsjHP_0Qc4f+z-&*S@9!߬3zD1&k/$n_ {x<˰+0 2E~ĚS\UQlR0ģX)|8 4^C`Zc3E'8DOO/)kc$KAY'px_/G-8y$բVDYML_qCP8 ]Gk:P;x477ִ|65wZ@E mݒJ4U#WoaRɍ֓L ز,,>s\ZpBi'axQ\m᳗á9Iu6sSM#8ʷ1&;wFu$t\wY?2ÒωbEn+u,:EѶbuH_*HJZ3ExڊxIT^rUߦ83]|-: #c:a-`Bp_{ ;؅#밃6 `jC*y /Cd/A^h ucd9{BpMeCD}*LO`pT~xa^hA{5KzFŮl-\⟄ְ JPIV2GR3o^,zh|7/ 7fU`]s*W1W(w3R*ri8::󺹷`ZmƝXݔG#i%3mD,h@)+`}Wƌb"oWg(溎Ri  ɷk_J f9䤏"!n ڷa V;}1 Þ:AxƝj[l F_TW6檃1{&7+ Oژ a$TUZ|v.fMXus viY7  X㚕$izRP a߈_Bī ;Zknu/YbW.LEB[NVY}zQM \Λ7$,xd6ޟM0պ-NIf%ܗzl+t]:=[yF_^+1`RXPv,z48㯟rc`&ߊUW㶢AU U#]Vnl ^Y:vC' ڰj9 --e1se^Z-ljpwefg ZxL7_l sVzcmXk>_CB 8[:'(ɤCxxuv:FyccP1GpvQ.߁BNA^SҖzewЙ $.+I0FTT ~Y q\nEq., ܾ,6IckRHCn"2#'d75|x:B.ЗH!#O]G {92Tcd{V ֎-{)Ps2J@)i?i^'K- sYػU^[UQ|H:[O̜p(x.pKc&|SN&T*˚o:?uBlN Zu*X:'z14t-DžvkQDCLMưeQoa}mٞ(¼]7`^Q扔kE1Ќ4l4@'J*f%9{,1Xٵ% &[)` {놁L4+-^/M[=9ե5M(s ^njçQ3S_aR~gY)UQ)Vgjw]LfzZ۠_x($ vٚm}h7s)x=YdZL^q-7}':Qp6aBh*Ǧ<-9S%'e NFƐj'TYoB7gZ0V60G6*Le֎ڮT;&1!l[eAQ bwjK*/ \<_HzDܖ<#p\l5漡#5ѫ1`^ g4+++ }6l&WCm09,x=0Չۼlk E+^{C- \|?b?Or )g0 |!8,ԏwR;į0HMhH05e, KC^'Lg-=1H:LX/Ҭ=O ho--[~j)_ \ӂ9΅6z1GP<&4V`k>KŢ1"d@VHi~2(.Q³ ϩ^O0B#QK\ā0!8Z/޿yDKP: / (#yAC˲X?ƯÕhd熔1ЮRRj/*P/31*sn C-xVբfb;{^K&/"ߗBiMhg tU-[5>oY%51KAh /ghcZ:ZkMV<x4Pa 8)?vEOЬO{s̥Uyw`^H6QfuZlnD0`pkc7۲7Un ,Nnȼc΂_1ѥk#,({wϕ{V_N$ T&pz:/wz&MFvM l9nq X7:.tgQT$&^e+F.p7p@'_U'UD$\ۃv68qa`.Vײt4M Qw¾;flzh{Q~Z@dч܅M!ft%NWq4`7QThM۫">=6禝 df'==PLUepH,\*,E%ZE:ٕY sܚwg*s^^"z ZPFہgfҧz+kq{;Xgаx \;K=6~3f&aL(K6w&xbycB诠䯚@fx8C̭ HCjUq綏w$x,yo9N$o%pNFR3_(7+Xհz6bXwdT"]yuïk>iU e 3S?OmQCHmVČv'&\Utz 8mA?&msx0iRD"d{{j$due"%l^9x9ppUk{q`yܐ|Lm=)nqNe oWd.рzdsHT)A=H'EhI!o*dO,xw>Ȏ@r4o ]MrsUn,rm4]>1uuȔ桤Ly CD:񔥣ZFiOUli}D~C*P  5p[zu/ vLe>HZ}ՕʆE 4ob-r BjR(W/H*&cb-l%!T: PuSPD̟ϗ9t ;A,~Bؼrqӭ10-Me jk#e\Gſ9)uH~!*/BfSR[P܎޿FoªؾmӋ]gK%~[7 1_=.t:hT}c9]ĠHӲEػFRVTf[;cVMfd3U`&˟[pEϹީ1HO̞T0ч>,D^QҤƉH2ʅrY)P0)h쌲cerjpxMJ m:@&p$6kTP/mg(hޠca@&#j@vNm[ a2E窑ט .l$S߂_j]hWPuuGQCEuqgr-RUaRFGi|)H(߾{n}htb )&g2fɝ1 :KK,aRثڣ2q)zcW:+{"6 zZ*MM{ iio?.s 6Ďq2Ook/L$ G{Wz+A3 bɌ<+-'m0ԑwi'dan uq~A1GIi[9t%`zdO뛆>.NQŽ˙kN ;BcM gù$ƃ%x2"H+vN,ȌҞs? l)k}%oֲl{q$TЉrjԔ ދHg k3i$e$ WКBe%I#4I=fy"hC_u .SXh%([(|,kRh1/4 RUS,$KtJzjH> NtzR>%ꍸ_3Z5ϠHznkFQ pԂr% W%5SqoJM6i} NtN7A( 'w[a^P^g^ 3"4n9rk\4b(ޓ*aT7EH-囪ӑ{f?*9v{-'Y2dmJ4 [+-v؉-®I[Y g4\INhѱ[3ܗB L@l߸bvM|uXXR (x (Az+/;+(~1YgL<+ɻ!YѰ_lM?ͰF':U?'VO{?.󂫛I #`IY*`{·;EJ ^%Q݂fq1&-7I S\Bhl(mj2Rv;k)TVσx0u(m(/2r䫥3p|rH\g ZGi ⿕><ĚBGרEEzE.53DV3еw0n%qgg~H9·ZKU C5^9CG&o>f׵0 Whp&)Ai5 k=N2x^ ev% D)A :灓C{ G1ri! f\ )KFLGH:R%EfȴDw Eߔ6=;+!'p92 q[\&+NZ/-D;6]|gZWVaq:L-%UTt/:od׊M];@+Ii-R%A-gtԗ?YfB\ |RS(y1ťo'J\ru'K9f)Nx9MҴ&toϜޖ4 }9멛-Ol>Ìe,oPe' ?p0ࡩX} XHr.yD eJ3;(#4(~ֆ3'rNJio]I4c_=)m[w:l9v]|C/Et\ɧAC=.&4G FR2&D(*5}Coǃ }B䳥AԧT¿,Ɛ>Ӝ,(U擟A 26Z-x@7euCʟՃraziأuG TviKtbvfSw3J6տ)P]_DfόVCU=gZhK>R.1Z.cEjsQm O/I Vfn6NKj^vwFZ{Κקl (iJ}f>T'f8"D\ҥctJj@mYkH؛.:_L*Y?FX>º*~EI'L BU#=#S+nM,-S|D񅙢g-?U#+>xN]U~$S/ӆcnIFʰ dh*@_m~Y鿀h|-jzyJ_We :RFC ګ 5IwE㷳bs$*(q]), bzd:H"0z彎7TBx @lUxZ {C,\\W}aQR#Q|rm Gq7UǓ[>o+Bf@O/Td,Zp¾@ܾY8'Kж5{?R333Y}tIwEiȠ|nOV8d{)1g)5Ȥ,~_YV_#}}֋ @GU![I{ ZJ^MTӪGQYZ [.45`pՓ˰.XrɞL\qJM=YgF|/Sv}¶ eyIV/H.0H# =_./dǹӜ8yN8h]an+sq]Al *D.RkC)osa}\ @5a)=ZVA4#e3"T!] M΃m魰w8(g b9 ޺ P2]''D (gMe*Z+@w+ga4`և/dSb^c-MkkFo#תCäF_ЦPm7m}frƊew N;XM}Sj {BW,C5hJ\/:Q.^rfE\H4=oJp`|#ח#ܪJCj`@W0𲏢N8*x~|Nz`1|ajrnǮXq%fo4A.v3i;STPf+fcKHRsJ7q) qKBi{ćJF8 i ~؉F}ډV"5(9) dhN%z,SoͰ!9?lfm,PfgcQڒ 2N5P1a zi 0 P}8$郞[c)? E#iORD9$Zirjň`؍4$; D^*]j ;%Sh)~':j o{ڊ "([^cVRRե*F;`b}+L@ ͔=kviF.݊ EJǒypg4~A lQqsn=<:(NE gӔ{M(l)qw24kX-mb74i9ډ}t=`9Z <xQK?+U<ꮙXdr )ӼD4@m"{0R5qR _l9r A@x?T٭ǵRsbS\_*KtE~ݚQ b^L)F4)膪]uu}XLFM;ȉ0UuwcܦOqIM#d<%V!=cR/Xg'r6oTBTi sK ΈlFػ^NIm˹attSսu\C[1Jq>L&~(+ieﮥ yUjn!`" ܨpYVH_{9{C;s̙;p|b0*2xmU @'F&$}jכhJJ(|m uQ_<݃N2Ϛ$ht㸒t poW= FOv7z)f6pL߂ZH͢=V%pn40'YҰTf~R_ ;/ D2X$7?LgdCu/Լ{I[V)a'\ϟo,^օ~jL.ԻTuȻuHs_A)VޛʯSyoN2w`_r|ӟ&wJŁuvR>'lc%NBVQʼn?"׽N^: U2Zޖ~ ٣6&X{UÁOB= U ^DdIe8{K4:ϹXm}?Oh.uVjF>;O#? + 7'WG݀wUzeBO( ض9SrOyf{爣2*G"2 W==J{7pS#j! Z((.xB1Cw`5 @@h6KԀ-pP\E1m2kKqz'jؽ{)4tӠ Tc%`6vy Low>̨:('íؔ+,zY*c[Rk껿t6 k ڍpq,z(50~VsKPл?T%P'QX|g.wϪa*(Y|!-hŊR<:t2k;z7/Fֶv]\R\-! Qw_U$65 2 \wE\ z&괝~nʧJ.ZIe!id[g5G"<>h_Kwr(^Nů 3:}ig}e"ˣ3^Qrdށ17Ӟ(K/!a!r8\8;EFRNȷu߬G < 0 8^k  ~K۬8qm_.G9&hǓf>po!p:Է ׾i6}bҭO 7"m>׹}Y3:E +B5BS b6e@cP+Ug.$/bل%=UʵtJ(OaG+ϡu N?2Ni_"¬0!nHyiZavR~ bʌTJExxMHKNMyklG2ia^kߎ\Qc "o)_0 =d(n%e]<6ؓs!(wߺyˢbꩇtH=b:K1gpcCvL ߔI>&!tIW`1gϧv!=Ãi%HzZ#d;L6|'[H,icw\=-y8r Vβ4Fjxn;u P &32JD XgCgzÍ|Is%Vj0WR\f`G3N9Cn= 6nfͷFӛh]MbUE)k\ nkQӅN闞GXQɊg +|=߶p4Օ>#R#B/NeU?gZ VV{;"Li,;#žd@m&%G,<'QH7hfvs GWݘN6f!Ro- q~ &BQL/Rk+!cGz ,WhIE뷋y›'6qF%=&Ֆf(!-W-2.<Ȱa]xPMcHBt67M'+ž;+&\xAA@U5bNpyP1qآ\#ӵFޑ F&鵹,,]:v{Z_yfhH6I+cҒbjiU:H  ׺{t C.i`ogTUy8L. 3- <"XI(;hO3Sả(n>8}^_r'sϭlV!?(tgplV`Tt V^L DnJTiKǃy %O t6I84W~qiY`1z"PTN M|ulTY9Kf24@˸IՅ/6ϙ@<}![국u*`V% 1SXǍz\o_mM,>&1ʹhR:cS(FﺍaMT@S<ZGY~g9KzĊϩg] *,]IhO]ƟTgh 7Lf/j= JͯSo5LÁ:MY7,Cr|K Uz;n:/ꭽ5oVҦQVǣ 9"꽵֏+i~SJ1H ni#y9Y2ZzW0\Qq[:tv#iNjwTުI.bShԲ\5\Q\=0$ VKQVǶ:ޥSۣ6^R=zw7a eRb5Q?IQBND(*hݕ,#rKJC1B~'pc<O6}KjfC2> | 6ϭ !;.G>=`{֬-5K6^6j#i֬mO6>x~/ezm%7 {:K0.#H. 2ю iXݻ:=n=( mb)]w|@oFh4.#yU(Od]O-hVZOP.敌ciTrT-CBWuLNB3Foj*z!7,tI[M47I7fœX nOh4\͐.ٷҲ9gתV]lSdxzkqIaĞ92/fNXdŃr#DF̛#̦'iVS5Ö$obL=>OIZ-DBXu@qЈf~fM4zn{!R}v/{<%F"g-"i1f7hsRo)T\kbˠ~Ԍ FS uʼJ&B3aH(!Mx]sW(~"?d0A̠2L lsll.; RU)U2k~8GB3ÍA&x: ܽ߹3+%N[H;^{ޗ[<ďҁqʼn`6 ,ٞ 7oh+ 7sׯ|rݻuW>~fŻŭ}Ox|ٵ;0A4K< z^~0a7S_ = > ߅XӖߏN7g~;?p@Oy;1~{? aS':xV.f7z_Iwٍ#xv0l&5az'ltV߇:qAeAr]=J^~6㤗'("\ ŭ/^M 0G_~yeaZ^qeoy589CGq2L/{r=d$ut>t#G0yNǟqŸay~ѣ]'o~<|юwSo}cChS 4vn?Ád]?y {?.z7^tO_zwڄn^ca<(=v=xT~9 n̦$"_bܰ8Ͼ>a,`)ښΖeGmXl_exa\Q:r;z̐?=fgۣ_Gۀ1o/9`X :_C=D@m;-ʨ,~Og'! A8|>8zVfwųFs{lx}D}>w)C>N{ ZL eq|86Oֈ ã=D8zx#næo%#~B4!֞<уzy[q{ C0eԜ٥=`Ug*XPGAČ7)O8t36QExRYkm(%]c # =ҟyg#&}ȮF{'(Oz4ڏ1ǸS<$׆KD"-mo`p$(i$/V$/xӹ_ouK =/ L 8A] S <f178wΦ W$ؑeu-,dPK`p2ҡ'|/=k .)4/7폣X\5S)Єml,[d5fOo%6))yz~ ɄXSAiIK65/jLU^d47{=&G,3}K*F d ;D߃gw{Owl8uy8zX;e !>/@GSbsrUf~\3QejA 6힉C;PKpĞILz&|R!C:7gT3 7/g-6"!.- j[_޲[0p?}y0K]2!xE9c FIG`?5mY2 +\C$Ӎ.pHD|yd6_s ^d2}).toR[F:|L!34ƑIU@p=S\:A:|vŽ(Z⃵Ȩ,YB"9ْnf>V8 +#|{f:?  =mRn<؝9 ۑa4pP@0"p 6D!e$ĵڈW@729x:6Ɍge0)Z"aYR,٩z@wCIӔ J+M<2dgRYS`T޺n$fg=߅u@W~Q7g1%EW7k.y-Iw:`E)%Zp/g  u&2Ss Mw cR)I=}|Aցf@C)ay hګ 'yD=<cݩvWYv 6?'ː(`>ܴytl{ҽ<֐Cfr,?)zT~Pb?  sC*= _?@=@ =O&x\lK1h,Po5Fa1AR}A6b:j'VПeKt-1VśA;G9J0nx1Ύ{0hg ]d(UcpGU~ϰMo Wxg{! F?8? 倪edzt 1G gܷuwK~kXDV%C|B4q&FS?˓"ґdoQS ez EQkYEL)Mh Ai2V OzDo%WL&='<˳cjHO(+SjctrjඖʹϭU^?:(Wh#$ m;LTQD s,&yC#H;z R-0)]"O]{a:[L%Y0I<Q%[~5f&Ba ,IdFx7!% ;^IX^y.Iק>uNϿz<5<HJ^¬jN;Edvh;?jLpOrA"}J_-Px+>K*m\Tk\(}/.5xla,X.Viliv[F?77Ϯz0Φ)?bWWMm5̾XvkՊ].ƿ7!S1}GJ7F ޳RYe[D"rP`deY7p:ֲ az vY^7!.B2m%Y<ec(TR KHl)?Y8o.'E 94#\ea.(4XN 8\* *X.~`YfτRn> C|5Tr`xYd~wpBA2 Ec 'ɺy.+cpJ0+#&<'gc0]d{(#EKʔ{ 0*%n; "vf*=!Q8i~zhFS$XRFI g8f4G Ջ7d >)Lë=2~IqΟ( 2&}c3q btvX4(c> wgue iE!9|t&zVkT-*.o YCF]bZ`!U8JH\ p Ȟ`% w!x=0vݽS҈2<#TK'cwdjtԆ`xjSh"Q5$mpRṋs^RUEpzc'hp7#YY$ūDuL57DG B;$os:]::e+ʟ?PMӻ-a{|#<lR)q@[OR;zJ8pD*DZa1]WLbSsXNȮ,u.iysayX+Ln X#'e$S%[Htp/e #axc/%o!U\2Y8a{i%>vvEy'V$F"K[%d0ƐqvrOFBSR/GȻh\}o=(A$6ua>TNd%3Or"SCo EvuITپBiJ5ڂQ (!o^<ȇZ?pFHx-C&GoCݢ\e /!4>9\ <gSJrJ]r?J&o1wLWa+hѯۢ n0;ַ5=<:Ut2>$7 01F'AԁU krq@Wz[i{FtC VXrRNwa ^oBLxߒOp;ksa8CG5Ge ]C`QK*VEI!OS&8[M49q5tTmNwӮv*`߼U|–pgD.5䈇|oO$@nY ɓ~'ӂ< KqO3 _{R~õ.͋cǁwF8F D`\̋DGЉѳp|htjbWYZ:6UXO~odg= +@'Z-g$ @嬡J);P r9딂ⓈMd RqOrUϨW,acX xQbxu= } s@tt$B?ge 21m=i X;U[˴,fWƬٖUx0N ubϞvbW?m P8#E`[H!7A`h>XZ"J\ T'LuPջׯu "+Nޞr̋Hs+͂!s[ϯ)R-S%< @uӸN=Ɠ%)Eq]NaZ_5zA7`´g%Ґ;#);/>Q+J z 5/R~pCMqMt6ٞM;1>)6BpY}j\XsTMζDϷtu{nOKITXom;GXӐ-p_HziQɎ:urM`Ý:j4(,6UGx}~l.U 8H߭?eQS>ףp-4CCU<9z,'jnsT/~N MH-kHjF:޽]7lۢ hGEbF;F ݴK6ho@T!AMD;)\t*"wMCLRnDl>8_ Ɲ7jza]C9M^t~J^ yNq h b tA4zxVvI}NPkPT"=N)ًQS4 ͺZܹ7>1f(TEwyTuR̔s$,G]9l'i'O}q_@C̶4&}qiEdښY5Xp%fGIO6/_Ƹ8*Ct/0;gh"౨aJ܏U䱶X>:J0ReZZ5jh5 ?(z Jr mnBdrưgLo st`z*OYXJfٝŃk|{X^pyfe2C=ٶ@=lBSأDI~hgEQI-nbFhTYzwf5jNb!bAԉ8_+AEJA&Ж0#r贝Ğ%j54`Tt4Bڄ,F.m'?j,yBB9u1{4fL|pT cUJy[/0Ҁ^T|ף,DBd>;;! ~쀭na,95}vmRSRtǡ_\l+ ~pEZXNBK3 uktIMl%VmJB?`璈)¸UZ(5GTv_2ݜidXӪsnM VqH] 4c5s@QJz L3^|H2`t]z/V۶H vgȑ>nr{BSF2dٝ;b-\tBt>w=dG(IQ#MLv<7V@uCLߩ ؈n:= y`M,mQnGx _-ִb56 ׼86"2!+B ^#޼Lj`E!ݳ2Wȁx : ٠KN=e W]5;c iDAז2b'^u0zS qH'jUn7R+7q0k7`V`?n i\v;d/ixnWq.|l&Y_Jg1 kNSؿ! UyI3\ms-(u.vGF(կVL"b$ݭG+'-KZ賥gŊTʋl3N62if "YPb3BjG"h-nQ%-nlGy. b"ޖmZUGq fAPN׼2S_2!,p=?'60cU[LCW7P+CSah@d01t%&o$X/0/r :L|=og Hi$ZBe[ N\\OpSqWo,);0(r͹5u*1i7`h57H?.P6Cm32ӌ&L{a'W{ȝd+W oeTlA=s֪m|*IK:h%F p}c~`$U(< QPn.&i:?L2D=d[[h|Zb5-bظ('ЇR !z!)zD(NzLJLÔo ǑvNhC'D]i0Sp("D_$P tV>Ó&ì64ڮ`yړL;]2NWݜc4{G}t)T>xg :P W$~I3F[^)4+[D8&@icP%~?W??˚m$] ЋFKJO ֙)=v>B z%hjpj+&!'MXPl D5A9|4Ku |=|l\9ع̂ 93U<"&ˊB@p{*K.419 E<˃鹔6J *Єbb3yr@4n?sDp'(q3 Ő$Ç缡o<͏t4 i8fI)ioY-&jəA4BNcV3]J/F1+ 4!ksB@=ȇ9n?eI.#GӤWLwNsȇZ.N [woqUwׂ r'rJdXt!_nenk šh%Y̎&>YK8i=k |8?0$хk D)Øw : @$ 1y8z@wIP3^ftCU JZ߿AD%]}>ǑHL )iD[ۺs2{EϚGxq;b{Dr Mܣd7T(b2l^%륵0f-t +%:,Zd@uh:Z*CaFˁrbLՈwi0Sܜ=÷YDw%hjl4nV씿4LB:܊ J3t)p2$ѯn^亂!@z4 o j7 lO)0B.,5ςK7${Y:Sk1-w} ~1BK FuDKB $E [gi|c ?b/xEsyyoW P I8klqRdUx_@Bx2Vm)5Q? SgA`ƴaR:xy~%|=diP0[MehL*`@rJ F~qe?QDYB?5{Olз3Q j[z*E! G;nisGWkDק(K>[iG?p_ קU_x泫DV0fW)8H#|iD rRxENRDǵm䅢%j "3'Q8C2Oc]TA'A,09y ^ 4z%ť IxRVJfalPK`B̼)2@mਣO MpV+Wۖ~nI~ ފ|;g/nZ>h>ۢD _4f2!:Tw=}$7@ ')Vx3 H6< ]YΗ`)g3- 3ho^b?bv[E(ۅ"`RE9{AcM@3K gUo<X*8R4|iRi{[JE>o+W`3+7[mء(Ll#4<31gPEhI;$ -Fy/N$1hBE$2@mc2vəc>"sZZD RFszs[cv";RHD: c:T)FuK$OsxQaunz3ӓv?U8ݸ2ku5 x߇/:B}ʂxLj>ٚE(;oY@245ۚ]uM+)'K2b?~+)}[d]ho=&%wyD"ҡ(0nߌzڛ5~3;#=H\8A 8N;y1@$Cg\KQ)a c5WZasZ]9νL0A QCf@ ڲ*gaDt3Yʽ~'hR㯭݌d&;v͐L-\_62oZjK!Mwq@F}&qL0hBBU *ԘAWØ١=|IK2 Tb'ʄ`AJfƮV/I6| +T{>hs7EX v/)YAx"{:d1-x0j?VU. wcbڲI@HMZQ2 암>* Z!^]Mk)mӭ)%dZ^-E ׋))y1gSqԥiI)&LrX}dF-D^qC鰈AŇJPbkL<\-b#FMFw[IC_Ν/yr.:V u vXT+ s<xEmUT099EzݗBAp5N&zkuPbMbȊk%5 s+]˔~70| `}4ɒW; .*j)P j!^cs.tQw!ytzF1V|?UʣrHqRsz%:Q%Us@c'&?-dyD[im@ǟq:K%u [nL>GJs"8.U( &,3|^Ϝ`EQ%D (ci:1l&݊V')H3OMq7m]}ߋKz"~A?7x  qZ {G/`BRe,eRqio=e 8TfNu,fQ-ޓ<20> Gٖl־a-;ӓ=ɡfΡMD2R9"+0C?sB!VBr*ϛnQakklK QdV pTCƾ&K%B`\mP;=덥b}5&RBL_CW͵:{- '?=&{-lBS.=Q4WxGUzT@]H-b| ?R˄:)>m/xZ4_* f0S?U`%yip5bM1834 xK >&Ԇz.eΚ2 gezڷ 3ʃu{d /<84|ږܶ0 t0.}2Wff6F`}4-a.{/a?(W濜WWjA<_eb( KRܺgyRnJDLaoBN1*"Ž:>xs*KZck6@7U/@C {"z̾5ݵ$zu_<0x/JUµy;fCj[~B$-kۮu,!xv]-5܈q^`#ƛG9/.%=C(dXrV7/aו P{a.FT=Cqwc|Nuj5[T !-^ i`u1YgGv ىXp@Q35@$t\krȇVn޽s_K V;u$$fZv9e ȥVvY3Ѻ -W'ҁ7]E^YJ0kfɦHW$ýzY2͎ng5XY)̐C4#kw,k"X]*~|Oꙏُ@]}r] 9lUqEp_ Xy587Ƒ38HJHnKKOԸ3{^P>ST^HecYQ$@'t]ث/t:Ek Fa~1eHVs wK|U3hy mzQ/( $?U ]oYV* 0hKD݄7^XqG81ڟDk6%KDEW{`Cѧ*m\()ܾ !ZBKJziljٖq?+YieѸj͙cEZU9D|xe:HUM DEuqя=sK ͈M!xd\0H8=oUSqO<}"S mw}srGt2CE-O(&뛎Su|ki_FL} .;ֵjI:y$mI$b;B:oǗ?gli}VRսON=SMʕL$j ] Uxb +?0zy3m$vS74=3in@AA\w61I0\W dVY훡 ߙIB56uAon%q/f 9tr~z\sa 6Xu^;WƒkmsiGΧ>w[Vǧn^0е Gj5ݢe"|Q d2 8/i⫝̸6P=a8aZE"ݢR4X/ߒ/xى%0^c&? Ik~\'I-PU ̅xXk B6twX8dQ~-9&r߹!J$dʸQrKYpVUSSnZɉĽ8)MXɢl.4V?Zg^'T)at,'Ip=@PW wݶsq쫏0AV c %1I0}ݰzE@$ZM0dQ 0Påt(s)  pjdJ0RØ8,:5qO\ԤV$,efgSQTB2dX*$pl]u?xaKZI9΀+EC6ACO2Ca?e׼nbw4r{Lm>$'ۓqoh̩=^AQ_h'ܹ2J¡ϸN)qra9,\8TEή8aچ"/o`g१b*!P Az*n RqW3\kW Y@So(_kf)8A\(̭n6 cK^Pˮsr&tE<*(z ފfI Qh9_C1bS<>% "K-ۺ@dZa2R_2Fv| p͟= f8}Pxl`buX#J#]*hU?;9+pO-,pB:?]i-a1)sy7PL,kPoøY{[JtC!Opڔqa6J@6\X*hJF`0O.۩;]2XfPR1_|ڴuNׁ+!2MP.r"U-9/ %e-|J U_MFˋ6 n RLd4CdS "yh~eg!H󗴁tA[i"%2`2\抛M[{sI28< c]lRJS,n馭qN `*@m 풡JI v2iz >7U8mӜ P@zQ뱁Y*;U3q̡KjrFDt,w|h7YR2-]pBYZdhKis$-؉" dcio2BV%Oa\ y:v?e ze(|S\E| 8Rq h wFdNb'1~351umT<}aŞe,/uDD$ Ǿ/p) < yW:Յ E"R}Tt~osm ,}TL4.bE2%*7{3;N>k$|Q9wyR&Dי{0˘p`l+m6i,,b KU wy))h4qP+X(!bJxĈ \ZuAxcw,Z 6=:LZq}AM9jLWP/ٕdNC?O.׍]'|f}OmDw,sd,XrNNøXqzwGwzl QN멟Ni_ \%W[`k`xDe"py|O+($-ΊCSXmvà8ϼԿ' &~J-j xkaz^@3onB_'⵵_| gz][i~B]?y⍣E8K9!yUl/9v(t]~FGQ@*xaא}m/\ ;x}fs5~ SݰF"ku$7Yke1P+`2 ;uǩZ`ҸQGB>#4YN:^ѱbQBpCҩل/L%4ǻ[sDJ>MҴ+}LrNE,7Ǔ/B[G2$'/D&KZw0ӣ{t_֟‰~%5#)ki?}?J˘񱥿O~SG=5}o#]1?q uwFe*Xv]H _ɳ)̈Y͉O1 @1Tn|x Қ8 "]=L #ٲBy-4+ےW^1cA$P .D'mUe~ t0|OZ[6.(^$L{uLB^3xGeMx+ׯ~yƝeI~Əa ʸ&K8Z sxtY7Icg5-߽q -͌WḵׄF' 0]; ZA3 u:U'-?<-$& FKHkqBZx|XNGMf@}9tTJ}l|[ONOӟ,켋[MۓAo-^ح5nM[uxY4BZhQ~4Bz[YC`t:Yy9hqF|,bqXQ@eA3&vp2^0~͡m hطJ3vC I%qK̶]Q3# 2RĴo-:9T,iL&@_|+-f8)YO7-nb ( `6YW~^?pLf;⭅@qP?=-EjaIWHuGH?8a=^ǻ5j.FG^r%˩l0UZΚϧN"+l,03Gb'<4܊k|cLY4}@]ޠ:MlNT5޸w #Yoi[O(_AE V mGwrH&t8=-x%a`lo#\՚^|΄m*y}/ nX6 v(ZA|\б!~br|&;>s:=cC[nNW%֛Fe }OŒY& PDbYET@r} 1{ߕq8|E@i(l@zd'lfBtc2K:[0$I|)CD{QL9}7ƭKڵ`~g@XDAV'_,I-n)PZu(SDIiM 09%}.T^PM1!\Wx%U%T5ԜWϠLrRtFR WQ͓$j7ĈBuTh%Îk7%)/.^U9]P2 B%a%n}࿿ux󂣅d -\̓lK&-x%-ΗݯON="O]졹cէuAk.>aqb\mSʛ\5NsԽImiqe`؇]xsHfpMxںEr6Q23bG?u҅yԃOW`G#߱M?敖P!]gs485Wk- ys9\\Si$~ĵ$ߺu |(d ť̗9iVxY(։0beȎLD,f&Mi[ϱc2ep @Gx8+2) A'͂^Bz@n;01$1wBʵ :gpȱGҦbx_2MGd>E:+۱wvљ8M{A2 }w*+5vkFb] Klh&VkRRIڇSQ#.r-~"1|ALPo'YOz )l$!3͸K>" y5[\@#V(ZDὩ IDJ [VΤՕ/ 9\P`U>艈N1a}]y[f`5;K%DS,7yoǥK%a(<՞|QfFנJgԋ\Vkte + po8A1 k._xy,/{ԛ~FL'C,e"0ʑ 1 U X. RƂJʘ%k<9w>PI4E!wl,.bo8bUYS…G { EWs s 5f Kz,s҄(SiBx!:m./b芀 ¬/rz=dhhE޲=yEe 7T4,E&4my6AFZq!Sc>'O7`5wN!}N-W $ tp;7Xl'2P&oQqOޝK]> G:C@<5^m-(L75Ps+w,H6f4L vΕ/cBG2O^_")p o\c׼D`GKu1P )t!gd((zrV$߉JA;UPf bQβ C w®Dk_yC쯖#YO].HW ._m[N%:ӵ "9Á 5S[+}h2m`tenYҼQh2Zqp_"-]*: _Чl9>.w)I! ܊eVavS)x/n~!,Y"8t%KR4QE!֞֕A|G]vb$e{LQ1 5`C%ga:@s(=2i4KJ>iV {ty!':KUŔyy?Q  1srPi)LȵpRϕ;}rvWKJN?QIJw Ryڝjb?np,(U@gaZ7fq*zZgС5 3 D쨅&Gئ'~, $rLLgfI—&@!9#} *0jeM 0:G*5yET8CSl(嘖Q J+%`fӧ0oh{Ee^uIoj8%Ӯ}#J2FBTі+OCC:)*ssZJ+*0#.ůƫRt1\F''jA)i4 nAŊ2%#E~^JQs8:UU*! t@~cFVڶ@Z;BPRDHX e}B @ PƨZ&ƵM 1Ѳi@nJ ̩ mynȳ+AlFJS%pERM ʶ *yAzᾉw ܁ d;d!d~XŸf)c34޶= cRIϥGU|lR~ٻ ;ӽ Ӓp[Df6j66ȏ-asn$ W}ډ10LN$MZBEw[o5ư>XACǤ6qlyD "R%Մe~:Dވ0k%t8KT>,V& Q]p5[`J/B' ;ƐE[3q8_P֓%}rc||o>'}:¨o⼅BÍ/4|~nv?cFlfVmD}8qGWWߧ6 ru< N&HN{(^ /Y0> jK5J$!p/<NbA7(̌Ư6/Z) O.'eǿ9AN]qK lbIл KӐz (~_97qVi [*k7v:2!O3F:ǟP=BtaV3E_fďz4~4SD]JoHsPO dd[[t[ ‚x(urd.$3z<D0sC<0 z[\*QQZ*DlYҬ͝HGŐ)>T [cZ!TSPLJԝ#>+ĉR>TՋphIx_W: PMUk(@i5D|K jrM#͙]XTPcMJ(11gIsdf~%rbfI zc%QWUm칅~:[cCѓ,mVyƕ7r˞ cv`yq"͉D'ٷЛ}+"82Kr(/N?tfxq[Xr2MS1Xg9zٱ33uir9M_RZh$ө_W?DRYm  Sޣ~-oS 90pB[NX+ya`IH&Pܽ'ښ 7\f9~#^ij? 3< p3w?+{ /ѣDo;^sD2ˢB=.ֿAyڇC PNMzq_S{XʬovS]Bwn YY)/i@Lƒ'Ȩ}; ֍`˺x~"X% 4gj (nA G~Bhژ .Vcu"~fsJY%gh֟t14:"  L`8 4F즬,E+J1A>H2o?YƏӧ?pcqFbQ:Ir x X,OTIy7䴥MeV߁HPE 8CqƐJyauaqٔ:hH&7$&lH7Ϲڬ5/iJw_æbPn?/5T@O=8AZcz]PBhsϥ>BA/uSX J܆FȟsfCOFWc*+|L dalϫ{ rQq>'}aXᄋ>FokvSX-T{ܼSLyV!>ݸp BOH'w#vR-5Ⱔ 0"% P"z<m˚)/^)4;hv~ BodSy`1bqr!D[KWKTX U@c5` |ATQqm>=-5Bۣ WX8˺7 H,sV @ 6_lex籨)L87B?4-ჼ-´JgJ >2/.aZ$f;Me.ovqfQ\vge™ʥjv112BTHmU=a]ՂpU,bdx>C_؏ l!Lu3xUx1$5y~P 6 6=6Ķy%+h\,!/EMQlIϮ|~VÐ( O(w~QAhd5)Y!PωW>JKO4f HٰhF) Xpo 9f g}U?@}N)l C|g9;P /LPWHLIil(R84|pr2^]sW؆6IN<,kUҝ\:ƺ{gb ͊ZBu(P)>q^`.PZA4E]'GP ߪ o~:G#*-[LZO\[][XC:F0k^ibyCόI#Mv"d)6ZokWPp[ ͐ k3b;~"w;8_o4Iq n!B+(82u%_Dmp|&gFv|.+7ŵ.J8 [.VL:&H;eR]4`-H~ROiT g0lbg4>28K`z͒o}J6=#+\ i,zi>9s}7g,y?ny~1mKS4Dyv(;!ob"L4E(.@#Tތdog ؿ3dkPd4"Qoq'6`@s,$ 1M 2Dð:gIX1A5#>2ףp- 54ٛ= 7G_Wo荞 dGpA|@#r|@ 5> tWG. ] 8;sFa+D✡|u 5SyY;MOtIEьk?{@CT-8=y*7jzu,#lRG17#Ա66g*1G1V@ڝHץPtw.uvC+Clv,Rk0-2ރZk|{wjRT)‚A# I#O0oH|T&:#~%+cV*QÆ)5w9GHG+y/ fGqbz : 9359k_Մ=:Wa/DӄaQ|5CV5!w*h7=j0r >䳷-pwP \'z}TY=>fTLhn,gjx8idT0^B`vY씞~Gp;"̣" h}PPp&piRh]+ϵ,B7Ϩ'50[L3ct@y|ڏcZ"K1RXŶڎL7A8o~,9,;ՅPfקТ 14Z}UWjYMk92PiLj(˺C6z+| |O9v\11$ t*61ٷp&Th:TP۟CՃƻE&RiZE^ܽ^XKҾVr}2sKefz.›9{ 3l3ێۘİX/1d,&N׵יL5?S2hF^a9I>k2檪2u}*jmO25㘷eZŋ/A.M{on[@o?,G]R d"枟`9Ny7Kkef9/ԅq9A xG4sfM_NZ*U_t "^%z#7{.Kp4J8U$]Fr% K'XWmٓъ D|ʼ^3Vpo͏S>)g~3*P(4{,9J&?A+@9obǪW$m*9otpe*G,#K^eИ) ZlZ(+ QWQBn?=,TZGq(-wIP&$~'DsZ\EZPs!yrG|6qm%>*U 9CCq{Px|yDHbŗƢuz3j0m=<4ΖH#fX ҅yӫ+|6qxLQD0nʀݙ׊|O '^*:?hF/3nIU *~}x1<)!S#‚da!8z ^Jk%U"MWJpj?ta='mE:r420_k`T*Ra 恙$F-FL ]llBa JnlC26sŪJx HO}f _n|qpJo4~ꋨ9՝BeZ^( prBm~˾Tb >rMu,vډ5+F !8 M.K\8Z;: Ō*WTMjV\6 L,Ud-P!,%x"0>.0R}2+w?c􊋤]8R~QQ"R#l#S!m0-+MS  %TVM {C'1 l /?a?|mVc>Je,C(C!VM_V CIZ1ת8%7 s. 2T2l2]ʭA২3ҐDgVpQW íPyKEsbЀImr=OEGFPSlOCR} P%zI H|wJjr%|˫:T"BE%mDawм?TV_` obrB>8^jzẳPQo @^}#cc=]-ԁ^pݶX?-xR]O0}ﯸd$&@E$q#q> 6cZs#Ks=7c\i^[/bc,I~"To8ƧϔTb<`{oңZhj]P8`aIi-Iꐅ#(V_cQ Dz (0R?Do!ؑפМ~]B2T:YP$6jp ߵ}*'9MR&gX*Pn|"k6_pھI|# i!]njoDTxM 0Fg:7pHՊ8ĚhՈ7B}rR[1$SԪ3BU$Qa3%*0$^ 3O$%ֱe4<-y Tw4M#8yCl?H9 qhVccJ5BcLvxvuUN-.ϋKMM)ͭ J-,,JMq-K+)H$pg $xvI-./Pp+)KMM)ͭL,( ,Hu,(LN,rHM-IM-P06309xY[sۺ~ׯ@'͐j->i4QzߢV<$áHHBL^{w/>" `owAq.&gDRX$ hSTdHJ8q^\-}2$e `fJ_ek>S{!O>9&ZReItp)OYd"g,f 3hyRETo%IJiD5(3$T*;̠B?7&4LKh{R_JrF& qR ; |iP$D.F7-zY-YtHyBO{8ZKGg}!9xWS2ZP:kh|z:qWJ۞_m}W9ƪ3y7rCN)XtREq3z*c q>4Q@ix>/nFۦLq^A_(Ŀ\}ON:ӸA.@t^s.˷?WhMӅHpV42Jxa#+6DS8fLKN]YQy81Zk8_TSҲzbZ3 po \&EwoȊ &@$\1Rkd&l:=8+69lV\<*K"w3Ai,d4bQ*H21TDy7MD? xyHE,&M)$YC 7h'xD k?yK 5>sk($ y:>4L#91?N'х1Vjn-9DL{ELxf6m1Տ^\r=H 7-^xYoP( )_@ݐ j]H6&ՔUuI[4Q69׫sIBD-DGI!z]IdgjxSjɊ5 )ޅ.Sh̄>\闳؟\ǣ1=Xn@Nи,IKBJDJ]$XD4Ơ=iN[ŊA0e)$x#gXCqkqT 4u{}lC,'̈́wWPڴC"^0~ ]ZݍCFGM۵m;KP7t%\d>fGu:\ D/ͨXxQd3t. u$=o.ՇyaK}X{ i z[UAʎ@yAu=nŎ`{P7}9ѥ9 )#$fӈ*R` ڄ{ IGiS"O` _ݤJA7+ywVԑÒR//9IjzП{xD7Eyzˡnn&7GFQy{>?ܼG!c8t)R+2)۫{=lEwZp4}k%v宿x NM.SPrI-LNULI+LL-RP*I-. e)J\y)m\_ӶxV6^} G')}H2ƒ* m '>qxJJ?C5! <0Y8?H*<8iix%ژοyOŸL!m̞Kf H_~=ĜGQ7 aJ/)>S kw2YJG+Cc1%iQu65nҚ2)K^{m;{S§$ۿP'R7$ȸ(} (Dsk=Fd>rGdp W(>NPڿ`b.B#!e k{o_ Y[.)\2Gwy] Uww &=Gft죢Va{P|̼/>d[)SчOHjqN>UToU.pئ2^)p'ҝ|E;瓻!^дԎ[QJ] >V"pPRȐ86uτ=hFthGϦO+0 oPEPj^;ϬswgD'R1O9G8UDsw+_f|Ys5;ԇ؎dR6cڢrRq0.MiAC k ,U ɟe*E%%^bh<RIZ]tieRMkYYO/Зh.:윛*c%,&˳"4㘾.3].Mb^] {mt#~hH@+HIV YsDeQ=xObL951򾱴߆ɴIPZ7Zz'Zy 2qm2Cj4c:rx` je 9^ M1%{G}XC ?CojG]s6xAe<>':ءo}V6"uInz<;ו[{Em渏abQb~u;%DI(' 0DS)1pw&RF"k}Y^FvPFW/24U F1J  o[enfTF'j',-hUە:"T"QTL8ӭiѾZ9E:8EHOBlU(5iXdz)5{e^AMq/xdUj3OkU1 "}V>?jWcS6|Й; sj5"2y ْ 0OD%1&'i\/s%_Zv7ת]=~c8G@m:NWj?ot֐hcn'=r7|"q35yA(hy{འAR;Sᇻ2e^Bs3Bi3=J,b4O_`MI-tXb]N@'^Wd-˧MIMquXpyK1+`{4O tdWe#ECA,yir'F^%BEwG29x$A*3'OZ<h}c 2tA5 | d˅xn2gaDSAɮ>!4}sX mf3͉m=$H3`|v|F)$\Zכ9vFq[ so-?ӸvYKoӧg0\2=kaQ "D^EqQY\Rg4tCt}M:C1s+'Ial4&t}lEP{Gek񝒙Õjc]Ι KQ4i$G'.ٷSxi6?vTgSjuҕ<{rXГ3-Mi4%-,uF.@g !`րCTZXG^m*.Le"urXR2+"\Lr ;8*KyHMD\Bw\Dt4s7QyMi/[_ם}h+6I]{Ƨ2l[~$ͽ[ċۍ*^-8לR 4ػ͢Jxqە #;HӍ*R\b#ȕ>ڠDG/VTq+Y:ڠnCbmGBȫM=r<3V(oTa,GZt(˶ Ca7+*xrxX}8#:aC^QCM,rB:(ϟwl]My>\ A׸tv<=NߦO!8\^́>iPbQ CO\jBpyՋIWfYOf)0z!紝`[]`7nrĭ0 i"۫!]ry4KKoP1l?` W5(b}_|3Tl뒼 NhIBHo %0HƬ/Y=˗zZMhr#Ҿ>RyNs_y|YR~C ZϣPfSG܈OXUQ$Mڑ;f'FL2_}IMC(5$^`%"%*(uOԄuHi;=ڋ]B^ĪCU\N[(+s{:G_z5)[ϣ 3Si_̜Oïg3,7;mw.Ģ,Rxy# ĻGܢ1m'M5 Jv0gtI0AԫڅJ˟y8A=}.xi$ObrG7vS4t a$ a9gcpBb Yށe;Mڇ]=޹pM'%GK3o.S`1Զ:^ڝsWOiq %j '.( ":=Lx[K}k5qwęx^XYu]l\E GbYYzBה%4:m?XFhz^XW3RMW:czhQ4Kێis8aN1fFi V6FVTSbWϟO1;+{5̤MT}J4KVCB}a^w'2zIϱix]yFtH?1IXeGX}JT|CpOwƒ3} w}?`ózRg7+fIUG#R"[W/"a( ߽~8p1$TSwda%҃:& |y9h)(HzZGQׂڣωifRH}ߝi\H&/䘐t}tKadjyzL4Y'\{C:#_o}5w)6ۖ~G+m(},[nX9593zJPwpEN.LWgR:^Nk#.c0f̡y'kfsm]Ga§PǾBWwﵺujE?م?qM=~"қ|\-82+EⅧ4ɼ qF 8ŀL gjF('&1aMhvW.{] 79BGMj!mNAUGVwIPJ Ka?;<'jmC:fu/$\&gi2 Z4OK?c` >"4I K[bt.'t}L~Q|Wd'>|v୼g>+BƹA% I(' t^HW8ǯL񢡽ȃOs9sroniCW]eFVHɏ]ګ~?#d-VN/nVYPϝkݳBǪ]\/";#̠ݴN(;>i %b7264RFG lN}a ǦGxb3QXpP4N qײMCnJ~Car'#yxa~w|§nMS#˯NlO*N~*_pm\^|DY>7 \Ծ)r]J! vܓdOt`$OF68AaFEȘGύ%b,F`0EՋPn/x´:hݭܯclf`B'j0ko)^A۝,aMKE>Ϝ/ʕO?DpwU΍]|AJ#{K+3 Ed+{RH^͕aiޝ<]iY1-z-RiNʨ )-Vy\P76͂|)NLI@1Ӂff,':0_B8FN({_cvkX= E.^sLtc,za)eenYwI=sU}$.dFv7ztk!oMT"Rऱg(1'ƶ!v7B]!HԷ'JUS75<s!/酪Rtpۍ{5=b%m"aR,0ޯ,< IEe[)wFy/y@RCq^ J=%WBkhУ<h d{h{[.L)POZn2%zdA#o>'=\Zhay"]d[+~~k/RB|]zS\pWi}FJ w]Ne4& +l^mLw*sɐQ+Fsef; ;b񈻌nDj}UT?ܺdUZ˟^Sޒj^ k:uq6ʖJP $ű>|G K_mdeu&WNlюcW<8ZOfxӈPֹ%Ta!te'21Mip "ސ5:!t Op bT!eu572^NnCjEsK-M3Dyxw㶲g"޽o *.'^ !yЌWKy/̭+F;Kg=/5>S7l{#M3Z!]pSpSe~R?@J&|MI;δc1o~B`i.-P0ZRii}iDռkCM }9v8wY ޭogv]R=ivq9^T!HugSvt5voP1ְ&AD`Lj }Q5 G_VR's嫊8t¿>^f^])~:\)cG5pRGR;dB}2g=,EQVu}edWL`aLFv\Urk.%.N[vm*3 wTNƷ~(y٥Ah[+5I{g4ۯ'epwIC_2[ /'bn=)72خ|{0TfMTäKeVcRu18h2͢EG#H8:qMEj|{ڽ/*/h$*MPLu;xND؁g88N)ɗon.^F4_| ?'O$Rp>Wr3e\:5سB3-q*Lsþ1I|+&Nfl# Qn7ѧUgfxmGIe#[id/?`wtS㐊2z: 4 J˶l uqF!}܃}fK 0--V:k&rYDZ֌ e?C,cYmKPҤA/zNʕ6N!)2[{k^>{´ֺ͎~1=1{asޢ#ȴM %( P Mx$sk֢bz.w< 4'X5  )hӼRbvSp+3?Yrr"aOXl+JE/.qiL.^ d-8Wdw^w}$;yt͓ITIL-C#v'>,|yBe2]kWq#UM]^)J&7˥LS.DcN%9A|e`gND!;KYɳH<t=k.I5#+ݾ.l8Z,* ynY+'+lDQaxJi6?@Xտ/kh1ǝ]XBI'1圊9{R 4QuvZCۨ/?}d:',фC.SeC-vj707T7LPDC`x?sĩ}Tm(~>O^{OsreWRI=׍=;y< :&5#Rz>yx<ɪ#5(HP6a4uv0lQs'{>Lԓ%VxMbi mJͶ]1RVos}ўa.K6]~ b Z!RJm|Nv=99=$ bA¼"#\V=XXWާJ&;zZN*)(WL921˕D H M<7o{=$W\pV2Y8k݌^ BN?hz5@%5rP̲l7Y雽ͤpW[7FKi@ǫ zUY2yNdNe"9uQ#N:&HKj`ɦwZ~od |@ {pw܈oz{,*{ü\XijNgd0u 2H כ5."cOu'y$i|Qt>Rh |YwwMS";"%gsS yo=74Ҁ2xBHxeSW/S;!sl،#ϸl]ȕCoG^$˟۰80(:qO?eD(.C ``[ DI ۷).*&)*.&'Bo",l9mGh#m7'!.6aGIZ#P " ޜ$f5Л4ӆ;e+d!V= i4!@t@( lG h;Ym`ANN6Il`آmAhtM 7':75_ ;7_*u7'rXh&r m!aT46[`2Y"| \WpA򟰿ľ&-B0[jvDڸʛ8&?8pK,Bl!(`!w0l=ܦb'vm2VD:oao $* ;!7-r$"e HC0 HC @@:nT*F HyY"')7@.xg*i(e8h@dAM0@yY 09RPFہQ஀2@@Z$@\d )G[@o@."HE@FC'.(Lb($Pi0V|@,P .$D`;@^$͎x@ 2O@:HF;69@@1jlroUPm(L&0@- !4)5 XGVQ@S$hg@(1z(`@ L Y墚 ~.P`?4>@P@Y`uـ0MN]z}i3euBWh ȺwX#FpYnrZMxaMt}f}vA( qp'<4^p ?Wj_@~9/n k#@nlȮYlKfe p'.vC p%E6~+l 0M/- FV6p[]  `  F ;`Y8 7 Yg ݰBر$3OAV͆ 6t fĵu :!0k m p Bʻ``p4+zaknZaCߴُ=HL ㇳ-v_?\6t~_O?Ś 84nȮ16ں~ 7 -V8Xw&?aG0!iu ?%l=S?☌1S6Cku-վ;6;3xudrBÑBktf +:˿vA a5|hkǡ5&6R?(E &;`Aa x^WH*v%~Uֱ8 UT9n?6xc(j׹0Gfw?ޘ8:E*9 qt_gS oS nCQ| `7-q#֎5Yô 3?b|ѨGζbwc3 .&~h^msH8벶֎B~C %op60,A֖֎]F ŗZ@8Th:O'kHXmsC2Rw_#@pa0v@"ń#p5;_rWX75*XB̗=r0 MYh[4mAn:Pkw+":ƌu[@ŵخ[FK_ ;~m@MCv_.N#)__>l h-B p/5#]W+D( >N&v+D,cW(Aa uSsɗ-_h 4]X  AwU&V v;VFjqf_{Zϲt O;}#s%U="OWߨQgZ'OO?-_YxZWDfEo<_asǵ]* ͑?=w3#ʅ֢+7VJ ~XN[ 'p:w Y#kM6vWϩ}xerǨEn~vЃiwcZ˨zjyozd)$%$DYm. AaHĖ/H?OS?OS?O?'v)¹xK3HM5Bc#s43S3C###SdS$C3˔4 d.U ɵxe8Y^] | _TZJS}n.JB&B%H*#su#qE#T)VZ]ZACUd}>!;3>|=gBa49^fU8<͟J/ʟ™UM)sUT*YGW{*Uv8c;v&770/p'h='b8rU]T*]U*Bi«~]e0H ǃ5I+(w[e5 #&W`[ey!8 &I1^5QT¬$G04P,P} 3:>QhThq.glf ca!Pm2VEq *57 8T?fa&㴂3*;2t0 0դ&5VkdQIKsfIOr1v-Ʊ:hM̵NhLЭ#q<([D)n.3}"v {IZI(@9LNhqzz10B A+zhHԉ`r  YY &wʀ`@ h 4 *Np,쀮$c`0` dy4+ lt`ּ:ZI 1,!4""p\Tƨt1W5g+KӣjA`f\60 % x)rq^vR5Za$ƄVQRvqXdSz"p`ݪP{$,&F(LzsWDqLYv$-Mff'(Pr\K@Tyaq bYPK0 FTbM GzJecT|xfEaR Y T\#(+i|WZiRqyx*W<WOO_n**JF*|ۍbCT5"SfK ]>JPxt_Nq|72$@&dorM7zL[4/aj4 ACl{gfs1%T2Xh6`y(F8) ]8JM$c&-uBfT>x=(D;D@V[)J+tF1bۑ; [:1$f1ZAQ~Ĝayp/-]f`x9k6kACU >R wx\3J| I'9,GIvm.qFuW~{Ϣlٙ.mwʽ7#,[r)ao *<#kv%nyGuCg,3V}[9`6Gpޛ`D䯾Xtf{%wk?t5=sci797O2py$dua}^traE?朙>1#瞒Nzu[{KsuTXSAI?dբ9:Ǯ%|< (<ULM{_nUgTLWF7̤Fts^W|_IfGj71n1Z.L͹zaOw!Χ[>>޶nS[׮=yJXf1׍K4Pn{8skw5q@^x}sN ޗfXK ^ ]׭7sDZYT.,faQt{uS@J~fW;瘙R~1 =ocL[}PQO֝OY0.^vvHaMld#ՠvvˮD2cMa{޷qͽ=~zgؕ_ȼKjN.g}l w8ߞd>?Ս(DFx3o찉㋓L}yn}DNtaMb=xV<;pq8Y(R`٫>[Q[zu'}_`7_ͿyBΐ艟jT>sG$ݜ$1pꋊp_Æo(ߝ}2~lX]eڛjWXoA|/d??\ikχF7=}9i};8ܺuTȤ&0tURӌ~iNCZV=ΐ߬ oZE?q!ю bk8~r?/d^yO?w;P2pe]8& ņLw||=qɼw/"=FJ .D{9 jхdvʑnIU~99gpM[_ЪǓ=wVm?0s)Y:k|ZJocln}|=j̮?R#Y+69;wԔ?5I? MѭۏNyn |ݱo`_n4==7ynݗz5{Ն)[㝼mSú'7(F)/2w]Jʣ+aK[oo׮drjǍ?eD}[1}/88^ ԟ>Թ4g/U2Z+ߥg{M8kʻ޾ҭ֏ݔ~.)ٜN7 |0z=?vQ;7~1<4u{0ғV'uo9Vuqt^g)VjW~1Dܧ |MI4hO a,MQc<ԓ])uryLڞ y/a[]`а>=\A'oV=/[7Our`U{նiϜx'6PvQu7~33<>dmWs-#`WO8ylK|wsΦ&sNF s4=(?%V񖶮;wzbvI6bZ`/}fkw=oԣq|$tIڳN?Zϥ[向'NP|^N]phO<.=qɻ3Q`nƢF8pЄ)Yӯ6̪dϘڮQӂ{KF9q??'lvk=YjލV>_9x%^|6?qo si߬p,Cp X\ ]ܝK^V{3S[9u<iqx|}痘5H=vqClMDP nd)tUMOkU{al4ޤ4*ӸcyrbpSTԭ?Zu*ó D >-T9 17>C:(3P2 ԓ`=*)!l VIu8R(YAK3iy: VB0lP7ҼgWق=hg YN$|)=:+]l ($0at jW9ԏ li}#Y`ۗR:Nr^x?7SO7"kV )ڐP ,f2V/%2Zp4 siivDTxLyP5_F'RRVMV̢O+h<ѩhmOaW`pJJ/N> hXgo8D/ca"m1U MĖlcPt;X';W  i"#aw<$?#{RCmG(:GC҃Yt|#r)ձ bv'<={ }WGX^SXHx:Sܹ2elp=:TL׋\8]i+d\2cGWd߰-qT}@]'aKO `z3V_{-zV|"^3ʆ|4`ߤ}!Ӛzi,4KT1Tdluv?\aGTLm!cz(ꁃQ%!ZO;gi~0?n (Ey,PZ iW+R#~|@rPFq*~\?q׽ Sþ#gzH3)΂}R/D+,sD|#F ,p2.F%Գc$J' 0D%g5jk~Cq{եhP*X$ ˳`ʔmQ5ֹR^v^Tljm;KUr0K ~)!Lp\K9O#d#"tmU-h{&“lV8 ۭ^7‹grPo^\|42|<)oG#+3-=q-Ul+'ձ@í l8jz/BAsАi}9_/y"XP`[ʟc#%jݯb.䉭lh}ɱ9K@pWE׊K+Zt#6/KΗF | jRXPqi1Ӣ~LQפGz}s{)jt)ix Ij?^ Jn _p\o^_XLNIssL1Ž$EHkEEpBDJY!+gPTK8~;ΧVc6Gʎc{P?:&iBO?DX/*ϨVqKVJ.)GEm>5R*_&~N Y}%l!8jޟ총6! H&jO~bwl}XݥV43hhSxW_wO2pwNtkX/DVߊ?3RpUX{16ЋIO*e+l8UYA0O^]{mVaO/g+EY'5u+ՇҾs\mUԕS% U4x\leѯ[ɠ]I< VW)Doʣ3p5/m,uˈ,@ ^ ǥ_xbD/"H܍1^ Pj;}϶Q_Z-5}r%[l^3zR"q&Dʼnޙ`>v0)4K>K$A_V˩g_J7ʭ⛓{G!Hb *: :9i (?\e@jb 9X]hoТ`J{̷&9^\ʦ8UIGwMF$ Cq3"#/d{ߏBXq1M5#x;.#(3YqۮXv`Q\3B&+Cĭ)_d{R70l4[p)6ajP젷J[ڣ';FDJ5k[htp*RU|fJrR*/ NYuodj/E8 ??Fj в۰=Rӌ}}A'2B}/ nF\ik޽yqmY!_<)ӽ}o|2|eW'92J ~;;AbH@h8JY 6~YIm63giXNE"Y.N' /d!UdcZDa@Ëaӑ"7˾88rH;U;g 9\3 q3FyYWK"m( yvqZA1ŧ݀_#|Bh B:Z#s(wc^n!op\M}B[2zҠE[.Pq8D_.00P{+*]0p')3@ H>䍠%.dh 'sAӋ5%qgO;}`  ݞ 8D_G6C/F~e҄˖Q1Yl FDf~{#x4 n*/S$ OE\@G(ѾJxrơnra@!kb1!r=ԍvICA[wǓ)JJ7K07%u 0$ÖTRN[xiU$Ug |U@gڴ< P3'QT!_) ||7j%ds3eYP@ pD뽡!y4?-6dsp$X{V%IP+$?Iz^E _`Q5R]53s aDw~^$ЭaDk%-QxA>8@0edy.o6Ӛ?Y6lkEgbjot ?*A]WC$sJ8 m&LR~Sbn1GM&s'^h'\*b'pYyLXy P慒*<;({JpC"zƭQ%ɀx sE(a!? Չ┮w.\I} 8oyYꝋ$8)9Hvtb;㋘!@I+ϼ,cnloHWVkoUm>|󭄠ˌI9x)#t'MT|&:nGb䌂PD`نH)jܶBɇ$t1s4qio6Fv uSY;6 T{guD˪04:-ߓM' /kd:e&=+xå9z3X#Y_V*߻ '2\UΛ>KASp% ʲ 2!?fmzYćXfUO8ep Btgl9rW"]ըq},YO+;sa(€Qm!Yjd =ZQ2D &K-s|rcQsV`2IV3m}+,l[A3(4 -Ш(:? xg(I(#K/9XHF[ihYGaH. ,.zh hfhw[++`F6TY1oi)%j 㷄9F.]2!@L)<(TBJv\"KrS w,:ݩ(JB.6/C!KuH#nBc!AOe^y)r׋_xXt#A\;Md -}z iNW7qq_(٪6 ʖ#@#(E'rr>_mPj6n`aqI~Us0؆ۜnߵ[S O*|ԝxRaIO GTumq v51"xVf2~{i;c3m#x0q( :\X5gsKS"Ta]5{if8T:lxjQ[̯*[+\ l&ڂGwQ˓Mts[E xviVu&-{n{;[ .PkP={l2-Jԣ]r ss& oI~ɗ>XyNu$_<OOA<6 hE]j4ȯ}ރ˽['~ DۡQ:u*"%҅N УauR|zOY7F x_Um gJL`TN.h%tVϾI?urn ( KMk/Ul/c_`YfbV&E:6>d8$h;ڦsbDy5e[șnꉆ1 7p m8xf LwvTK2SY!rWk+>bu]~uz0[v榷|y9SGвf{2Hcf_Wfd$,yB,=fx$9H_A$w}E)#n- ){#\?>N&v2[imXcxsj) rL8ȕD/mxLD@Kq@IMTקzMEeBONO.c = %h .;lࡄ e5eP06U'V,7 r٩qO +,_ħՀc [ZJٍeJNQX$e0hm8Vt2τi i"Y'&^LsZW4 r5ËV66;Gωh0mumi WGJs;;} ؗ:F1+U^/s[MDyxdk޸ؼ>D*.^g&D!OYQ_>}مNL#_7lr$҄Yֱ47*"[7R?8x.ԑw/I)H}T+IKMb|M#kD9GHC 5[M{~p} L+ELtFWC"ɵ}\9ynO_NN\@.c1`af4ZpXr3S 0! ??؂הÌ x;9jp?'?(7 P+3(k>a3}Ё宭6cՅq ̟0geI:lڿd^9@E)LTHr%LiQ #_ym>rǁo0sukR!~sa}ۣ,Ō;4HSn4lR_jjz!Ok_a2Ns5Rs*+695o=cvrT QA~[`FĀunIWήD"U{9ʁOjM@~fc-F' Gj\'\'#} ZZ{4dU_MIb5.֎ K_'f{x ! o!eƱa$)a3 sx6;^} 8U]Կg%2 `@뺸! 2)I%P2Co[:{s~{~k}ڂdx"'#))/+J$&%XG<-H/?Z%`TFJN" TWPYr$XFFR WnBPq€h(f]]O/)#'' oFm$du7Sfw""3q+{}k?*{WdqtlB cK_m=WmO$AA1,F72*(ҫFz-fXgn<ʶ)h-9< hrpQflpgGױWGjMϫLiM${. P_d9݄,py.MXw}Zyt\۫=8WDսZpx)%e#1 VfdK0..B0P0'$$TFt<;dnw=nҬAJ¿n8`Fܵ@lwsՑ~BYibf{Q {zS,ϿϛVwfS#6//3:[z٥NF}t.L`Umk ܾ7JK1W= z%wkSI"Nt#X_'gmuۭ29ccXG )B*yy#QZb}gw4D=;avaQC-_~es28<ȼ,'W"nꜺsUz$7+g`*GN\KES7>r۬yB^ʀ;Bs '[\YSS\L]$U ǍY.y 5^'io&S#pq^O x?Ȭscb|;ѠR dJ72_,vQu@#Xo%ӈޕ=ħ\`k}a>*zQvX0bLܑil(&IĿ2u@Y@zjIDaQOTkZĻ]ڒ&|d{#L']ׂ(*ءOz{_ 7{b'G~`Yq,瞷=O9٬y#JyQ-{mM|rEܩYZG<: ״?玞S/m8x6G/1{x1a·Tل^s>R{<0 V$\I1-^L!]Y)d.F~UO/x{.3jx5 jD4ona|0(1emSX5랈0eyIjm pp*&}|7XHEbx́SQۜ@y.{*f 6yNo6LFqAjƍ\&5P;o>"t),YerIݹG4ly~x4 kɌ{۽8:h߶C=K` 4n q Nmq{]ϜWOyPE̥mPz! yO7HbЋ[C)(wP urH;FNӢnntT=daqO6^kV Ӕ{ mĮE/;{'Mlr!Y9բI+oOJj\>݈ؽpw2$ϛWք;#;WY؟yyL4:0{(lqmg ; -LA1۫'vב &5.9H,iVSޮEW{ʽstyc5 ok*BOӒqv\v &I o)MEjDy= OJU>۔sgπE&K饷Rv^|qxƅtcnp4Ga|M̳Lb}Û8TDd,T {]{+4/BzR!BTqme:q<TsSGFEUly:ʍzs8&4j7-:q@34rnfˍ+:ʿ 1e00{r%vLFeY~͗ѷG1tK,x1 &nMaNvX6Š?z$q ~74} VvoTnf̴wѐaD$&oyrcI kJri />BÚuϦ , ֩v,vsܝ雥ZknB{k>m\8pSxT-\ؿnȬgڕ <֤sz~x!DUI\JcGڕTSLS2P\HiǮR2LC^19Wļ u3drrĜ857Z4|*mG =2"OveKTLfRcz!xiۨ^r~7R+)Ƥ":$HjvoTd3gk%VYqytPzp|0ݕT{kϚp|f`9נ\thMx =/-ICoL*dYrϪwk8gdevOrCDx;p~zOdl ޓu#HnN "".TL9%_`/|RWIOǮc/Ū=O%$WS$8O{D7OvYM`'L(UMwp;M#seJ.rx#E|O𽫣G?ʌR40;/𓾕c `8&;uHcQGy˽ a͠j)};G;qJ{/h<,pCoy@0gɛY:bg0 A/ s܂}PlslX@Һ[ONqd-O=x9F!U:_+1z{)˂rQpt_Dl'Jr Q/R{F$:uW *gnpA置ʰQMS4Â~ڌu&ouꘄsP8QR2&m٬eP󡷕G,=.{l,gq6x̣e~b!o G%b?O^pyFeI:%4ItZX6:W s[jZK+kxiΨ{Y5l)).xVqa(u.$JzyCS.=<[.J@IJ6U84wRDyZuu6[ZIrQ)q^qlcJxt&(0≫Wi$,Klk_izA !LR9cQYL39p<ٰIafㅇrᩋFli׷x:%,bM88R-䮐 $QUdӭ̩( @4L]qeg1fݛ(lyJ}\PهZh;f;])e:2.ڢݡ͚2{&xX rpm!2=S N|gfbH]ԙJKOb\=>Isakɏ>{Rr&GYcUCQ^#iqRrtPXc7tpa:3cKB8$77s,\.ڠފs޽y\9(<+MF/-\:f᜷Taєݖn<>48yx+ ;ېs%oU0^];oȥoMɓ ǎt=!2';: q,çWwe Sjg@d˗6" ε,yWˢv=޻BتdPQeh%CGD7JyХ;Ftvm}OӦ"C47UU'A~xXgNNn8IY@gwۘΚ蹏e4߱1VyȬ'p [wWtE]z6g{+3w:kOlݺqpgLilMNw9G\^퐺A?LOaVɲeK*4^ Y!aiNo@q+5un|΂[ 7u`>u#@J 9^DxKَ쎓?!Ӑ<3.ZzlD)3NwK?r',{u|{n@VBBv/mH8Zmi3%z\A.9X;B7d!`XsGYyG:4T8]3^v蟸.t BM%v7j@75L8_PZK tKxxvjfLC}]HbO=J4y'eB5Jn<^$[xjQBY.w ,.C= G7hހq~_:"i]E; wXA @}i-Q_/SWwC!M69'/e2dD8>~wLI۩? 6";~`PV[׭Z 714Ͱ K|:sέ؀C;twŪ'7q;ZhGL7Ծx&T鹨YK(zҷ}o8E o=_5Ew̖L?J6lc Hd +pa̻tJ) hJg)weG%SP^<Rڹ5ʶ%C&w.ӵk( lWS"͜dmO]gx( fz习yʐxYR\usW iVon)SȽc_imsJ-2C}'ra%ZX^a3, V[ SC0Fg~ŎNK?pYĊT2)e]qJlY\=ojc7&^SkL9 2PH4hͥijq.-/ClbDImF g%{-7,vޤO{v3i?wG!`HD.J8V75i%L:6&a7-xdL b9L9-O13(w5!-ӄ˦uN5M{r.9LyƝvS#9*IE7_6k;uoy ~>g|SwYw5 f9W'oƙ[  y:}VˬqsŏaYuڎf?{18L-ɓNޒ2>v'N z dc='|3AGw`}rAqjg0PX1+J گh8H.yӇl%}AưgU.xfoThqxS2 xK~>o#K %:5FmdZ;Ȇku7Iݦ.Vwygl9Ԋ{"t% ('(q3U.O>2Ǒ~5ea:Ř<m_JL>ONlxPk3}Z==|k}1o{S'o[Jw1zܛ7V x/Č0csʌۏt+iV?s-$~O{uRkrp;ǚ\QYVNbt>wEaC⋭ 34bW^vY|p>vtNuG?jG>EűʍLYHĂpX:, SlQUa 1~!;}s8i)W}Y NAFDu&ݞ+^eG$_p%C޺ F Q߆ln3㟪liM<"I'g^F'벿`^SgaY+OKE(I>~ӟ1vSa=*޴ZlO^Ccsl5s:DFf bC2Y}nro}HƜ_&{Jޤ\ЌDR߶0׽a(KEP-SsC61VoxѮY=B;o߿)SSBMW-=U4o&M]6=Lz'9?LW)(,(EgzPkJVE:撶9g:fPӵ{% w)+W;[^\SK1vW1샼υ]Ѯo3DT ^}X~=2p3;1RWw^W*̛Խtgj\uif߭\6NO%\m&44Dq^cŋ<.6STK}`Ug޵ʹ]Txh(1+ݭVzyBV4Ȕt&֘FJ1ff}}?)CC-h5Wߛu8g nGmXޤk`w!r'NL*TLDw ˜@G(h_=:FAIF ktIJisfQTޣ%7>'8Ge),ٗ.]~w?zoеo;.hG: }7n e`J+nt~k71ίOZf|R=I -+f(#BA\91=M:g)7v5cgWꀜ3!-| 0̽4.$*Ҋ!'Yj1goSvYCc$%$_^Gp. ,!m +0B$e$ZYӷm(/Y#mz(!0$!d& A!a6x T Y$n)k4Ӫ3 c#.bXBX @l"YK =bq5rdk|cbh!h3ZR\%~) 挀 5&qx鿶P6PvmrG\keMdEU4?a}5Z jF&\K`(8ؿ `8 í)6ox# y|h.FY $"eHCK@uj8@@4{@Ohͩ`IaF aHZDHW RN\lIu8x@d!@ݰ0@yY RTڂQ2@@Ak. .2lHaR-5LbPi8 MC@]>ԃ h(c .D`[@^$@Gb+ N}$cakR]n [1;%9<k`M`'@Bi;P$RO}Q@S΀$X@(qza (ؐz@Pg= (# +(}eeƁ8u"Ag$QAKWXZȊw@PHG(k"K5Z9xdi<HHL 2}IA, CV ԿuAG _ T ȯW]1 YfH# d,' :$І.~}zW7e*;Z/{ `8~x"lA`hzؘ`UFYl8zPNQK  EbP3/Yj?_%8o} oWo5v\hF/s/@' WeP˞+[D ?&pM38t`Tb&2VQ!V&QVu0) {B"de}-.LV $"/E~Y@.( R6'뗨3rwmΕ_VAVO!B]RYK!&&XoŖ cHVwGGRDPu_EO)ʟ)ʟ)ʟQTP!0x0qPKLC =ɚq||H x|wS4#q!g_ooS#7dr/?//G"Wxqdā%l\\a+CRtxq``v.rKmv OshaҬ"`BQEuw*!찇,)G%W?P!Ou5 ->evseUGhⶭ br+BQ @I!Pƒo%;(T:)m@f.C6˽r0Bk6)T`B p B*hpUl[!l9k*yC( d(`Cz} q_3qp k63`hWf|^v-si) !T&a#q?zy?UM )CQN^ ?E(tsY3}a*b@]ntg?-G*EЎaIX0P$<+LJ-9j-IpH`,2HݮA0xY%Vvyg#5,:83P(VE`pMJG9QĨHm2al-ġx:DtK17AVhc$Na_$}'AUѭG\ p)L%)Ӥl~hLo `;k55CKE0-%)Fidh)=WZBp~rM tt>Шb&*FpR: {P@,PeYIȲ2#Ua*i ial?ⲉ*̈CrױBbš%"Qb0Sː7wW/G"Wx)د{ȝ0 ByxHݑ|-fՔg7]Qy^-vidۢ)y>\iٌ=Ŝ;5sj6aMf1}OmW#4lG%XZךc{o1պWpjTogtbq#dܿy!]شɋst]M9u_g`'=[1_Mۯ"SNyfeC/5t.N]xǫ˖:t+FO{]}q&/*cݟFOqaePN"'ֵHoK{otKF>gU %ǷbcMym! >!̥sә-3w]?y_ {uɳ^s{'- ^eȥјǂi>ǚE1f8!~fVmʿ|~)9Qm|q }Uߍo_;fzR55\3}\^6b۵nͣ2Kg{V~h!:ԌG!󾟡{yugy]{F0}\l~xXݪΟNܗzo/<ϗWKr؋['OZ7/Z:c;SMǤ_ uWnq_R3c M/eMA͇[nAf9S \ض3{z,}ՠ?mewUI'\^bK|݂f]nخweE>_9X5:3/I'^اTwٜB'MRm֌6Z$e?1h2U+g>:ݽb/˵~ZQhߦĎ_:ch$#rowixmN8M.&-d6Non5g~hI7n2Ȳ.x0c~yX}qmU~E_f.p溟>Ξ o*bI|~}QptleOQHP߃y =׌.%/] S5gR?KQ;6=mUmEda[훉ϴhs}놉 j5PUN1]ݯ5ks$ʊJgGfuq=k#On5hszw^r!j٧fue,ZjNֶOfa. +Dn5ԫI۰;_/(j&wj[70l{1 ؉#|FY?x]c z|^9L͡1? uZ̺ G^hKc \~o="C:Qbj|];~y簁SskxpS\تM|aDZ bI~Wk=rYnngL6U;Uj߃>>J!7 M/>ȌM_\ι=w z2,V&ӆa+:txvOxaּCZ+'Z-*V/7^maz ;ʳ:ѣͣ/LX`9w/AԸyZ}''uukkg7sk<8Ǩ؀Vv˔I)W<8/c7ߡ2~ >&;xǑ۪wV{RwĂ $Nޝvѱzs'vo;WTi!;YalXy#9|}+A_ȵm o6&L~qݤ 4dz{ò>qDeq{mQ,!BAS[a̾?y(?C.=ϙ9c۶m۶m۶m۶ddT*zuwUWmU e>ԎT#V(4Ynմ^#x5yεKz4pu@\g2Ê5iK2ol;7U"H&0x%kX,&74Tt+:|kTOi$x}Ŋꕧ`!+l\ƅcߍvrʁ c+w)iU Ah6$XMpkܧvbxhr\C*ن/Kj:zs!BWiͭM6t&.>&aybzlZ0t+0W EuhA- n%p$lU ACE4Zh.9SDzh$1I_띱 oTxc]ff5rn HfXc~O>(+$ xCr\Cdk:mĒ,-PxĝOK'xzc*De:x:3 <@&Cݵ*z㸩FbJ a"M%T003V 9_~/$NF5uU3eI7'Hi}U4܎t@t7.$EvaYb g&X`7 5{v31N0<i٢D%Fۓ>M=t]'%-@}9O;ԻQ;j=ĖRL Lpѳ;m#A~d4g:NfJ^)=𾛳6(=O~]5@z-V\^hԋ&9ג.>ߒؽ 梄~:etJl檛|%mT$i+51-k̢\ذz6D=y@a2mI+zT3t\ĠvO(繿  QzW XJme9}X_L@kv*5QT~{A`v-LHtEt5>؈6j3si0wG#fh֪=UF<4C2} 6cshՙjn=e[G3{CZvB=3fdŞS$Z(F;]JL4v$P?7 lAL @5 GڕmϦM-Sz*Rh^;{=QB7;aF['|uD|(d1}bj)JqHMԦZB3R@ 7Uԝwń=x.{d|/'brlW;l8^~Y2slJٮU|Y"_tΠMunb ygKJg2l,N6 s8(۰s"*L>w|R 4_ W@+ hymIQ `T(V.c|1%. NfM8tpSheӔUo nԅ.<̦, wOJ4%ytN=R7㦥bCФ}o\R=^N1ɰܵԕT[L~P eح-b~cKWCP?ѵGV ɭ'^ =Djbba5SʜZԨI9:O;ޡ'6{bؽl:/\BJ"N߬kI)aQAL=h-&(ꋮ5x䶟iݭrׂq,2Ht^Hc"Icіq[#5i[`=^-w_J)|MVn^0>G5 7eO&_4=qa cDWmra0T؄I =}Bz< N%W Kv>`fg'qЫTb!6+ǂ26TƗf;A0XZGߍjκe^D9&K]̵˄qqdYW08.= yb7HNH"--")DLiF@}s'PϹa˪mB!$  Uk7R,./ d1Yz"tXZx+"3:$%tD fܬKӽ p_Kwϲ'.хb$ BIL R; 9!oEttop}T$-) ۙGOV/]DL(AbT'@*qeًXQx94&ڝA Qy%ot$,Q'eHy*{jԌG, R_̤N[U33' ŸQ›; ɽT%SʖHIUPȬܟP?W/tOH,aB`"˂ķ/ —%S;W!:S_ YTv! EF#).aMebC v~B)@f@ydJo"ukc dm=bg2+ Q%'F*E99^2J|+$.x?WQЅs@7WǹFPWϊjffƑ yX{<~[ TU>-j(Oi&"yJ\%*$fl0F>{*2yZq[ן~.o;/8 nup.)m;tF X7, ))"ۍZJJkGԖUxݤFMГ@kE@"!!qyWe}87ž> LKA%GYc7>pL^w2aClx!1tȗxӌ 檣I%t4KHxQKM>"i0b`r+Od~ ?;(X2:h2r[gMky~,[aD` ۘ`{țWP-u= 5BCzHcKvT2n]O&ԙc̯pnx̟]rsb\ͶoeHg_I~ _)*Mr^ Mosx01ʘ[qwt|^XΠFDHlbHf̕"]W4?ky1{.ZF@ 뷱q P$c-.w=͌39A/kuG:k!0ЃW=1n$X-nq nw^1,ODn3cjH zINIa 'RB%1:$/ER̷ ?q.)^m6 RT%%f)9ͺ` xg,"UPT||)0a1!/gmKxrPHSYPFUX GtG+n@.6Vo2ƑBemK&q Xb6 zk+L\s3}ҕkj%8w.ХҐ>~ףG?`ȱ$ƘqWJzsJdyذ`WrY`GOƤ@X$N y)%QP`1$w"{B*L$:[{J j+yfwg_+{ 'L?qe,0U:uuKΆafa F_T<p?;n ## ]4a ÷.V ]6yrc7fӷMHu 2"SyJ(TP s17 L}xt &{alCǓgG.`<<]qg&Z<.]}[BP͞X P6q&7.>6,5lh1j>CN"y;l 5fV@IRhe.:1uԼ-Zq?y4wWx@.ǐ!&&]_-; H] zAC ҇6nhG.^v_vTk@bD ~ZFV?7Fj=K9EvWʥ'ԍ BP"=4ۆVzL視5lBKg37>dF䳳c]q&ڛV_)4Z+@#Ʉ;&Vk/ %Qvp~쳅$#u.IHMx{V$ 5Gs^#<ؤJe9t<Ήf:(^ ڮLTXNe_ y;C YYwk Fә?!̬daW_ ԏQsח@BFxSQ_ gG o|h h.&iSђGNgǮ݌7N^ EK5)=`TB'AZar?GAv UeO_f2) Phrar^xTZY7*V@wzpq֎{,jwD{LY8wq{OϳY1m$ .֪5 {SEQU#ȱR&::90%va>3> 8̓|jou;++mh>4qTrlsGxᲛ1>r?7##.&Gq[z0θX`@k6Y- R/ܩ?}Us(9XU*؈z뫏Wd6`~c!op=t'pɿdPJrJ 1DI(CksjW\<>]T97 y# <$MXưW) lVnKM pٝ>c!.k-<-Ѳ%}'$(#Z(&_(zi pB@oM 9V@w7˽rP7rS]qxeQ][4^+6eYx󖐳S}-;MjRH5='0)ymT*hKԃ+Nf0ƹV-*>D {%6=fGJje&zbj24ZS:͘4|ជ2&'ьѼ<o07T%%P_qڒGkgë)t0 hNQZԼDkᯗ yDcNE;ۅdWƝ#((b`p|Z +kEZ1J~ j_' d9Lc`wHeQcDZD ~h0^A(X"bӵ W²ba8}l ~?ז4VScu_sab)obABo˯^{!" 2ق<Ȅ}{ZFZ8P8NSv$OH{ qrn95,J?W3/f$5DAx|+;猊. 1FМ+*d4!ˎo͏u1hnlqz9Fƌ&ƆLFF&llľL& ,l,l&FL,Yooy‘T~x W=T'͍;p_ 6>| 5x=a^} 8U[ؿ2dʔyLL88833+Sd1dL! !Cnuu]O9{ow}kY H -<[EH@`WXϭ'$'/$,,,($LJ+(ăA)$Ёt ؘ'`-;!S@ lǸv rnnl})A`8,V𱜃$T!K{nh^J>M7Tq]=%aڊ0)sH'$so/: E0jAy ^B<燏gtɉdZV]G2Drڐh.)]m69ə+d(EHq1Xha~v_ު27@9l۪!^:dplb[ӳ5ћmsF 142dX&Vdo l=qxл]wc^UI]1kocڪ ,zvp1hYޟyi([$|rRygYMVsYB VU zy@HQ^;{hAvAA\2niZkB+4zS "QswuEڷ6kv'A2.'$,K܈{l:o8A}zOtQx䵅Ey "6t=84?笯RP=JŽetccoܒIC4}Hzv+}Ck@n[ ˈe+HDRt:z);.x8؝A 6*Aۓv'%N Ye%e?ҫ}~HBUgB3~ VdƑ&[kck ^ÑLh?܃1Y)j!qQ ^3V"1 <[DA+ \z)o iB)L['JWJ`y@Eq~><؃Y7jiOnicb'gUYo#!-|jՖySʀJл- UNY 'zn$ P)K6nT:3bfVAMW[O =s? *SIud2UuKr•Z@| gx~_0dք<@pC/X|y}ze`[R8s4HM~OqH5k7}}J"~ +U2rqI#X|W\Nw{Uy͞MOEFj/8 4G\YaWߪ7J9n ZT ^x$* Hq&UٯnЗn>jcxZMfxIC!0oƷwG{؈{X:lnlRoZR1PN:NYorD. ,MN~ʤ9gNreC!ϕX'Kq %[^A %]a4W]9s')su՝,3_2>JdZTe1A8S1gb%[k%m0#B,JK H^ʟ/ϼ;X#cU _,B꟔WN7TI흖bA*fmc5=GRYJ5i/&@uWj`Y,R5U~c%~w3/'>ar_LsRnZBj9WgiF+/ȎMNO]]|zY,MfbgK5igE m mQ܎hN=ssА;z0vLpE]lq(;C&Fde?1U DBCggX[ln;z]HcAb1ېk}"nΏx%~Uh gyGjy+Ҿ="x8Đ/{4DȂd毜Z#Qne1 Ѻ-<+Pmr[':Ά*%]P>)4>0fz~KL1؄Y1\&@ycvCM:ҞЬB$]aRc!zlݗߎ},=wrCehkzW^|EL_^Mf~yfwځkl#j/U` w\uχ*GM0P:7"qsЋW.f o_gJ(#lbndHjIzm7( {0:ll6bрBa |G<#^7ʠA@wyNo+L_u=~~F~ c}ۃg4 x$|WHH]֢\%Ȟc+e\U>"I!R7tq^~~Aū;ޜ37`d-Dj}m:K. lgNwg]6nu_%T7.3  { -5Q[DArQ`2Q#N3*$6uk4φRM%baYnq)N{APTFRlϋDdzDn牽KR<70y˰,vMAp aC<[jS"Wj@ /d[ߏ+o=$GB98+G./f" Tz6q+e"܄`LedȌB𔏳F`Sown'+1\r'+*W:J.̿|Ly,R -s>MtI96\YU8=yG|CJ8m B |u)Z`H1P/r3ed1Yf%{1Wz$<yl`o6qb`eF7yƔ_ 8:r!X̊L1IɆwI]sGmiu!g|˂z9gwpS9 ֽmmHW-g b7@gY*哧J.]pM\Oz:Ss06/ "syyoLI. IT,u{!n/M/~n쟛JsMEx>lΌh{Wfi3y ~{a 9z oC•)7Y)Nf9 ߢ"C"3@aFTEzW?KFDFIS:?{)ңnƇn}5TMo?ѐ{`];Z|[_3KWFN=v;}^Iq?<];u%,Amyz4lsʬNoi3 o&kNj)I(f@G4Mp 8~f ZZcSp})eMk&' Obn5*G{k&Ô`b/gl%C~5޸UddC+n_Mu;ﳮE~.H[Ue(YƺqW+(ǓW[ DjpH1AVY ]3 4.;lи<琻lSI ۤcuaīՉ2 a<ڒH8s.I\{V$a2k SD5U 0tBb'}$46攽>Iv +so{,rl~PjEâSl=#:?+`oԾ/_rgn~Z t8a;,1ZLV6$[0}ޝǽ JB86#zcRۨ)şen*+3[E٦~竏`eei<23[6t/ZFb%3XD+ U᧸}pKʹzn 6$"z'sNAeX  f`=̔v./~.`r k,-''>1?]pTC吖Q*{2xxg5r)x:X`i4vyHceCCQ˙>};o X]^-GثzMO1FaC om6;L~YKٯ(V;$n~fے"93f5Zai]S鸹y(Hhp`dǡA-/Rcrc4cA5˜]H+fN>lq1ׅcT[6W^aԥ?k{QDCjWܵ^nYnoEVElQI^h(8IGߤ>|@r*t+buA^`tSl/'b$.Kjy#Ĕ{s3sד)?Ȯ@$0/́wrxB CyA/L|$efz7OGw dX[ƾ{O8sH϶,s|,͋Z2mQUZ I֐U!g[^590,뙫:w#HβO1#lbS6u oZz>bN"=a"o'GaP9 lu}s<.&% *K{bݾPSψ >Lw}]]sry?U;h,c zK^*j-;u O@nNp[Dezӳ't"?@l}C}< N+u&{ ZB[ I'D_y̰o]rGz|WWp(t LgG*bi?& ZbcJ%" 2&oz Քx>ƹ:~bk`5X$Lf<9M95wÙ|,K&yr\W0jcljνb=43zV%E٤^$L4νU`\6$Rf`&htGLJH,\yܑL~I-1 wx>u6~#ˤ5c?=H3d ;`H1 '%eܫs1Mujf9\$ǭ|-t-7֟oR^qxK[?Hit6zgNIO]0l>]3b*/W`xd`tϳwvpShLYSV($p$vv-oRt;t9Rv5HicYx))oFbZa>fTk4Tjn4 }a(=an~ ̟oLeZŇ8؍w*Nao#.Ife}"7=[ɠn2Mfl:XSjNIva4ؖYc1Ŷ{.’l0_ies:C{Gܯ;`0R"9'y6\C$!toX'ѻyB7= ~yb]s#gw6?'.JC)./VEDGvOm>]i )yM.C7ԑ?oq-9el58LF ^yNQZGQ\!=ux`?ٙR nhyYDNw)ؼZ2Ǐ*hJ7ڡȄA43c<&Hqo<wwy)%HiOֱ{v7r|e^sjucw΅X 3O&;W8JD/269b?IitZP{*J!ydx}mWzBC`W!ժmb9uB>|MҜx(hC&ǝp1gNsVWYIoaL)Xj~{`k M[pH[``ݵB)Af,|"u {b瘚^vN2,2g8rI%]N]S#Eܓ%ࠇ9eDjX7Tܯt5zl >z7n98E]zSCjxʋܸQOd!LF'-/l [C1N<А+TEm~̘գi:TH=TZt?WUW`IlIѤց}/&a`́Fb8lŞWpZ|j!yMe7X,ɂ`/Ml* 9t,\b3hu's~DhaE煹Az@Nq `;qC+7Z}(z`0p 3yyG oX=+n?Ҟ16=sD+wW7#7gi>2;)=HS"6|F;*hg1u5@ܛO= ĩޠm>y/?H5XC_V۩EX[vD<-T!Nx lT.*|+Bo˯1Z"՞\% Oy׍k&bҚrG6n/\Q)}Yr,J)ݯlQT"퐹V_SL6p?%V=>8xlˏas_Q`cŃ+i o8dM,(s&^|a [} NHTq&KȏlSdc >p9{*-qAO#b[,yby^i9gut Js[#h,˅MfֈvQ1ь/TV@JͶ5}99I07S-:p] y,~ͦV}eW}ܓy={?hད>D1蕺bǔoHU[:kt nOޤuJjmUENC|3.L2Ҫ$Ԃr@bSsFzŕ9pzUqCV ~fbW[yog^x68n351bV}Mn|`t"BӉL掐,;M ٺ2 n2OJ8Wڮ6.(!=dWGϮL\h"u}hxzE;eLMn'!Dsh"2nI0Q; QqɬvߟNxRks,7aNU7.B1*;kO [xP6k"C}N5G#G=%جDVӮ^=Wp^sR\_.̻~xBx|r>l[^dSW# j|R0gţq+,K܇G!_YG,LbxG Kz "% M+.c|91'EdNbrhY['g{qz%79&*3j:{I#$߮̐a?M8fsCƼ8렮Ua1e*k]}z/W~Cwp Ui<.8RQ҄LWl;#kwCė}RKp(5 h_!m,MClJm&LXTwlD)hEvjLPKf]I܊AK\qt{Ɯ0k^̼"7[&)m.<2Ζsz夲'8rzS|4W!ku_PuPwX_h u,2:{=W`n"=\z ?# Z^-,'\Fk2 .ӨA-fnuP_ak);{+6a J(Tk>Iۜ^= qm8qǺcI.h̬?PLvNeŧ*QɂF+G`u~< PZTN~)0J37WˈlSێ_W&tQ]ZMǃj#xLSIB:Ƭ뤜=Ru7Ϩݫ4#"`+pj%z>j􋹂.=~R 5JbāRjbBO=uyv|8bvL v%>nEYU#DŸ1gOcy;_C"g"4y԰ў"5u*ؓoɕ}bHH= hʓUXcdeaJXAhywNIu<ӵ^~O1UQj!fC~V.L52#X.CϝuO-a%2NR fd3'WHt^]lil;J^FR#+ǧv!vc뵴)^7_:\(_bY\`&B]zIt0seyo*>N=pQ8{|Pgr:C|$#ո&~:QJ4=( eP R|ZD`kuӅJn{ sCS_[TP1Uu8ݷ%RmP@'e:hFBICJ%Z(>MQGQrAiHG(%J$JRz9dJ3CA)9lqQF %~tGB)#84Dm% QJ@K"{g>H @Y_@vs9 QCX@0ǭge 3( q++J;3{wvQ\eZ/p nWj_@~9/@s8Enn[lMfe .}Y M0dpԲ9=ڮBV a lX~ A@H wDr#耡~< CvQnhXݙ@ [fCpX[:1:]+*mPA `;38վ# A|8CQ=q~ڭ?Cv9 h|=dSŀ㻳ߪn|ֿo nm[+싶G/0=0T3}&.v[w5.vE mu(ɏpaKHlȌ@uO1(: vxCLh3MlA o+ T E  mיlͶF6@;nn g0G.~ ~9`>9"h ߿35Ў&mJ}>~hwDv`#`s  Gy^gH;*rM&&ck/qT7?mQo u"|sfs?ޝv]ыcUTpmɒ;wZO/-pUţ6e7-UG+ski4g:Oѿ;7'DŽ/V9x8;VPrD KfY@hl/%l/ߵ-o @K6_%H~eM=aтI(l<@OP 5!fh h a5hC4z(1ь?!ctj !1ؒ#QߔsHh?_(6 '_/v'NB~yYʓW~zd?7M(iʟ;kƌv[Co%]hájwU}T˟oh5:ZC'[N(.bm?0J~h v:Q' p"3Ha.$wE'_>SEA s:]PWUA57@~(K_7#9J T' we=a[Y#0ԯ;G.-Ajsu@aHĞV<%c֯j+~-B`5l` Z~aßͰX@0s>Oan `ov(>o Opۿ_\I Ƿg'o~v# pevV/P.UQv޵4Z3_0->5v[<ۣ܇/{f}Em)zlb/ նv;b Ͷ@pGEnkHV0nB\9 rn>hڋ~p.Zx;5"z!P8'H(dd mɠKAX+vK-[խtpn DXIo{ bSdv5=C[}_D@rڠwew}m6jP=J9x?#wO57h{Jopwz?D-y׎fDa ;>+hV/ Pݜf8 O_꡾ lU3ѯhߓ~dml@.H8_ wD9zL'. CQSA07yat^soo̼6"@@>š[a0d+56#Qz(gA`8r)cCewnd-FMkߒ8wgI_'nhmÿiL*rkY Wy` ~;|L; :/aeϕ5 @녋'3RWDu?bG;a;p o0) {@}@6Y&y):H w܁quwFWJ;sq ~d㿲e+.XVsb amQ78"@::ݑb&pLW\Ȝ624౴0 X xA >Ka/Z Y  !yBr@Z??ߏ?/H/+gK10:x TZ=D+K6t@*g8oʙq| XxY=^XS>i"E(^ TP  $wPt {TJK)* %?GɽwΜ3sg^@`( { fs b  bqa1pf%D00`Y[POKJ,?/ǡꑍ,k%:| 'c1m!D9ݐw ?m_/)^\l5 %hĕR:Rz(%&ߩӞѯ:٘D| yW TdEw.@>K+5,eէ跫M1{'oSjjzg.T <:𔞔au(J$: Y[.&i,by?NOeNzt~`_kY4mwN)+X8ht3>]x|2i낅jߡex' k4> JWzӗ2.PZD<@4ߣDɇ 3릮\K n1TeJ`c6C,rWr)#`e7߼'mF8"'ypR?`HpY.;zK{؉vҌkvE 5}P7Vg ^)6ɾy!va#ԋbz[N6ZKV cw#9 hlj's2 Z# p^CM8[T'I ڎ)6坩v L)Ƶ֧ģ~X02g92\dvCQr *[ID:Y@₤fkľwmQckӡ_(f?p, +Mh^5TIcXO^~gh7 rT<4ѰH1'uo,;L=1+Qy]Gug(d M+J6\[=4$>_}uU)W.rJL O) ;ઠ޹Al؟-YѼ>TZ@0V^Ϝ\2G0]=k^;;kxQf(:ItZ|"Ȃ Iu5E{ˉ ^6=u݉o]CTc$)-Zs^~rǬ>!vorPKG,(h%uZJf t*'Ȫ&<b_9!ʂ|Mܬ:xڶKJ+kx[W2zl"5e,F/T He@ahca1vQ_{Y""n T{P2 `LUFk*m U<ò,El~f=ēڳr^з=MSL9iiCGF)3C%R[Ì޿:<"8AJQG -D|Q.;y"i/=c8]G|8C~Os[s<n,O]<9=Ǿ6㊲)M]ʄˀelj|‘40}xύ2vvfʁa:R`U]R}BH']%›'}ߥX" ->"DGse$ Yj;=1qOԂiSZ4ӘZ֠JP" H.;6~c!QPm8fiP9'/?WNR /)m@c%h}f\"LJz yh !ԢB`˄ F$ɶY:V&Y-ES^V_qBia5+O#ec$4IFݾ$re&]Xxs%79ʱ-" =\/?!4{FL %/W7f Ri0$fkIS!0S{|PBprg pp-Z5iQ{]Tq Dޮ("^5#:<8ЙV; vQR1 4^ @Z!W y <+&z2ns ;V 㭖֣DH-zX]?í/|u akye1if &d=\Θ3DZ ډO"ZSiM9]/JDz0w B-Xb }<>ܨ֊Δ-Ƶ8F3hjI\`s`3w}ǿ9TA՝ s׬.Ou~ 7xjDvb ae^*c%2ŇLoY< #rPRT۝oAqW uin9ӫ:u׫ج2 ܵS"՘^rdDH5Vލ׷>و5?ɍ]Nr4OxɓM>AV2O/3ƛ<Yq[;WNE4Njo uoVq]bϪ8atO(hkt̟ic"IT:%]IORvk+0W_>/#~yC]~% YɳJ ꯢo0:;9<68%vX8 h<8\   iLzcSœ1y+?k4&F(O+*k>leU\R0!Ɍց׷)8WW6j37`{dMyb>}VôCWJG N {NҨigBߴQjTnEsqݹ^z%[Lo:k McOvv3$a0ޠXTiZ\u8VӾ:jmqșD[Vw7'2ku??h/Kv'&rtȺJ1;XAD h7F@wܯG:J)CĪ Yb߈m 48H3]O,;GҲti?M$2xe%9m' |yC"}KhʉAG*lh4+sűP컪 &y98g &XEɩq]iIT4YYw3jhTT4h0#Qjg RoTWgi/i(ɦ1JjWa \J#P|ŝyJNgƞ=iB~?>"کIq6N"-ɂ _ר:ӂrͦtQct?Y3]j.1I>T$ޅy,6@YD,/Nq}cֆPdݥd!mTGBr~fvDbmKOyv[AZ Yt.gLJ>˾|}&WrgR^.|3MD#B[tS|qȡLJ ?Z<;F*5hgτkMTsuh֔{CFܵ՞R6|ic@>yD m$'r'yMV>\pOѨ7l4j"PO_`^/{Jac߲em_Mzܱs(/ju@##OTdO_\T@; b1E"C G{Eb k5s|u6щJ Fl:nd)xE7,UwZGfҡeBAQ0ǨjѐgZdD,.@MjPJvdLFS& u3b"Y$j^KEEtnnmxI*1Fjk,E%6B$bp7]lCtjiJ/^07&FbMK7:VGiEGB>ݔXmuJD6:Tݡd{3=>)c2-ս 2Doy$<Μ`Z`Q}!Ic?r"H>,b=^ml6vǴ.9.tm"7(S]0o)=FO&ݧ+OnviHұ~짻W+3 [Jo{*)cH' ]O9!Ns, saq&W (9qWv%-@S9dWEďJ0q4 o" eyB\%yMś@lKW\Cy 7F_7XL񒣻{T9V5bv?Ǹ)G6,Nj?1 8k:Nlh=s䃑C\A/oeM7STLtmbô%#U9:QMԍJZzU.=TU*T;8˥a,Z9ziQ XAM5C:~yV,]S}lA+ 2(X~ BwfBy_JK|s:/r _"mzuԇs`4iOū )4a1zVuz^F5TLjBA!zVpM@P%)n3B2SWAm}7$-d0N~9C@o5Gpb,JL)>r2j' kH(Y)bd,t15Wkܰ4/euy~iG2y3TA$Z6iUՐ@l.=gu"' X l!P2OĪs|[1soލ z{ݵZ<Gg$u=ձԁ1i',s{5LY!1xiZ{ 9A=.q;f6W.] Zv\8~!?)¦)1]CeCRm`$6V{PXz$+>}tq{˪amϓi4D3̧6ݚ([P@G^l%$q$* Ig{)4a8o\VUwjz9۔0q=)6C.eIq^IħOh 8?,- Lŕ9F#NTQUl!:pGC|hV %4MSg2R9orX +XId žP0Ӎ'EY-}ԡG(h?i@sq?]aXG߯}3*!5L1D@!ŚieU,'cdn /um}$==а?͹(;/@۴xȥHB%^ȥ;96b}aITxm.Hpkp3mKǭx\P&v׫BM\ KuZJe@4r7;IT1$Ͷ0G@mai#J,6r&䃝WJy|L*Seuxkn"r*dҧq9يW<\>ѝxXA=CJC'y';B/P:E;^yQWGH5 t`Kz9}`}$ܕ+s%(2rk(tKsX#cr NqhoS®$/YX_fP|g~7j#D&ʟhiok28jCg 22:_І\bkLc,'rO 6d;FO1)5,!IɁb>;D w^u2vѝp}]Xޖ|Uˑ[G'7N}QA,T"gMS ' !D깣A@Via{KΙT|VT[EXgZ^=p*qF|N\^}Lopq &%PNen^;0Cy8k<$6y?IY1H^O"9fgIRdUVj9g B̳B)J۴K=Beퟶ&+<8GTՊXMZԏpͻr_fYX짂YzRg*^o.^L&bjS<袄qL}F՜ɐ +>-ǪS/Vi\((ݭoupW6B9ɼ̇|2ࡄH׷',d6r5ۥ,'hV#^+ 8Z2Z'">Ŀ*%sś+rn+hnOM#Ys?L^ ?p SZ+tsu)u˙-,G]|Y\úWV nw=?QLEmՂZИم8-.H s~Z#jxE"u饄AR t4݀x}lg#od9 \Ke.UnYv (.?;q~yr|,7 LքcXϗ7=-`p {6'.3i nܓ6\"% xٔ'yQk Sy`dI MIQV}ǻ53 $"3 jtԥ~RwzՖYn|4έ.*:%^r*U#V'4PS>]do?hhmHti r|-'SAG. D8ִSs ;ϙw,D08;ފO6 ɂGT!g427:L"C64[=%ɦ{{rUstJc\xT+1NSP!ф#C|^!4-Fhbq}ʼny4[a 88(]*ކ>̬'`25߀Os]UeY#۟nyTƏGM7MF-[ҚtG֦{8ZO e_kK9 ްw y$PBdkCqnc% ~PE('O_vTI:dƚ3K@]%∐ Wַh!!NZ@Z -h2_ ̓7s]F*iZpGŝ'_nw;a<ﲿyuqGHgO݈0Ln8{I)Lbz\9%@X*/kއ_t,Wh}=b7= Y |)dSqE-%1Q帝S$X ^E BU'Kcy2Y_ߖ>' FX):#Aku)mXs#.TJ|N pPmE\_XBXQ TIf >Z[|޶zeR_k pΰ](hW5uIokwuu*=!oœGjVMO%]~*/)YW꽂v2Co@nl`k;>ԽzN1{{D{g/%N ӊ2)tX9Xk"꫋EI?U &vLx|氎da]6?\ ɐӛpaj&gEGHK?kL/ s977Ч$5D@o޻y[co IVX9 >4KcLiw a_OYfQWK *Oَhj$\(S9u" O.BOoP 9~[x'1*9BG^" *w٨`s``R='܄ xx];I1g?yhxxzݿ-Vvol74j+2MY׀̶WvyEB YPhs7pٽM+ ?0tXJiD{ZeKfUsGs٨X},T4%\wɾ LLֲU;*Z>ܗD6zPh{M>\Iy( ynFlӧ9hOpW26cҬӥÜx_ |ʗge¼L#kB~Ag37 Y|U& Mv0iLYbyLH;@˞dmcE x vEv̹җyQqAg\S'ވ/84 +c?r3_x ^qLFY CE"HADicvnJ0eˌx/8 ISi#+կ' aw3jBOthQ_ez'l/˦/VI{,USKԐ"^p(~~+W^jSwGbcɹeNV@^O=g?vC뀁u洋r|2k[/~;]&Hyu™_ޓs4=uA\ai#ϝ%ŰZpB[:vF&p 7뷑bgsRԱ1T,%Cgfl-Qp} )iIfA,ySK"hxOX ct׀^\z*)yq(D!˝2@??KZPjI?vDF4*?'7/@!8g"䥖x*' Gb<({<gHm _ %>Fy`9G\2}X Jd EHW vD*w.]aqs@\fycYW~Dl VI댥6j%K%h#!F->v ِv$Tp0u@#Uh'>}U=emjл.ϞHA"BܵL !un:+}p*I=t,kz9-ǩ;fN#& =8\*pUϽA7IfJ!Ѱw/az5qɋux{q^Q2zoJH$J:oN8E$3W~\ "tl\#mr"mO6\͚^F` Qqd l4nS6ŝ!Ђ@Ulb-3(MAgf2:䜷 HZnri]ϳ^!EXu|bM|-~?cS`o8bIZADW/ 4x7v9;>T"`1c%v*yr҄f2yhaT#UHۗ/IIfgcjp2깺?{zJ (&c#Q sMER벯h Ab$m. & IoOtb;zч;e!?[WưadR׭0'O+cvTtwܱԓU'E?l)[9D|J@5QYV*' VcpD;c]XpVXxTqdHYWe`)|ˡy{aXli DZ:)yy~x_aC0/$,d   ssy<|`!!?7!?毅yy_XH[邲5:9|l6 p1 `$wϳ xuKe @Q( fp{'/phW6?~G3Ív'4 0$ 0C% 4؝$j34ӎ aYrnUĎ4Уph 6@7m8b2o6m 0%Gv0 in;i뻓LtO8m̠B_פťHN%vi&% nq"w''|Qqm&Hx?^5Ge+/ϹKK;F3Fj߁mY7b hF !p  pBv*6fD? ; c$)rw-4CK ZU)ZB! - ́H))*\T)kfNZ^C#eg!БFhޙmJ[EJ]td uZB h^6^Bih) !hQ-A`hMr]C˶hZh)TDˈ`!Zpo Zf9JWZ]>Z^GH2hG+>"1Z޼BK -7{ CS]Nn5-c_RUtߦ%Z-Т - hihB0z9ԕ@Ev! -R(QhIw@` VoVB䢤8Z@VFDkXaZ>heg&6(  /K ?q`Y(t f9:嬵x-!NK$n!e`@ ojuЦBsyw=~/.#m 4ɍ-maȌ6  5Gߥ?"· 0z16CJ- bEv2BpK&خ77pԇQ(n4@"18/!y l3m 0BٱĹ3DfpX;[:91:]P-:mAs}8BS"8øQ=q~ƭ ?̕|vb8 yÙ㻳ߪ햿i|ֿo nc[+쉶,06=0t3=&V[056vcuhɏp% 7h2-ݾG=&o mТ1gS`F>S-&C?ŷS I 4GvG$S͑  n="lp/q0?}ѷD0g 50&m J}~hwD QC=3mv?!~VƱ18tCS{7lvxhqeߜcow(i`bFv̢X9KldɟwZO/|p@(T(_Dd=cܚ,n1٣Qߝy½KYb_<mY#3A_Q<…W8C#L~@tb-$j+f` sɯ쏱',Fp msB m60 S3} eA%ހCд __<䊙c!b_!lct`j1ؔߔqH?c_(1 '^+v2B~yYړW&^zdZ2@nZg1ߡbPZIL׭%p/a w܀嫆{}YoV #' E?&f] !3k ab?C0~"HcL!1k.>, B7] `hFlڠ8Yǫg]VnnK5w˕Qw:TgF/0s/­Nn5kk 12F ڋnafnaVxHBMjx_2mGb3o @#׏;l}w ͎ 3A+ p;mm?^0Gy=ʇ[ nDmMJ=>~OwT$7 O/~BRf!\;ؾ{o @M32 };+ܝ׃(sKߒZI₭0`;_C{?XwwF5{λ-39( !1C7So3rP$h oN{*;{ wpt {n Ko[Ĺ3Gb>/Ts+lGo#WNa G|Tn B` ~3i G ,QH&/aeϕ1腋c@+]u/rGۏB`p8L?P`@"+ƀ/E~ -rv3c~Sԝq _J0O+1nŁa{"_`P?"#&|xK3H4LLK60L0HJ2J4H224NJ4KcCdD. rx8O^]\jŠEDP*%$G.w +uQ:[ѿZ7G۟{7 >Gݑ>}w$b4S̕w )|J[VxZxT+afXnBfVI\YCvZpYFd{yT͍ٞ\T^C=[=>W>R=1O  3g}m*iΩmZcaįF耶v%Gfص~vW#rjuf!k-=ϼ<m5RƩ y,4W7rcl#:`b!Yϴ;V=5e=ZՂ˧mbTmq9#it :)gy7_deһgvUc~ZqÇԿڀy?2lƺ?/z{ծq_Oͨ͗yzNƧ\W8G2'bOe5ͷeњaDI\1+(7\,{a&qւ0⤎A4(fHD+u?^^ޞnN}/j8Qs,珌2h3iA u1D2dk1 ZրYjd!"j:'+fv( O6A'uBC!qҐZdu'#6Uu *B2&80o *ZǢ3 Hw2'G2q3txXИ R:J쒹cXhmFmPrw*JͻG8E}&R'Iω"Npckpƀ0& HF3Kh#"]+熌& +NY! uEmj*a P:y,v6NхU4!ƈҬlLkW`:+7:ʰ^3J _ŵ:kPM-mLR4 P@'='֍ʃ%{dsTY:=$lpb%BiP95GU t1 ;+!dcҘ=,S0,OaH^ 4HhT{YHI_$߇/:m.Q\d7 U}ro) 3ctl@g#+ +gҨRtJT_,ҊōS?3Ld\nBLN%Px"6ij3P۱k|ZE ~#lNwS ! \@͉r5贊4vXKX O_ `ɪE۵v`t HI`+FHFN~8=ևQe "0!P /3҉`:n$n[%( j/bID@ P|]En\dD3)i)ҩJ7 P"!!xF]a\0E-0#A[ v 8(&}hp}@("hUDA;_ <:߂`AZ1Ұ8P$E+ظ=cS\AHj-.Vjh  [-h0hJJϑ]5MÃQ2H)R`sDfqEHŵZXQ]u-@y܇!ӓܓQ(@iy#* ke \]*D]Tc@<'%Y' E@(`ξ,`A!pbI*+rd|5#%pҜ,  eO)uN, 0 ̬.|VP8brȄvћH64W  “"6wI=&i†w`lDYa[?`E8薣,_U)m)(\Ȩ)|E\թƈ) zQ]T_Ϡˀ].<@f)ܛDS<!pcPcB+5Q(TP"1J $(!Wx('K͓`!KS;?E'X,58d:SWew EG*H!  Iht hsIfb=/AؓnEoPKpwA4rd"jʿBts ArP, uNwãB὜ulLyjQW@H RD J1HeGY)5b;HR `h( '4PY8%I@qo@Hxdp1NNZR&CH @TH "h2.i@\!" ),CfPV# P}59"~}h@"J`G65PYP[  d QM"[ @< g$U Rn`BN%uX$LNO 7񡽀bL#0 T(c@LjQG]n)pA-u@\L^1@Kģ(QK=]z$BPwq8U\c )tp%W-N[W[@;ߥB`X2vZuI-| a[>kl167juM2:peDDkk"quHA\CN [W0 4' S㤚0k0989_+L`0ٿ#Xexq/PyrR)S+J?Kr^afXnB&>yPlY(q! ^Կ{쨄h"[e]]Y|^ ͯD;dO#Z,==5e'VxwHӌonm6lHb1o5 p_WG1T噦aJk:ؽi]ۗ)mJ߮jg:?,uzbL9M;}ԝ~NlIL[{cnl TyXlH99= ۚ\3v=ٓ'0xfʄ]4=N~$֑{^ҏYS\vO;*tkWIٕ,Rᳺd&8'zrar^ӓ>2K[ÝS5ɛlW-fYV;^{ĻJ?<QQGkYz?]\}x`nf,D\b~#wuȆ!q ݯzqn*OUJ.ֹY㌡}\0q*[Vg jXަ$?G+mlƇPkjMc+fx Y5^R^;+$+}pt9=\*ZubbvqƤw_ٓZ!ϡS75ss'aCZ\zxٖhrxNm>Fz>nĄ+]q{$ȥVe}$~; 2_6=xsQ&x"1.!ؤu?6W ?!`;ӈI B,m6YewۈGcӫ>~XR[_zo-m|=O: ߡoƌeI$Gn#=:{:l\1> w^C}|wg}Cr裑3Y>|"uNIgX{{lϽnfODf;Z䶏Mce, {v#gjMk^)y&挱xg׭U/ 6Am%|Zz5&YϛN֍kܧ~QUKC^>L}u[7qpNb- ;s R/ؾm {nOcVpͻTv}_+k0yT“m|&֩z ){&w޺ԪRTg:Ϩ?&G5Jmq=9,$a +^?R4q-k>q&?T:6hS6t{?G=Of>sAնvQ4ܠfOCO^ɡ T-lduE)WaWۛ2NFl ~~d8, _ug{uWƄ:y>̱ʇwOoH/qvնUbXL{P52O4W1 6nX|/mbeKU׽3.k=|1]P)6?S7S׬<5fvP*rjƪ[wnKZUAM:5W,=~:]?/Y=JV1.Ms{Yyʮ}21ϲ_7{{u3%F$q|gcn{4auӅbo=~r{.YxnAvv$f,q1{w*J(6Nە`49ԏ ֮mw{׶ڻnwmݵm۶m67y5ɜy5399XV|Q翁Wxp3!L# YdQxB#"F5O0KOݡ3CɧR}m MYVWg!!KUMbN'L5^9#QSϽ.n25\'FI90DtF!4O \-32y@cY:ayf-^EUd63/P%zZ+E*oɨΪ#hsҟvx_Cl(2"|KgɔLb4b좇BV!2|BvypO{a޻*c-bNok4E3ܗOHӝ}W5+ycE [)\'hrM6ϵt}as 1ىWQ' K_PhB V)gBm$]CL0>q!;z1S؋W'}c?ON=7vÎ乾1l;,Rd7c'д\Lu@UcSIw]u!m_&rJAYn>I@ #iJC>O8iԅ- oPL:GEI5)10`Z8U04iL0OWXuPWmŴHHvgCKmB8{^82 &Bb)j]zh/~hdj.b_OTAo7$|Y<dCjg-, խEC7qbBϠ$r_,qPQM@'df>+ k .%W)s 7/ٟP M_ǐ? H#sC-  [ofRcOs;+|ԷPͥ^IrVO%3U(jnr,]a AF'p|Ƭ&;*5A~:ZUʁPSD V3b%Nl} >`XgjL:X`4r(VDVd.8eu z^aEW㬻|ݰ򽅔W~] y^xz@X 뚝lDlnI)K :"Y#ͳ;7=TRf.,]E ufR. d)p26]:=jff5f %9oԁLGZ]/̢7'{/T1[z?1 6-d*b,3N5}r݅c*ELd:lQ+’ưiV̢3cfe_ʿM\_zz:Q-`u>kr{P9]Y@_-<< [rVfKH$h&1(35 q%(b׎dY;3tZ4gM4C:ʟ>M߫懌u@iLrryٱG.EqL?)%wh/P֐8'K`XҢ\:ϓEv. =%ɏ蹨g})=Q?u:kA](^6pd@J$ٌ"69"{niM[f YwGI_17n<] yD;bz6W5l[Jrơ1%88_*&dۿÆ8'r#,h5۰,t3f+Q iÉd? ͬ NʘCjrPcUp C2%_A&W4LL J]6S KM"m'J[oh}9MBPm,eYr`,kMg(y|iN,Z'$vT݁eө롺@ r#S}4QID+4b:3E榥Z2Vc}Pɏ1bn:+ˣ*v%B4qq, +`9+A&tuX7Ӟ ;0I. Gqr&^0;B/dɯh!reOg/ٚ )3ҩ盬k4`1ķyg\:lK}:փ%hO{-RMq@&Jcwc虝`mDjAY4^,0ІCepi>F%hLJGW |IO/?3h4ilCsqp =]ymBJӵI5ǘWe<+e$HEA0@2-قz2gf;wzzFt 2.) 8? Ĥgr1qWVv*hP _T@PyYdQ1B,%};DYaДMEͯ Ӹ*.% ekn2=~6y<11ʦLb>]} CGSY1(*? M.ĞZ`*sEG  M`aTt`SXa2ʵrv>u;uݲEޝ;!h})Tɴy0\)G&qSs_зmv`q/; mFo"JȰ 9u;F!^ʸF!TLjdp]@5 ixlBI>%S|:Ek%o|oܤ2bT\l\{ dM܄Gl+_yKB|5L}FwD 6r/ 87dRt0`E!mga7ޚ6wlD!GSvbȷH(tIIcjWD)\9 S1:j;ޞ&/>; x Lp\>E%Myd@n:y3/aǟoZ~7~7a[fw%ޘ@k̜є2tր8ᎬTЂj{t‘ۿOkD6E$gjѱ׊Z0l5XE>ٲylVĞjOSJɢ*^fd'aX>IiKXծB\v`:<oCW_<*3J6-wS[D8H ,ڿѷǺ)&T UlpIRI/tř RS‚]]_%1LS8 Mfdsk$*c- .~[iD=_^}=qB溴BKLU5"TK%8~վy0߲eAb3P/aJϡk QOFpjj:{j) ӫ؀B|Ҳ=W#.:~jqRK5  . |[2DV>zKozEqL޿C3DɼM8Vob3 [OE:EI,jI̗V~4l[^[_hN/G͔`yL!22*:F{M{>cگSxx7]C)"EEٟ%Gn>h^9Lc1ʉ-Ox94 *ug.(H;976Qky*> Lo} 4aXYѨȕYj3 $hjF[x,p,gs瑣ޔr8bԖ c~k.efKo `݃֠L2~1mNr:ۈ l;0Yu[`iuJ)NxԃV)kAg i`U T|\W4)!D.kbK>ϕ5 )7/_"gz"<&BQ9hͻ@P˹a'7=l/ 9:mh>Bu˱ b51 _OַF~@<X}eW>vb_/lll{#yS.ɽiMJ͠ )Cravz'pV1R7xOv}\q?;ꣁ)T$4E!IhE+K9_m8k r'sCWqI)0^zVhOU1]sSٌfM)urלo~Rwp Mhl+|G)EK%'՟,g+/4@U&.9eGY˼LlUu.T/cS^YnyL0f2Χ{Ln<(Q`0>H`B-eD4CR> % )F82}|\ωE"}pc+jjb1Yt_}t\sKS^[UOzڤKX*vO?@Wf Α˰!+t3(-7ɔedb.|>4EPgϔBv4sCyOkJv O  'OSc?Ud.7v6hn9PdS;+E*"g-$L#+6P. GDѥ+1ʫ y蔳Sw;c8q y j}W-з$d[ܰ;cȄB?X2v?nDWFS[J0dl @r*Q.[:A6G lHܴP!WG,hO^.؍:.ӯy6x5!ō4#Ǘ$-vرQ=y;vB?KdI9ޠ 1Ձ쾣 \DAۧNgW4\) 3;Ng2P=0 h%$mLGHW.zo x~y젉*Y=w~f؁{Z#|QGWqOG0SM4ǣxm+&LRn|e@6iO+݆J<b>R+{9 Z/댶B֠>ZufJhha`x0V,H鎗]do/ގݗ#"3ϔmKQ(|/ŖDumf-d(K[cE>{12bwe"hM:w~,b8VFKP[_P~?j>@8ð`9fu&ObJ5OrT_Eug:cɝAPWюy9#r{|,Qf#X^מڭ-b`(ӗMh s07VѕOeDrPO:<=<e[rM~#5;~VNiH3E0Ÿ!eKWb+/j7p\=L>FL|"~16ax/a=</Pʼn)#Y+r0$0%Š0 BFTAB'k*"R\;br*ɃI^ FJH+TSdXaTY @p_00Pus5tD06z=S0c/QeJVQa{.f[{06HaKXs2/z3^kj_Q%C^Ill%W;t|Ȭ 꼺'x$~GF3toSndu#arٙw)28񚮶u0Ō2"$oSPHSFuޘMh|KL7ط94Oy*j/jD^>p,ePP.0@Z 3u78OX"d=1 de'?_'I1' C6v'aYXY ,@NSNcSfc !fhnjh04235d70sqpq88 M،,?Qlعx PPq^bn=*k7h/tEz|Y xa8^<?no"#{R8Y=K8889&3MFHd'eFVC)+{6Q=>s^{|}]׽?H;vs7 b mb2}MHΎl C9?Dml@BBBB !aa]q! 11AKPT$"!$.*! j#, @!mJ(wG~mgE\d B"?^?a#2"4,Y&++>j )Ln(󺎨'Ӕn1p ̠ҧP_ Hpt"oϘ:9D$ #z+߸arÜsu|Om% o\Nt#t8Ժr0ЋiPm@-dN^+XCWdv%l2Ze"Z:A"4Ak#y]w_J-Rp_^]<02:O[UVjtLA#HGU'69>nΦ.aqNG!eϜ/*u!9.6 p  1-n3A$\jKS@Ƹquz(#SÁ|O;!H܍AQǂ "QSYHB'}T7_NNyBeWgnlm k?.?J bqU5G"KX2X.^L~2?:ch|fph鉐zsx _Ń/'g+VK\IH}^W\5xʈwSd](Z4U7^yfs&twB HRs,d%!{߲N5/x'RAHoqpbsX[!$L{Hk68Ի|x &%@z'd$XkDSPݤ}XA0)KkWO>_*S-:cxlWP2s=u c//ʗ?nTIEš/-rZsBz; F09EQ2NUehqKPJ*8}3^L&u׋Fɲ/撎X0C鑯#s8|/PJn+az$ 5V-4sR4e);nd9D pFo F*I )3o6y\쐢䱼 i*frrI +2wWyX6-4vZLj l!1^a,J}*HLDtjTDv(ef G?'{ΓLO$Ć7NP`[Wu˹ɳ3mKl8oS2F‰[]'s?.ӬE٬*Qzx$ťbh EX$I~&ÔQ@ a$#eR z؟[ c[c<4! f'\7SmpS|`s)_CBɔM6N^zF%2>Û}y)TAt4-c #5-#4j)HKHWTo1cS\`mܚĝ9dKaA@5}۩k(-Ĉ/41_AiOqm:YW&aPKaؠl?),_zjn?*ş/ˌ^ YphyP p=bN+S9֔3>3x|XvRaZi8싴?ttgc&{'ԻiT!~6a9;1WR q?}=Om+N;pqMkȩāѣQ$7OrtD )Ys?S4}F>CMl䇄6c%mR^s61jS 2)qƁC5Ku7mG 9j.`UP0}D 먜;_Ph~x+2;;&z'z[4 o,ƀn\97ًE-.'QëVdXժz$nwN:co'pp1ĪdiX]c-|X‚|Gӊf2M>'.?{TR+y^UT;dXbeτҞߜ:fߴB(sBBfpm7r:5 OP[[$Ó>qCKpdu:q<- NvhvTzFi+(4i)Ϧ`q[8mW5Plh1J4⟑ǺTUuŦԚld>()iғy9os[ר.He<UI^dp R4 H[!/_I-[fMC9u'񣬯j3UeУwv$ k-?-YMGUARGO2JnDxmֽ} 7tLs4ln%E+}x=IG \p R qM]>V*-d~Q%KDm]e.01P\ ރ݄S"k&wOȱ&+@ϖxZUmW( ә#AK?fH[ћuign= 0 o)XY:FuTX!t> 6vFWo<$ʸ׊O٦5遷_x>(8`?ޖYx&C,}/w5R1eV{2j$wK;yuYxk:1)U+w'Fz4 RM͹,E=DRTWni7FR3q$3UߝzTF}X'"4"q ܣ-cfwBN4R5  8yR,I |"p=Mzh|cCe}#L#:<C n3$~q-ƽ0I1M[hS-rQr0h+pJ$l#ž bMTx wp+5]&MzJ! \?3'4:,Vs^3WT nl{Z٧8>WVZ(駹}PMQ~;\'1V\Q`39*¸ǩju$6t1HEbKp34GY ; ʡ~:FCoNT$-V▉;a :4W? }O>FㅗAGOcVM+Dlc;0quq@gxbowYI ou.Gi?%{'N6%%fY|@R J!~!%3݅nHەmHkqZZ%OqxxZ{=^r癋f=?7,toYb|:goI0s^AB(RUyTJ4 6]l!u5"k1M [}; ڀ.e :ްM"6N!]r5Q׌&iƽcN4[2~* Vb Ee$Pwd+, A&-Tü\+'K<}oFO272VKgǞj3ԧMd W}L J{|xg 5;Agy %nql;brq`)a \^7;.ve@M#z{ҩ^(sۤ_~n}J 1}ڸ;M>2im{P[^K8w#mm,/&d6Na1{ݿS&jS@Iha/YNq+`ͼ!tY+C-ܯM#t͚ė\jxl)^{#Ȇ5#z:ћf}r,YO0?j+0ɒ\舻{@C)E6#)GEt'| sY-k6s'69۬&]ِhUKx$[{ :SGjIŐfCWEl k4šݧ\̲ cs:N>М TVX=:5|t''PNiJ%UgvY֚ɔ*l  IG[oLj8u:߅s.ISA#_W.qW?8A9|>O_}="S"4BnoӑjRu C$+8-s,c4U":gaKYx8j`оe_{ϙ4QSqTO|j %Y[,{B* Y-6J_-E@bZ%i (ƏJ9ׄEz7X9tHObE.Or6%xUOb)m݄s| ]!dY"< eOy'YX(R<cܖJz tD_.sc6FMպˌ>}uVąj:7cq`2+1splDϖ8QA)8YQ" ^ZߴV_HArPKiw!%δZ'9$2,]6Dhc& u1FVjHnKĊmJ|rI@f,p MuWӫܦ/l%\Zbks3H5$CN psTʧ=Aܬ*%q JBko kDD@]ŴLEf;jZ 5MwgKeNi3hhMh}*~b<̼f A*>Ɨ[7FId;% :ŘC>LWܯ . D^oUyLHݐd#G-`#L {M/=8wE$iE萏ՑI. F/_+ejm+%6_`_JmWmzvӜ@eL^Syt`TNq&iy)SqS3^ ퟕ};il[_7 :ꜤEi4 ayML5G PupP\BN!Xf2VzӅ 60:<[ϰSusm$%|@W=!sWiŒ(OoǼ,^"ɝn%*_&g?PИLgTdM;ބs>0 ' wU*߹+RO2?&%QC$LM&J%!vX7ǞR*Gt2]VIdeA)% 7%9?%E^|Fq#FL5gq^QR)U5S:Rgr_ GMVzDz| UB)m6jDX8뻫ؖ2}!idK:YN*Hs'%H<UjݬsY;_iY]uڔk%ˁe.ޣ%eykѤ2nZxes~ 9=)9=*縛qh5t5=qѮ9eP}׎ơwmŗ7FlZǯӽ3w.3LJbGUu4=)tw;7| OD1@3|9f[V rB|=QR$:%Y-#E湯淰+%5,,-f& sujGFNe%_R`x3_!}4W‹^@W?[ %m˝k6bL3JtjA509Nu[C,,j$ML.ZX^tۋDs)H}v#ub%DY&X(fAS@rǝ\tRC6#KR(t>Lw΍H{j^RԴ2_뭆æq3'rQ ,'wLJZS wդ4ī\ b?QeN[ƪhgv+#w38pʼnZ.*v_2Ir/5S/Ż:N' `-R+>\Sb#PKY:)xD} 3<;>ۇ;m){IZz1@FCByiV˩qǒl JQS5uɪ\|gŃa;acNxk8YV` a$ WYxW\c1[{5-O..lt;-2l}w؍{nvS'uL3+0a%=pŹB?NZ uF-sWޣ.,>yj潉35xgI0mDX&)z8OF^SR밺F>TgCs/ihӜ;}]*3j'{:HOe_Ѝir4JRBt agq[zw=(nIT í:KJ:fYr!`8>?% m@H|w習a`; B0[$aA><{B"Iշ 0m{Dˇ핱vB N4eEZdH5Y(~0v`ȝj?[VpͿ'vJ¿,;(G-oRn|_sm倶 Ŀ?CaˁQp `n[:(!mD;t!UT _s|08 h|X+8tЖy'6 };6vԯaіvo\Ú ¬{wDaBC~Lٳ={ЦnEG ǿc\ a vto!`$ })ܜQ`Ⱦ7^a#Dӽ,ڊV.}\q0IЮ^( l; 3 @"13mChwۃ۽*3A  wUrۂ=bIo:@!Ћ_FIq{m˷k jDwOv⟢nap%#` r O@ Q pF;c'k-6dbl`7;#@3yߝFG!@@(4kbZ]PLKG/ P8Cl ^ Q'KaZjg0ƨ5| ? ;Cwt A@gk0`mտ0g; `('5c<Q[y;;dxo Jݘf7dwF@ 2 #7v/0\[uFA!H;#tRYtǠ`[#p+1wp!H(`odo1Xi y?Oi#n4~@;xw~!1)T "PV7owgZB*KDBc%5E>~qTU6f}o(0|#m߃5fwcM54wZgGq~<(<~EJ60 D컳wbhr=&d!Ѕa7;8kl F_fa㿖Gj}pƀ^{mΒ)`/I'5_ˏ>wLwllu ewwrp݅CT(0?Uc'b ppa(^_-=1ۤY9#nRxks_M{HoPE{7_wCs;KtY0ƪe=]c;0:+p{O;+Cn݊كC"`v`78;D1eOj6Uh)PHY==mL{zgڋ3"df/odD q½|Du=;:CAow~)FВ틕'16shH4{0 H 4?BphI؄Na5i?J= S?BzO,`2a@8oZq 6o[Z`P1b0 %~[-c pLZFiC P+#Ab`~?z08 l]Q诐_h~GU_i_4 \^? `[;t׸@9B`V =@0ԾO0y;J5tpowr=8[ -^U@蹌ݲVP51'N쿀.?Z쀀o hƄy䈀Fblnh7M  N `@%zN*@SHH,@ 3;d"A :Gb`Wg!oܿc_7E\{=eϊ/gE{><-|wkg 0E-/Km}uTӞ|^+}w9m@K4bi\vۆ('1A ʠ$QI"N/%]J9vwH C էUj[z&ԝ;\L j!-n. oPl#ܷMu0uU8t=mhnB}ޯ?Ϗ2|scV˙4ב*kyʏ"%B)|M鞠:A7-A1&@kē""loţgTI&Cڲ(n9OF'rE 'XzX&)A*d="d& d =/Pu1DyEQ)+4-q"G[Yd7mQF8!;r뻧p]pDXJLODΐ"c%晏B-F(k9D^\u6Ai| EJƛ- Dj=@dњB#lGlJX#AJPY Y#4ja-_.ѐݽ2U4wZiyQ<}YD fYO4lǽ_[X`8f 鑃HK K% eKsY@iMX ?+ʐӧAaO,\c_FeQFeQFR˙9x @yVϟNn\ZX-ʭ x8@ ^} ~{~e9smBbh'8뇘Ƨ (6pBc(ff<' '~!!((d!l- ZZJ K JZJIX Z KX%BBBb.$mdO/ K /Ǻ + 29DŅ~_/ dz "QPu,0?? b17=##/xO,*ߊuݽx)bYU'jeGcbL0UkVc n{֓f.uy5rOIJ2kO^qLåW]suĩf^`"~MK<*}Yuj;0U?^ .}iqAm_W.|V\׶rg=OnV~@s]o (h(UqӉULv?YJȥ>1Tw'4~IpbdQ }g&䝅Ǩ.ԵER^ƿA/GU9{G"v)x2o Uc)0IBWXIusJ4$@a\ECG=Cbd|_hJi[5GY.izWAﲝcrn/?Z zC'#阭%~ZcyE M晹?17?rg2eA]Jp}R۟-E +IFUST_Kp7'Җ,s֦S.j 2*>)qn z y-T5TT 6a;J*< - &L׉ɫ?;M,W('C)$#y f4wu=ɲ*flcpZM3DzԳ\O[ى)+Y/gڄG*#o>W;~YeXvOFrP|<Pp?"lyw=vxHʀ]牋"4dwT>je|CTDE]̍ߚע/ݎ0w|e~0Hi!' TOrgd$= zݨH*[4ni8rs@7̢khN4 Hy?sT[z,[,XȌrVZ Bh]0cYRQ38vdF >z7>3/79b|2Զ"DX[DNs1iRH< ONjI$q/%g98>MˋIONin-/Iˑ'_JP*ũOϼgaƳ+#;%9-L{6 òs@b#GX"0GewN)ЯN0ZxU"o[~YEpm`r]v ݆CoД+i>jY - 9/e+j?8je?r3<*u81\~:Alƌz>oG e}sD2p_yM/Z.BqѦBD:w "Oc:Ĥ9O Ŏxli}2}bp$AĘ ?P鋺ƾJr[ [mAГٳݢzniyzoLkJ8f#弟DQDg\ր{czQեҋ{:ޞLRRY30a5 O1,x.a:8C;6Vmr^.;ϏWDUҎ ^zD:٩bτ9݅)]>.yIC\K-X2-vhֳm=LTA_^zRDZ Q\9*\NͲm+<}k?ؽؐ9ͨ9B{}r)&3K`䍌UМ~)"2"E=qIWz׊"gg5,x0x·q(}U샹S-S!=Z-vTk_<ݏfO&p*4+zf[ Kb?kI'"yӆ$T"\Zgdɖ=zACG;d=!ۢGl«l}QZ]+/+Wx+UnvǣL^7GH=iG2=qr2hD|hF7rHF޹\Q¹[/ ˫R:FWӭ)Uss8‰_v; 4)zE4m* J&] |:&]s$q#b~5UZC3~I~8AgL2nTg|zTsq;nKDd3n%Y5 > ,$oH]K9c 㳖HOO܈ dQ0fUQ0ҕ&$3SaIOtU|VNM;%[3al|R2XjYw嘚1{]ZkCM8ok <N7+=>v,7<{^{݋P kzE*]ߐ-/Y6 zJ+-G6޸)Ete"%q 0( ]r;m*ĝN8!Wʘd %ՌG{G٘zkFG|;<+tS427z|))f|=dԁWz}5Ɖʊ'R PǺ&xUSq|z{BNw5Gc(RDC%j* +ϐ"b'[U#$S&bB^\'5%y`wާv̒A^bpgz5K\c Wʚ] >NI!%4wJuBNCJEaGk[BO,眵|ŭXh#l7RKR},O"!=-N~K;].d=q/ImiD&aOJW{I/'|\jL~&APxɓRWzg?jiv@lt_pO!IT؍#s,P;!Uȭ } ~} @;4b'#{|;%r5$$qNa _ hD%v:ɗܪ,DQ:ec햲(G݋\#f46 M!PN;|[~LFZD+yW[N&B0QtyX՛a)x±NM,YE2\F?B۾찷S/pxh8tAէp8U!Q!so~-sE g͒3 !Cٹ RX>ҤevdZ:Jy$,E7::dd˾D~KZ3P~qvfSZͯe]ߊ~8AB]qEݻK|ه]lȜ\kE; ΂4ifr <2{W A峌>u n\y-fi7\2 ʪgkEޒdt_`Fgo}~EERfh&tXp/ `Ez;XUn2]14皢cDzTr`e/rc؏2a0ܓ8¯m֊hV*g!eyݵj t9vE6ɶ$v ܮk*?׃\\(qGky76 ( <wDfȇkͳicwcHq)H[:uOuMpIdhɜ4ey@t‰0!Cx=SQX4mS);^8AnI=ET%iDi.4j@fG>+#>drf=u*6>R>qՀh MogsC F'r̊6!G|:GD^,qD]\GeĘ/qoɈw&~4]HD6e֑Y=Yه"!OI#jf! ^6)H& Ŝ_>?HSKjUnsG\_x,ţľMbm=H"4+( M-MU[|߮Rw_v1Z O1gU9SX.֫.k=V,81O?a<-=E_؇(2a7``[S%E'l5q9=TriS]YWvqM_kz+4Nְh0px<.Ջ7/E@x.*{Qy@f)&pC_g Yٍ涮45\*JO]fLmf\y ~|dI͖4q" 9ݑ&Iޢ\u`IJո/@stIҪgx%+eSC=V14;O$ ַT[':>{j?SjVxl5['y Җ%X+jk>Ip5iwrFׇ/4kSwVPT0;>4[){lmh |o8Lƾ%VZ)4 +~gX:׊5'8xW߻%?=yi<ϴ3OWV !?X?LG$=]|s;Z1Хs#uNUèJZy&eQ<%[y}~ֻ JhWBR%2{Ŵzpz^0-hU|yk_9or $b\'#00n:G "N :zUzt t{>1]ż⶷\|F51?|e_аTEA-xh >Nz'!p ݜOԷPIƘn5H,~oLEYMMk2v|Gv7eG\sMU}O?W"ʋ$ͱƈT{NzW{LPRaòVtxObgqOCk \w5smc{{r.`# .ka'̘Ti7Sb֤> !=Dx¡]Y:UOUBAy;\r'Q*D %離ߪ1u2v^S{I\]LQaд6ud>zvg:̷0PkVAרEkQ~%rgk ,-Զ,T:+E>vs ^V\tJ\ ſ?PP᱐@9yWj]9|Z1=mj\n}iǻ͍ @./<&\εbؓUW`!-2ew%K=AxY sjk쎓t;wmh_Ow)Y4sa D%TEzK:y}Cf&$˒L! toOс8fبN Ѧ<^5 .|r[&#*$|s !A<#^!^҆͗g[e) \\R:W3TNxfm;:=`nKb5fJ|DdNU$!!I>wϩ9R?C"KunfU> qKǧ <ˀ;MhYz2ݡ)gsݝj5"T/S3R+EqJ}VC[jP\^8Si؝c6#:o?u> teQ=~iZfdW郃!m{,F.i\!Y]Ԭq10P-r98u0{Gmr"ӵT U ڧQtT5{Rf\!z>ƼnuA>* pJ+Gc iWw_̑zDc_o_`|L+=ʥ1 5˚'A >LNgoAѝӇxwRu^31 I{Sۄ{e ;d2 Mܼ%zAƳw*KY+P_hBU8Z ({4ޒVuw0}'1'zԓ&qVcdFtC}a+kō^-SFJWޠWȿ*;G+ffCH_AE;6;~T9W!$N-rͮ8U3U/F*pȟ~=sOůvⴭj[A1̊1GԯUg}4A/g-֦"Rmw0*xa務i(N(:7oomnezUvZuf$ SDM^rPtj7sk.BKyz#WSfVq/ڇ.$ɥF^ $J*.T;&ѫ3R{9 s>K1Fs-Bg!г9 *bne _׷6N(yI4+*΅Kw<{퇔ks˼M2}f[ItD(i#:r5j:;9;!9W]uގF7$$l8bt<(|?3Mu^C»"UV,<|wx*d*YQdžx]|87ٶnBi? "!G] Wn ՟72Hf{emHHզnfI+Ԫ>|Qahn[9ϧ<3B)A%M]Ѣ359fc˶Rj3d'utD5)KcbM^ǐ|vP%IV cNk+MmR,9#Uil =ɄF4Jw|q~t>Y+E:HL~Y%̏o*WNЇܙ!5rQ:r}Gd"׍+=4/Kti +_1M]_ c,x<,Ni?%#pV9h_]EG(f{I Yxؑ@1:5U06k[*vcavÛ%yۦ/X5p]IA{͖zI4#R\(DGSRygL/{dRЅY^*y6´T2; m5V :o#ѩ uW6h$u^ JW&NDWuQO%:x9''Q~ZL6p@dIpdGM9 y_fLHϳ[ }/{5$wb}qͣf 񇲗Wt'?⦰} (w17 Jsz^PuۡR74Ȗ<$<K6kEd:ߣ#Xnc51_g_aTxY|ŝHғco?;}'rA QI5'nW-al$Ug#?H"Y:{4ZkYyI7 OL+2ݻiї0I~Hx@NiMpLP|5սO<]NZZo~k|1PwN0>+bRBEuo8崃˴AJ- va2FWēvW!ֽ DciF>䁻32of3c{uGt9swd DN[#1XTI+]3odN`=T24s >H>t^~!ͼGɊB}%whؼ/2YU5uTV#k ǑzyʵgW(@Hn\dGy`pZx2r.KKDp|Fo(~DԪIw?6w-sw/Q::vcH #^⬪ܹoǁ,M1y↾c]Es^!xpxPURQ)U?yd!A'/Dk>ոLСSnsA"xsʾ T&b$ Fګ'Io|\\ U0'/:r )De3}£#IvJRX秒-$H:O%crVz;=$A&j |}TgҢDdw#4gno^q9u]"#um&PHHgw z[!y!ݓ n~tx7Q lf=O4w>`~c@!3ŗN,4PZ;߄oJ)h8b@oA@lP|*q1T~Hda BvFh*Dkfٿ۔9ΝhȐ4wԤ+iw$jR@@Mۏ ϛ/\TSm?6,seϰg/yc4ysϵZҐ+`~Z '4հPWde2/(>u NCr!|!q{6ϫeS⫺?-s+=[CyR!yJ=5% w1$2$sZCИ, Wd!N( `0P d?OJ'oC0guDaa[2VNpFC Xl8!|n-;8YA -cq"DـD" b=amHf}C|p؟A9l?uR_3кq`OkHf*6u9(uO}Wc=$`/7$b ,tBۍmuvg@!߁ÜOZ"qIgYrA_tı̥~~wmu[;*#P@ӆ> !> Aap|bK'x*!mXm~ob8t;0NkA,`.1kꄁ8}GX)ex'X ߬\RX|;q&z+(>:ʠm( ¦"p3% ACc@Xۭ*ӷ`7Ub݃Q%+06z(uԱF|Ɓ.` jrC:m4u0 Bl`/} pA~72ƩźCW.%NBP 4 e !0N;OAApYrŵt^D`PHpq@@`QM^r@Aܓpdq~`y"˴;t'v"A^m;1Pp-=߽yxmv4w?QL7 vm[a%Sͯ/E@?n:@g#7@`7e77p_NnaM+ A7ulbg$r=7Pwc~ oz6iN(4v/[ۣئ})-$jnlndx.8j/⯈0+ p- ߗm퀄A-ݰjv;~\1Ԁn_t_8đX5cƣqӼoAk8h|Evonk jK+(a=_@6~ۨoa[Ϳ o nM؅oRVNh!-AHkkW-jY+Bsp.hKálZ r\`:%2!5rsE߁nX{8n@<~gn \y45.A%d ]ͳ'0I-@|fs?L6|<e`8& 'W0YaO\oa@0 .a+~dp&X;˖7"~Gq濞bIEB-6ӄec-mg&-8[ +^UD؅%|E|SCS`'շX8zo._oaNS` x/(8 A!bl]oXwM 7c0 \)$$jRv h6*#X0p7o}CvCOz 766O}Ymx ralT`>+ /Wz_k~V`bj;?;-ʦ,݃ `ú[u8llTӖ~=wp;!n6(m |H8qbca(BCU7!0%6E{/ea݊oPݍA b`dKӍwRlN^so[q=u{j+ۢDݱ Z?8lx ,aaP% 3IyC5m?mVdNȫkW^/ 21OAq3d LM Ḿ1``hdhlĠ`@SWAAiqIbdu(`?퍳^ ?h|yW=gZ>G^ }wE \jnu%K/]y4s#y-NRDB3W1sqڗw'zڽn]l2#dػL=oyNoX5nM)-=slj͐ +L\a!Qvg?'z[~5]~="_Z]_SEvQYƼek9>gn>2~Xuu n>k96w|7;d% R@-A(!Sp72ƣ(`Q0 Fֿ0:xI0,e8,PKhb~SGI ,0u> tx7L*^]X_{FlKE̲,M *%Ktvwvwff<@cTD-b{JEQ40, }Χ̰wsέ3IfLCj5 PZLPJZ TZ10,J{z, ZK~=8ux}ƈɅe, eW)^q`_ҩjmBkt@:*(VuV kQS`?hH_U)Uo9_ÄcXWQm+@; I,NDb&DjMT)jZkԷq'09jrNq0QFg1 mFǟhQ-@fcX q=%ɵ ҉m@D"wK'NV/:/P@h"2N:vR߇/;C8PF;[!UNg) 09OGl8xH`/x1 //JֱLn )f*ǝ̉L|A'8tc;d.Z[Q+ %Ꝡ(A(lNZn& əx8((>!dz=U*h 64ذ6JTV2./iŧ u!j'p"pZ]ItW dx prV.4NٙęzMGnp:ҰRHѬ2LEnhi #9hW;Xnp+V|#AXh81VPv Q1'5i%q *^l`DYD$"4;;qo ʀ$ऎJpfѠ8 %G+%Mq 9S *]1)!^ <10beaS,&,jWj]P5镞diWvTO%I"B4ғk3%;]GNbڑl! p s^9EjmxdN_鉰yyXإu'\uʹyƴKvciUw3&0vA߀WC*Q K!RY!j5rՃK<gƌr]hq cB tuܐ,a)+=d-@mQ2IqC,$ǀN^x;݁ӗEjyt!s% nyHishcBiV l6ya +lB]› UX cZZ5Ц̖6&)H(Siiw FAՒ=ݹ k*jZHRVb1q1g4or#DH*zGqڔLMH1iLOc)qV0$p: $F4G*B=-,e,$ ڏ/×A HH`(G _2E*~9L׷b VprÃ1 :6z tV3iT :%*i&IjI&L2PZ.7!f 'YxtN(g-tӢUS6T л)Y . @stZ~;,@%,k/d"ZD;0i:q~$$ g#A{#Tp OT Nj s㨂2h/3҉`n$n[%( j/bEDA P|]En\dL6 fSSvq##SnV/uAġDfC5C4ͻøaZ`FƷ" QpPډM07lጙQDЪ=ԃv x|u[ HþB r@˯×` `Mq!-&!^phw:8V@K8^jl čBJ˛<Y7 d

+S;?E'X,59d:SWUw$j آ/H$f0"ffp 8I$q닡NJ`O+DuKNAQs,g Z)N aIZ/MAphÜ~N:l6+GH RD `'2;DgA}r\0 ADJcScD@Di ?(I3q|M)A,q@TH}g 4Cw\L"!4@ R$"ebr8(Ѐr HĆ4@~@HEPBZO(E(HꀜԀH waN 9F4`)g7erz ׏@dD|P@f(P:NruI@O @i̎ JD И ^ @lq@D 0eJ"4 F[SNe:Bw WqMܢ+aThT KĜ~5veFpROp15NJpg2"]5:VEP'- iqRKXtܤvN2,v;Q1N׊8'3$,rp0CC,2Vʠ'w*J Rd 2z aQS&>yP^qaY(7p둁,DpI z= 0rͼ2aoDl1VfvxqE1t7&5.Pe_?&x\isenE!*T ;էܒOͲ,mzwO]^[r5bS;7oixolcZnG6W6rNmMOx7f|]ۅde_+ }rz-g91hۇX9H#mv`G3No<=ڛm>| > ռyRSy/(\0g̜q{ ]7-׷'.sBc^now;;7g)>E7[[9Yœz^ަHKƯvN=x5xˍwD7sJi_fMYqwx|mQĵ]~;AZO2W<3·n׮n{p_C:ܰuR_&g1]娐bkPtck.p%*!p>g?¶5/I}j9mCWwV֦,>n[_x_SKR[Rqum;lxڔ7O,Uewς6ljKk"tω]ݖ0<^fA-oA糒k5Zqu@FC bOts7vO9)@ݷ^7l9걦+qAD_z. ,}4+_7R63.hJHUsI/Z~>p}4-|f y>rI5 #I [Kn߱[\zj0'kP_69~dԵ٨l#9hͽ f|mLQo>ٚxYre!Ԏes[?wrٲص[c'=/3͙}啅xZ3~tfx,pƲ粶l3WˆǶec\Ssv݋=_yIrȡ1zuYYO~VV0::ms3qs[۩NXԪ|M{T~gnw߹aшك|sMg)/fT ;5Lie=Wx 9'5;mѶ/>a?}>&} GfIȢfݸ3GfM?XI9Ӕ57]U[1!3tFk_DN2w2͚rb͑=Wkwrf<6,ԃg\8f`t˹nwjQǜw[mὫs63{̐ #saʄn:}T䗽ss>-nˌGhn~ʾ_unČY)aԤigh<]+K2?/}!y>yp{*z?]uZW%nKuVa"˾N-:zS-S~6”tetT*%!{F5\0袟}r;?oa0g7'O~>y빶s9En7zYt1MNGLʋ2Ga:`Iϣ3<|z\^Χִ0?& i}n60&}뙳kn69j6kWU/z;ZevpOfkSN$FLqNӮbj5oVv/iyB>M۽mػ]y\Tɏ^<΁cjk[+vo]m;b'Um۶*m۶m۶Nzң^wvoZ1ρMri..Z&#Fv;m{(^V'_hD xgLʹbE3CZNsdKf4ckaTt8" tʢs (p9Ct`Yo?Q{6s[ܫqn lM4hD3ixy]ڹ ގ2 ?* 'Xq;~58`Ԑw"DxӛS%2HOq Zn1Dz~ԈϏwDUSh0M:LqĻ;ۍx>} HAłXoo͟fs  .`yc=n#+ 1L :>(D+ Y^Dz}ЌQ`կ15^x$B9~)Z- ` {d-:| 9X)yf݌R׷/aC;iX*l2IYU!=<@hXEL+[d њX<-^uM]DSM.^ٙ+U>F+җ؀.yc?*fļfrh8jPZ*PB$qP:^@F.9D9,Q kUY ZM{Z6}ua8_+F4zMwRos:Wl! '*5  z%yпY5E=)ZkEGqjU!mD ܠS-2S"4\:Er=#TCq3|?SbWt>^zB_^U |Y4f鰻OQL||6lʷez7j5 @Z3J_n s r@HIZЂ -,:ZZ}qb$%Mrݬ!ܰTQ!Tes!cQn>{@ǶЖbXbz4yҵW7Dw3n[9Kb^CQͫ_ NJ,v#Pӫ/=\WIA#lgw3%?*}9~,e-_>X}Hx"۫9R~1w|!i1Wfxaqndc7exΛ]Ko9a'=& Qw&JBlpWsC̑ WH.]}Jθi3Q+5 ƠC*4̇$ Ȱ;4JZ;V #7Nk`wPxf~?!pSEFa\jczbRµl yˎMo^z%$2c~ f]lL^ Z==oJٞ [ SLϟj=V /G`>h ׻BH1>J8cX5~Uj 8jC~ˠ_T|:z$R1 R.Lw|a ~^vC^+-dANxTT1be8EØ{+qoKf^)?NVZ/1KzG&pT &s'<+6' ߸)*I&Jo~n\$l0zy Lu8`Hk3=SIS* j֥;o!gM]󞁃O,Bb$m|͖9U@SkN,,y}|%@S>}]tK zJQ'zsa MI5e"b4dj*=[EQQݰvI1>Wi[$2/T47.s8#ALt7'B@ T7qEYO%Tt?+elxҊcHTӹHōtiIv^CB5+^ΛO@-wB˅}r# L6$jVޜhݘeZLglŽK}"ɶPmƒߋ0.EAJgk9 BƼAB4_(^5[!"BG7 W/Č8&m >UˠbF%?o?˜!~-3ǔF\A0O5'/aZjqiD\^1G|RftW;de =w}_Ias؈y{a0%*Q &m<$B1e^w"*&QSVfP"-Yum;E׏"Q~q@{#p ON'.Gȋ #D  lH`Io { )O3&yBb.ˎj!$v𣎓IȟZ:Cakyn &s߇}&M#eiS"_V;cI4^gbņ0&>$$m`٧`w\lҵQ!Kb/x+rG|Kk28+oYVaSHUPQ՝˔6ʂ.8'`&֭ T0'B(!bb3ַ+OVf* }3 ]/īv>&֊Uq c:SN|!fL~4Od1+yX.4Y'VQe ?}j۴[rte鈆v٦AJFJ3@ XvgO b}74<3;X2-ՖJ}BabTTk~u~w'O~qM11 ʙcBdbp7".TȐA ͖=O!Vn{ z.:,O<1+j#/ 0;$d"0(.GFGrqlv8:]F B( ]iΌæ0ɓz93iw(*ax+ze_\}qϡH^m"Dpd .eYiHQ C`'OH3.B'ڟ E /2KX0-@6aG0L`o˂Q2˰S-1:Ut}XCiJ;]Ҏnߙ9j#9zZ2ujh,64{y3i7ڰ#M=?W[*pam?X 0,Js.U5nLpF[$:^u5޶ZX2߫ABi`@p`qAP ML-:H(KXByӐ2(Xq7Pch&^6볳Ylյ>lC)?{G6ߺ0j2keO5ik{fZ?e sFi,t&BBRyk"8݁;VZ<\40 lQk%ꏡ*^>G)[=u߲=tAV}`8y͸rgom[NC^M [tndG`I) X*Z aR?L*<[{>PRr& 噮K}Dܟ#,HBd֞:֡QD~|21l 3(LR#E$iHx~s"]g)2XRJCQ%хSH[h7֡O ʹT'Tь_>h֤E 0o2t .侏hCŠԞ_S) Iu"ug`5ѣߺR)V4ߔ\98H.9ӐUC3zxxCxAbɤ{PI2YL 6-H 4kxaFUL;RkMv% ^Zœ/D^|keeLs7%RNkd`D4(fo?"wD2cFC9 rm6f_%`viKH:Ww)dch~ج/KN~N.-Uܗ>á'b'1KwoXg\kgVL+<~sgwyi8ѕ&vAFPm0'$TE7`M&>3䗹xĹ6~Nà XJ6zp.I:ǷvÔT_u,, ݾkP004qEN7E7βCceN;3&0W.{g 8š犗 K-ԓ ;㨚! \ n^"J}oO"lnw[9![!>C|KIOu Bi2r]~ڣ[[)b|˹z;Q'hh|'VoO^ GSXk98es#)YV($As;"Ô7~ۣȊإgD"[ۦa:I4.6Ҏ0YB1'o-3)Zv;f q3 ^XIzcdaPwt-@t[#|J/şnewJaֲ(6iwVƪ#g>+` SN%Jgxrma7oZA0,%Ȝow+鬭.V*Lq$?ZS{kUymtMf^AjKmTwzݥٶMjCQ*4m awtc` ewg^xͪzepH6 p~B/z@`t\0.lMY(G8}>B3;O6"*u?G-'\.\ȷt{CҎhwHWwWyI%kiR˭3d`,YMu4u5npjwL=gW8Dzi4AK{F _5ʄ[^fO!P7E5umDl9%֮p?4ryY{ P a  2t @v:Ý6_ADj̛w[ʫiktN=P)o6>u{Zπ 84ԕgulU / ީk:py}[OKCn-7U'aRA` 8c?+hxAգsU X*RZk:F of_d8D$zg׶J "#w7>/2;:Gp*kƒCPTW!Cnl9w"([ 7!Dhh"oIY! )}T.^uX$ڼK>amb6P{sl@вLA&IT:E2V-l50^ߞcG7O獷_uu0n%AH;0G St"Nt{`ʋWh]﫲SkpG˂lჟdcTTX(7|bÄ&6w¸NE`=CS].p5nAZdtAIγ0Xfp?.BjTh ;dL~g9 U~x$ 2䘺Gx H\fe;+LqяHmB> haSx03^ #%}n&\`L,N"~q4 ~8(L˽U%7RdѵSQDTG?Kgf<@V$If ֛Khv\!x dtߑ A G!ېϽ%T.pE\fB\]$AJZFXLeIW#d H=b2r m$2uKAA!Ξ-S? !Ň:yA zՒAf|ma;PwZt7ق3;_+S2ZMia B5R׀l|U$aD\-ƃHI۞L^ڏ]e~f:)ǒHa^~.@+,v71״4`|NK{['KpN#rߖ0xWkf֛{^}j//w'CSWg?,,K_⿰o= -徢~.~_:[' ޻=G6i~c_|+֚T8'G ~$ ?v61x h9u&nP!}H]e xO4^} OP&Y"/2RR˟b?~⋄Z\RFVVVZVB\DL\\ZJKlZ)XEl9-U$d( σ5 z"c3I(LJ*Z%.;a GQ;UHI7^PMzDaN6#ض0k"Gw8Rb)*Չ3M Ty,벞LCLAte0ћ@RZ/Z">(NșŧQ%- %<M"S~Fl* ;<& tRvXINZ:kn6mT6ʋH[/r٢dKL3?Z9?y"aIsM2~ɹgEX]ǔ/ۏo9"yˢY0TҶ={"ǡ~xC]՝~#$ħI!:58 $T!#zzV[!Ǚ,*g\:Y!s/ KfU;bL;ť)>&aUc sw)G[ < ޤžG#G&5/eKpHH{I(S@'o}H4rofՐ?f(Z\ IsLJ!آ8CijYM98ħys2g5pQ5˶GS&^O}[s?C/wGݛnՁkh,~^ uA .E%PWe;o{F9/(]!4uI{|_*!e,ʬ\%NƵsk]_z 4qn{ܩJ[=]H.Ja.ղD Oœ ZQrBn^ ´\w 5$he(Z3?_wdGV`Boȑ'lџ?{K]`)=Ys}~9Z ӆwemw:(ґ)wL{0(WKezp8I 4˸If+fȞsgk+SR?Y|Up,ݑ[h/([bDi mt֞ጯ6c\ɐ7^<͌I{{ol<)C(]p?\t k'Ň-75?j+{QcY*)\B|Ͷ䱭 }*wn`|~f@ݦ1=gG;jnG=m846(g槭 r6 VWu^\ʂqMKN10&Q/O(R/)t^8OI-) BیOVqL`g'vn ai0.Djg) a @߳q~Z\IXY]f39l=AX\𛣒!w715+jgJXPq<9DAo?e~ax1WWK2\kӧ劣r-@~,†Р{x<*:Tj'zc=vzzsk1c}:avy݆:wNT?W*f>7l6hRO)g]n3Ů\Uάﵟ8e="?}<6:+LR7WM|]haȧRK[yAR>'*Z@mAN b YE Ꮋ!w_|uhB!ԸbB1{7Yr?А7Clss)u(@Ү_g*X}BBdz)Mbw3 RNl L\"L p"e"VJk޹8_1ǥnom aLlH8Khב"nI9m U:T;{}Lx$ #j*.L[Ʒ+q<ϟ1ؽٴQ<6}IV2mT2C ]f)Wu0R2_=|AVŲhHˎ .3Faʼ G$vrJ'ThL=휣tBj_ݿR%sڔTX%\(1'2}siꮒ=/5} &3|hh>6~B)d 2N=5ȽHO%W&G =IJ A!WQnr~U&A1Q //4{eGx=_PO;ʜ5Ӝ?.dʷR7ОbqZ3F\Z+A/xοFY"6Л)1&e2]:uGs$Q8ʜϕcćnvb?2?K*H-"s%9ziy"ɶ*]RC5cC7;=*YG5un*KD1ߊsHeki %h'̽z8_V)ވ5-qx99H}!d4֌†!dLDy!@tGvDnc|}mEZ18 N^<}ce r֓vs`/rv3ܾb1fN^M&\3TlwR9kG:#./gs{;)gvsFT%)Yzz^J#dy~':/L >ÞDZ;XDGwn{y5oJP"\ɝd0CWaXs{.Z`>o=1'WSpYHrgSlqQdо[eOUf FoK@۳O 4j&)ω$McfB~k:\l}}ö]GO*yj}nJch+N$yO"eæKגE9B_t cnQ5fG$b)do[M\;}@n2OI;gQs)M*HBDzU/*gIBYvO-l~r6D_㓩? 4%P[Ќ}tƧC) эvf!oF)qT<~יVZCO cnߺa)_2jӎ Ԝz?"~ѩ3nj >띅 }efa+zpo"돸%ԪrX! ṥJ[,#%l&ÎY+O$sxYpCa4LϨU$g}072{6~y>q!xCiǡiz#'鰛r䢰 [9Lkh?|&vlTl}E7 r~Ǜa<%o"x2w>ILąi*GzrL,qE^49R jǂI=.nto0Q'uU٩TZ;A1)ݺNGTkL/xHYŲ`@e?$ |ULAjyPJ9oFcnz0ݾ0 "]Ɣ?a_Iݬq(PSfRI9p̃:;a{c>d|c֎6Aaw6֜䤌'h~AEݧ3F]Q/4dSS7wvr\8|\CYfVQPq}I|)DI^Hxj}~Fn!y 0#[Ǩ<.UܺTuV= V"|fiYS"#l;$'NbeULCٵ)-vLҽm-e\1/%GM>87@\3Uuq-&xdDhA wg,)TS'箽GWzt%꺜ӂ~|ϔ/\՟.u_+i-J' :XX'5dC-rjQ>[%u/\n dgLɆ˝ӌOcjr&)Q[H}iLM#dkߣPDe!7R[>67Sބ^ f;Ϝ bV%s#nݹ׾5활>ޓ_:J5\O͚]3?0a ؁(ZLtK=e6el~kj$h˥ .(\T[5'vhʓNe~Nz0FqgV$Dv$dyR8Wнθ8 \q;# d)P^s{NOG^>H/շ<: h(V2u~H' :9^Mu .|QeޢRC5sIMF%L4l*mkSm .N3.^#l7ȓ$[7:R`;%RSs=Zo8X^1KQd|R}BEߙÐ o,18^G.םhT5DĶ'e x='ĶGƻYŜY)O1dvyJ3QWLp}|֬C!2?~ LNrUgLi; 77+1έJپq;Wdv=p}~T4CfWE6a1u\/OG=My! ayg,j96S%:㈞f(Dt]~UR5ŝLH2IthVGpζl]TоT0e"fBB4=H*M~nO}hHI.ل@Eɱn:8:D7UaPKׇ޽'%$rK˘l:0zMl\IϘ̐ec/f=-[h+ cpz'\fМW8$PD˝qQѸ{)jJaO(3*-f6<=dinҝ&UfvHwwDL3y?|.I-1~y"<}mwkD&: Zdvi2뗣ȏ*x.%xK T蒴WB&K/W~ +U2h 9CMMr[> sOLN?i gZǣTؼS]ĕ&mk6֩cl L|K(Jva fw:%Au.Gd>*%eoͽN%a4c,O@.Whq/*q(7h\9I5Eμ񆶌o5ɔd?R4=㱬V֩G/)+8&kxvWmRsSqq6pW}~R,e/]OD:+gR'xȜt=%V[oVtVkƻ4!7^&ETžI^Ym2r!eA/';ȒI|(IuI!Kɺ{mZPEgMnH3mHbkIU{,)] ׎m>B7d~2ʴ&cuvNhnˢph7C?qP֜ƹ!kDOnj˭Č?1.?:u" - v,T4]L,4iȔluDf'1kg#AG'+CEʓ'?.? ;5-Z랼7 $94ӳ̉h'#}xn >zM󞏅=ڌ>jJsc|QEW9U dvRyVT3Qt&Gg+.0 Bk|o /J9(4k eځ%eΎXq1Ŀy(DRZRϹLFZZN\FBBFF&')K@%l`bkX*)HBFm`Xz/eŗ_BZO73saa8iA0G$.%"OxSBL\JLFLFfM>v0qxĮU] Pg[,tD-"PBmp0wi7J$Y>%,[7Gڠg[8rnU vaڊA!qM 80-΁pH^oH#PCu! o7֡Qە-Ss? A9.:/'euF_t$ͥ~K+~wuu"[;*#ywUyYKiK$4 aPUUXՉ0J`lV_l$r[eƥ $IԖ!,>!8@wy#\ 7g8-~Y&7qDp%%X/K0η+"gAЙTk 8,pͰ C@j&lm`3_ځ"e^'v` Q+1 uߢ‘Pz_(D'& .gKkx+B.9`匁@(gqؑH,wuؚK|PH .1zBH$ *:yq'K[kg8 s~`y#˴CK:+"%p:L"EsU(NWC;9Ct!&p>K}[%B+;DGvM 0-P8=~G$v_[6/qCSa!Fo봕>l3s+n !(ecП6܉uj"%q,x84EL!`!ADYu$j910rG@Hn;esR~sȝ?H\V,/ r]k^q%@603\Z~p#q4\$Om@. 0(y_PD31{Y'4L!blwQ`;. rAeA1$!bMX ҕ6izL, aCCx+|!oyܷgz 'I}EܿW'Ǿ:<1z*r:+{}Z/!6ϫ}^o+K5؃eEx _A07#X} &<+8ʹaO/78-lMbSU_ m\. B1X8 5"sƏk0Z+ҿDU7(^wyuAEА5'UMIF{yPXaj6 u}cz"jkuZ1J,^+J D D lD d )g R 겳T"`TW$"em LI(`D+67>a$uKC=ԉrv([H"4,FAHr1G@ 8B"H:@[Ib !``HE(qB*.`  8-, ) 57 |fl (l[@yH( gDZLT8/˩ہ0]Ze&qD# /h(y3P~ȯyu a<P6GZj;rK[@PB, %",9){YP 6@57`]v  6vzk{_wVhu_aā=T0l@k6u4vO}e`.s,W2)YZW)E,]U1r~A#rf/Ü{;?(}RIlcYwo2.ɳX:TsUWn޳n/mO8 jz{JSd:oVnܧiQaN sFD髦-&.9{}| ?_ORJ秖($rR᧖xȓ ByyI, Xs~?zZZ᫑hZJgOѡUȕjJW{+5J\T}/??w//˄wQm+r.\+". 1IRe0RHB?o ?rҷgCģz Ge5Ãd\#4F.YFe1"IKl"iŃc)PQ|6E )z1! (NLPBiHB iBAJZR"B!PG YbuH#.g'٧vwTgW(ˇ5lsb)NH '.U \:Dbj]5*>U`p" A\q{,$Y$0Ivq=gWϐ!d,?"emϩ^T@7Y(ЁJᷡ~/aɎ3ma+lYһJPRZf&DCS@9 S) ̈́0D&V@ǩݢdÁ h#˸Dh@;Zؑ6'$e,!hRh4SU2n,AD\Vܭ#t,?˻xLWpa:L'M"-/|"pPA`?3OPx51d;1[(y<` Zx@ؿRfegqB-bd@]ʁ[vP$.F_.zR3%p8kA8n@/bj=3Tk>69!>܃.:,N,-,[0ҵ9>]sOpos86[pE,:-^榎U\~mnZ(QFSFW0Eb 8bvC_EF&׈!M,z Fc?Q]`JLGpI9PaN`rYH[ PGZ-09;v4 @ +588 iϜZA҄ s[$519n+?^ v(gmx5@v5Th$ӭ v'vlݢ T@8(8Kw,& :N*yzUA]Ea Li mgHN@59DfuaK]h ISNwN~JlHZh4E, ` 8@@GX'ɧ)f|q$j2( F)_-‹D|5 pJ saؐٯ* )b&P,!wO+"crG$ğWp:28Nw;ɪX&!zU.Q0sICJi`.O+B@J i0!8sP~&EЀ- 2#hO _ YdǬLBMē;kC`Q+^V-MkЌU'g66w Ǘ!n~\to݆jdZ"4:)a1/ npĀݿp`R$ " (Px"fZD)S ǩhjѝQi,4A YB9pJsW)k-([zV#|i5 Z k-́6!ns7(jE..eQ.?7aQ"Z*3Fb[1kD\꾚@ܣh",|#b6cJ6bz] 2JRaզeaHJ\v&N Q#vJ9ՁF05A#]&!f3lIrPq, T ̀PqorBE.b9B58vH?$ dwgN"t@NF$c@ぼƁML`M,Ԁu 0$bhD TV#x GlfE* % 3 &@jĀR,* jD&L$/R Nbl0Pa n{JF mbԈ>QO0@@H##Fx %?%;`8P_4&D@C fwU.t@`(|LwjDu(hFr9 P\_xr@m D\ufS osF,*C\\IyjSu8u׷xdkά~PŗIV)jPeVol76DXg6چ>>Og饔(Tj???G'+ Z%w+WCK"}=e)lF)UſelIJ$u0~װ7v:`g;MVxi#=u˙۪N lrȼ_g9㑙.n\g[ K=_{ӎ{Ȼ )g]QjQ"?g~aLYNn;5^ra:G'/Z8dLd\Y HZiwݻk 2_5;Ȥ}F-Roۺ8Of+lVC/W4&:N t;:b't|Z[aaO|L^]},}%q7qe?Ef[hbOܘ:|B%ޝg==lv?X^X{^&Gշ/|0~~$A"v7mխ`1j%ҝm<[6hvt͉Ȟu9AGFa%#ߤrٵ[Y& 4Z{|vj7]]=}/8VxCm)Tikgt}^)vפi2()D=gEZ>Fko6v|?M7Qo;K<ͷOݓsnfOhy鏿>^]7N0 #Fn{\^h~ Q;x۵&=LaD'z`6ۖO]pnLf=^i,&]AEqv|Զdv:,@ͶfRn zϜYhگlZ5Yq6>\RޙKIk%-lbBӿs_ #V^޶>l] [n,gmFIkdžw~NN/  =HN'zrigAi7uOYi/84Sc"Z\3 ަ}&u]WsSĞ\X!>SP# .L Z\ ·#AۇE@i)^ä~ZUM =uZں@a?Si}Dx ŅX=68rDEҖg~9p -RR^؁9ԣ<רq|Hg| #g=QsIG@x|>!oG6 {9ğ$s}b̪MS7vK $O_&PW n}} Re^&U3᮳hxU@YUKv:K?KVOM_F\ pje-h+OB.ku~ 7"O-9})\YSeHq 󨵼$yE%y@ j÷?PkOhO._9_Vu{1,/m2;Y]_;ϹTví~A1ؤ[6E$BFՙ_}@ L,s`mgnrw.H1vsᩊ-dMY*5%=hF _*LoKSSݷbVJp.ZrG=YXYa]-{$`nmlu6^̪)̊y"ȗl/Ȃ}8VVn]ج/>zU?{_Y:(W3 ~\,5L]ؿko98Mjn$'"WL}U-LZg0Ì[ xx[! ejLAR= >b߱i5 T =Y&Pմ7G|ۤJ3`G(V7e.jLH^msdeg;^)sR3tS͌~ 1Z@It4])7:BV[$%ϗnň"./ud)͵u&ГDfpٷwgFNsm)ce#{\XsJZӝ]~1=D1nӘI2Fs7'՘fFBdeᡶΙ>MCyqOZ>gF#ǽ,8T--͎1ao`&̛քhDa 3}KCeUN32*P$Hq6GMJy8J ѻƩL ϣ$,d\7$e Xӝ°:1rs< Gn9ч1lj*_ka |p^p[3u>vxcXw8|y^& #d ;tJ(b\+US% lA)=9**JMġ6|tz٠<2Cy=2#:{i܉Cʞ5HҞOFfKK>.̡bz2n~@Jd/Hs-ґfr6]]`iG/\NZ˕ 묮UҬPIFANJm Ld&-!jϽաΨ5Tu@橃w5&kIYk)uTKHH [gF5$bg?T/^$h_Sxfϥ`U9oiV 3J[8]i߇YGYyrY)8|\ ^rbZi+йl@!`P(̃oVԸ MTKXX th#̄+Ȏb(`pQ1 ^<(sSf!iYqR.)v ŮpSK´Vt#[T֋Hqɽ1%#v8s-mX Fkz+ߎ!ϲ9ΌN0\$-ndSmFvDՉc3]@j|3^ht)-ۉ\O10%il節"Xy(%oaj9۾p b 6 EK}jSF?sbx+pliIAʮ*;6 InxJx FB\B G @{^Mc^ՎRX;6@#q-ϧ>I YTEGs ^㓔 t{eb]5x '|lAƛO.-Fd_5)m 6S0.#Ț$vVW w( <,k* XhMb6ot^#Q^*.BQsp0/M]'pzTRx(%(sIcv(gh 'Y׈y;©E_E΁^3(9˃-2+Ók=ϊ(E'Yߞ RW.1'5ޚ!'pn}VXI/(*S`j9 YY=RsH=scG+WP)^j -1?BMBT),i^3,+ߙ2>qp9N>$:eLxwne*NZ=G| |t,tD Kсaq]bqkOzQLkluV?iq*U~̃. )QԈo3/LmVYn&v D쒷 4ӧst K(M0a>ssy=jor NjdDOHشY!`I׿x4ОzVL;P/Ehk~8( j#ɥu{:P4YWiJg@%ڍfz֘uEb CO#ϋx2+AN\hBl]Edi:%뫶'򁉜A ږQS; =)G]<GnXA}`xDYoI4#=nTL%?}#ă+i)kJFi@G; ]]N8PޙJ '='捺 ȼ(D@ҷI+('6$ݡ-\nO.ғoUϬlFA^O~؞pJ@SюJ˅xQBO2#`/I V8ʘ4ZHt5(-X (R-dQ=:/27@f(x|NvZu=ҭэVr3t?Tg{W]~p!Ř)e"Wo}¾)v+#wsWOa e=>4Tk$8 mS7wUdn]8֪ɯ7v! ٻ1ȋWHr/M'F]#-5HͶ i`IE^^ZMK޶Xk<ݚhmrтݔ+dӪpі%vW?qy`Xcg$-ݯ(5mպ.↴דj KݸK+*ѰG R,' eЩtn~DE }L sv/@B,4՗+ bϡXwoft^+o0%}ZVݢ񝚝f uFGn1B7'szk(Twβm۞bë{^1@RV&;!?? gf7}{'Fp;J^00F"4`goܼ%6-hOs4ҤၙA EڄpK2.3𭵭wE{=b蓮t:u'Jۦ̈Mn+Un={n*VI|E-yi~M,tꝆsA/ެ޷UCpm#l3()JPqKĚ2t. u8%1ITNW<"k'wLǛ0?g;ޠDV|-0y.P$[QjѪuaH#VXڠ6=z@3G1wZNnE$hPSu!)h,S9K^V&+ JH \[KBș9mhð.RWs\i]쏘7HcmCgД!oNQlJ,/q7*Bǎb=ҕB° etp/(qgJ+:7a@ϛu1B~ U`.N gMJʻ<WuiH%YʇЈ E]&uh~ԜQdY_|]T!>rv|)*$S~/\xNٵUWʊluzD.̀u)*hu5DJZ qn:bt1 O;'&t$A-N0]mVĤpvcOp0[#mg9g.xm\:"QwAqFS9!ĒcZgMucDl%-@w;u5@Ꮰ0GPSxsqT4+`ep]+jov`nYزooCOwP=oV(6"(\ pTo1FH-~uh 2Nm:Gf?LOt S7(W' ["i}/@`w/| 쀜 <.풺3WY w ESk.~Ed%MDVlZ˂<0WÔ&H\oG,Auhjw 5Êb?{Gdd̻ fB5kGysn1;3q`ͥB'^V=% ^AIfx)4#PMŸnioslZcT8i]xTߛ1jc+Q*:!dvymj;t] 8 A X$HqIJBĆ ! cmX~v鴵g^ƽC$ _ :\Y$7"k67v,.6؞ϘgnZ&4F1q!קzd2LN}:h^W15@H7G!=0XrBe9B0l$9b#d '[@[?j2WŔ"Hϭi FIKjv:KeE~hbQ~-g1O aݰL#sbDPj ST\+ɔڻң}p#FcA)2BqV>\7,{vr_jB~>]5~TZ9F3f4O3NkMeDGm5{UWz+z!ù/@iAެ"Ec-}B@L̜ʅi! SApX)'14,,ejx9M]B6"cp6QH`;/BC<2Bx0 gi3+aH_Z9|5>6 = J' tt쾵}#sRɍ%_=^(8YYO66-^qM3 "v󮋶W0[t,Tӱw x>?؂sIzaȴu_dWkR6Nuz9/pBѮbHt` j9, ,h2g˅FpqXO"Gm=b{uVؤ~X OԛxΕE%ߝ(m-7loi[=ͿNMa0\G&S ,}D$6@ {òlVQtY !LA@ c =@̂JӡCA@l*xm ~Ugj4\)p!) č]ΧU"&NOU!)%sσ54pQ(ݐkĹws57AJ d 2{zwmYOX㽁TdpZ82E϶kdpo:B6QL$yƊjSrFIZ1FXr?b]fv0n|@ U f,=x/MP~{Hʳ?WN)u4FhDLV : lQ\n/ã=L(},w>o9ioLA Pn1Pgb^~KCMpPiVRgthD \m>TW|{ ?wVAo7@w{t{:窆#˗':>=JJL_ =y@8OMKn|,]!E `:zg"$Kˢ%0r-*=! )MueyT T 3~.h/'7uD;ʝF+VlvxJy1cBign@Ag$uMԿ8K.}h\ `Mp"Mm#*Y:pR]Ĝ`GCY禒ZPvg93jJz0.nvk׍fV[CRm){pgRv ;C[ϲr7`rҵ|P-8: b?"v-A۩HFP8APnM|FE8X,f`2yT7ye0x ܥj%=AȖ~5IWhg+M;6ӶW=*2%FYZ+J1zV,+wg#S3 *ڌ{%UX)^ J2?xXVd[}hws^;ҬU\ᗗ.ԹpҲ=ayI+GvK+}̡u=OUu;O(PEHX+~){:Ńo^䲞KV] ->{?D3] sdQzI j{0fW'w\u1DSBڎghMzu6LLϘ,_Ԗy{Cxd9EjZ Yy_=>Z1DfM[T|U-:pʼaPP0z{;ف+4iOyo Գfִ{f@+vԃ6G2}*>T lve*ZghÔ{Vu'.AZ7q/{ɑ|,o}ȘH(YB:W;*qowUvpwXv>#s齂*gPf[Tߞ_hkK*h ?8 VQo(6nC[ Y?:x_ޟRqstE){TL׹G?)oq5{;qr4ո_9r>5?]{!PTnxn=R(~qlsxqar{wmeDiӦnuU^=z<!\Oh~۲u4n oTڮpZ-?8h+l8#1vA\nc`/M,Uԇ'@{n,2wE 9EYǮNxEVkVd}j-}+إZJgh_ֱvfZ= 0ʜ#pS}:3%gZ;Vѹ1f#&JStxIW-~8$i+4!j-߫f!v0 \D;ɰطȨȞpYY7x CG?))}}-dr C@b9WrQLdqYkEmFS]6)WԹbv:5B1H;

BE𼖁~T]^wKX+Hϩ3wۋj;&6#o;;m!<ll$8s+d =.`$A0-4WλV1Xݢ- Z=D)3y%Si mIRpY޲}t3=FmQq"sSu1w`pa)F^(>yoь |6{aR1O8"H|i^G[},$D ^و\رYϙUx} mc3ͻc6>yIݓ#o9m*s2{u|kyG* ;okP] S %q᱄i sŻ2`ՂM w;n} !G|COdkxV'@P75͝r7<93%udN|ixdUF+aǻl"}xDܳ8\vx*zg"mNȿV)sEG?UG쥚l= ۍ^L28Goד)?wk]Y׫2TƌvTQˉ*_=ڔރ݃n  e4!c5SL Û1=:K߿by6c'ݳґg6WLYuUtqĦ~h.k'fw@Jg(RڽA9… lSN}D;n hՔW=:4Ui89y|:ڵ2Ã%Gk0QGS^$d:&d߈bwc|xvv~Aar4l:JʴÙ [ASrBgYfs\+TE~B^evХ^]CpOo5`&rd5n{1%lHautW^-)~#KUMK6v;15 pUEN oΧc{mw %@B%{aG( |bMq36o3>ݵ8~1ɡ.gЄxDk.XwW=ٓuWl*p-y?l#|v昡'+`uIFIQ@ԍXnsN #U[AL]&ʏ=ۄ"E6c.3j$e ^m|ɷ0Eϋ:T ^WuKqx{woLmex4M0*6KdK|^<_ze͖=ԑ2;tvrRXhö'Tpq\0>dXiC ԣ۹$sҏ!%4/ cTz,c`Z|Mx^~'1>7$q7j?6`/UUթn:Gvrm;{n6mb5,ͅ'ժŭ<]Z '+Ȳ桙hROҟu9EۘCB型T)r1ʵb7f1:%@ak̄DjTڱsFamvw-Ә^+B%6m1|7"gQr`Lt# n|i玄E[Gڧ|eWJ>QT 1Ι'3aL[O$2^}'vVjtoڞԓјJ0IJ8UK$Pc~v}Jd+ܵ: ;8e+{=HHS5V]֤+ AoOTu|XRibjҤ7Ce Ik*3i>ݪڷ=.%(Hp@Be9z1%ѨxusFOEZ.u* t-{ʫCWJ7:r,Oz0C}D26z`X~9i1.µN;j5gn],X|7;R!L@!'җJ \`D&̷6PwT0UB.ׁ$\KuO 0[\k!M hWT71tP ㎢SvmO8`fY7cBKdx.ډk6ϼJ{ʠ7jL${|O8{~~ 87B{NK/lHWP Ɋ$z/ ڳنҋψWYg ߁\NӴV}yC3wE>_,[OWG>P&⏯ b~HJ'S#_CB@S36uow4CsA(9%sw/o#UM L^'WSY70/eۡ3jG_Wڝ,S8tt&3Vp{S&絒|ws4qo)6G5_~mɢSmtϯy84qL^fՉ;X^ź@Z{ΜıSׅLN2۹Kn<ДS7,:ٰf&kJw]JZlX#dZ} Ĵj3 '>Yp?t5xw?{G>W[)mGa6ktm?$FI>zu=EtEXa #^"Մ;5 FnQqW^jzMX ^ b:kjs ^@yU41;]+LVln󑠋iϷD%]٨X "vKPj@TN 7W>sx,dIN^XJZ◷޴29Y2>|3+ĖFCncoތmhP{Ug U00~=e3ڦ[f?v`}ll9[`<[Fg3Úl%Tn*sݫI=burQt[!x&]8ܮ"7΍F?蹘*w6s~Q\u>i*#AxfElZ};W.?)]|(d,Fר2mIu>{.rH w쪨РZQ/tP@NYAz,Nٍ ,S _+r2~rӜmLKVU&/T"_V12JiE.8}yT𓬷 Xe,l9q lf Ҷ&Z._]itӷ4FھՔwC4m9ffpp;%V2ETtg5Y`HfvqZiQ2ΝX68Q{Lyve+R_5M{{X NvE{쿙༇'>HuS]P 6 1#"LQ3ϷĶ+[CCUy$`s)U.>*};6̉ӄFn߽"jC=ޛ3 djUv}Ȫ);pMIsbk` T4{h` 5BSznfk('b\C'iy]G:MJP$T{w.zp?I'znzpu3gkn~֐goou=OFSkoI?eFoD{詃sKk]sUz3srz`sE\gX'=OȘjle?#(\MI;Z;_qS]ޱ:_-D 4#erBJBTzη8}u.3lnZ PG~ DO3;;Ϊ: A|aYKk>>es}Y&T+LWN:5G̵֫`{lYc ƏLOP" CcXک p[%%h|2rM7f.i_E pgPnu ]5ֲ%Yq[ؾ!\pEӬ~0>:h1ʲ.N~0~d8xD׍GiϢhoxcxmrNrm)מIrix?愱8綰OɄn_r,3orW)>~\f+Mem6Qcp)[Fvy$Rx~O]h,DOtyu1+0FYɘB Ra)s[cwZ~CK=o9kRykK#ԙHKQ~Q[;ߺu}f%GC:6"#9zmJpŽhMՋji/wt;qFXUsH..ĆP6IuE=:L]rSm=~"kPQq~{#S\ SҜ̐}}fH:MjԽ1LE~ ?4}Q$†@޲-R*[-Ӫ}޳n~9L-^2 n偢*N5Y7q[tkV]Y֩EuEfra46\f`k>#,'(J1 3M> 533%?t,_o7%gbqPT繁T~sSvz64,8-~%f+uBI0pi8fۋR?48,&љj'qHJw̪ó&:|rrݺ״S7TW?CUe)y_Sn`m]LӆK/N}c5 "Y-#|]2ӷI P%@Q&[^FTblfY>laK:b?OaBsnhU\JَOR0U|S`֣;M̟߳G}@~#豸'Wيu,pj姭JEkζnJpJkG|Cw4zZqz^ֺ*F݆n7ڢR}ye(% ӕhO <[Gfmَ9OϹY$ŭ}v7?t (j;r tK2uX}qFꢜİTx5׭#{;=en9!3O9;)rlj~HʯLKJ8Vi2„w]kS$Ub\C U EvƸq(G=Jݑ>]~cМ&ܧk}*M+XsI&J:YxS #7b%6ͼ~ ?4@U֗$Q*"%KMs98P[7"9zm}a^:m7{ϖ<egL3 /y .n2^Bͱ6V]s0zi)|EOxS{͠f. WDԎ}JCL5L͂OoH /ЩW2⮘iزWGr(ٽ :7d?YU(/9=/6/RY2I1+ Kh9;ɴS>Of^$`(-P%0U}sOhH Vmbj[޻H9cףT>1'_V93#ӝ'?é)c>AF!O8p"ז#{z!כl:C'匞"ͽ6=,eصأQZL`jAur֨Qiр쯶&bTZTQ!ݩe:'#s7j^{{;} \rsE 3zD&+DѾv [J=s5T ^JŞ ( ũ8:97NNQs- "7y?RyЏ,5,-C]h1ZA{y׫۷.ޚ)q<#~*Zݗя>ljDHLv\ NrN덲*о{N^ E,=5&!©M%ʕ̹:nrǤ07%O= pZ_@gFՆxLW`û5 AL BmY~.'8Rm .`CH6f+7&6zpRbqV/˙LyX9 exyv߾g&UԽ)S[nkL.!T;cǍl_0,F gk]_4uk~e‚1O /WE  \p (D@2?V^ee9ZVjݪm v90I0ru:{Kj QUaRG DR + !3cag_$Q?0%t!+8X3s%В.(43p&!h$("aJ0'|Af:ƒ]]wwH>^!u<%~ A8 ~!~-C_CQ徿E^ "o37W(_P;0įdjorʿ%jWqJ2WH&?C$Zu% C(g 3Ph2'd9iI6EdK Ld `]]9hҼ(( l+`$<0<84 xI`H|#%i-9q ^!\6)"I~E$1g!HB[ q&``HyC WC>qIK+hK®FJE%WA#IK$y!#GDL2xYgN` M@A&oHN`}u/[=d#)9A0 aA,8$֟!D]B͟9j㲓Hq@Ax 4}'!@-K;IsXsXrsIb=*E'+cK+1J ,1I8\(Β1W.I?Ɵ>KI^k2A{ -ɮ$" qH|A`'!ǥ!(7 b$nqF\]Pv! n)JɠsAaQ/oI̮~>XZk!Kҥ%B,]Jb*g` ƃp(MX6qKz")*S₊^^Pw-W'/7bK2uPOnB B½q!#.u[E#1|8 p?1 `K8ÇQ(03$XpߚKLvנI\XK?ݏ pKəՙ.פ_~/C@``9_u* {K܀ P#Ok"1ܗ2.Y*h2(ik0Fq@BO#_#d%@,@7I:vܡ ?Z~ʔV**B TdV?l l:ڪS~/=8: Tgv}:`+^9˴+oA4[nXn{[Խ6߭qc\OB=3`u\Ο㮵sTUYw[.FLɩt=2cR Sһ~Yp^{}o7.i}}`䓮Gw9QʞwB&l/EC~bYJ. Yy}DH?^t_^&/5}L.W~}wjp_{IH]= ٲ%{j! G޲M V-v^G+GF38Ez+ǿyL ÂcXOQm+VZ k@4E03|Ou?tŤHN= Ă'a4P6Z!ڀ;OU4Z$^u@TWz()B"\)R=f$1* xJOΤچ#,X8 g/tӢUS6T л)Y . DstZ ~',@%,kOd"ZD'0i:q~$$ g#A{#Tp OT Nj s㨂2h2/3҉`&n$n[%( j/bED3@ P|]En\dJ>fSSNq##Snv/@ġDfC5C4ͻxaZ`FƷ" QpPډM07l1QDЪ=ԃv x|u[ ^scaEp!qLCKVq{0ǡ΀6 Ah8܂T[\IJ%tWo/lpcHVn))=Gwa4Ez G pKYuI!)7zaEtMtwq6@LOrqOFZMH,zuT":,ʖΣ U?1#yt((N0,JOQ.y}YU&R8T!WV9&;j"WK-I1˞SX`vADX\0%p, ,7Krhf'!E6'!f\ǿM҄ ظ¶~ 6p-GUZA$RDSQQS k[S@)>̟A/`W|-ӗ(]x̀7"R7x5BƠ*8(ƄVkP0tDa$@!4J$(!x?$JR"I@d2azOxT2 i*+{ vCd9xCRZm'kg1raL|=Yi* /T~mwjX<}o{ ؅JT@?nQa {KB-V-N#$rUp2x,D:H!  IhL.hsIfb=/Aؓ nEoP\KpwA rd"jʿBts AjP,D!"ɣ"딻٘fDVw_n$"A0 . 6)~",hAf ɱa@ d(cFADi ?(I!*gq7'mR&CH,(oq 4%P@.fb )='8IHY`2a 4j2a/ 6P0GRԯ0 M@ @(PӦ* X|bU7ib7Pd\<IT7渐 7 ݔ &\?_"%: hJ7@Z֑w{vOʔ`xrl$ &tnJCVvlDI@l @QK3]f$BPavq9U\k )tpW-N[[@ߥB`XvZuI#|a>gl567jL29dDzDk{"tHA@n [W0 47 㤞0%=ɰqs0'V=Aaø\a#Xe(C*j'wT B hZVTJ:P)k^acXn^&>yPqj>YR4nxСѭi eu9h튚*S=Vs>֎9C)9YZK–1A16}j,l8ߘx$>Y88gCz@ş<ÓGz|4] NJNnkcSDǴZ;7&ٰN Z^.vڸK?זW迵fo5cjfxc)C9nsݭ;d>n~gUѶ/w6BKfr>y;Zz'z~k~ɓX4pӌE__#vֺCٰ;X_z>[P`BF9~Z18ie;ޏ;މyZ9+.k|nߜ+Wվ]Vu%ڨG| .]ixσggS#i=_u^zAm0) |2vA]6ìG?9z zi;.zr7k/ !#lmMM}_3X\^ϓ9p69o\2kM:OuԫgӒuӶLmQ6x2Eܧ~uKӕs'򻔶אg|9~sۖ]3zoG vc'MFmbfQ}9Qkr67W{嗸:L̚âVWܛ~/_|$38:As'Gle[7~ԓ~mgxpO>\O5"iWuHZ}I-o]t;o,\.o3vD*YM}k>UuxƔz)Lfnbo?BգԱ{Rk/]Mi8圿Bt{O='/PTS-vYI' MwEby.?p ]&z-l ߯_6cY%qE7^G<{Cھ#gv8ѰA[۾~ܼ)~zҠ_w`n>mC*XvG\;O740PQ/SoȍE+޺⒍ߟZw<}zTԴ}ڶ;n|zbѣFxhט>k1t=sK[zzZKǩ./0.biz(uΌzLCZu:ܰl+Uv|oƸcӻ6(N臟2n٭S}A.ܶۑCSˈR ?۫>_?;Lj&c7Mh3 }t}.S.y4B2bި%yxWժ~z#}ǦMEk9ٗaICA3l!?kQQѻ-غ OoHzV}bNFės>{O5,,qʐ4fuw.fKMN?~8k8gu#g{Gf=`ɂf_.=ם!#Tuʰ;rlCS=*ٗެrj ZNE2MV4ym/kמ"a gvvmۭ6ۜ&ٞlo6vMv[sunW/CSU?c?D1y 5TE';&  HK vv=|FBr,ZIh]1 :qG>EҞ_>[JaZGT`瀯Bdjƒ D2-dzRLB+äW%Us|4E4]Va[DhdXH?Z2bcH?GaE7yop7¦EbAP+ARyF3/Xv2Le%^j~;1]Aտ+ܕB7^gK !IQM??E "{Gxnls37խk0%jS#K+㱏iu_ rwI(ლ5f@2ٰބ&xݸ0e0q e7k[m1>ǽ*S:˴WO\0(|ѤhH%#RI4pq0^n_s?'bIη o& 巬ۢy ST@oQbcR\_e1HہGLb:Z^UfSaEd?d8- AU*8[&);*& Oox 2pC-mw6YɹCQ/]̓c.u?v:pQk  )Or$>_^S^vb io <+$l4uZQ#s.VM&ҾugM1T W4}eUiY}S"97y$3ulإ18G /hڊ5DZԤElS$W]a[ GW&p)|=!=D;|ś*!Zwk|Bȱ{5iPoGcd1ʍdHSm5.U "a4鳫vPE$*OpH&&8ʴVە{x=SbuJmg<|T0%Hl%WZ]Ю&Ktrվt; 2Ǭڷͭ}gHgǠ?N\gc [m|oUl0B&2?Q ]>8[w6/q]W.~ޘ2D}pPt _+Ү^1|#QLaϿD*v?ӈɿQ!gճ1IcDx#;Ipd-|};=6|YI4.qX+4%Ćcl+(#?Dߌ"wEG1hw\ v'(NYlmU-Iȧ3VDqI%!=/ђ@OhǼwi=R?88,]e3k'rB2M[m&f*bN̤kfnxɱ;jb p:c4,Qg ;}Aۄ9bPs{ie}"7\BD|+siU2bikOKT\T,Q Ihz#tE[ԣ폔テ?1`ַM23jLV=?z,9N L4C bb6WO` 厃-bx0W$24_IWGL p 7ֶWtxBj3u\2wi{h p^_NBʲ41I}ا\ј/Mzѿ?9"I=hv rij+?1m놳%%ْ9G;1E !RѧĘ`$^ fIfk2Wcw|\zeIwSe EK6FhUZD),̊Tj:\$G;=? S} 'yحkGL Sϳxggnj3ߓH -yro*±AwOeQLKTC4:ZZ1f=Aظ!$ hjvO:FckHâ~lS>Yfرvi_~L,vzv^V ;Bb<-I~~X UlL""hw?vڦO#ݺǀSeJ[8;z"4YvhouKT $a푻^ %<X %@ M "=`T"&+YdSK xlV|A]–ރL2k8j30,.q %"uetEI<LV9a]h/Q"3Ǹ:S/rޜPHwjP'lt*, ꤰ ZG}V=mQ H']Sy>s :1|y}*?:RTPңl3CyI7z7n!׋q#PuN>5g/2 TiP8S0*S)44a\Gljka;խdw_r&tz-h)UW~%MOƠ. )qohѴˇ]Wِ#ُ̩XwZbn QHC/%R;;$p}LVdtـ=pXի㸦A %Ô>zs(u[ԗ*2A_n(c^;Rk@#D>2L;n$8LwaWyH5FpG~&GoGhDgt {M>+RTvt1oxL6 3sDLլJf?X"3v#oՀ?qFj?18Ʉhl9XBp;;+wA@02QմF6ױmzs#%/Ж <wngVI\4'n7;ܬIJlٔx׏::^fs*T%2׺{FQӐP>}oX)J';5q]V% ފOl^gUީ%̳ YW%o"掜M*.0ɶL;8<Œ/ZkP6)@,([$Y{@={ 7jmFL\S))Z:<,: X]‘aDbW@"'`n9  (e4o]*VxBD{Q`$]W%G`%Bݔ|+ŷt&GRR2S=dh 8KoUb4)Gэ)U\)+RRgNNvB_ ?/ǟ5zHTПi{>x&"[i]5`ٽ\ Q1Z}yqO~_ZpNRc$+)QMiq$[\Dhd1k[E[7 SJ%kѠPZdعHk4qy] N e߸ Dh|42$/lFa>*,"*F5㰶x}nSSdI:Xx}\WzVHƒF@=*ma+!pKMDZ;>=cmJ63<հ I}pB::yOS^Lz 'X_1Ro[-ƥ <y#&]iA#_`h r>{s[$s]lb_׳pW:RѧQkm)a }i %P+ E *48Ԗ4˺huT35hp#N何 ћE| g9{l1ϪN#>T}~ 3g2Y:a35 <}r-G9g! S$:~3 4ĚL mϪ<:m^5W0|D*2K-ג)ЫHan?FŚ' 3Կ^τMH1iqFvb%ֱ oM].B"#[3;p*uDZy.M [4_/շe haL{ 7zZxCb6.jFtkD^AI(r'_d\d;N}rm0َ'> ڳ˓%sĊGUcTU օwa1wIPaa9x \?+@)^k M%-haP@R>օRZAOO< B3b9H'Oܳ}3_XNe}|/rMzbuHZ| i/D׿v"Λ S'i|32ҡDqy :|foi;ҥ@܁aA$7 k)9.5)c}/$әYZk5-/V4p2)Ge~@KqjO`N~v[LU힝x݌|{899,(ZRSG,mp(rOQ`Pzsjum[YSmz뱀u.a[Qj#/Y]}O8#,P2f# /q){ A'@ Vd[bx=aTKl d߆[GXNRХwVJQ_m^$1\wV| nW6c,fi_lVX}`;E+:Ij̭[Uw:A7.gCx :..Y˝v'Z30PG9jHLNWq+6w  a/~Wjm~ԓGJMӬaCX+Rk &8IH_-Y7_7:VgTX`'Ɉm8jIj+8.-su(*ӧtw< qO" m5m0ow֤6Hrp0!ǮId=c0<.C B8ZJp(9DзwfXFo[HRrߝ.=Wg,mCʎ|6Ϲ ZByncR?7HJZ 2 Ҋ MRei '(&7XnT~#2g\mc@H1;`1if!l4%x6Ti]H,XIhGS.Ej\5䂒h!𹘶##7~B8&~]Ud`ZfaRt٪fSՙ[fjvsQWGzk,??EX&pܹx37N22506IffIiF&Ifi\S xy3g^] TO*ֿZ*֥D\J,j낓d ę KUںupnbZZqVU,hޛ9Jf{޷fx(#( TܙBRdJ ZVe J*ܩTaeXY5VVW_zXIMEeq :3S$ +~ܧR!W) E`:.}?j8Qk,珌etV9U` S$FǟhQ[R-@-cL,e`5ar-t EH-E]0K ; נ,Հ]TJK8ԀѮbEH=E|QYJL C2&,O0y 7 grI1;U9bNX-e Zg>ñGt%s) ] .6UFI wEa+p Iω"Np<;R`G +fRe%R$! \|j ܢPZvygXx-R,NE;OPdA|e B׫`  Z9[B㔞II׌p:w= )aj, f0fru:bcAD`}iT<XNi%lpFiƈr` AphTb@d#":\RV!ՁE~KP$'uTT՚0R<> _(i2`fj8U9I IZx'AOhC(+k7*Ggi 5KdVWR*JHP$KSDR%zj(IbU7yb$\[IGtX.78>:pxD5ӎt+`USjt(Rk%a$pJOݛ%"ng9΁owND%vݒu3Hۏ 7d f0 ',+xKZ]QBҪ@ fp(,2F\JBK-c `U .:1!:ƌE7.EBsPVzeQZڢJe㆘H(vԲB*sKܲץƌҬHkWa2+7:*^3J _e9{PM-mLR4uP@='֍+%Gds7Te:#$jqb)iP95gU t9U+!d:bҘ#,S0JaH^KtHhTl{ZYLYI_*߆/m.Q\?e7K:Uuro'@f Xɝ4hFW XAV ϤQ"萨?X1'$q] g0@i܄X(d.9Kj;DꥭҴV@cۄ(&E$"R8^MY) pW'ՠ*;`/aY{50<}%+!< :I(׉#Q'Q8-#ES8uuRt61\ˍ @TC`,B?ID \I\KPZlEW#"O]En\dB6 SSq##Sn6/uCDfC5C4ջøaJk`Fʷ< Q%pPډM0 mጅQDЪ=ԃvrx|q[Pi}' 1ȅn.;_:k BZ5!^9̄TKIJ%tWm/lpHVn))=Gwa4Ez E- pKYuI!)ZaFtNt8wr6@==+* 7!y8(x1бfQd F9D~`C Ѯpo`XdwQ.y]}Ye&8ΓT"f1& j"gK5E1˞SX`6A@YYa.|^P8brȄvћHv4WJ !E6!F\ÿM҄ X²~ 6p5GeZA$RDS^QR kКS@)??̟AO`W:}-ӗ)(]xL7/"R7x9Bʠ28(ƄZP0Db$D!qAJ$(!x_$R H͓`jDf V)4[JJ.,o$UrKՆ9V _Vc7ȉ1ThfжPE Ӳ߅|{Hͳ8WHw5 ,>6u`)¹%\ 4xDv/W@(3a@*&vE_IB<` E,(opBH 0+C]hy ",Hv(g\|\ˏ[.'QS W^0M@0*lpk|WNzTnqul"A$)T"Q@vIH2&Y)-mbL $ȀHi `J0F4DY8%@q= :ȰX9c];n43Djrg1@y~ f :@D*@RZ Np)9 aFPn5IذQ3(#jWW$Fjq qj= j|b7iq7Pd GR䌤D*Ň/zQҀER.r}" % =Q1 o&!. P3^ )dB8P' tnJC6DI-@QlI@fjv.#PF0^8vq,9s3h W_ [@;ߥB`X 4/4z-mqw\=W€<Ýmݱ"-r86 m_mfH&\|'UIq3'V5Qq0a ƈٍPpGP@T*?CPʔAj:P PJJ UQʰ(+wTW_z(` @U:-W "SX^k m]p`. E00w:`Q7?b=HU.8'Y͇qǃ%ΝiLKc(ܨ9#VYN doΏ^v~L3=W1Ꮱd?[j:pYYY`aD݉2g^lT+97y=๱o7 +wNȝk^ߦnnzfWieq=>pUL}o⑵.`OЯ%.z7isy$h syۭCfw`i^kX1d4|]3Z~x~{v9o < 97n./j=B}ӛu|:͈ uNUz~ߩ6:*,vb :&?{v%NMz2Qc_l<ܫ4ofp> #?<޽h*g™Պ ƍ7jx>?]n}_/5ޝƼ\;lH{ 6y3m^//BEe#ZPm1;&dCXtԊ. |v&F53bxԺAsve'{ƍ(]T]}by{ָyܫh_?~fʹ>74}_X~ՆKw/V,MN-*Y9FS6xȿniY^6+ oRw+/ ߾Ա묙33.pG@=. E-O|'1-rb 5W};sYlA4r]C-S[;2e~:1⯔HXY Τ<׷d^/V=zCk|vѥȂ>wZS֜S )SK'eMއ~kBŵwsŘ0qMv;xYn;eݱRE֚+60ǚrcվQSJfCt/};b,_%q??ħ=Z/;vNO0xߌ½:罓dv<~k4u,VM=8pӃ :׮V1cS/?ԀSzʯ~̊^[$횼pO-.\mz6(1Vn|z 4AE[Tn:-b&Ϩ52}S>'j3jѼPx@/:ڻ"ݽ+-W~.M6jÉ+ڍv?v~V?kxl >Z1oHԼגẘVYK>#?ۼrdJ uWt`qNwƇMxek.߸TzÝ[# f|Ь;ò`hx栴U, zzm >mZ]3jFRDzF7={vSeƞEz̝X3ﮞۜ$;3'(*~gAl7m9h9޼dޒ.bZ~2;2܉1I=>V]3.q]3jz"vMz?{Bfy$$}=̰GWȖec݉97TW9Ȱރr<荴  }m||ea3$\D>cȿ᳊Ls(~CYVw$;~Şg;f(|yiug۵:N[БڛG9pq0?#k/OYv*33)8?wߨuj{Xͥ= #~8p~w_+[43u -9Og;%eڑ9/x0ӦF)SeYׅ"QeQe&nɎg0tyE-u`\'E '(::5Z5E8tGݘTvi~~_ age-+l>Գ=cQy'vuӓs}z[p۸Æq; N x̭OSuܙpVzu2FbȽipjaɱ)JxzKI9WJX+H?vp^BW|ڍQg{iP;:Ba M jɱ@/hԍV),t*Բiv~O75}f4~jG=J)!Tį,ZE.s,M|$&)O"+4$/Wjr8m!wĜT*y +ƽz/LI2Tg~)7dvFnh7XT=, Ӡ)QOUB ^1uRK`ӖЍ1STgzM~1pGaK,Qz g!?G(?sP CZSٲ/l}AG r0/MSgw6#n.yCCJëKȹS{Is0[]9ӝ7&u.C "kMS:7UlK;rypUJuEVpbC΀ x-BAy;Ǭyy% 8oV {' f-5+w2(T'7lbM[:~vg9<4 a+PjRa%r[+LalRYq/|=įIVDZݚ-@>RŧQCm#؊Jraag]kpS;к)M+Ztv O#gILtptsT>auȿHl˵7+Fm II'*φ1^ٟOX:zLn8]撶gЬ }q|d1Q|E*>w7²@u5i֗.w0P[M*Ûa:|Azizĕo%19ך{@aaIFg"gbyĉqU難@8v.(1B {Ftx鶼oR>r;>cel \Xb~$$H; u⣥#<ћ%xJhg Jgh7* 3[1 oG۫3#p.7._Xl֋C10nN "6qkx0vvə'R=B#ҕDג9i}KcK[p ksHz5?HQft LjORO?nyW>$2n5JìT'Ղ%ZjoE=kk 9eF&0QZ,kE/H0ptn,]H,O$ԝ}l*nN3{ֲB&<Hf>` _,/'-sL8#f3'D,(]S> / <6*H;P7DׇcI!%b-^}VvȤbldLLFb P3lJ[WC_k2(y4qqZ9~2zYqf7l;kƫ`]S.EW)6|;u=K!ΪiSG 2P[Tv,V`)bHM34^tXMٙAvj,RZT3J6L:W?E&tI?zb̒>&Js8;"bkAT|2Y%). Ávvmn?to#%w3yqkS)]Cmlh`Hk^d\}ѵeإKe&iRzB6E8`=XS 0<%,Ό婥R+ёeS0D!ߋp( y(<*=UwggSR 0rƑ垵l7>1@cgy㜖0q1&E𪼻ɛR x% Zrm\WuǡM'8h 5Z~C'^"XܭoRZ?D> )tLd/o,7#ۆZBh(9Z9퐊ĮA;\v8OD3I*0P+%VȻV=:ikT E=6&?HR#؋YV{ba d'MA@DBy]iV]|K&:bMvo*H:3`lT5 8f5)R< }=z![[{rkS{9!d ',=V8Wg)dl&gPVlG'sDqX#Lz}^P`'!p.$~% qn՞>vd70T,SHa-u Ģ#`8^?o颸 ]*xT<]/F2>4gP3_:V6M0&^(,ld>9ávyݪhp LMyJ p5~N&\ j"#Yv"Z4y_$IWg`HGfϹVAYDĔXesdK F$I?5E~.{q[zm䕛\663/:֩_T㞶1ʍ3JɝLғȑ(J (戃1Ǵ LlM_()KOR6!*LZNj|#>t wlퟭ$޻M %T$2]2"ˢP3Y'! )2BL$v>7w M0}Nxd[B>lN__i7>|鴇{W exy4"0vFILYOزux+.$lNsT3"np|j ,;eo9fi {QTIbaO@aJܬax Y` 8r)L2&c#9?vѦamuBR8=Zz:KϭOD 1 F#H 1Y*ni[scWf4`'G/6U¼aà5)Pv,kiU&junu/+Vִ~}jgw_=y5F4fis  .Iޔɽk*,JL~э0/7=AO|VχEs+;1$%~)KG1`0aK0e Pj\eA"ەF;Z%)z+z2zz)B|/' o/x3 &pg0V a;Š´7<Λ}̫XP)tƱWCE|֝ɹkY:Ě# ԣ{4-oN*L=a\#OA udž+NJtrKSL_ f3yaOZ[!I1uVYu4[̗=vyN|(nClӆn wqNaJHnVf߳پ{5KLyѷ sAi=>+<=Ϻ",$LЍ.8PW=Ǎn 'YzlLtQ8a$M{[ڏfvqL/Ò^إϋ~ÿ<1}fٷ TxapEz^Ћە=E{tq;;M;RNDIA1} d;@ Ezė[\UR=wz)EpZm;Iq 2r NWLkMx[w4`Cm|sc~ ,ybasYFX c!A) >yp3iڐXhVg:5u{T$aJY&O\`/P{SvmiḸ+-,x)(L7zh+:p6f[6j!;u mS|Yܞ,@Q O .lg2)GAauܚ$D(z <(: JFş\99Z&TfŁٕ䡧i./7l0fyν-$B<i&]LKG kATR3y^p; اevssgI?;'!{8/6~ae_L/܏z]rM(I$8+![oz/A`A1~:aqx2JQ 辣W6|ex},1yp6ģ-\$^Eę6(T$7K"D'm.4x.ԩBWWUOQb?:mIYW7P|ΠuPOz랆DD㝾C]_89 Fxt1vr2wW?;'O A@@_*pe||+o9 cTq dyFDߓe1w;$kJiUEwԋd&@́>~/|Z}A`n(ƉmS6з"zv:gV \+}me}Tp{ h*SxtMf*aIqA@4;8Ar޾V_ Ջ\j@ k>j$ oᐮSϞ{pv[0L6yClaCasDp2=|29~n~Ǵ FSwo,ds GOD?9؁G___+U/9鲘x9}^|XT>-J *H 003C#4HHJH ((%H# !RJ s{?/ߟ⟟("B1c)?1@k/*/LLDxĄb"&"K;w/$(_7 }Jm>U5/^*;v0]v{cgHPYUlGXJ[y%Oq #t2C݁A B|;R3m<2R'L^Q,=QCgٍUomǹ˴xyBpW/[8=UW5F]E7-RK_UuU>ЊoUC 4R(_&` j/JsT,Q^7}hn:o[TK~(D=>۞8)Ƕ[vw q=C8(0@ZI9,Oo]`:GH9L&jUl٭=LaQzʞxK6"Aa?/@0/(__HH( /P0h0>04o70ɡ42y`FǒFκK8 H0CKPIEju}BPRk +;e]gtRBwBW9Y \Nn6J295m;ʪ~cZo^ʹqh5}XXn#)PH]QnaUX {;92}=3@EW w3H|(ly AR/A6J;F!z2Vn($,'Y33jmw?6wƨ+Pƺ8>jۢvi+ODޖ Zh0mdTay)h}Gf 7x^fs)O8(.rX2ګb-dV(YWD Ѝ-ٱo%^lZ0ͅNID,S<{6jL#3/-Aۓ8yݦ`rfjzoeN r˵%nzJps#)gOf&H5Z#"QLՕVH"[,o>?%Zly7#9u8nDCrv݀0Ʈ8g24KK Ul;oMҒvև.I3 4װ]WN׌㈎A&|bU~G{if»q7?5#7ުuI?\:OaX(t_f-%)<q}tP9[ -{޳كF0M+4x]dG]:gSs5:MaV̔dU ۈRMGnpaR焊/Bq6"qL˹c2v{I1l抬3Xt&f״|@pEF<]JAMB`pjgAp}y]ɋxB}t@5y5|Em6i\\:2ȯ$`kErp~IT";⽚E<p֔vgsNkL g/]o_E÷n^3[>tǧzg#eZci+XQ;gm.b/]ҕ$-'|.G=3VZ!X "  UT^NPR O5}Mz"n衙Y?>`/D.ejG)ܹ5˞6y*YrC=t⦷Qᇱ~9~.+ OMMW۠zl~@QŘq-AfP` +۷F,ef>#/i¨'w1͘QMi7f6 * NmJ&|'v料|2[fѴH S?P+YItDk=E{w7$Qn {W4S$p&>}n ZyQSeOE-caflcyؕ"aPȸ}0C!k(n*Ga45@ZMy|>%6¯;MF7˛CAXc-Ifze;570_"2ـwD.=zd+|?,wm.(z5~[DAA8҄v59Cmp| i5}~,8_C:V/&L|]Hd`;ލ;F*o$^7] ' 9u˺=i/s, u∌r+Ms)=ӈeXK3,RS EʅI8U"޲ P~q1MErʢk.1܆o0__OrOŝ_\_i&W nzxBi)@e|VP7 z2EɊK:%3x7<oRm:4Jr8pNgPi0vcs帎7v'Y2+:P}tVmf^Bs]|fc4VI~z^pA \1F~A{`sna_^NزtSRd+%Zg+x"Ovݍs#m$jRܴk}H}ŰMtxʝǴG};nL`~M)BQ]=T,ڵ`L nY:|/TĊ`UE0CFgͱTE'ѧ@]Ѻ?#z0u LirC/6q840Rype$!IN*uwb5߾3ֹQ7H&iklcwelE.T@}C lrye'b5ܡte? ̚>zeƃ% ydwOe 7=,HEu_tZ-1dw):U.{;e)NiL΀u8_;K -M ufxdl5-yJv%-胝G'Ѥh}w& 1 ]3WF9[8jaR,:'' _HEߛr4_3^LhJlKm?ȭۻK fABDgĹ f_:8ڙB(wyHzM'o2yOӳ.y~ s؍e")]\yWN;$'%dL)3M}9Fgq& yL,ixR%fI:Zih<A>CɃ.*yi|J-9L a{0JIlykyl2F6h|uH_*ī7B01UMh"ͧ8|%Q0&;^N97^MQ@3"(Na /`|E|GAmbbNh(#5/_e-VYU='(ͣp%]t7R&lXK(KhB*<ٖP#ñ* )ӺA+(]#t4 A /I5̶!j=M9iXuU,/~D"}<-X;tUTga񍍍2YTJSapQ2T!?(^=yZVGMMRޗD',0 &ޢm"і;՟x7֜eC.#FUG -&] suOwh H}}-Ŝ!fm;Hm[#DRÜy͒;8(P*G$-]UX5}!AAS9׻CjqL!~Jx/6˝Į q(]SjS2B*6>Je"p脩ct$gZχ,v:_.,ĺh4ڒ;+\mDAZ J sDsBϯbcTIm,R% 'T9xɽ%ж={nN-9Pةi%^;Ǘ5+ԪEtIsLH4^ ~|[M&tvSE^"O xYC-ZkkL%WbH;\ s9e;ܧ4$UQ(Ng*xun]b'.r$piy&uEd5#%l8.i77}^SfkA|Ff+355&sWOK`C8U7A6U4c)Ie*ڑ/]ZkO@9[IcrA-k̈́w<8=UyK'ﶔGD/8r*z61'[UL7]! bPq"OkTҪ.,ɧ1ƇK HnwW'/70G SOk UzcҢIpוtw8F4`Tfz~69I R-.b~D#l4{7Z>项-I?ɪ`F6t *}-$c04*_H0AHWXX ddiGĕϫvs+МF+dȞOj. I3i܈YL+)"ޭ"_{#*=ʘVo%t%f2cBH~UbjbOak\@`5v3YaI*E,6KIA W<%ai,iqGp Ho?yLw@9e;=h2%QLK>nj)eK _-ޔȇ7L9\3MQE4!N΄f3 ulcFdܽoṾzV3z4-&*ǥnW5jlkqP.zM7pomZ\dòZ|))M^7.t ٻI͞ ni@FֱCf99mCXB8F-+O:o.t>xXX,hM)cBd8$J#V-U}>4*XIɑ-a׺lT$]x~"/ƃ֚Zy2]m7gx>YO%a*eKm*O_nuZ2b{h8gABjn"XO^D SYSxG[Z+co5K M{-2tD//udE6'ڋ!l<Ь/PP"1j>W|DL p&4h[IL'fIDp\-:vyiPCZK|B#Otlyd+XhGܸ\)4SڧB1[E {[g˾&߾72%WL4""^HEB)7YCx5c:o ӧifzVTdgGu{ك9"+20a|;$]| PfBd'pqL^cܛM(f 5#%ev~8IcѲ:kJkYp TEsO޼bZs}읋h7*D޻m/()y9GQj3|g84NƘдΫuBώ9b̭&. t8O2 _Om/8x0)%v]з&j_:Kj5!+rOʟi:;:2eC8=d(lEI{`M윖瞧ÇEI(&~ 3*.U( r}-iA+9 /c|KtC\ڒhajϜe7Wm2DP(x.2ceRxd~'q5uJ켶s3eӋu]Y -3נ]ʉ).P,v4rE(K׃K4lPP"KJ7B|wpkV&yQ1r 4Ixg Ҵ1DWG'yi\%.œOe=fN;CL$4-Tr5U}SՐl'wf'3?{]B_M"aDH>s}Rts_ƀk^!WԦרr|F!-J^q5 hsZt5<ٳtnz᭍SʄC߆?[К0a-ѦԔBnS(\C"\7C~;V]5zJĈ_. V"{_G7GJڇkVX]LMpQtҺwJRYi8_`ff;EK869ϓ >yySVx7~$ ۬f gl/NO'P(ǍeE \ E\}DenqA~3G Sv ekmgszk˘Z 2(4V*wr˴z>981X!9DJJ5"#[P̩'Ned^u>zIXK*|Do]`+X⅃u._׷=MȈ-OǙMqa|7; .5;0eRgX*z-OyO˺%kJˬ܅7ۯ:OWK*E N5Y`^t*_-G+ߎމfQ2O)DA}ph*T|8/7^ (ky^R /@J dh1:51'xw>6~؝gwLFޯrGpл`/nLа[Mub D}!B5 ZZ黖3Nз7ALI1c/?7 i ٯUժ퓛FJKFbeV(Say]T3;ͅ}qôB"Is!Yot͜-S 7PXb˯t?uGR&E3[ōEy9?' R=b笙ҵh$}:ZYABxl\PU[J__Zl Ilc{vw ŶxU=4!AN-v4rYL]S/wײ@Z+>XߘzQ|4dR42>^%̥!64i}+.˗x\j7󆮘sM i#X=Lұf ,sCHh!>Pn %B*y+>i.W6|ͷ \Ci0HRE[7d]BQuqX6FW9IR9z7׽ KS7a4an|.$Iq 'OX?v_`tS}{ -[?)Хfy ƞϗ'%yvdN‹ d#  uE@/Pybtdq/2SՔ>eŨ.ES3pBz[/\L`jRA@aGW M qw 6qmuvu$='ތ5> iިՠ1RS!!L1FU_cnLj ݋sӳ|Ed ج)<7v[LdwBG.~W1K73C$yTulj 5%v jJѩ*mE-uPH49̏R1aZQ$#^L78#%W}wFw+{ \cFc5uzb ORƱB쌆RĨL_x(] >*5ҷlҮ|վR!ܢ.Pvm"Ļ6`1|zd BU<:izҘܶM /ݯ!]x2{_O_F\p ùL@+(Ow'/7?/ ???*hV!baGmLm@8Impl ܦ@%j}  a t69Nk{(̜H(A짓hfOp[5n[+߾tk\́j4Bs!'\E5GX"yl/OH@RSNJVU(H{~:*7Ŀ#jugH|tgS0''R?EZCF/wWPb ;n=jls a_b~Bhp[䠐ωG8G>q$r<_9zBs(~H+ [_(ZY `D8A@K 3['F.nu4_ 'h=y߄:>>7 @:y@?A6ND::qPENE~nⲆ LNZO?.8GFCZ1@d?;= 񰆬a#CVI|;e5m*.0zI?tG`G O]zPC,@S$G##RSo_>b 8 3"ȝ!nNM HKAOHm$ך'ӽA@g4dw)6?m11=O R ?p+s2ȅ~o6܋976X&\P3 :s1!' %q"k}1B0IzΉ Oc@M_ygO\" .2wOgHHG@}dc8:fz٣~r;Udy;L?`$j4?r QB=$iyIhAフpx nډ&Y$ xQIlWR!EKl]R0Q|""*,:Nچ부o"ʥ,3dFq*ߗӓӜ$TIgֵ#É|5o݉B<)'KДSϭo%Y8 u|x&50o.S%\"etJ(R7`8Y$i #TLº։>Vl z2sN6Ή-1mSk=ۦt};kE/-[eך~S Mhb28R,x̚%K4QP~:rjtHm_ʝjv[;w"ȃUݠK,sxoS!ڎ2:8@X͈(X]؂&m|uyCdGmLŪ9ň$dY $O=|oLL>DG|0 3)̌A˥+Qѿ9GkΓȺ|Jl69b."(@PosgӁq s Ysuu /=]t+)0>6Cp srC̼~Q=yYPg[@-%6ه˃HPAGsߒs9Ď*~.x~hF.KR4qƕƩ;Su #2o\xD~ ~OHgC[h~jۣv`9 $k)4 %eD9J``U5 VxH`/(XȸQj ? 3amH1'EIqt$Y 4Q ;;2 ̨-/NPE9!8м;$}SL3fDhj> >'*8O(:I* 6REƥ6 az%FX#C-OSEChƑr]!:KS2 m\.4 q&.^IP8&v@{(-,'f#IF0r;J-$M&Ӣ9`=XLi%lp9ނj` gA/Ƀ~=Q֋)\XEyQҬKMv3F+ࣰD ^2tjU!+"9N(1Jr:8#n<.p$nCd(UuAQkЋ8F/hŨɫ0;G%zr  #d 7x?:(xDiA$ (3^CZ[2dL=noFbs՝GRM#n3Ǘ̄]l %-ݮ(yJPB":H{E@Zj \W&(ފv\l Y¥ ކ)E?.ay(PYV&!&b@'pE"(B[mN//6斗GZ ` +Lx(bxͼey_+4dP'yB `v^m* _wiq?Q1WP2Ff!zCpQL&t+"MHe(rj*lj݉b,Az$ VX!)6 6)*pپ4R^}6W.d, >.˚6Qp ?QO+Ix)p22E! xz1D4poI';JDsAipPɵXEPaF!6´XO DXNEIOޮS(˅fK εȅ{U-4 _Tc?*ȉ6uWxfTжPIr߅+cPLo+`'RK<?RF1,TfݒdL G*&E?Х7\pV2HŔ. (fd(f9K|DRV9Ķ$@KdYX"V 72x4e(e`sKw!B& `dȌ]^0;a@OTbo} 'Zӳ&\muF`e@d)"E@vI;@tgY"R$EF R3]y " , 7᭞1QjJׁDi"<"9 гx%Fj 6 x+r1D= i8@DĆV h@$ebT^ ?m@l`"Ԯ ׈wMi1R@8Pfz $%e*nC7PdGrF"#D/"-8c&cX_yz؎@dڀ@|p'9 4P>5i@$ۀ @i.$uJDR>Zuh!$3$#x*d>h\< }{&c!_$%#Qp2>3IG!ijb'#1%" CW~m;]MsF/$ >>H1FAj[ozq4Myo2=$ćO=R8n'9>C#a!!ҧ6XkCCu8~Rf,GE 8MwF{W7*MPqcƨ` JsUcgz[Dq=QQբBM|E\=]UnύKyzA*`[i:c񊪻*xzx^W^`¡_m/"*x`UÃM{?>xy//;[}ٱwFψ{{׉ӈ_ugӯ 7oZ!}׶Wqe'6:6ӻ֖$Xy|G1ge_y-,ɘ7#t?ҥI~ڏSg'ZlyGX4`{[| ?8ilĸ^'z̾d h+?ook]s5ϳ>oUuwǃ6bj߿=x:gPתWTܣr܁on:<Ԓu?2kT2eåƷy]5G{e^#kQ_o uvWo8?Tw㕏9b"~yޔɭ+,_Zmھ'XT؆;VYz~-u˵'5։Ş\6Yp˕&j:mF_~iA}RJ?P27>ʔimqz6G}#.=9Xƾgˬv㶟|}>}NMz{zDkhF TqxΜNglMcɀ;45¼syoGF*}Y&6V`rMa-bBZfWnn\ӨA}w&ZttU7Ն=ľωlcJM_{ ]ۦ};W/ܞqCM{G9()sq$˩otR˳_Z5)~twCʏ}Wo[lx>~xTslnmvk&ݞg_M~ި>CCg6OYjНuǩ9n?i6̤ |hiu8i-_{أVp[_4yw.%W.r0~~HGę_Йٚ]jgj'W_s߅VsWW<}őQSj.X4{0̹20yɫ.JY׫$ԋά붳 xL݅a'boU>F37c{Q̬kɁ/:٢nɔ1AG V;ve_:{AshR~`~|aꦾ κOBlnoRCpFܺ:V_&vhzZ0s󭻾pyGYsn}{zI;vN:cwlul۶m۶:oN՜xoV,h(t%vh~Jf#'z_ܝL>_ <窤 : d%.Z0/Ԡ%fvEV(Vt94$B튗W7WњQ2ѐP4Gt K!GiɽvJ r=a"Lkda-.TbL̮ۢLs"5 J='d_O Ck-KH8Rac;wB;.aFiG,v䐒'|mAVN;O+_g[ \8trNfM-%g9D#+[70*Ȁ`nXҪ Z'a|NٶпE҂.ebG641^Adms>61/y~)] 9~-cS>P/4^e8ߗEjFUH#S]95?\yXjt(UbBV?h)3_^`$=.Bg#$ gqC q{gAb 4 TLX?$SGʋn࿻m@A~3i1 ]C@t -/aZb \{+]q(s6 kl)Z\{E/[֎E''ϫ>-]K#`齃/.̺V\͍_3c?s[YWʔnkq+/^ 0G^kM B3WEh&s?qӥw{G{1jnE_*Kԝ<)@]!yIH!R>D2Y \ރK&/9cMreȁ83-OLM T,Đ׉:7c9ܔbL"m4c9vg4IzZ}V4acřKG6S꾛MK*F6 cWl,am c''1WMuK$`ɿd6CV %/=4;e5UE+6 V}[&aQ"QdXoCn(4e<7v:\~zFT!є=8M(nMs"쌍bNhӃh}@qɗ8]8 ,?+E??aڬ$=I 6"Y([dzc^rqr7:g"F&{~Dukl쉱E=4dLhggb+<˔zKIcnF#AEH 6`4h*t~Y;S.;{|LZ%?!#*7%5|kB2t6=CF~ PDi|v ;ԟp+vlńv(%ZWw/bR7&|uA u8~gYH~5xaj?HckcWݿ;H%ت&4o!3Vx3CKNpTY[+Wk9U}8S3H)U,uj;z$ 2n9JK,K/cjz?19\nFx?kek{̓Sߒ3GeL8,)O-Д1,J qB]2)/sҧ5++z,NiQ郥N;n7U5ihw#,}>r H)8Qqߡ7qiT BG-MBX7*"2jvJ ЧG%>ruD$4gE(yS6gf-p; ɯT3渳Wbw3YJ%\:ŇЩ,aR&Nw.-hbLnw蒽wT>i5X=XO=#(Ǚǝ"$~?K| y~J><' E8?ٵ1Dߦ^5p_$uBA %3\S]̜K ż r/I~lnZ)tD5F9NKI b_.iz~ ]l2ymlpk\vLzH"; DYd$Bnj5*j'pFOV:8xf-G8RC.l/(8|Y3z3^dб:>ɣ'֥Rj va*S>G{d惱IӞ)z%FoI ty*q8M_`.6`Җ|NJ~sѝe1@A׸uqI7u\L/i.<|27kII7eYUu::,n"qQ$]o,;t2T);:F[v."*w<ѧ&Y ~ R$4? fd_B3qۇ!N*@MT;@dw)SRפ?s?g䙱PPWR<$ Bh*$?Og~ MBackg,C4$Ǡy}x {[a l굄FƷQSRC}WT.>K2P}U/ݿֻCdHI$ /X(gҠǁ>qВܘVm4e&}QB>+gy36'cǞ* yөh/y}7u\[AZ9@p#tBXAn\5&p)XYb&cX Զrh2m^sE=H"iD$(27"kN" ¸]6>۹Ԃ7|cEs9O;NL m)__(`6L`Y`@Dܮxrm޴Xś u;=wewWͭI8KiNeBa3h>9aqYo[ [)+HFش'5eDb,QtlMtտeI{D `el9gNzJ?P|o[ 4eðH796}B|"Y7燠V=^~tF̑IVv'~Xjut~ڈ@ur,nXUeH=[ɕB ^ptu74y#Q~վ xE`-9H΁FXEls] `+Ӹ@ZcN֛Ҙ4e>̾\~K =6_(ϡ)]$|:tI=vMGWCʶ-p&"BN4f#G@hŚ\!17ǕWjDM#Z1zNIԏ[-@)97xG[>#4 \,} H&cH.%6`kot.Mcg!l[OvĀ}uXzV`'*oTнWA%?~2JASSÛAiC9OdQc nIaZ1z 8HOg 5EvzP,]S;fFcP *ܜè)"ٙcD);nwn/YՀ&ӜT ¿Yks>0zߵ.mU_ xYv~SXՐf4b8kM8;kFCEӵW}" mGyFOl&߆[BV8\wp!Pe sQ^-exUZRZmB CFs/mLѩqxn4 oب6I8c. -!S5'kXc9-YB}Mӵ/7_2H}x~!xyG ~,Ue봾|IӸw _Ğ屜)Gt1}k[>]T.Ϯ,m4-a&6}[r+^]'ޡ8\k{O俹9Aӛ9A?p(k}/i]L5͛QD,C/7`ͶSԚ2T \ t)?8D t!b8тI Ԣ0 ~'ݵ` AajSa@\}KfX)e(Tmx}o F-NE̾\ 6/wTL⹪ݡ!0|CZJZK ޥߪ/{"pfָZJGxW)mgقZU46lԵ:ˡ'y- Ԑ4sȨ7hV;Nu7nFL9d&0̑(["uh=۹'vv9cCc.e9kv;dl\LzH^[% F7vn hiB_CraU`'diyA@EGteeG&dQ$e$GS&Gv~B O1?tšk ʻ t g+Cuh I6\{갧RءVʚm6e#[n1DZal:S~W96ks/XdOo,UY:7Y8ɵaޡ3u~F~t[t^s|cg'aw"DdO|U8>uF?Q|7-S_#z29ebvM/)d|b y3޸Yct]k*B P+.v'J'(u'Md R^l =JiTE JOgZ)Gµ! jHCDakֽB!r#eɯDX \ޮ|>:{4YTI m`q*8}$QWJt[Re:@kԫO_]ߚ.`-FŃV(Ϲ\I]8.tNcECLȝH[^ĎuDߛn6D(u{^cO}z# BաQ a?++HKd~_1N U " d5+7R:Vl:kDh\r/(HϯrC_K` 01ʀ3|6 tKM40B^` G+zb_.h1eYy7fv6? 亣Kċbĉq1FCIg7 vqML7z7Jp,,5R $   t Ҹ.pCraИnaj ncJ0uۓb,R, X8 VmÒgt@agh#|ٵҟ_t~qkIȁt>ia%e'5rZ㺐{ix ĻxL',r.)"qP~M |c3 JƢ_)\tQq*nXZn6SIhu|}r7 PtsLYp>譟$98)'zXR[@ mxH~S5 e.ongIVtS˜tSz8Ÿ>ofÂjHu-3[D񿏮vkGb\V "%︃ 3"‚-35#y fl ,Ad U{B,QpԄ-iZd`8UtǓ=v*sW}$ɍ4ߨ0b v{ä篂 4&4"hԤ3ZPE#Hφ!M&4Ѱ8|صuu dQ5`CUͷ;c=.ߺ( !sq1$UHƧs$ϕ8L2>4h m#pǵ| xH0|GЃ|l7 5wԹ %|;Zlynq9|;:ǞIӿޫ(!8Soh^Cho\A/INF5Zv ]~++_%CM37 ޢpE@vBz^jZݺ)Pd)+ @%)H.}6m33O|t3xV:_B:g9"Zv d f@h?*tޫb2AR6ѫ8r" U-7k->1t7ڦW8|%'<3l$4\#Ն4 `+PmiD%qB@CPZ;0qax;pHa_F<E< c@UNk53jq BWtUՠr; sX%WC}~3浵_GVO%.3۳4:|23*Rn>,@j R]xo$}Ju\0WSծܗ/_|˗/_|˗/_|˗/_|˗/_|mAUIx XpI]- c68j (xK;^{T[5\$84nABC ܂,!' -ח;37wܙ[,zuUu]۟nGW;O_7'w6.288yxxx8x8X898Y6o t 'r2rut'_G7L@֎|\\\ܜm}s`aU#5 t|?*T7bh$x/'MK+Ob0Ph_#RPHŏ`U|LzѭO10=+p>ɵrG<x+Τ;yUL]Xn7ԖK:Aʹoa~@cID} \v^4`cU]L"U*64w:r^jA44Jy `C p?jM!vE 4, =6醼܃#i/m(?[)aR]XO4(ߍubKΦ;82TtB gtMGRR.%1ɬE{ b~2A'7"r|AEA>16"jİ.g%>_e?_\Vl5/6]ԸTZ}A]$m!Ο|p5dJj/Oz ϡ'?ش -}W tx#g-'Soi3ϕT%2l4^њ$!=DӷfM -fo-NgB泥Vzaq0-\|aN|c Y[- o5 HYaM2;65䍬5%r4k1EE8GtFS\7p|< ?8GB -#eouXFFhx:q;#͝ 6e]*JUL=zDn(ռXY0ݽт<Qdޯ l`SzJ);Þ#<818Lc 1I#|N&sP@$ڧ{@?B(U٨φQ:ƌYR!/K0{-51$˞/cA6J&/ytTlADu u/]E 'O$gD0]i7qNH]ye9b?|8< %q̾1t$~kPT}qaoh7V# {QVc J%?)s{Rgvb p2.rA<; ohE z.f?8=,ziD3̱ACQ=;:a#:!+julj5rP<'QMg7!z xbP$g8сinq/?8O ٖ؃={|sm:it+!JN98ztL|{|{%ɉ8JrOJ=.088I+Ήhl}kP#V}*ll`}i+aK\J2zp#͖Zօ x(Zwx2y9:itr nZlu/=V3val8"-ora8qM8i> k%d2N8۲#"q<2 ٚ}B!G\0>Nj ,d!~B KI`gmjc{leT =-u/T :X,02[ ;NNaUqC{/A;DՉv68*Z'}M4-q-}БQ(. f*\CJ^J/w’BjyS}l-+-U<Ά$Z9Y]z}2 *r_Y| STe;MhܬaŠuWήZ<>+4t A/aq-E3,KQUvo?c<<00L'IqTV^%Ĭ,%^+`'ZN+ NjB><$ҎGNna?d*:Y0W#gnyqqzٍZ]KP)pO<އ*ʉEd$Z_>y{: >}&8xϼ>sm~*6ՂZ+}å:jfDke"/gDZ&/\:lbŏjr@% :rfLbB'^b<;`4 *Ńo]S!ˎ㡢77Wّk`Y>N=9o>kZ_G{p.0˷^8/~~u| a"]A=b mQy>$)k܄wKAO:{d1DU3U*% WN!ptwh:wR8AwkkܛO-'6}HRҋ*syh\>Q\k[d&.I ^5 X0/.=x-dH6]`*< O߲aas(ND;-F`qPr5 X/Ji!r򥌝udQʋ0luq#D:Y# u>Km@Y鴫B8 7{鈦T@ ¹!%]5ISP8)Wj6ˀЭ$H܂婠3` {zt4IKCCoP4xFݡ,!}5`3_ 3^j"qv7E̓qA?:_f]-*j2piScp\ 8Tr C"gI}{L:?͐﹝{"2Q/eSsp݇ ʾHpw J\59@FȰ^K/㹸NeL1TWq1/z >A).| RxftÇ bWGq-S85-?ɕrk񌐦袂ޅrA0KNb%9Rf$ ҂=Dj3o񭳄ȃ51~) W#vNbJ^u1ʏg7@0Pww'2]s"A^`d:TWV#).'f%@(g]~;Q&!v]bA?`L.~ílRSLl.N#M}^9kYRn{QbjPqoL[* ځ9;`mi%@1z8A 3]+פFWE2B홊A]!} `㍨5h5GPhIQ浬>gGoԽh7.&3sEY}^֖S2GG f*]aϏzNF|açNoHam._;"^#LC1 FdDA3l@ ֲ+}HӹQ1@Ł8&ׄ>Oq$5Z fG&3fe6l*[=eSs;f _5BK,vu_Kg΢f'W 1fLsC]Lȓ81xOE†nVҋXkAy1;KSuS R*QŽ.+ xWq/v_tx?v* uQM:id{Pu!4kAT9x$sÃ`f15l#Au|y0m>dssгб ՎK=3hFr]P+wMF勵%kjO;O &ϰ?\[':v(XzByz@>[Q})Ɛp=EH!br>3~Ji.Ώ}ZwUK8H5=CxJ>4$$ʮ5sI\Z\AOzF@ib|Rϩfq5'yLx':f& 4Nj]y-IFg/BZ9BK1^Y;u3!^gbXYI8Zw\ G؟bb p1/3ZD8vε&b0] *F^e,Rh!ʋǖQ>`áOJq*%C ƹ |loB|lu?(hPT}!;;vq%EVG$n(fd~,77HeI;4Db$ 8< z%3҅8 ~r*H\335_94ZSatJq&ˠp#d|BP\}Ʉo k9\Q ބE,DIhWsT)Op>smCP +V.xb_ߍ aItHR'W,ym=]. XH0TR'>,)>~Q 5=<8]L[۬j8h%~>Lj F * *s3Fᘲ'G.6ʉxB#} m<̙m$6(8)N8Pcb d3XOʅُVMi! vh㮽Yr1hxT5<ȩO{KrKe, - 6MlTܔG)]^O^}1hA  ?Y%sj͓O3L;0"z$E,SU܊/lp<8ݏ紊֤iLE޹cw;VG0JBj˲IQ}w O &v^a*"TZBÖ>~{C WA<Ǝ܍Ht `3-Ezf6O=LaU>H4%Rz)Lg N dOD>QוRld7{0h ]H/Fo{%)4%nR ;V 7GUع} /؞DdĀt2H~(L)N$׈wZ-3عkjkdrhߔz)W< x84kQ8~C֥yOy) HI3AA1#=nk6oT[ ٛ6r3|b3y3^˄c)^,MAٺsn$ڎ(<\Yt1m֩ׯglf$DFz''^56Lx`|r&.moNWx0VZSkr5$̬~Y.NiV:a%V}(yi?e|2kG4=  ˛~ZX9֍?9?NJX  ;gQ_? {4P(BckޣU"xUejB޺YZʝ;{Ӎ&= hP's#Eg:PەɢqY(O $ǵtmN+>LpNb#J<שY{9׫dXfʪu_sYBi$VM>})ZOOwMŭ:}? 5AkmGn# Bj/TW5|U\ Z\v|kLM(mF&7&Et1~J[i.ٲj7fU/~w_X ݧbEl(v0t4-s&dqB>8"0 W|+sj>`N{bQfp&?sMO(K}5z K۪;׽( :@~I HJfF!#Eh>n8"_a*n&qL&E %w.W̴|`gU6n\,:n>@~91h{FCdU|ުpN[Ck[js]GB# 1:x*șh$5W65SO& F" ;LTܽfY@Bx]LU&th0k|_bF\2s=sH#{ix/18a8GC)jV&7i<D^IOI+Gq39eC?UsqZǾahj碙 9W8Hecc/(ke^Kba%CXVM5Od6mW !HVPStKTt1F'Fxf/~~@ϳ/d",Y7>)~Eދ41!ȫWy˓S 4"%掟#~NZ5t8|O{eBe]灁:*9 HdДՙ^7tl[ ; ?Q)#OOgW :lC2}qf9;sh]x2FOYBG6C1>r{%;ٔ;dRGL%\3$l3YaE+i?SFanped#Ɍ}feT7!J Ob6 ǂ hۃYɔh?,DbWm?O8 LGHEՍg3ы'=[M87k(*(=YjyS;!9" .R4]v7l7Y;q6eoL{xg2|1|K:nL/ JM7>*qH-&)VI: I 7RE A&CxzKtg)Ҩ7۔T}wTzZAHGfj qÌ/\st@+Fx{[OZ?oSG<9J¿Ҋy@{~́#&}\.;1!3&C}A!|AxJ@ a.rUHUTPLɚ1H ukby:ƅ.qA=om)Y cNzHiZEi3W!"8:D+&DnmLƴ0< 訆(={'eg'F7yZ7 U~̀|uÓ'IDvBpmۀO=P͒x+Hr;l5v#z ^]$Iy1Fw}- CW1+7Ԋӟ5Eo\B~q ^2NԸP+{ʉQbkjFlM8CV^m㩫=u$s>'$gi&}Ceyð|%,ԩjm*k󍎩y΀CA)Fc)+AM~y]k*zrWg!^QZ~Mkc.5 U˨8JtrFrkJ:wCqSRSw4:qv=+ŗ{l}8|qdJfsCL&6M Dw(v A mL!צ1w[if~JorqPIA̺BZ(7|,<RVcǗz `ę8WaW)wmp`';^$ܳ~.8ؗ۫8?LX܆C<g~rGX&Uuϰ8ɝ-X?G4D=O^7osg{%e`2\<q<|^X:3uelҩ)2Bp0d蒭2jRD7Z+[HaY mD}2N弝բ!H؝TK3o^(F8CmUvWMACFtrX߲7c Kf}.9@,?ov6~?18S򟋃g%9 E:6ke%EܣZP.trn(4:KJ: pd,Pƹyr<$UCq܉((Oo2ﰉ%vCE1!.4[wdei|s/ܘHrq;(mUVa+bWIn;c25*')Y"˭ӑîcd.d߱UsDžks^ $}̿MOuMSf.>^ ez|q8- ~zAVrqMriƓm%bS}ënkk\aَa{ K2f yEՔtұZ ?4X9888>ydk -l  l `dfOZX6nxɋ:ƕ|[ 9ALm! f;-r l#]f_4ۚ9O:یV8AY;Yٰ,|5hr^ߐ`[o0|g̯!8 o @LRܘ߶l6߀~=O&1[ݘ-~`d <[[  {c([(Te?JhkuN `d5%4fȓAݼ&kLf:/2 i+_ldoMK6[ ;ǭzfilmag:`6xs.N?\&nM'az+soL/ν1߶nؽ6  kswIbvp4vrn _RfUs_ o [ / {}wGn f{_*!o!oy׽Foo77ߜ?vao߳Kpٷ` ӿGqD~MoF f^?{_V(Nv6S $\55}bd[e_z1!37ibj%kW&hsͭkmDZCMiT$ϬYI6fs*d0<&0Ѯkhhm"מ2KeZR~*2S*e뇪GYImZ F-X,>bt7R= XͫՕQ-Q GRQ(ŷ5P4&CYNt-' Ϙ, uU E^iptA$WSD "iBM'Bjt[e l-,#j-zxl>[@;|*#+j8G&StVՄ\ISd~K/f/J ,3 #)x.+R-b1!q}DF29kEU3γ8 ^(0MEhS[ƖECIKOlhIm^3avw#N0z&&5Ct$I6Q#F"qj%Sݱ{͍VoWƎ[ 1b@~Tn`GRlC/]&q,l:$m:ZuD"M{' ڵEm<{>]lNͿձ*.xpo3s#R:D }k]kkT5ɖx5bW'&n PAQuglYԟ ژ6h#Lnи|}MMc ƝtnV,qNHWPWԠhT$W_ 4MAiC&b<îygAID@7|"'p GI_oX2 V2E sdpd1=)垧S=^;'~8ݮ@+c OIq5HWaHW W)Q;CW[vpM9VJ|3]G!&ؓZ ] s{[%'،m;a&RG=3f֯cJ,0GD uEo>J9Kg>Z)D?}(d+899j],m-(Rbtr='[Πp>P^N>"={`{Z?^s(dyu^f;>9юEaog|}tM?B2KئwaiEa4Q[1ͷߊWotmPo9_-TuyIW\AAjo: V&lwۚocC~'$[x}n9e%SYK{IOH' |sGNr˚SqŒuL΁F3v.*:6Di/CKF8?~W4n<^=<3GťX&'l/r4RoMb|>>?ٻ ei)JV{wfNWJ? B~|zůWl 8 |4_`4pܗWn9rȑ#G9rȑ#G9rȑ#G9rȑ#G9rȑ#GZq`x0!gvp/!ae yK pda x6^]\{F.*XM$-U*@qU\] QV\ujtVօ?EZʼn#%}T~͝I!&JIJ??\c?*WR*_\!xW,fSbV \Ϭ*yhIÇO jXbrr頽2iA%7u,gUt?8)^9fde{Rzwk - gXzWo`X wS:.Z/0.ΘB㗿֓S?\;~#7C{лg1ϸ+o6]hY,ŋ׫v7X1Gf%y>{ +Ol}ޜ m1&ȏ<wwB Se9+%x+pm[._׫[PÈ9FT(}_R}0 Q=-"$r?}Ģ: GeaGh< $JQle r4IdC).̤ahv){`QP2-J2p c"y0ڑ Cp`=C311]QԛzEhXH$K@(ӽ+eXhD 0W8b"3#C0L  L:̧4 {U F5,4#lTRa0`%`&,tA+X-݂R,TDLh"`N 6,P8,,gGb  5#/l֎L,?Bzlюba:04,t=$X.i 6 V5H@2V"t`d(XjB,XnGON5`Z`6 fa5؜aj0QK ֭WA* JeߐC!fףW_GK8Zq4 fԣv2s$tL2DȉY ePM8 |nc-!=J@-XRVDҖ(+Ai$pDi,&J DE3a;,W) (>k@uvdXDPq`eVB)V6QƵUNtAS@i4EM,hD`V6!Tj@q I-ZYϗFVB'+" Bd<C& *8$qhJ+īV,]vVXVAL4NjbG]e|`A7Ӊ!h E⸫L!fZjf0|/͈nJUJidVvТ#3Qe YM mvl"AӼ>E 89-RFG"T^b*meP( V-[ !F3G1I( e+45h<Z 4/,iaa$NMnA0"( b vg.<-#;%-pR4-@ZƎo'`4 +dB^뙳/)dlo5i0\cJnx^nPuI c[(H4lYCϖWX6ΆrY"BF-_lR@܂1>NT گ?o/R;n`38F+vXG-.,k3)I)6ȅb@߆ ^ ld\.l8DZļgA^.- %8RO)rZej(]PċQfx>R:G,\Zrg:6J`u(@Tȕ4$?keHR]P/Jw$ Li=JXAv/2,л"'+6TrIySyFNB0g5-|T򀋞B԰BD- *(E0v#Fkv/9!&1Ks]E\taLCDž^PiW4FvDl8D|V̫P $ _1K׊!yb`{WscqfؿRQĬH(X(bňţ-B((A1c<?[^I3 E.r(1@5)X`ˑ`ܬ氹@O0:"rae1(G[nK'x»-cey d+o}dՌ5#^lq[6Uxt8Gms%=ffӈm+⒡y1n3ur^W lXS~jrt)~331yԷSn<+#;٤opyo˘? zj]?7?CQ'דMqf{< {uqQWSĿk}n*XrP}E3]?$'k6GFv*_u+#+d%5l<'wb㨥gM*5*+hҷk6o _m0ixo:|Vax7Sҫ/䰮O9LZthhuۉ=ںݵ `}C1mU";D%L/#]NZjѾ=>եmG֝MEdž 3e]K[ɫTϸ^5fΊo3Mw=|őA9yy䜴OU?Z-y{ۆ|u̺Rk[:{H'ytϫUq?s9B[ > !}R㞧n|:/9ȃ+9-=khW<܎ϯ.;mzn;;(Pq;2t{n|jIy;%Ƿ%i=nrΧ6o-04rg1?(jebFZuM0!|~kg'7j_ճ#?|uۏ)W y\2h织ΦK'=kKظiO<}N犹?]2hFIRHQrJ$ޕfzeU}S^e-.ncى/OyYtWK`Dw':VS?s^+wY]i3V>u{N•S^IӿxMNӫe ^?PQ?WիV4vʑϞVN(_u4^n5uʝ+{ x9bڔkyFLb' ZnMg&(!=?}ЍqGv؉=Wտ7~u[eVk7bLخ!vYYkEgz"V%s؂3 '4mȶ8k oJ{,rYڵ:㹖œm˶ml^XmNZ8<սoq{o8+ U[7f%D?ӳfCG5uvRk|}x˻X707\ӈ\Zmast"&4/Gk Ž۪ 6N"{laϣSzLL#IBLx?oGEi2&& Є5Z M"0>jv= 3]7D3Q&cŢ9PXs$zPeϦ_"M$oB厦\{gjrܔ@f[xjxyionb儗)xIk%eqm=B;(1AM<>Xap#)ȯmoQp׬S\(x lPߒT 1yŇ؉N@6eѭ<#2c5) s]"R׍.5:ɋƁoPX6LS &͜DXEɣc )2-Wߝ!sX~3W KW.ֺrHA0rJ9x}LMC*氎 B˟qx &<_I޵`IztvlH/Z,n+˪:W0:uop:f&Qu΍D#hw4:F1#+_=௼FQu`I L41E!&6PF'#_XRf^%e>; ܤ;?MeZUjt r*Ͼt([儠Zf9APZqҠr_lVf0v_kxkD6^g@+r@imt, Ko±𝲉xLD-+I^%i݉&m ؞p+c҇8d d6p>ߘh) +K%eSH q0t<3±Wzp^R-MOO,ḷv;GY 񓞍 H^K2ء3%{8 ꭫Dk9KH Lrp]&n_<|^0sg:د=EbK"G]P{OFf2kSQ}QOGAUFnqWZXL洚H&[ȈXo?iZ^C0&G`un&j(V Z3VRKn .Dnj(Uyl&.C@&2NGشJ@]Mp4a?YW\\#]icMIV&4ABi^~h_g]gTdXg p,xlku;.8ƋF|*ƙKA #$MGxA¸EnyQgGr]sэ_bqI$|ޓi %$3Cbzxh8X)%|}eam'Ċܱ,^:j aVC vb\XX@LYc`L7)zڢi|Ht'/mڢ"'Dd@ҀcYsg|cP9rr8 rܺY( Alcp}ӄbϨbo5i0r=&!찋Лn{ц,>\TF\)G,l>97Ad~G\-JGM{eY9fg3ea!D oyshsU~"2Mmlh$,?><#fvAcydEM`Ƞe2)mYRb_W.|嗰-%m?lS{x55p#EHEKN\e/V@.ֹ5љ&G#My?^b`hwS|\.؉!s[!P-;:3zvuOaIa ـrS(Un;00>Ͱf͸]4] yz~ēs1ul-2rfvеK-ua,у4dwqLEy*xW6̠ɚ7<+ ĉ-k*$B--M%ڞ|CX evNg[Q2/iip*s[RUXVj-Zو[$JKq+)=Yd==~Svc5cm0]]# $9gGU?جL;ifԐʕo`/8pz)±QyШuKJc(yFH4t}BY.Ђbl`+cR*$y)GR_LOUX3+W{,VR[L(qo <7&#*c\ ɣ$ ds{=2?R66=/3u6c`.i_za_/ߋCKTV CĪ"ʁ9!&SfNƏep(Akq6r{4buH2G\ĤsS<}B$x^oԦ'nGȱ8C~siJy/Γ'|'zJ)VRDvU򭧪VӢQ%.s63n^;]GҞlZ}O:g:O]o.t> r~ia:Hԉ!«oћl s4>>mٌ30u!&:8⇵kud1ٶQ9hϜFwcyM'׽(Hꦩ_MЀ T(zA™W4554$EEWs{ʣC8t,c&dD; R!`߶p_-7g{i=cOWCׇҝO;[FT8b9A92sFZZY;9$blyAܗP}}WxVnR d*:ֽIWBR"N!' N$31}rT[(Qox'ghF=f$Q߅aScҟ1^ 2Q.ۏW @mZ%S+\x,3&+V?}uGC9njGlBSrИQ$o͢ur5cW`e4p)6J6AO#DKLL纼̊dLϮLS'A"p:l}߃h0#aY;߳$LZJڟD6 YpmA_K'~)vh72gr+wr|v ;Ў-/Z32X w_/+ @6q1GSH[!>fW3G]fX OȹS nhjUJ~L'fRv)gJy..كO.);,ޯ 2"0*NeXZAU; ym#[r"X?NubyHQڕi8C^K=kԷDئAJܲe6MQ"\MNO;,5g쌨BCo\Q)2s]TUl]^'~*F:o7--y!ݵmfn}ˎeJGZΙ07'ҹA\'uG^PiLs*~ezZFh%t $f[!::/#s?!)õ.t҇IGRQ fDfY/XjkV7 v'H5x/88C,Et2 }+ qhסxy Apk%qo^}cMU,}StJi0sI_`Z ڊF`?p=I~BDE袴}g7r{. ĺ%5a^ jq€|M`gA~Y<lci\ x8GYoe(1m850ć,`;'XP'd}JaE<̳l%U^S)IzYO]Zc̐P6KdwZԨ_k s8п @!%:ӒP KְdVE 0,rңܢsjPhts }ul[GER>.pmjGcMu!CWqfK,}RfXbϸi7_!0/ޖ)m"p"l 5K6*םDv6\mNJgBOU;3Aijژ4q Wy򗥃ۇvC~~Wr:@x%%7P}߹4&t ^tk"6{N6ؼKt^qyk-Zjf.B5J4Sш΋Gc_ 7W>kD= p":௕haOS`Q ﵓho|i-ea>*N/\)s5ǩ(IVҲʕG H? NN4\P}\G z{ ^@R[Qb$&x~Jאjb5W}dhH񏃂 68IZM:atw9[^eOɇe^1u\"λ~-pV%ElM1pbWhp4 tr;!|&rȷkyZg#q{$ 0{jzȯM*Ĵy#3ڳ7Ty8[v5SlI-_PR-xUEaO\4xC;VZhqȝ=دH+M);w;.cRz܉z~PB%g|+Db*}.*¥> ;l"v%.GM“c_Ҝ.Li_JeYk#k%ۅ/@KCCׂJ8].>kȜB[AВAګ/'6E\>rt[ܼaR{/+c$ MOj#[^F:.*41"J M+ 6b:<+/?Z%t*S<;1c$#R;c ̰!=8(nBMa^Kre示la.M*"SKR$WUrQ} h x"Z `>&(Q1drW4yڥlxPۆ0Vh`hxUS'0Ȟ-D+N ú(e FX[E(p=W#u{&2xgZbv"[6Lա-!NӼagi׮*_va뎟]߼ =1/sԨ. e)J{;ߛJg|bQhINL ̬䭊Bi>32_+z3|?Aɖ$>LWT Q;6gi3AtvȜNBuj h!\xUT KO#cV^Om"4A>#vM7/FsRQ2# i.sz# w'TJG Wa{_=vCF_fsv-R*ǖF]^p^%)څ dM|ނpѝӹLl*iJL7ajH-:ݐ#q/4{Pi @B{ҦQ /f91q崨CrɌ,%LNF] !o)٦osaffV亜T<*T_v G [hxl(i?|Ė C _mrnR0X߅.ldj/|nf5|6Zм0{uC;bu$9LwVB,VC5m7ܫ{b]Et;Z0)(ϱ)=,!ͥ QVIFf`2TMukڻv2O}p;Q+z%ҁ@Z7qm!x]ny1ŵ^!&ܵfaf}*B@Q<wh+q 7\3ȼ˶/m՚I?JʹVj]Mר]n#JۗQR!'näJfÅ3<w\neӧO>}ӧO>}ӧO>}ӧO>}ӧ+2]bߔVx jp`0@tT3 :%r}n x'ipИ*HVw>UZh&nm3|R8Z֓+K(q{g niIZKYuҬvO2i@xddDn"$%`xL|o@%Fq@ f n I*{BÒqf87=[`X͙JEA&BH89Bi!HRGp&q30J8Alal7A ˪0KSG ("aJAH) H"ų@R@6 ) si@Rl Ia6H ( O}5 LH ,@"9 @1F;ӀH2f ӛRRfƁ2t ("&3P $EY 0R"eje#P0| @2%olHCȆ@>OeN~P0"L03@L%uY@R@r.m&hY{@-S%j$(hq ZU Ɓ8P{@&\"0$9*fJD9(M9 )ȱ 8,nvwԹB |Ȩ8P|iG>̌Ӹ`n<Z,HTFQl gMY) Vb*2/rE`^ԚHh- ӲB (A]0c`yi weauƕVWd>xU{(-42Z) n`h6 dLjpBg:.\nSWXcPf)8.%?Fw0BKI1 dRflFhj(F4Q DD:Bzu8DQ3QGB"CKvRt CL%tzul=2N V `v}"NNt9@*x+U0YB/\UYA]!R+"d PK=ɚq8uD'E: eYVwH92m:ɢ٥=ȠpADu8(ŒgR^vժQ-*Kmjp4Z%a*lԂ>h,AF, 

\G#%Jm|XGtdvPV8'0Y{z@tHYhNPT؂UAb|H/|,,I<O"InwU+bAvuτ#wwN0 @_~+?B؂Hcz5J;%̓aݶ l=SwWM7O{93~4ҫg6nZu;( ?ɃNhb.8e~w>\|oћ 2}W]!+u?))ǏU8Y=35/竵3a_i{lP~|pmg'+4xl̒[w\;G[].}\~ia[ۖ7v|Y+yɜt޽|Yُ?rɻY7燌SOQɤzȈy1x IStߜ·roDL,̿! >D6M_@eL5͟_}zFsMhPͶd,{x݆F K?`Qm5+sgJ?l3- LьTdrRئmq0.kӗy1EymO&T;CIu(-~{3QrX&'fَ!QpO!{=2ɯPEyN2jN19hJٞr,m9s>sq≱gKT-[P.XMv.];_pۃ mnQҫ)>`<#"_}K7ncu+Ocy/ֹI_LJ_Yye۰:ٔFS>O--uΟ4Jjq;>~VO6Di\r|o]__<;oބM2tzWnzجq;+ʚh2ò򃽡'ߠ{z?ɧ+Gs?zeo-{ciztR\pRמ״pϝ-ln]xe ]:lwM\Sӭ5.3m/tgPmIޯwߚ҅MMܸ+!2!uޯ7lyϘ>x HxZ& f)>-_j>MӋK*m`OYcu_vҷ.Zb [?`ı-6uEajQךPt[ Noݸ1 ,H^EL KMdosK(%Jה2sӡ}_w=xz.[/5a~[6uw4ho9Vەmύng>KK^ӭSņM?ԫ7 w~ h7//|'Z>(y[虼Y] ݼx#-ƈ˖Zs>(Ym٦_6nK4a1]Ѳׂϙ c(7L=?u:&/67&h.YR_ _oc{ֹ/)liq觅-]z&LiguXwFdh 3y ^?Xz~cԲg#εy!뿢>]V|A/3MwlwQ4bNYx4+͚~{"g{`koD;}ٻa+K/儯Mosh.Z톎 WxD:xsZe)زdDޣasvczg"',u>i%VX&=v^i͏kQo%eV\֞Sg'{%wQ;;aĖv0E&m0mo͕ܺc۶ӱm۶vc;mt~;;:TVzhq^0x! )J9"dA 2p. jrE9%a?̏^ߗ Hې.`y%}21.MF eOyԃ!$@+:r@/ -.P G*>x }RiJoB+t-u?)M@.5Qؔ;~>O Ͳ>B!!OFKЌ6bcEθ~ =`0lQb|5S|AN3x_Rɉ W. $Υ!Yw0Eڃe6ב$NxEH]7aG+ 4Xb1@(|!BM|Ku#^aJaUGӔ v"$.r[@MCV''f5VaPO1k2,U##DEV<#{l"Qٙ$UPسc7cOar_>c؅CiJ"*SpmmeLAN|3c/sf/sx8g82&a$\j`S9Sm/ Dzj !T(`%c~~JWMFGJA!jsޮj,6x%?q 4t\\D2S-"ӝŒXF(?6sd (LR[c3#ښGC k G`/+0[)).0,[VCqLEBmdb1P& \_U6m4olȏl(.Q)d>#1,ƌ( =㻣6z.U\Zg`e!GcyſbVf9/މ= [L}ˋF{f`b'bCı/7$ BBmx咰Cۇ%BQo9D*IdMלSS;$9x(3"Ӳk߄ Us8ŏN3ô8KWd a'IJrB)u GReQcf.zF^#Z3qޙ釺vTrr񯂨 '[0RtlF,5LmUMjL\(}*:c%q{+yWO6ל.lEf1\+Imj@p峂:bWƜUn իٿ%`P!i2ϭ gvÃ- k)C7"N1@vP*)C)Y?,x{ùzxzԀ p xb)h+R\q7MuH<UH^6]^8I}r?MS ^[" XCD!l5k [֓>G:PeGמo]_>7 W~gm[?vQAs[ EN+13 VLnSl r&kEtʇ5mZčtVFL5%}0}D3Rg'H@˚H)&&5FHnTNk?T]oO `y GߛK"򵐴>\&YbGLF_{ėyYkqqZXÊN]lIL&N[9t }`QULi櫖̋r66#X2NM6JYaiin{aZlA]C:r)?;`{Q~ND.y"7U= L7m2 o#$ Km]MApqIe8S]X4@F;i|~`ߏoNҮ=-W13;f/M//H9IðǓfa߰>aԉ@p9Tj 4j t>J+5TWriLqsoٮՅzDv\Ow7ӗ!Yr˻qT#~kՈr5>yɅ!1!v*LZH! Lr-rE|n* Ԙ:ݫ@}*A g\x^KS5멆kQj2w.BI<1ϴF]a[?O=Dz&LɬyԷ,Cx鋖TtusOgE9W(=G&BeE<2=]JQfr]HfnmvfneKUH@7Xo/[K >~*zgtag)KS#k ?J#?R0atbړxH"ۙ^힪y 14~C& y,a,4?5V1&W'D$T::%Ts֥7- Ϛ_+>YTcUPKOJɗgG'@f>d"{>;V`9\S'iHu#Xbɼ`H%1f@^S6sLTN0W2K8d n걑%xζM6I _POүxi IY@cs..9HRw%Gb 'o^˖W֚oxWܷd09)X[ )m͍5Ms e#[͔\ vZwhaoJ:V;qHR4,e<%w~!p" 36F'bKOb+أ74,X+5z^tӠ\S _  Q7ṎYd{S$JOJ7Yp}6 2xkh,lG/yb̏T&,)o3 yi~6"d$֔P9٠`^IkncC/.0h%]4"e~` &6EQ׏%.j5Yn(k3ږ ^"{ x#?r4h72^j4;Sm"1=k0H$Q.;<}-ff-5(?V\[o0ࡴ\&QÏalM T<ۖ"H.ƒ}/gQf,P%=h0c(҉mMj#kaiAZgީ?g۲-ֱbymOCW_ON0$,k41)>ų?!AygUJ<_4KR^f[?(p +pE`E(Fj _=_4* D,~@JͬCŃs{ߌA+|2r@1 |X̪ei_F߄C0xo@'c8J-JF>ҲQ.ց%#8"F*h9V/{ʺw3$aՋR kW|hVٹ$!eWxP#$aHbVdՌ\NMz(՗-Ctl1K2LŨ*3sbɝt7(V%r6,$g%h0ENJlNcȈҡ|2%҆*J5y}VY/gʋǿs?/Pa}m I~AM8o&RV6XN׬-7nL'e|UҘLxw b2z5򺆷"gRɼp"'{;80 3G$Bt#TG چUiQv¾qi$o-H KO0UC\m]AUYPO-aX:FCries<\fWY)L5N9QGJBA!Ӯn#?4ּ(ʆWt*m+bV 26e$Pwa{ˈ 9WGW n^RkN T?(<~V>qcx9Ws~$hɍ꼠t\f8F{;,Lƪs SP hdю~X>ᇏerID>/PsB-6yKpoǿ-tf\EHPu^ȸzxEا$7,ɯpJ>VTàIzSE&][Jc.IYC{X fG639b#?;NRotjm" $?-a=3[ >Ϩ/ld (Zod}gbdqv)Xْ)Xv*US I9 xB:KP+ :F!FF|YL/Yd:Zk[W[o`n,2 .f/!Pvuhd }ƷeNj@z^2ΩO3Ijט)QZC@ue&4ݍZ5P+e3XHB9)uT}*;2v҆r|Wܑ 42_ElZI=:&bNl޾E8Ж?feY_LD !hлSeU>fU 1^޵rB|o {-!s,Y|yнR IPMF[ff U?*܊T _ޱ4m{i?0ĞF +H9`QB#}m;Xx;_"#o0X~zh\"- J' ?aO'ԍJ@L;xr̰o><HNb<Һ&Wpnv1[ DYl>Fc]ْLY g?))v31f)IMyûP2ED,0fLfXN:4C+JÍJE 8R++Ű(YC}# Z,'wo"dw(}K=o3<~.v<:hPs[2CqySG[,H^e{&=ޤp>!&4:UDކL`M5E>䦭xkcn-B 9)cr+PkyJL.ȒPhcm L.r%&nst6_k^i5qϔ}wJZ^[=v۝"q>(Lɓs{IFGLfժ0IuAT/ dp>*vy \搇V;1L]C܌dzD:3{12^ }$O&BpxRdJ>Ot'^s86, @*u<~n9Ԝ2zŋ, *nwݵcV+=Lx`XQrd SFʁZ"n}* M e.ȍ)Ϊ>_@QsW[PWr+! Y ןaq;wIy:L-}#.(Ab&u9x!M&gR?C|x=,. K+ks~ *&& B8Y NqH+CG ;#h/Ac K74:^}W_^:h:Vƍg"p%gۘaDsr%sؔ6<0~\j(.YE,nB1Z-zƉ: D Utɶ(i F^Rr?Zrov:yҸ3&hO\Ԑܚ;ٜc L[0yk % "1-mʂnQ7񒙉) 4+Qzj-sasxIwOz$6WF:Õ׵!nְnp&b%TuҹwXs-5ɋ1mrA1}#<4SK&NF= !&6SOr9o xͮULn͟>^_:' ;MT4CQ XPΆ_{]gx2> xh 8xUJ4vfCO D~6Y!UȦH`S6苛N9?؜6_BC=< ܸ6Nu?B RHxY\{U-1э-Ro{uk? pѦϦ m'Rtm{F+RgblQ(p@P}5AO`Y Bq~NIMU*.BD7Rz+{JnEZBo4mqLs.ŏ(KeԽ8P8^0J=M: oY4R,Ylxnl-m-+ %#)tļKU*uKvh~[QMBt;7|BPRaĴSysAUu A>Ss5" h Zɑ3tl t8 U}jt1qrp/p?10 _ +Ӳh.T|/o~s\IV_Zt F xq u۞.6Zr-4;t0,'/IwѸlY:~[Ѭ05IGW_:+.,C5r tް]>|RU>y Ym̅f(vLC}Fl;jZ{OeuEV锽wMv#XK![.KZAg%<xiAP[|hWoO˦=x[S&ҥ"4S^4yU*,bd߾}۷o߾}۷o߾}۷o߾}۷o߾}#n߅[xI0pl;  $.Ev I n(q x:";^]tU B" ՄfwSB*%13lHB ]P@4EjED(RC%tAdK {oo΁ͽw}}֌Ӥx/J ?Up hTA&DQ{)U WIJ+㬯Ukyk{K+MG*Ed(I1ѽbp(hmg #͘ ;Uf>tٌW1a)RetDJV2"E@kաa%dͮ3dq**datڈMAguG Y'8RCSe Xl#[ȸT"t;,iŧ"-Zg!jH"ʓpZٮq)^/6\*\h v8@Г8&t~A{b(L <f%Z1ru:r*IdvgqV`u)헰Qg9N)D=C/=1"zBJ5=GpӓzLhK1*W1b#HZό4 OW Mq9S!v ɘwBD 8LZy͈,Ċ(jMezك-d+,,8cB"pD~-G:ҢsYX1I_o]!AG+Pna#Qգ\C\aUh ZޤTʢlŒ @eْ1>4`JmUG:3P8zLҙqe@(`<`A tb z6ypb|5+ߥHښ(:ق11y7‡Fi#'TL=EBP<)?iw'6ZqH,d[Az%`$J3ؤ(Ag"H~5(DSZQ1 $kԙ1S@$8,AO:.;."'ׯBAD3 uH4\ŘT Uvxf_ P4N)pAWC 4"A6IuJd`t0lP`X:7]B[0;l{`OW@Nɯ6+dUtx?.d+>5a۞v"cZ#vkIXzCR-9NDpb ]pFdY\ Ŗ}B%Ƚ@<-(Ҁj`@aDX* 6L4.Ǿt!r{b5k8RO_u{cyEb܇@ –K`i |m+)-z{l`$m`ຆX)LIB(!*]'U>̠zp ; %nPiq5kuaܞ7F5).ⓜL}cmiOڸ$p}8>|C™c|.8oca&.o o9U}]iɝ}㝞.Myxsb Z7+(oɻSn6:z_+ڏqZֵR:fy]N~eqSRb&_VlLg,c5} sk__]g/)U_Q!U$.Ev_&փT&ovºux{uƩZ~ͬ}:5ϕUOFᯓTsUV[6^w%KonK \?z-z;96ywuK_,6WKTU 6vdUv mT{eܐ>|{,>=]ȶG|=ġ G.o'4AjqxcBs>Uq0Ⱥ~?wy3oscѬnSV<}0pUׇ7u{GN-2皷)-3A{uajo42oYpP;r[0m3e):WՇoϪ5w5>W.>?m[|ʝ9psO}zްMe-:_A)s8vۺ#6QkZҧ:O'FNqzpLڰ6@禗V\BN=O ?v*:/gY #& CҦOoZ7xՕN!{-4|pjHku}?ۇjد߹h:{q~xwnEԙI=e?Xhnu񼉏49c/wv|ֺn^,kS~vu욏B ż0ߢTEjR'mGVM6 ܔ.͆~g\8Ru./S$M;wvy.6_Uͷs˕otV;a.|?GfS` }f$3rgn[uaecW׾]n{݃www@w׍;3S0unsn\~oҫZݫ?A7&COXVdECеmndqrص0VNQX͟Z' c I u/z0<޿ פ wNkcix/h }="+`"Vw{:MJMչ}XK7ʯf.ȩµ[iB`;b{ݫ.v,9{8dDd8hLۖhIK&>KGԂNiHŮW!يM ʭj*%1f*RFCTTA_p$7ĬOJЀ~Xnq^o;*=Hق\q9%t;JcKlxOFB-l*̈3t-#_ݿ변'sIm|eB}ńxe#I,Db>sSg3TXQ_9$e;):lsC?E-i3#u- h 6@B3O7 ~Er*D G*x8% }KyP0{2x-ǻ?QdQ;y+{;o"{_:iaa ub/>/ 4d7d!\nѰ PlwrYE6}$~Lu:|,\W :Oi_!fCsnYZl"Ey֓]ksIjF"#1 ـ7fꯑX24S .E$^&_4FZpvm>0 /am\fµ>"IP㮁4k)T~ݴmLIF[ yFQPtc5n|4YI2]^.sܒupF;WXB"./3?&EwզecZ~Hnk2 4]8Cf3:8MeOp؄SBĵcxQ7HSDY˰~æYT(a4JcWkD3% uz2woΟiéF+l]>б*bNoYU/tRrGQm<F攳U #{V%N Bgk-_"5d0-QMȵTS6&] Xg4huyWzN݁g8m1tERH./nJZ4y1=ːY& B2X2=cd+=LMňKH@3bz2Ӓi2:pL3x\2_/Y~JQ]Hvow(N<$r5a3k9h^ߠioڙsBE˺j9%[r՟ʹ%FCˆk_Rblhlu0=SM(Ke̕LR"S8+gZ3&-YKU^w}о-S r Jb-kPpF-ȓA}\Pf=MYjYi`[G vƙ,DV0/הEdB50)̲|a]mmK\8uUK|5A g` ۪)*S*Ou.;4fVJU;w'N1v33W mn_׾RF #vJُM3VْZP¥&(e艎.R{s{GSVG9]0@u3\qZ9;oG ˖qq[ۡib^p#}|6UFDn6_XQB z\en8-K7ѫ_jB+aXNaN6` rK7,8\cmd%Q<`ЦG<Fo:n4p;.[yhUDIw^?(4@YLb@!˩Rd|NyF2/_r it Ҕ?YM:GᖦF]!E]y!?`ߣ/0SWH}W֗jZ Efw~%/-we> ǜŴ,ʾQݍe9«rWrBFPu-huF6DJt[Ut苍ǀLH{pӺW!ŒggT*7,6<OtJe#&^(S3ҟ'<) oH?jC$yB et~^_&ٮ/Yy,J(?7tR+z RL,wz6ό;jy\0}{b"9g^Yt˓h){14"鴇DP;mn8fad_D!IYiE_4|K@6S Eh}?Jyɿm1=vq:œ`I_mm)91ܲp6UcHi6~ypXc]/cBų"Y[v~T$O5UX\Fto4u~LkI8{qfMJnۘ"/;J5T:n:- !JReZ+ƺ _{ܰ S!CjCi> gcћs}C LT΄ V7 ㊿G>Dc]kds#یJ[H־| nMdahb[_B#r~{;/dy]\ᱧm_YTK9b@Ft@ eS'U]%NdҼ쑎jPR_Vs^ygZbo-GN1=FXYmz1f/V>u�H_$*JYeH:eDȴ5'p= ڎ8XU*)Ar6dz˹$-B@$iۀ"^)Q fM5d!=+!jϸqKpO<9֔^uɿqMdz `OR4D7ՒaqcC]CKo} Kc3W iO.aOn@EZ'ŲrVC8},;C®GDK;R0XLp.Pq|}{w&[6d324^&碼v%}.ED@ijSjP`Í_~}c# dx!iei=|wX 㱭F{pՀEw]Pi«Y<3 RX0GH%϶Ę(Fcd-=mX*`JuCSP +`N"&tL?(Oaa`bs%kiKɅ?|U/A,\\aRg6} a9Ujv5 9HMIK*/ne :G(y&MW5"&ZH'H2`XNƊot#xq J#N'Jx$J"3ɃGb-#oщ fAQDf6OwB? M+ ^|!l6VkCK/܁L.x{}WB>@qfeX%U@7H6;kI牘H jqmszߘe1XI+cڨi5Ʊ$wfJ%:OS*E<ӈl0'#~$?ThZqk&GȂ9vLЗK5$ZuT,p|6b9IYYGx7᜖h"bN_K5R ^)0e`obvQqB@2b;{:>H s3! `Qs _{,yS 0 MnaI\p;"DU,3e2T U0*YxdN {EUeqAz Q*hRSDMJpߏ6~ 0z4B{}CT3mpEFz _5!)4SFx* =K9,8!3Z58(V+WvSoYP׃Ah7%>n@AN+'LZuo_$O9G2CN>:b7Oʥ_},]w2VEr21wǨyxjfFwH_:Fj152ԗǙnv1Tju3Gx'ƻ%(ְ,T`6ixc7 ,D_~|z6ǝLVa B-TD#wOJ=Fe猡P]e|EDE0O֖Ba7[kVCݕ<XJ,dEI}O3w= _å_JqlQ`n O :vEXgj=}ȅwP|U?|93ꂀMiޤ/w8ȋ'23/Ci;_.ULI<iOJlEmn( ;-؃ʉPcO*ͦq)b S_]O*̯e}q :0 a׬ W՗v(~gE±^)ݹsIiAH..I6%egS,󰂖oXzѮ-U7R 3uͪh óIxHѣ_{`aK-o\fˎc]7ճ~'1“A 3—#ZaһhLV0m=}_`}cBX9WWNe1,&~C)"3wS"g pіêguڀDU@:$P tu~ cc%|FzhaW;;GP^@߇_Y Oyb*bar]ȧI7g3'fo34(P(o8^d-r:AJ{v)93˼C9p󋛙(V@PJ$Z~۾vG\.HvRv5sO؃rAk?."r 8觝_U?ב1t0Q){*pϚ56}+b vaN4"S弝u*~JjA?jML O[)ZM:ה:dww+C5}EʹSz:5;{0HYOW," <L"0W:8*oQgWYky,E:!i.y &4#>8VTe(< rC.ŋSv`0^vxlc~e>5AȏUD_>Rddɤ!*6U UcGS7G쩋"^G6.Jr2dL7,f^RRgB|;jGoIt/inwhB7/cן(D>{yjlvn>qIҿQco]O>}ӧO>}ӧO>}ӧO>}ӧO>}f8kSMx ՠ뀔r_It6ic̷/8  xr&DcĶ5m[۶m۶mo ~ꪵ.0 HkWZ3UʔF;ЄS&zQx6њ8Y)5>NXʫQ*q*[eUұăt 4}1:""&2 =D ,ddxdDtD4$ \4JH !>zHVяn ]/ҏ.>?TAhXID&\N-?QABI/)%9tk3LxVp0]@PѠ_Ad`Ɉ߬l(E_eo\?>V4?Όoב\ANЀ}3]I):4'hn}R~DGq(=Xhm<a|7e2Yc\$K̍Q*MmzjnXC#ME4^\:+,:;zoYY2uaWF3_]{H&DgU'&[q5II]T#ݍqՉ!UG{+nѱU3!{PFM ]hDgmؾY>ikY"6:3v0J"OE[Um=l$G@m jhWÙk~H]fOZ̀-l S Wt$OfV:D)KG@ +iKQ gWJAh%X'0IKwgrO& ɋ3KNldO{$q<.ʜ9h%HltQ}n^{* NB^o~P~I㢇b.ό龭&CdCl?1M|ݒX[˄}N>%O!1l!(9'VƬzԏSs3'aa=.NOUl=%`ǛΒ@cB]T8Bb߼r'\$P<_G2>>^-3T(IEy&FJX& g0 +~RUQM}MuIt Ij#7B,#7rb]gM.cgAVT[;Ƿ{fCsJcd92?"J]sR_2_6:-d rX@fBv Z×reѪKhf\ HWeT~,6֒JR(9/NIL.IF,uxa^ +xz7߆p*l**U !*鬸`+6x9zS<}t-D;6)A'<^zVL[Ir34<]P!\nyzؑ=^%V? $HK@SB^ c} : ᔡ<qI+a9x a},ru@5O6%FIjKQYx61gbHPG`WRqׯXlَ$C#@ViaVDuZWtw\od"Ql\Zrq[!2m2ǛuElf)G? u&Muއ3,KNt<4H Rr7uOOՇSdzܰ\d|ܬ+>@F/նԺM,W|?ģ5Q Yd[p+`c*n{Y<o\)n67总-x_* RnbwII+iw.z2֨GڋVͶ!tU}̮pl+;Yys(9Z{"Ҳz<8i ܒ=V9 =5NQ^a'TssXw6jIMK+ $ AC9U?c/ӈsT%[*oB&y6?7DCIm W\1@2‘~=\hKm;)mV_? Ma&i H8.ͬ[5vU!_ p綌@w4@R,@GKTMwTF(y[:A-T 8}>+muC3yP}$][EjfR$u(UhRv26e&Jå ~iͧaΉە_k٘~sI~SMQH]y"g~Fhׄ d@4#*0jm;s eђ87]ϡK)#ƲR (m]wJ"J9 H@J=48xJXH"C0(;Aͅ'y[N'S0\.O2 Lu%N)vol)I)A*] /O˛h󖛄P՜DwFLHpr--8WzL TJ_WO՜|gtV/ܡTޙJc Ϡٜ0u+{Uu>cERvPü\Kӥ3$`]le&H-ql<%h!6{y[ &o;-}וi7S]SOu: /(f^&F˨%Ѝ AsÔt`0zZb#]L\ H9̌kX }s/a Ԃw[n8A??贝ĊaJ N\5~t&jŽk$C/K$%O ȑfCSas~z#=L1BKp o/z t]G;C; Q6YWڅ9K9=9^nR>j<}{zu jNn#gJz([ܞ Xn5vNǥWBբiMxkQk";{r!5L?E]K88llܜ{qgЎEVP^}o[Y|$pRk@:X+\_MU-3+/F-m 3Y]iwKFG ª(XVM8bx\p(s-D|x)b[~+{kbUe$tg] RYΥ̳OxL&Ӽ^{Fʒ[-bP3c=;bmVʙϞ>q"Gv0a0 i.m:P7:6MTc ;=Rα I(p2լ 1̱ Y1 jz/"z&C aQ 0eq(X6 (Nt R^Dp;\܇A<3H,2 vB5_?c9ws<݄&D<|>_M6 ;BV{:| 2}9s1E̳A[/RVj\Ւ. t$;v7%o9lso 7Md.3H%>7oʏbT`B@p ya4_Dd/< L0l%CA2u;(fc=Fl|.M,4 ?$"ǰ\1PlsoL3ry[5*"fx0$}#LЕ=䤨Rp:l}NhBb `}lrp?=\҉' =О B&2RfS>VFYa<~ ٗOYlۄvgaۥq?-JSwO!o4gb:Zu/GGlkp v2v8mga n M s_Y6JUmlJ&JYg`,D:HQ_}|nr`;4y.]8ksbveJmXqNRĎA"vu۝ (wZ㜡B4~Z:hKlXd5$Dk%2pn}!p)*rM4O$e"eLRw"R]gKKFjgdS6+;PRWdj""[ TKf퇻TK{4p)XGCnUW7NBHY6Y4;i r$}Ӱy)!$r;{"_[X*@IF`o>Zԍ5N:rb0+I%>]YGFyWQF@v /cuk޶B+z`|WrӞfZX4v7Ηpq5zw>m+>s{zH+,8@۟;Whw/E@*n83O\16yw8:"Hᗻy3W< 5!yY"h6wbB:4/:MDLBELIq|, 8k1J,U Mb-40tQ[;)zL\>k^w$*Ǎ7n[~۹ъYwpDH1e!F.$[uH ƺ{bqE)N_$ F<>IL~1x o=̳y91u׼$1_ApnGс[^rB3xxo$*l`v>Lv޵]*". GA҆KV@&(u"Ύ(yQ,azjqouk7o6y+. {o0`)K,7\10}sRF5*G}m-T]WzdRHp]ݚb3p?Zz*jaD-drIJ HxQo޹潬ӆ/Xj)8[D,`ߪ 7vW ^PFDs#ۼ%{Je/4;HrG)~D<&Y*r ,OoY]=;6"AcxEf5Ǡ2Rδ_@6K#u[WeP1} t)"xlbdPojEG?4_ l6)^167~ᒡT0|8u on8eI"ϧ-(`X 쿟 :iu "8udY 9$osӝ+öw d]6 n[|nJB$2ziYC2ueZ'=r>{LOTs!eÌq v8fXfwL݆h!B[.eәAa},1pqL'pg\ϡ<"8rL}1j4"uZ.ċiV^P۾\P'ةZ0^(z V< f+~;3=zRD 5!3%z1GC3hVp, jV8uf7~i/ItFYI8 {W#i {nԭJ6y F"Zi~jky4X8,^fB<ҊYcE w%SҢ6(9ܙHCG妻zd?>ElWF|y z-;p:]ǥb!P8)WK,/mw8sJp~ViTg}Z,Af"N"oJՆv8,L{kaڏ^ȣ|Z[* RWҍ͙t¼*f2x}-#",uATcC3b2#lQ+CP%˝d=}0Ag)߄ޮ82|O[p4zW/sdqVAwjO͈&\^v+ N'-d:-.+knoTW@FezP ˸%? p+h6 &?ɽ ̤skDٴ%gYQNY;ےnK Л#4u3$ޘtyږ依aJi\k1]Q|.=᫽./(̨faЁ*.'pqzj7#O~A}]DH]@1m2|4v~Jtj0C@pD4ۭrDU9RFseSYcBI2RCXs@ZEuOj v5# 煏 4]] }97Yj vP+,Xn*H/U—mX8:͑*B(ǜ4ퟟ]\u:jH_mWFE Yﺶ:pAaz%fW,slzjEht  `kQ P#[9(UJrT`Q O ۄ&= ʪK6 t !BNFlxt.DC;[}faM) 謹G22ߨ2[kO4l3ni&he{Qu zhX2,r8UT fTЊP3TC!^ u'2J/Y )n\. bRaSv\i-'n9o69PBd5&-ɹbpj7tH|Z BEyD;tŃtB. B}ݠ-p~ΗcQlLQ+#Rʈ/aqUZmρ1_Fx%X|PoQ?7#,U=Z形nP~_ y/4slqur&tϜp?wnI~_(m?Y.am2@"Jt&_ ȸ:WՃpk߉lfmpgn4ǥ+f^h&=${'-'wdj$!}ADĩFicws\]eZ`ԃ=4Figvb ׌wvjxZFlA xEǥ備!bIh8{XŬ9Y'%%ʙ~OcHc0="wU3Ssհ(d,%lI^#|%op\ r#Pi1a~~ee..Lu;vdjrCbä3m@k8ﱁIc06nF}D{cľ]n A0O͒]To]>-.]_k<~5&:2 p[ @Y,O>E`JX,UtB*NzM@iE6-ˏJӶɟ0"%c+aZBjgpDP*?hxrp8An<*gnM'IPu7ڰsE8mtS?~NLй[ٹ2-v8'*'ߌG& 'Vg| $z9hjKIEK>:r*/14MT?j4n;$0\l 2muk?(K:It ݈yDoR~z:?.d@ U2Tn~8[XQ7RsߚbƔ7Ȅv_Ĕeen̼0,(nTMZM | 2"9;_#6|t_詘M^ƽtp)`we. V&+YAQ.CCs_)RoMY˦3,*>% rC!D;x+.2&&xʼ62793gd]'.FD{Pirts)$Y7#8}zS.Qe͂EӁъ7ۧ=~l)ɚ_W(zEGa$=4 +솬f|;t_'G_(&QY: BBTRإB#mOG&|:ÈĊ/֑@ԆHH2ꄵk鍿 ݟ=eu$.^+fk1\At ː qu-IL:S+E w5T6L#|ܟW0y[R䪩KV*{=jd`&%&޴_/FFFEl̖7S`'YanNHؼ7?Gʋu?N-0H|[#<+~kdkŮy{sc9= k,ߓeF~&ֆSֺŊ'dz @Co,KQu$m]8IhUie";@}(G^]p>w8uIG{JQDd a@XUx!:WUi!$P_2aՅ?;w RVC>pc3kc{gZF_Wt]t7dBSÓTQ#fgׯVbTrqu%}Wʱ3#8Kɗ4Fwj qtpȈ8w. 2If1v.I|!ιxn~Β{TR"ؿ{w gC~fRXz"8+[h|6Yf!2W"_ENif[19׺gD,)}( rj52_|{۩Y#fEY D?F1Tu{Ҫc<VC"2Z-W [>D߫@z׹/82$\S}%TG9B-(ZkQq}I3j"st3dOƵK.2RN ZV98U3`^fyAlC {>v"%*聪*Mw#Vu1v; uXጭPTh<8'|7Xx\aoҹn~H+Xm}5c#m*WVLb]'59"hbN{8gJpl{[\eS;9!6eKOT#yP>W׬f>Lx9>@ۤ"VBm< 8U=/m/ {f &鋰xG-הtNƢ[kENk'Z WbG(YʹR zaO %8G5;ڻN9Kxa>%lPq)YXl8~Q=/sZs$qF>rP6End HSi=0Ckr_8Lv2C6fN^DRvn'ijxLt}ҟΗEU=YcDK"7;z-^ UndLtM#K6ˠF~#95ӏZJCQHfba]|e})C!<%- qcmAjGVi yAaUdl.sB8+wq^?i4& LWy40S\Xd T87 ]? pPaAco~0PQQݿ:V~Ax{HѰ@D0P{@1Ȃ?9Ys3LFj=xX1D{k@{MAD5DW[xDCl`4@vﻊ[ᆂdiRdU!T~ICc9;)Hj}FMN>WADoX/U COBjp0V*۳knͫB cym74)-es]KOUL=Acݯ#3q=gVl‚#tՕNNIӕ#+ŋuZxE :c~NR"W*;`P,o[p_4Weg6*Ӿ oMegzmGCcME* ubf%,zK 3 c d_ބ vj:Ljק4ϮSwr3YA1Zh:[نBQB+Bvq+j3U¸*ѩa]"? uqB@ε pH{:zwʱGߨя2iBpySiOOd)Rp$Z7CKۣ"BL<1 #WBiPwv 7+bS$n2(W_AhCtý/ N@o3}Suay_ MY՚R3P X+ N9:oG)5={Z_ak}2%Y#!8\vj*]Eee72Jn&# z}lKXwn]S][{Ug =l1K9gՏ()&>Q]ux:I6ˑk{缀࡚.7Յ[G_ҮU@"^Zաu[oHx7xD =Ի 9u HCC)EC󥾽0DX~D"p?1_ڝU.6$]mfj/+-PBz>EX35ߖ ?sK15X-NnN`_ؐ3>«K!##Șo'md<3ߪh{X_m2^w2qGB$۱!P7N0(7l+*Ymk_D +kjNlԻ{?+h_QU?,7'Xvˍ7oXC q!V#W q+6yW_D=Nlr0 ti,Dh͚6֗]  =g~l@i6CR=wM-W9L]ePF3aފC^ODV޳::FĘYZosv )_ۺ!0?ʃPz D0o_7;疢vKX@6e OȖ8p4ςs孎f Iҩܟ?*&{ceyh  xIm4ך15~FbA )P|boݚ]Qmi+"qB ͍0O r%w2$*B\m(ױ~0,·p4@}["44|_3 b!V~5Ewl\o3#}2Ć{?#rKsO?D"h}aUa]>4vRcܷ&]r1>%c}z4x!?:4q{D rN@tE8婰gϲ@k&_{7^{nu9c y|¹Wm -X ;!T3|9fϩi݃kSρƈt `OI{ ڠV8ttdbi,1O]RSVU~P5j9~P8/#Ȇ;'| uۊ%lw*dJ209j+ Gʩ&wDY;_+ԝ^ckAH`i!W(V@qŠ p&1h.LJDL-r# k EwhF"a%ecMaKɪ-ڵ1ác"U  5z%Mb 2ptvW,8hdjkPXP؈6F b>5xZPUӨx425_`CSx"p5gzG}d$ "І5RG+A&4 P. eR7O:h#ۆ 5+iK9ORXo/#emvPS6nĩ'P5004>Ep7,cmUWDrD/aholꥄ%C"b"R4Lŭg *N!~ RZ5Ȑ\YT44\fN{9ޭ0V?B4]!~%uG7@F1y vIZMRf~Gގ.0~ G묁|^N)v`]ppL`!ֵ1GXzBre0F 98v?MOEtC?2Q-d^wᐠ4~~ ?Ryv?DwGw'~ڏeI&MB@aS 6wvAI!DHK0ӐxeͽrEv=.KSeDT>R<} 2:::*:**H?I=aE.KK_^T_PnT; #x ?Ѓ*Өd ԃbZdsg}c x3(׶m۶m۶m۶m۶mx.&'jh?=]HU4:hiF˥2Q)J-h LɅILC>U "&J)M* @īb&޵>%I2ο}]rGh5j_+AuGܒeK_AB\: tgEk.|VT*g??>XDR{Rp<0%<( @rZ` UZeOQ%P׋G%v2 1f%g+#%璩,0@*|5=P&YH PsI WɍU!o0R[Ǖ[%>x{acIOQXb QL8$ J4{dŐeH@x13!Aa/ ͨUc8N;WJk\)uՔϞ#bhPzeAbI=/K**YIݡ7Ud`p-z!6IO蕪HĬ(+#(9n%TH0.]6DJH 7 h/s«rJuU2-# κGRJL=P6:ӛPcɂu!, d^Ft4dcK NLyɈ 0:s}J%U}fމ kQx;Et-OHl@8) kNHcڎ1flh2^nг/ S^-Y,㰌 \a74.lr`蕡3hX;C ^,!9zxAP5:fq̅Dž чZO5P]6-N)Ia@-]A"]:] 'Q7NwITX管i)ը%5`0\V:DpKP{vbQ%8ƍ,ވB\+!' ı8ن , EsॹL #hڣ=&P%x-ϨQFtOD4MaЌpy3^{lгH,Ap,qVެ ZB㎄/_ Rm  1MN4R"G><, $ @Oz"~⁚Csfbj1(=D ]Aq&Ivwb$Q❝CT-=驲ヨA|YLP$L 8eʂ2[+P>) OZI r|O!REnz8Mڴ fN,J ИŚ/y>(p RB!t%Xn8}0g܊1KY&PO$j{ddp\%(SՂdYEQC0K7M5 `РW^}\yp.\:a*` ]%@zz ;KSHO9 H8(NTj*\Eaf~X4RWBKà$h8%Ei'[{uͥӁfs@M=˪,հȳ7TlM+f* m 8SF tN{y3 52hJѼeJpb@&TvQvLdA`1ĨE;vIp$L#^)tmG [ljd&fy@ҁ[<"Jj)#mw$ho&]-"#!ؘ RijNKwF"PILr0؀.4IƁNyRL*:"SARΓC{5& ٬{rG/:“ŖeI迠`aJ^ez(d=T}F%VVt^,O!{-|WdW *ޓ?Z$(?l%XńYCZ+\M( %k UG[ ,a W.$sH )dnCkՒ;;+m7!W}W(}Yo9 L =׼~ jN*~ƚ5{+( );Qc9 ζZz-Ƹ+?'OlzZHEW⢺y\)H+ntU:^8Y^W|[ki \vJwP8E|r4w%׹{`kre6!nZ-y>[owW_@!;h9ko`Zgj1y)>.6g~ˤ5ВnТ'_wu1p*o0>n+IH]gAn.fͽWNj~m|v_Ŕ @Oh upP8l}шgpȂ8 &vTpXΤƩ3?leAwҏ\w#|smfVg](?~,b[sd}o5ދkjg|\uS"˾u_mjsg^7>/BAvm?I?U*7yCM!0jD>1t5NWȔW52ꀸ|~5*R*\>nWְLZo߳B2 3g+vLܦUWM&9Lnȝ~8-,xhXjCt"x,_d3$Muu]5bM[U_@|BLtm7878:LI}ٓ9vߵ.J_T7厛e &k5o]w[l[r5϶ny=VywwO_jh`eg73=#*}P ˵i,,_UfYiyÈo^\ Wv| ϟgxR د3 k}m4vecu )W[](}ys0J+vӧ{? z˷{)}[zܝwcbTSH  x5*^2gѾJ }7WuJ!uP Dspۈfg7 IMֿ;hGw|0M+<ƒ^tŎ3X|}{wHSY=K8Cw C!눼Na;SKV3}_Ƴ.IޘW ½xXkx Xh(^\lmA—mWb*ZѬn[#Z')9muWT.i^}k˱M}0꫼[ɻt3GIo}]}}(lcpAk16WevQbܿ~Ң-IVo?*@cn#ۃAJ#>Nyo{wm s8Lt;"be+F e!7e9Gc 4P}>: w~IV|: 6 ǶKP1$?0.r0턌*]}6bݴA :"Fq={ }uj[|"AsL]>:uLZrx;tSYP$qު˳܅hoP͜|ޯUo~)?S54\ lb#Xh\NߛN&ɨ\Ԥ՟#De΍:^Rf氤NCuxW# y'_w_Y(y?y喇7QAVڠWdc6'ߞVD4B'V̤1 bs;b){;(?CǤ LmX3q 5M7 M]famYGl:vj)̂'J+iYP:)>3r5gJP쯍Kܥ&+wWJ(㯓GSȢ8QeI?jK/1/Bf`ڄwiM;3Mc;X%٘eSN‚:#rV a'0D,uu?G&,v]'"`[pqF4vHC>0|s&ȭŮE`!eT]eWw M.Mjt}fj+lChSP3y$N>_S3tbwV\}脖tm&[d 1Xj2>Ot<% v| ݢ<{`;?;w$Q;N+hQq$vg9/lwy|;(Zv%Kуv<[`&lg C0*Eά ƍ.GplkQhТ3u `H6!kWhz?^;= !Rr+]$S[uA;EDV; ֛~Ok1w$j4ٮ8-כ|y?oap!as'rMjdq`6I^7bDW.[ ۈ9LЦd/ !o[[Q~5FW6ݡ||ߟA2m(Qir 8}͛4(;(Uʠ}X|*|-HR[Ddž US  ,4J9n҈Oo.aTZWob|gy#j1z|9F<c7f0^WB-h>~C*4-G6xgÿF/T+Y%q21QĄlؔ&Qh 8K6|@ WupmXdd9: , Vuќoxp9ڀ/ﻉL:,sȊFm1KZ1`ֲL\lN\M,W:wB;3&t^WZ;VŒ)yI03k,2iXZuzCBj%FЅ:}:M\&IiNo'!= Iƿ 00]V&v[aCm*8vYe |8|_?KJx^/)yy7M!`{9?")ܱP*d=R >A.`(Bnﻏҵ8b5zďnޒ& |Q\\x '@'1ƚy)sS\"ظq\y^Nh>qnp@gDTڽt&QIF@m8zMspmf.!zB*ckHm?1֯Ƕg 1 %`^(Ɨ-6z)h)WItUkQQZW!νg\ *X() 9~{W =jo|8E*R§?uM8ښw| #^>^-\g7<a: ~g.fk#@XݍP>:eD!Bg}buh{qޫGCGx1 Lƌxypl pfkcͅoz>b΄vϹ:d/YGأ)P9hQZgHpz.|XW$瘫ƈ߭m5QQrM!]Nl2&F~'[c. !( "䍻y> &)a1 TrB7rq݂]l%6eQnye1'\pjY"ͪsw78$#lBfoK'4WpgƉIz%ЗwƏȴcyy:}0wN -4&^o*۫B׼;q(fqX>sّ [i*#gOp8BG\'BԋN,gȼyDqIV^\$+h>pxnk+ ;]MNN&Gm':FCV&{gz8 mKyU{y hq񗴼_]xX )whGK'wMI%YA,1UB U]!Z{D}k &,}ϬPhpD1"L ʿ]-o53Sfrn2OL=^2?]V{ZP[{^AL%r 62߲XN U$&UBHߍu3|}~"00yQF69B4$r@GԀ8 й*Q#hy4Jjv|N}-"UJeasl 3QWB.xI-a+:Rԛߝ7 XP2i{ qG ?ϾM#P} ݆!u_/{Ra K!B|)V[q#QqŭHO\xµp| #M"WACs }AnS'uM`3T yA\jy#vbf Vg'- H󣧮ql6Ü0Xb.@m>0ԠZJ3|ZIX?iG /'/v~\XwOJP4WV{P+֑맍$ u`T~aA#8Q&ty>9L6kpM j[I@ƣܸq&yFWy DniAʨpKK۽vCW#SAJзo;qGj9dFg<[cɴ;\[vΒء)Vĉb8/m9@ ΊfPJK5K/ 0tQҺkT{MeK-]cME{9?e|N?c =xf}yrJ~,"ܪ3Q_w3#,(c{tW6 JN9O{Шl3x_Hsʋ@Fb9ss=˗k{/5J4t1+1w1tq_cFYaN7E8+d V K)'E]={WwiSϑI/C<[u+ǎyrd@TQRd;)x`,0_l}oΞ*|TޱkzZ`7 N{8;  4]j8Œ-vSK{⇝.c&@h)E8(×'/LkZGT,,/DvWਸ਼P[w:sE&91u)70R4kSΠצmSSe= /Q i KwV_fsf΄}|fpCKDlJ\9fxߒavlzW;LNVߒqmiyЄ$49YcQ|%E TV/uU媇\CK\ ҉ !r(a`+D%ĜAӕ>6T69ҽ3%aН'+AWώcȈ^;d΀?6dcDvҦwTdHb;@!#ys܊BiY(۟yKϕ#NK2mL?30;F>bR#ڃ~n8'XȖ8MO5*VT^' x=x4&*!Htxs YF$z'd~.7ymNuy gSX' HuD=\4bYڹ<ǃ}u AXm&gFymO- @5IvG-O kkZBorJis=ZzwଙFv"! 1ࠊmo_dNu^o!'eKq>_My*d>_,E c i(BO Nq?.Pg~P.J^nv7˨B b?"C|8/Gŗ^}_eb;z*j" 粋:PeC.w`C^Ʉ#ˑf]@Daz7ޘWU-wPH:Flwi#xg`3rB~r8ì<ڥMDd̛csD1-}H Զ@X+JtQfnsW|9#;hH٘-6眭9pfr@oRg.0yue$5ػ@P3`ed>o$G znEB8Se)yLح5#d 9kN]B~!x:3J2>c]f; ݚ-\b2GOMv-چmWW[,#q>ObRHE*e/7(Ny8(5زy'W:8"&gAqD]*!)AI]LHVV *k:[^]@“]MHI}"۰%)|CJ[+ʻ|i~EOh2V,/[}Ii⹍f=k?2McF{b~^<53/wfSR.(7>R>'W'᯼HBІ[:sDH׉sGN85wKKQJ3|EK-JSK"R)wF< cn$ c>G\wW!mv_' {3E%Wڷ_ڶM(`5 4+,rJ*+uYM#ӰooE,e]@$uȕ92YdIqmk*.jg`Kp{W nӽ.l*گ]K 4q$ Gl@j^AEyT@+5we()po npf]79<~xJ1}8N>gwM&MTi]j!9&.DkAK3ɢNogDVwjTKw V@b^8KE+Z#d{}N"Q͚w1\!p<,~ۤq:Jcq9΂ZZ&m#Zٿq+mjtՌN*$ݬ"š*WoR:L"h->STh@KF!q hKH -74(P_M^mH}Q^0#'DMv/Z,t8[ :Mcٗʒs>֠|̴@㸣y=Eӓ 45z?^N>Nd= x=rFRH H 0x ֦-ԅTdīb0QTܽ;5i}^6Q1m\̸]d 4;|Wp0cyNiK'h ;!S4C5E/ۉ ZQARP! r*4Tl%D)*0CpcR&&OJbQO<&Ԡ*&tR`dЩ>i]T,tU o>,jD _K'35xo>W- KR8 0&u׍!Hr /Ł )X{铫lTQzmY13EeOv?j3JҾv46([9dXZc#/y=eQ"2% ĺvFK]~JBեGZ 0.ysΚQ`xF6(~.7AdyU9/i*=A֊+jhOl\1Wt,`|nTܢ:֞NB;:{H-iZ!p\1@`[Y>|?^gC$ =e. %!Kz挳\,s:3x.Cew9PH5$Qa8v*D+>v,=MϠ% ۞ d 8n@1x=EﱝC&y.Y>]zU"*rTm*O!IAꍭ Mq Nဍ_o_HwtۍP+m3\6(Al䊔 .A+ؕeˎdWc&.Z^1Ng(ޯj_Wd'2Lp7~cD~7nC {ml>h*f|]ˢ tۉs';1(bUXt 7-u\!H:v3/(n(:O6[X3ZWAB[X j%h(߶e[ w ́wEJ>}ҹ5p`:\>h}Bd_ Ϩj#芙U`d*E< 'ؚYb0G4msjɝ/[K{5xlPqÃ,>E?JCFOמac?mG2BD0pߪY[ўa dlՏ*!AfP/Ȫ N`DB+s?װQn{f xx&QGT8 +RK Y-^0g' ,8ڬ/sVt)NGp0?Ǖդ{x!%'I ++ ׅt!䡩Wiك.=fydB5u}pjfUR_]KJ:IEQgDj?"t Z^ʡl?:2L@3/r R؟Ǘ}>Os6Fzx$(x iTRwiϨ@ɡ A6rMtb ]xr% cOl۶=m۶mĚض'ƉmdGت.($ c~/?Yr#:u, bk%+oÕGF[ILL7a8cq޻0+d) b+ʪbtuHHHH$`~ԡACvvF3cbs>">3?Dχ쪨쫜Pls$N=M gIH2~Qs/d.;ŗpYHԊ +MPcubH"Lcay6]N06PoLþ De܊VޠسJRVξd>aֿ?&*7@ӷo[[_=-x.g뱫f2UQ>Båo6ͤ q"j/$$|Nחx_VUQaKĴ.՟DSs_0sSgW!1?̘A߿-[W;l1UJZ`L,"anYbaڝƌD%VpF$tiw2V6<NͤzK23:sTpJefM5Bo"Aխ[q6 e8q-NmwIcڏ[ mGghA7m&^UZ?E\ 5ܝ[d64)bjD® a Q1Bwe.;90,[A57ڽ4\ )l(Y´V ?|X ݁F'=#cS"\%mb.x|Kms;,6;0Il]ؠLRZY|v9!,[MzW{Ϭ:7N@.-7S,Pj~=\SF2ܟ1 1[vnn)=껛ԫ}GTKǗ+V[و4}LDUwԏeQn C忥+1؛~]KL3kwOOXޠ 6Sy jL[^/? Ku5{8 5Yn5ٍ1&{tJUꦀA;J237Or,|4]fhT1y$ĶJiךDJ#/7+.iQS6/~WVLECXyǾ=|n!9tEr%g0PtJ}4yzhooZFGv`ɵt)Uf }!i+ɂ`+K͇{' n+1}ά)UٍFnP|+0"Yq=w:uR~}'hW;w빗sa۫ԓMy<+{},a4H0T>LWu㠈%qW6aEtcI]e<@ŠwۍB`i=SV>MLL 9N]xr\s%l`QG֓\xɏ"{aŐQj9ܠ"ǬƳE++:X6o {턦fcAލm殮w Eyg7Xm8bfe!?Qペu''Lh8m@ii.WHlk!Yt|En`BBXſlu"8A?Xe3iĖTfߣF򠦰L^Peɯ*$Q ;'9>FuHڹ$?St[h)<~GP*h'e]Ɏ +{=&waa:CXdNNnWh5\g*xYț|.^]gnpot4 Y^1~os("KtMdmCӌ5nVcPuo0Rj,F UFy+ JZ6=0/ R)M-E'(EhͧF\/ 'y!:y-&(D+<O/ Wz%޾f/:2_pǖ - п%wqIm2mƶEBe5q.nR9ByL+|և8-U5x8qA4CQaJ|CvXQ줷lKcTs]JNh8r3iɒr*J3[XB)>[ܲ~ߟ+ %I@М!J%>aNEvrpwGKh!bgK4lhh0K(aXbМt Jy ?"aUetY}/AZSʈi+S7zCi׺MrSc _KN{/ 7ÇXUH>Y0a>ch;LDV}9P"vߥ6J"5H)A:S]*XT_]}|RRk :rQHm8N {ۏmnR}Bs›}Z{=WUw8,Q",[̍{C̳ǻnHd"<9f1ݑnbcBB;wm{Fԃ֍|K @NN3/ ѵI+& m5_nN}4U,/1փQ;Y_ț:\SJ[gfC:in H{~H.{aYx"oK)_:+.?y͢o {FrH:US{0|$ekb삙%*y5gsSSKG-WOԅbu?8Ɓ3VRE؁ !ϰjY؛U/H{!Yt^ްqs̞Äʢ*ͫG:ҭ lc&e\"C*2 -?'^(ʥr|& \@WgY%f멞0#Tp2  N$5I1B.|u吷n#!,!"ƕ.W_vf*׻k2l~ 7DG(,0N]5{ʲ.. Gw&K+Љ\RCudm)>m WY:2Horo.ShN.v+?Sw>7'wggĉZX&J5N/Fɀ7b-tћzye+Cu+QExssRR97ǵ42U{ǷNc7lX#-ZR`&!0&|be4O7ta=Ѳ6m陔!`Xsa:,h2;Tt|v+NRI+R0 /f$*;=Ƒ"FU|畧AV'H[K93^U\ԱJvI@Xr36yx)z$t0ON1]@v8'+3o2yJ_}1ruYĦnDOFLW%cQ7~qi3ic^YЧAoc#*tR-gKi qyp,"L5WmފJ$6;$AQ\#!V3>Hna~qg,9T;ά&6XF &M=4xAVNDjdY%^9c!wd_گ$9TNVc.'uY"- -/#Cڐ.˸H4^94:i+n󡄳)5x<0(p諿 JfW`' GGG9~/P<Ǔh*$ua&1Dަ5>5tWg^DEJJ۬t /L:IJڳYxuq$k꾒bMz3U7pLx'Z*A8tйN4FNSG~]/&#AIWĤr]R]r?})7ˁޏOlm<!_i 턻yfsx`qo/6pM|Q:|n.N@f6ɴ؃lI03H pv]뢤܏Ӽ,>z]$6uq<Q/FyuCQ0˨+tBRcMKÅ󎲴E%uKrj7ݮ+r8K)(-:lveH}:&,weh-)E!'1V]m{ۍvt1Ɯ~}Z~6LvSm` oґmP &xI}zF],`YvyTihK`={c E)aYdDFwZ"؈U~2nh f yw;ceJĀavm31֥/38h̑ZٛK{M00ZwWHN5TLl%f!;+طt^]>^9aڳw\|!#mP ^Aޚr߳g&jo䪋)_ л,BdaWӯd`-\U+h&hz`Ւ"t e_ɫz :i&FZZ2pW1ҧ&;.Q][ A3q}86 L;-OEK #6lCۢ%n>KsoO[6|bõ?o^d"D7جl) z~1%m5`p6Uo NI24UgLXh/1]rsl+QY gvL=Ef}|-`-!NhcիHW3ϞB>NT 9X_`ja x3~kCm9)3/E>іU&1 Osre8MpQ(rSGdGKGA|QЮ_;׆d#W bO=%|3'~};@'gQ^ƔCs%lT)heۣŹ Fpr…cB E> %snìFSeˣ{'CHۢ{x<faBqɽ( gQ?GC2eeaǞ\994i)0^>^l$wOٷhu<T2> @CⲒP*BЇ#rr1L{%?{C18ҥNiO+ҡ1]`i!wi<)U5|Ȼ2Djo.pajTiBi==F8)aSҘ Uͱ@!JHN@Ȧ,o꒠. NF̠ );gL p ⺎JdKƼǦL^g xlgB!YzN \х}$Eœ~e@u ++f"fk i̤`-5]:hjOU"h2<+KݴB;UģNMRnCSzo"|%Jr}AԶ Ć9#_XdOAqITkl@ܚwORSfO1ٱfvT6pn8+rLk0=w%&WUvk7doOQl+Bz>Vn X !$Tp,~HrUZor!dtuW_幚N@MW)4@։Rӄhߚ5(])W%ffi=cl bƬ -G\k^%l|ZbLBrH@5pf~Բ^/ڢ`?,g* Pwʡk=!϶L7'4RkRoک9X<`ie'^8@ܜI75qWݍ0Gw5BuiiCow % żjS{ # A${^诹C_69Mg!xm@ek[f=z2m\*Yjfy5fB@"kFٓ袝SD= \ϧpO9j8"VFO\*^ 8I[y>_D;%Rю%h߀UPp$b9-^ V6LiRi j![dDgw" NeׇPO8!O8jÿ́< !{G' GcmwAöOӆ^5)hg^R,R9/o= (5/_D Z{r5Fvv(*6tQx$hHO:ZRI,uY_: Qn޴B¾lűղ#taz]}~C^c/Txޙ(@ -gD:rQo "8߃hY1-%j{c<';9)^K OYȹl€q4`zoZƆ:žGvxlzA^1J؟xiY9c V4fN:Zli*Gnp4-+H H9Blm4BB)K\WdE?n(9,8fR g=?xUqr~r*n#5p[XN>uhy1:׊rSeh3Ά%Jvki D=<Īg;N\FYAa| 89 ӖSߝ9'yVHLRM} {u5eّs]|oA^Şhs1VhP3YJiyYPs~ e 7Vy3>RcYĕ]; ǐ(LV \E7Y!gȁSa"jG$-u&r_[ϭ+fi3/Pּ8/#'37/1i-Qǚw[’qI9]əD X$|% H WGt7eĤ)nVQ‚]m(992qy*5b;=(+TR'\^Q|ӌGc0B*vH0pNH=Cy~M~֙ihVfHn\Rw.}ϖWRƟF"ՏBRy٘R3WtGaM*s6IńrG |{309 T^蟇N-HxvRjRIblb)8L(iWaܹ,eNˈ N @ìŒ{R% u+چHf2Cvk%t^Sk0g|a qrj`QKio%XoS*ě L3'콾s'f|N ?zqM Ft/ >ГT,-znkx|JV$ЄVy{Xg*n.MLh&׎BN.oKob?`P;yZ4ъa~:k:Jב}Ǎ:ߞNfjOze+wMk}c(,*U^k޽I)6S8oeollRbɪŷ`rRϸcOz&z&nz]XD&~M73A f!ɱ0LL:s#rLg?d6j"3 PUt]%x G7Ѿ(,8-FCj}*=?SbVoyL&h]p[ܸЦvM@d7#YAty:pPpU{$T!Eò ?j&uuqm?PXm ǏQ zm ¡uۮ7@-69>\tS M#hۀo᥋%˛Bwv^oԑd_&ޛYwiJli:B*FL;7OS]ɕ:~d.ߝa;|zYO49q\x+uh@8l@^X:oAљ)EUںT[l},>Cb'FiɔVY aWUPAMU~^șD|25?[dCtZI6E9S_5˽ۏ̵7-!I~,L P7B@ơ':0|U7CD, XF@O "" ߈ !- r42*b KVN/1jBBBIhNC֫tLG.Z~ecggF,?Ț jTǩ56C+YB I(Fpؓlۙ3&{ݑYqZK!kIڧ2Zx6 U:岱2h+ȿ^8U:b;R/M(̿ bC-s+*$kcj_ؑέv6 R8sȇ/︣k+H=(W`l夞Y!#B390]ʽ̫Qkrsrsv*כ->O>Ŏ_o79jr>6jH$P~]7daྩ ߑSX~(BfT +m8 (Q;'㠴2#LA{_]up`l!80,B(p1J ֭&5Faat9X,p(S;|q%dtC{bRr/XfPoС9$@bYmL)q7RDS&諵R9&xD! .B`($ "|?Q o-2 Coi-6EBw TWdmwr78' _d@ӳ[EL x%HQFUߨO?4̀u!UC\g{M\k!:7ePQbe6Ww[P%nP1q;DU7.eʗn΍+s8< 7p=0y1-oxgahS[k& u\+'$d{ul>-p1޻Y >Y^Y 13ћBnw K~yQJKsbEi 砝ޝ@Z„m!tC#+дz\#u$ N:_ "yaM JWDk !F] YÓ긜X B|D8Ԧ$ .!q7XԚP 'kLk<#cB>z  *8q eV2f!#41sx鿡8#!i0I ?EZkvI[怅G1@&^, 46A chZyTl#PLIRԶRCzT'[!CţF(1_s %^5%S˙ۉzYAFa܄ y|3 S\8<'č?l*@OCɘ9[;av MA~KCV#L#x m-cmnDNJmyTqv= ^Afp͠YZdZ"b*U`. ~@qOp ظ9Fé=Hvq0h/bF}Ps5$T+xc H$}뎮 aUj'=Bli'AV:]I0&3*]!xӷ 6!N ^!WҽUN{❝u+wUVo]XOA Ӗ?_pTLs꾺i`SCWI t`It#;1d_kGƏoA\OA aB[cCx$A<7 fNp3Tγjɽa0, *  _vfI%Wv~ͫ=$s=+u`m4Y< #܆(L>*&4Mb!^6ѩ1 b{%T6Qm(`Kr@%E3wAePUQXzbA;o/mT缣/Bf״9z @ҕ5$sf3vtx4/(;nRyelĽ t .G㣿HʘM,LxW0W?9kk@ vBGh- ^޳?+ .`Em*xD!g-oG'!& 'Z_k-nk #[P^Qz]Q'7 Q Ly|cL|c5TU$|f't?Y%p݁ xf]' |]/>2 ibׇ׋1P_ł @BP'n `J $hI[wI|vMS`@‚Śi5R"|e}S,a~mmo`a}ScPgѕY]ƿa`B$4JeBֺs gEA@hbbebj#<9`QC$p| *x ocu0<drn纛i7-3N#@~`|+.Ӿ_6* wѐIW qЃe RS9N"w߰`@=_(J~8ZO_o[}]87>(>[$حVXl\OudQ*/c@ >(%7jƛ"߁7uʨҩ祐aE ˘D_F<~YSEB` HC)/"Q@hcik*a B<b222 2^$dh)QBPQmq:3zw9hظSSvks3ɽVokxO(h-䴩Gܜqks3=zxt̴mI33Yenm+itǝ4'# k5{oڛt۽|6qCO7Nje e$yeZM68T_{eg(! IAp26L UkOy h4!ZM}KuWt dԼ34R4ƭ bJИxtC< @2m[ijV<oLSŋ--kHe9A3DX+"zL6c*Rғ T TBeA{1 ={w-.-R92M4Eи]Z3@0Q ldo 5r@T+ (q@- T4AÚVʖ@M 'Pea @UeT$v D$J@,eJ)@d/ IH@v j\ZyT2ϳP% de"#ތ@:< X"=p#PJ dd$CP@@7eD fJ@$XJO -@TP@rgH0عK5@k#3@IE{t1㌉eM7~)cQ]{FyFj{ I ä|(!IeHOz:QQş8VvdbyuA:#SI}TSB#p~y6vO/n o4^ YYJ@īEhRr8t]8HoiWJ 3IXMt@ vL^Ү .klvA ET+S챡ʳ%U3*BEh$ *ȑmֆh>zݫCZ]gjC#:IyFCvzFCzFŋQDlOWVRZmf!,`H.W `=:pYl-^G[6F{==wጁ4VT$I-qH۝Bmcxe.KqXsTRPh+^H04{V@\ ~@Op$fVE{Rt chVX3)k&i֝z0M1Bꄑ(VF8'Xd$:v.r5|єL zDìT*amR͌L&X*VXޗدG9t r)"Na2"Mq CxAfaHZm^3iL<^q1țPC;?旀莺iŌbf BjN B.=}U8FipN1&MvYb7`ݢҬ K{lX',$"1=Xݽ̀*rYC tK,H#0%+hrXaƦñ f[VXJBab<^ ({&Ku/NTZ9@]6j"@V$nppɮ F6IFliqe )xxg6'T;Д,"ƞ  m*bUqJ n&iJ!N+#zZ R:8(L ^B>m)hP Ip=M&6Yy0IBI* CWv%E(Y(p\u*j:KJJwPQY*HIN;SIA*uG(hq\4## ×1P9&S/&~ ~Z$LIe%z|IבIM5[CȆxGiÆ@m`MT!uYꑰs< gwn܃@HtFCـpZts67@Ph HwHrA,8(.M`V:#kDT ˉ#e;HG. 6T Tu{%, Q$#Yw.صsliJB+!t#4OF96,㲲zάT1 P??fq^Z)Q08bl)@h/JI";,^sNQqH$([0(VH-帇)DvB +bgr'8G97J i8k ÄrD(9dԔg@%MH85?.%'[{P N*oal``qum&X)O+ u)VćҨ2Dfr6ݣ)}txuXjНv'݋r#NRHc Gӕ.P{ANp[z|)X1*ۭ!;Nzyc4~+}c ZM 'e젭ҘN`e W8QS."f 8i=7Z@}B9h7]5Cs,WGOJ 42JBDE*Hh/HʒaHAw(A׬rPC4(aܻ)IY~_e% 7Ey|bF:TޒYIJ*Jcb, P k q $#mc/բ;|ƽpyӢ7`Jb5O*H6^d#"aaP('8Q;4 KU x}9{p@4jMDXEBڈ۔؀_ VđfyE9|NZ$AZ*`PD4٩~,XaY,>\H-Yzw%caT4ВA@-9| Z'G\#E4>\ B2(+mx p8 ]xSYJp~ƃ p_Ȼ: EqKZm"i6oh\% =y 2'~I 1of ZOVcgĕϗ/6T\\E:pJ yI)+7ʾULŭ6x) jp:-22 E@hp=xi2IpYAdW(+dYa8CCg(G"vK^yErHZ\FCCW.L*^apJtF iU/%_v^9rpG9߫ud>ei. 8U3G?h1v( m;#-! =zR-~ȅg^՟:G~pg*el: 6ܹ89?hHf~^p2=r!#z "6gw mk8U?H8ΞElGoeo' %1]^۹Gl[NkY{?L'B5zvͯ옘f~5ڧu6IJb4~!;7n{ZӸ66xrb=to]eCV##ɍ}̋$NW0;?tOz|FFѵ׏e2욱&^tœOOǍb&<侸tkK?β8܂ M&lUM@j3F_?+W]W>v|ޖM]]y]D?.l-LѮV'ܧۇENޘ=<<͠?` &7e;fC\MdA{ n75/G>߻x;~Q+̲|u=h{|d}RVw:5=/Y.4rp/̞j|gܷMN5ްڗ,rd>0n~Vs^ĜGwq#۪wwݺz,^;6Osm/3weNǼ`ɾi׭4hc}~~NB7ZkoS}pBMu=<>ZoT-W'.QG/΍OO47o&}Cۖ>\{z3u+}fP~gs2]6&̽lE}4֚Ӄ_ݠ_%}J9ӣ[\x #&_PЖnqc/{VMS~W57>jJxh;]ޓr)؆έwhKO_R0{\m1R3`Vz۷ 9y*Ӛvf_Fyߎ{w3CV]ڛ?a=YjՎofLtg6g;u"5 ٓ6uxU7M}݂a3OX=Ӑ(pEzxzYAwm}qacj+:\jopĤw"gϨ7j1Z[yA:?$<3S;@?u%&9)cKheܾ[Kܸ~h:kS苾,Htr2XaȓckDU @8dOm۶ɝl۶\Svmwq^kչ7 2Ec=rfr7|Npk:C5UW Qf<ֱw +8"6Mw=#!$_ƣܴ],uX_)`__Ns%s3~6oԌL eM}m/S̐Ԭ,gr7p?2aaRX&PƷrs.D㪊΄+=_vi}:J"qU𭻍ǵy?Nծ{=*k' V'ZppPrG냯[~Յ7Аaĉ*\Ǩ?e3P4t,)gwfYZ*dŞ+w_65tUr\w֟٣++xߡg?< 6狵7'Pj7Tk^FԣP+D ѓYyX E&7MuNAi`UB*ip{@W-xr[Зimā2v| ].]X ?z~S`;*F+(KTv惈4k|ȯ(~ K{{ bF\L )c=r8* e,?[4-MWP|aKlkķ9f?-T%Ee ٦53w{P$0uq"u3(r^Żrnk U,Д8K-oOYp?GzKX %|JXw݅NUIq9Dt֎2`ԁF.z/Ih;^^jh3)FQqΌ4/*,-"$tY\rۃvx\@fĝ .Y(#;-QCǛy;=ld)/i:cå;TDM+o:500S 4;LpN[1l&>{^< , wcƱaHOkDܛ޼vWXډ< !/|^~ #@{ *)%ys53[ T :5o(ko+ `yܻX\Qm-M~f[ۥ`>ꁗ]yIA)UFa@C:zM򖲾BVrzL8aZ3N_o^iѢUOIBG@,{|'k8?~*);,v*o7WCLM~C!-^ ҟx94rYIS bÒgH7 zgc eq+۫#&:_Am=Sw'alo&_zC4cTuDN<&~{ H:hrlvz}S@}fMYFFUF;{5}iʈ $hUϭ|]jꌷ"N G۰HMG( Q" *^xFjmtdϪB,grmNxed<}+|p#S1՘vyn@%cWyQpWW)`gVhJ91L:mZ"pu4pCH@~xݖ&Ҏ6~MX[bx5do6gn]1л!~|ªAYr8SqILnX˅10~)E< iGG.Wy?vV?K_5-6x`&eV^Q:Yؿmye=_hEf"`$oa@]Sݿy>PJ/&WU @<:@S|u,gX;~!0ZrR7["br%JbPROٻE` ';]9&I DZhNs+h˄~;[Q$o^6)M vG.͠B!RoOqJvS|beV&ynX3~9Vg/H+4 `?gv՗" 1o%XF-ƏsOs=<<~@htaU던술W5};"dxqlV=n%䓘lwsĂ`P$ j!k(opyx_c@kH?$NN![k8yg.x[MǖhyvL3)M 4soU%,-6 `.NGp i| ,vh,ULY IDfy̨_HFN\v/|;d6-u NJ`G~ u.ul!ʕ8o+HUJs\Y`Ɗ0G B_<@04Œ>gptˬ7^gla[Z\ O!L&!20M7젻eһMi<YGgF_vlI\&>ƙ ^sD*# L=pMo\*nԝ{'Q/"&p*yZf㩋fo6d1Oغ2֚U] rsbf4y /Slے*b"zyuҽ!ά8gǎI{Nݯ-F0%$A)Mo,kPjsƗTh򙞁@ǎ(&FLa7_)B @?6"2ͼ:{sFFzܝMg8kGNYjPjRvGQ]J@|cU8Z Ĭ LrֳSIv)[p$YV^ ge1Aq)rbYE@J=MN:@>*ֹ@h)Z0ud{@f/>q ' .SlAw)׽&, TrJț| 4oUq?G }qd E9t{~ %JÝ(!9!10ei Ղg6 pe77\ڴtv_-eìI+i]@exqcm(JAʺR$OG(ySOJAvHޚM8yniƟtRGC“6 Ir-48(C?fOJ;a)>l=D<ʢ j]ɕf̆ a DQ;vU v|D b<حp4J,%P ETS_񡳀=ԯ>>8{3x+;ЭW{t"G:l&hc'G&:hFLɣ("!-kswYFEDȧfx3"g&VYy }s~4 =W W o:ˢ6EdFRwiZ3TpO}Oͼ b M6߄k*aR[nn;R5U\D[: vƲS3H>fi9E!4ȡ)ZB>҈\%ݺTD \i k}Uzȟ+;rT4w(JUS2X'8vs;(3^%bz8ʸa$xJBFDHS ?)h9#׿~U]U\!uM :,1;^6-R\zE F.QN%SҺ uNMjub/؛$&>(լDžJ?/ `㚝x#B34I,hx+Х= o{tW^ j]ъ,1Nrvnr#UR/]/,W]KQZ[okmy6 e*qvfb qa82vP}j4[,ԯv^l]G uU|_`|$ W*yz-Bظ ajB{4}JzMp~?9*eunoݺ2w덏/Sht}ޕWaY(b %:\UԂl 0d;r2 RДYerȯ+OXnYR}KvRpѐ?_d7M|ꛙtm!*v8Kx?ZQ*p㓦me3!Nx{c2@ӳ$EC•ˬb%Uy,'[cOy:&ASB,^AcN*~1\3~]5&<䳼cjM!F_T}'$x.[P3|>-㵩j`!{qDIvWÂ)L  @ <]Gك (cڠbK{bAJ1.0t+J?E`&jm+{T?&#[/Lys\ȸHL0`"EgJ'̌dm=_#d[FO4oP].rXNyOȘguNc`/hfdZK;=7ɘf9*J} 1㯏ذO1r:ד*.W5C*֟  *g \1Itx4@zh| 'g5,ђGܧW.lZn<\vn#4(2 /W=+©YszcH,2ojIص"9xi 劇#~aH"sZQ&{ւȐ-VǣP&W $Vנ}->& -ꞑڨjW t#\Ğ)Z4C-Ng4HK-qP_z*|ou/?.5T15.Ac8}kOdfH1 OohF*_' G\ Fk56MyvY,@ֈ#$4=l+ C#VbJm0UAnz9'ސр7N\c@=|eiP|wWd<@8d/g {̎GLߵzu KJPReG$b%!\IKX=;N_$W/^%o0 dnȝUA N= `<<0gf(Yvw[*h0nA騙ˑfkafEZš 8"CT%h-C_1~ůes\_ٛ'i'U_=P4Fd4R?K\~YF"=#AsbY?&sRcz m`&̌p"csKOG> Gp"8!f"xrȂ}F\QuyL'`Vn.X!otZjDƜzhSC,=?XZr5$V*q R@$cĆ@7rl,U[%u^N 3 L=#~tuGsAqYagi?=N7[}v"EěRKv[r1DvߺI`&ӭ5vGUMX5pM@@ܓSGVlqIKܟĮks>o 4&Umx]=ɪfݖ y`uy5`EyN qI#-j;O+ M(\yM/XimQ,;LO\G[0v XO&IfWe?Tzc\gJ\*EyVp#bs/̛59d^m~J3%UKfyPa3{emARiP\5=NrMJNk]3n[tq 6a MzX#*SO=Od FxG_sF l aO/i^y22ܛ&iM[||BÐǎ>ctwiޙ.YV_y:Hjc'~>.$U!#a1[m]SRX5x?tHRj@rbAUbWZgl|3ݫ 䪩`qZ\xF2|L+3ڢFa:φk}*=ΟRu?kuw{{7aԦKKOoEغ|k,e]( bD3^˲.m+?-Z:U$)FG>zĈ+1d-3;ɖBi[@ yKnX#dtAt6SS2hDϯc53[hr5|$!Te̤]i$˵L^F\Png8|*PCֺ$>uWsjKfW2Idlj]\XC^~=Dڬ xgwVH7gXD_Hx>"qaĸ'qwKk f8k$V94F}BW-pkH%n'3Q*ϙG݊}x)S_`x|u"Ybugh-nhD/k櫻WD-tjc2 p׵c_:Kq,⻴D{ͱ 2.y/oȔ_+r{?+ _ZTğzvusK;WNŜ1t2n%TUu̎6*d/aZCr9>x{[OGгz.8pyhǬO`ۖLOYHe9^.$~3tQ* N1B0Ku.Vs6}_C,"R>^"//b~U$>|b 2 ȾJM4CTmy)Ѭ&'7^s/\jo.@˃צ#x:UHuE/s#M ۯ2q a\g%?|cuVMV*جYE'pOTT x ~AǼphJgɟȮFSb^?qK\nedz;TuiFbP4nLG~Yzަ1oT6!{TaB;_VlMg-E~&|fu! _p32Tc1[# Ҝ&Ǻ,}1dzBU4wk2߯w_Mk v/;fC4jS'qFTHds`Vj2NJtJgyscxr_{6X'hfre,MgRBҬ21Ura"nulx4ЙSf?YE+tEn)8}":vj1ib " LiUxJ"\\%T5ѓ(!F] 93W>JHϫ'dpb ? ýfH*4X[A@x˺4q׀|IcզY)g tŌq^%jq|At j}H8& bm4W7>Gon5U"'a08PӁr%%΋ &^&C}w/^}`c1p3r+RQ-a"FSF&. H^]MՑ"U~Ԏt|UF!FH6U1O%B ;CuAjxZ T1*6uy\S'.8Ih.ۚ)H[*ғxWJL֪2 BdhCe_Ins~I:@nKDDh]TE 3[+p ?mHzb MD :՛nx"xB:Ja"n3va0̧V=㬭BX33{5ZvY3)Kku)S>xbƔR>{r2t>νMJi}vm!̗[tteer<,ls"$7e+>VҏnἏ"%/w"2gЭbd'·CXs~!1.n0}Lm4C\fG$Po>@˫)n,V-6K= 5^d윷H?X>L<X/?H!j}A(bZ c:f]1OSmC- 0yj6,ҍ7^\F.hܟ礔H6.gGQ0#De*4j &ig 1,ډչIhccbͽڵ󘷱d>9_IkD z,Gن)icɨ\ds׵b*/o.@]}'3ƕn2RCh̯8=e4~ 2VhS֮3ŀh{ iq3j.ʓY wG|4_&ߣ|AS|qsڐNۉm|S ZEl^1ˉ9auERpEh+//#) zAb/x" s E 0ͮc580d T(X0jq?3qm(3]}1ځi/eu@M1;]_<є12QB^EW3tt)xvE>,3bŋVs;nU>b*H\r$˻{ZY*e b ~0sCUh0Ec,6ϕ&'eµkJ r pftj2i5Ѧ3×|HT U4J%oWT"kJqu ?~!x~D$bFY216rw!;7rKwʴvD·W˱ ;G[<$f:ƣ3Ӧy)Sff>Ws<5>T|`OTkY>䞖 *mWo::8` "^:7a-FO_NjW_SlHf_A.Jb՛Mziے0L۵ Tz<1PV,̇;|mzL8 v`jM&khGs9}s-:S[ْèu(1Jmeܢi`M.FS}$1\jq#Xh~OmVA[̽\GVsTֹ/)#-tnw^H;=]HoY2ĽⶦŮ.yg]c4/ yTvS%"?bV!_XS 8m3ȼPs1/k3^es9 U@!IT ÓF?ٯ1FeWR\p+1?dY"k;(@iH3]K~*v*IPΗCaLx^Y3̆C[ `[4<~r/PJ]'A-D%yȵ+y4ʲ%Z\N.3) sϲch|TcgA(&9ywbWnx%29̍[{r3,_esce?'\JC- maАJ$ QR,talתYehV.gbydK%D[2YIp}ƈD=>}!XC-YUʆuE/c;wπfkWγj-z|N|R%iYáJ!uhGjY-WŮ3#ڊBL*6׻_=KE d s032 Dr4 儛#Th\ꭁbfF(n*@1Jb|Eu #k63K|#b+uY4 m.? }qC7p,$Gi|xk"kB*7Ɵʬ+Ԗq_˹k;6yWpyE6^fq8\T# /hnoYAƤMIYT+@ ~6k@ų^;ζxvf狙Q]zl;s;{gÍpតMA,3*6fo=HTPjwa*ϫ^mHdzZ~ w;/z4N*x2yߞġ]|z NRd JU^1e-Wî\ps# >>} ͋ lK(sә"E-v aAWG1ax52% U|PtP`Og9=טn΅c9 pjj5L1W. vR=H ,m1ث|KUOejY1BPJU1uCRⱌdl@WSm݆_U"[‹^HD E VH) ;j\'M*孳ԝKE=i 7kבV JU/ȴUK^y@QƸ\q#CÈh_=֩j*yN*~.qk{6 %I _ct*H {?"I<E;}lV>$PiU1z&WnJ^:}a"7`DFw]4|cG]&:T2sG$cNa7v ꀅH_~i0Oj|HG~U-GXmrg~UiQ ic4{'^%['fU ޳@@y-b[&{CF. Ёx΁piȘCԧh&G@r+:P>s!I øMVI.-Jw;0JDY?x >LJ!XNHv<)y4E{֌ܰ:k_{s]sǛ4V=-?vl# Bsxh͢*gؾ< res,&魫烔n6vZm k5Ne#&*qȢґwEnlﮖ%O&8nRJWzύ.+!{#I;;./=WSаb}MHBJN[o%DLipVm[s7r[6ZCׅͩuY$UU)K,Us+_vAc!"kD@gqORs/p*mW['}K"H?Ec'-VAf|ȘCԯbC&tHI]%MʅAOH˜|QRW cFe^\"'I~B>H҆q1*E.kAsA\,[$5/U>9+v_l!t,:p#V= Ylâ|(/Ǟŷ V|^<ӌp XB+.|^Lh:`լkS_EFV9TO#kv;S@¹/]\ۊURU $}$I\SCVuv,ͶYD `x?VOACr!qɇ9+)s&m:T,1H'_Rh['ԩG/?1xp i< w4)"u i>BFXaɝ72 v[Y ᓟ>iupS8ti@̊ `_ǩmЋ_*%1Ï&Q yA$n92( ' oS)gم/ye_pۡZgOmL9>!wR|6N{$<ѓ;9%FI] ^b2~oyp|cpFɌ(aT',fD@,0+(d;\0Ʒ#|ix?|yyFCa}r|䤺SxAWuϹ^5Zdz,UBo=" 7̿.D PEפiKҮi't](g´ZF³:,p˧)}Vahf Tތ~ЈB&Ko 1#(d߿ԩ1>BFgL*|Qw#^GBOm 9Z/ X'B}9$k;UYx|([1_i}[`'MLbMLE2=Dpegg+%<r ~NLMڎ~z $U0eWr6YZ9o8cp ˃毃%vWL>ܺvdaQK`^p_ʍ.4*~3S|_֓t[LWrS t*g ; 7D7 n,i ٘D$]ȧreS. :w_o[KEtjL~]W,C[78E^I)NP/bVOXTnMMyߤ|cyQR,A^rɼ~R{mOPr`1rg)D3?6TnPU-M)b8?J5 mGz["z^~YpM)h (gq,˟&@u?[mnӐ]nޏ⛀e2sVqkȗ;QA䋥! 3tՆ<]Ur3=2Ir y[WxnB8!{1zl tҾd_^wPŐjy8MB* 7M;co8)lriNG-rޫ G:jv+M'yAI+o2ߨv]3ܑ_]N'A{Лh|dΓ8}Dw|ϻ,Ez$jyﵞ?\榳n)+ƔEeꝽn[}k) di,.Ü<@mp른°٠yUAlpJ-ЏB/۽[6Dl&vО{*1;q'+ O?}>|U>ORwAV3?Pͳ`G7 CXL>,vP?HΗB'ULaL8Дy zқ2HEc-} jHXquz]$[~[ڐgx۾0Ҝ%D{5`CMI Nb/WuO35>ε0)k;?pǹ3cda..v+^'jmal:ĕgiNm$yM&or<}lh+l/]"9+3ݵµ} v "g> 4٥M2]CSV1GRn˻$XaIr;6s5%ro 7SfǮ]Et6p^׽Lm1Z;s(u1IBT{ge dt&ҴT&6]Hu_r}|bւvgєK낝ʘOb]ܜY2up xX뭿kN$-|Jijt:K``!NNE {bv_S6(f F`$JvYTQJD{ %o(-J7AQjKV(1%ÌQj(E@I DQ(Q4Xp-JCi>J! 1%mQ9jB%Q*@ ;@O(I٠T(U Jtdi %Q[С@@i6EPiRD@Hfv?Ocn]~ۯG鱇(B6¬@1 jA\GBH :QC 6:]@3 jk>52ǓiԎIɟc|3Ɔn>츦d61m>U ;OMWS :>#LtL@gуؚOIӿj3=-^cZ&`t~Qb|w-j ;M'GX`(JG`0Sᗰ ~7N !)dli`1@6 yGrf"ïKq?p rGiٿ(v@)Y{5O%WpF~jkS톧cbKiܕSV;]qIOh ClM@VǓT:iR}'?}ܓUK,AF0ɩ`|?(qSeQ\-٫?ܿWYs؏$ E&ݭ?QoH 7~m0_=ߺdOq#Nڟ >MCOmsTOfu~K~T;ʟy alA0$- 9J''α"a,Gr ; GY'o 4jrm?v8xKJO') @ .:#|ڠ ;e;^ܿwjy4} 1kpJ$8O8u؂L@v`ӏą<"//c76B Q"2qZx~A_[ wloDr}{9G̸&R2[Q3Ng)Ƀ"QfCQ!}bvw:xwZHp߿r'}("fBu;h5heuc,AX<=5Pwݎw.oζx;}Q9w8o;}{OL# -L!c;#&E#EP[֪Q/+AG9Tw}?e 76@89Ps $;~>=((6HtњhXD Nw\ 9S'nv5dE;an>yow'~ ~,@ :ޏL5dMTqSb#l2DP).Q?D E`;eOIo>F@G}}A~w}p?j~=mP݊gmy?:~Hњ E4N;hlk]n:V+#&@%2?p$Pih֟gcɡUacfVńvȊ0*n V [ݡFkdHjِ8GnGlI|DP5G)k։԰P\-q is- nAef(㧓g:vܭv]2ݷs|82N?BQloe~:<*zlT]^kܓ-C&QM.F]pФ4tM.ʰ]Iw`6WDqP}8PSKkcM͈6ۚMlLS0aqjޥbrhw$5j ,SO 'ez՞be,ގ#FN>S!#D[955X}å H3zCӬx:B7ݖZC3e*+s-$.혋u@bkqEʺoK:~D+㑌dkȇʶIzhi U\T30Z(j>m5lE=)Sǿ*bcRHP/&Zz7;n sXҽ dxOh:F.BȈQKӾw,94TfeG &*Q!SL{c'j?P1 6b)MC ?Wo(Rayݪ?!1ڡ e8AonS>|3Ɖ&zˣP(.Iw E#G' e;.K۬=en5 m\<'y4eOTL"Ǥ)ǂ5U{6rzTE#:j.Hc*pe3F˯0?sgH|pݐun4ԺC ΰ5f}wBљwbË*p'('Kl_tԀE;Jz^ j 0IRJQ`ۖh NsKrdЩ$hgf_#R/߻ WQ|]*4;qڄyg R[u›H/ pN^P[< QP="Vtt{VQntV3b$S`х' }-9/?Ynտ{o]}Yov7]oܗբRU/v;(65p]qMW+o~'ƒlms=W+q؄k!aE~n jN<|0 `0 `0 `0 `0 `|/NNEbHx  W03 (Ҋ x,և 㽼xb%ym۶m۶m{Ím۶m  }WJeS-AV@C%DViZR6֔)DlJ(\#-\Ԅ~,NOD&[ < |L2EV6xƒ9w;}Z4Y^寲wO?!JDXEhP f2=ѵ=Oq]G3R(ۓWqVI BC{z_uYs5Uu PC/*UՇRvãe17kZ 5KUYOGs%+'Ig6Atl8_>VW? % A觺w|{Wrۃhr7ŗo*qf) O7p{ ._ekqS[ =I)V³=ߵBD)߿g[7?]3{;NW[VE7W537 3l[5H/⼌>-gؾ^;˧o6o\ %Ѱh"6{8wYUeqd4^\4!f˝Hɷ\ees?7_=ŐɂB6(X  ?FM &w)_0fJժZhJ^RYu[MxkUg&1&@3ChD&K"Rɘ҃?7f6Gw!Vq#!Y >QqMӔ@'͡m(/dBI5`RYM8> ̼Y&Sq+`A!Qb"Q68Ti"yK@}^oQp5%u YHTqB+ Bf@Xp"$GTA/`foЊD +hs¢T8<4Tt ~k-FmPvh+*[A qR开M@b5@Ds`O@9K8J(`ēX!6XU / YYX-,`h0. 0 Y4Vj8/(.lU#a 3Ԋb_ H3 x i[ 6%S(`+yjMIO{ؑ\]<xZC"!>#_89R>*h_TE?4|Ř8>DF2n" ###2J,)l""( Ws6bg*-,w] !q1U!aʠD/a1;>~XD%L#տ>?agNy@-Š}+Aת>,ma꒔4b8Roυ(wwp]i]"L˾CbF y qx]yjL10 Z") MkbINܦ!jaRG 4z1Uk *vCnҘ1 DPZ$  T8+D #JR޼B!MKrbj6 dյi0C&Ae7;V>[-7åkG^@U3H#ߔ=s,- 8D -U^p `{Et <~,u/X^--"*n@9=aVKhqdƦZdMl- hVƖ:K& T{uzL9t>+!Ͷ ܂+xi)v54Œ54bni{PZ S͎ДOŞ{l %D p5T&7vMREhr-%yMZu8`. M,U x>ɌhI2QH2жLc E! ID1 |RFbt=c!4fu]'jK oc(^hL%HnH<<ƵڤѢ Iq$"HEPk$y=SP{!i88@\BDʍͨFl _J8<΢+8J2P+n3 &a|P4Ar|Aʞ|+8D(Y;: 5`ݑnoX\h"A42S`?4j(YM>@EuM'fr~`XI4A%"5v<8аWB-0"K? 4XG")4kBu/u(f@eo +g$y@6Y;ȣ֑/4F-#wgu:w eI/ ?+ǢmZq'Cf0 -L$]f{@) bH{& LԴԮ;_s`9\I^e|#a L+mTh/' DA,xMQhaJ(Arc7XCt<&ɂYq] g!m_d)Խ<$TB>=U<.4$y/wX0OzH).F6ZO>9! YXF#ȑE>h*T##?1cAo:X_~P>XԵ)>,,w> s?5jI{8Y8<6Ŝ0V 7¹ԦpS;" {(C b bHPEX~WJ4$tZX $Tѭ|#5r!Jﵞ8 H'obJ)zD@ެ .ZS*[P+A@Z\8Dw`!hK-!G\bgj+UC::<ub\ bh #7(B" U!" nҖ)v@IIg+2هWzTIj3`-@Vm,rR'VNdGVhƂX,]Ĕe/$E#, Կ[ 2F +@}3_ <R& fjn2£,U;ŵzINҵI|I 8(snoZ]>df@˒da?6ب:U}ޛ"2QO14s:Jk!3sMm/E>lN.,b`K{L~.eZ4cnE]1P_n'{«7xwJ=WK2kq/Ir2Ab4z e|[pv1SS*$^KkϳqJONWm=X3}͙]L)ۦkvz˂q8_Qx,Y`+^Ǟzw! 3ܔ=s}|-?Xf`n[͗IEc _9?J8صww!V79'dyρsa1TE>njA|䤬?.Uknowc ,BUٯz-kκZ98yzz^pJKrf4Ƴ57&&NUy{ UZS"|Ʒ =wJX_/ͯ+悑շmfPܡԑ Y3k*UZ}r,ݕZeCOVg#o9o7~V# ԍΏc.v|bYrۏȩ&ٵ Eq]y!@pʮ?=7KQOsB5e\=<͜=ӉTܸ۪UW;U6Z[znJ=:]Rk=ËXsnttIe,~׭xK: +UU~!j~_|1w=s-WWj\֞|s/\ޓs*-b7j*#V'-;}Oręz{w݈Կ+ .D~)?v_'ҝS_~~*M޴F/'-a.G_9V; YͶjrv&W<. V|ݕb㾇f [+1gvzV^_9%]fݾl~b_>UO v_x~7Om;^vqDt"ZtfBֻS> ĥߎ1fWWm\gXoy /3c4u46qͭ[&%>T0O"~W?~b]Sz\f=߆\U*|rv+ .x 5$LZ+: 1n oqŮ7I^s\)߾s#/R2 a%{~M=NqT$gkxGTUDJL4qsí2x8RU&0q>țjv [6XE`l(R]j9*Z/ݫ~cOJH6Pd+jeSE>:5gxooDyX;2{1k9ws^Z6!$vv$'ujj=?opmj#5x`;N'27e'BZ)"T v4 F+&Tm79;4R؍TEɿCh&,? ޅ|TdTv%%U~`1@!3g!3Jq̝k_mv J'@R%$ʟ InA;t>rIZhY1g{CE ;)T&C0 rkXEM50\DSD#! u@8?B%z(\?ѭO\ȣ5ַiQgB$}.c5*>5"w~FF!6Yz[W8O,|-(`B^mN?B\P҃A IbJ>H~b 2-;fDI;h޼I[:X:Xҕ7VFt[>Sp1\<漼CK6Ϳ 芟$ l+.vQzBUmZtN&:F-hI2v0:y{\$/7lq-*v@,Ķ|S|dI .㲎FKw,ʁL /xd\6%s~>qދހ "ek~I JE_C4Zl^51}$>MX/GpIP?,bo(Je9b|_fJǿD#qqdӌEl&u'701\E'hj%T@7Tc;cٮq,tsmjuZQ!gS> ^A!y~J;u8VxQY9@8F qz0[3tG/[;|t` `W>DyCK#>.cpesmT49lo"?O%i&ÚQ@, Q %-:3)KPnh(O_YVcMI,4=GoX]zٛQ }ypb< vQN7n81VIVzt lnaG ( m,㎥ H} v̱Z,/rɮ̇(cY''!)׸9\i9,)[yatTt~&0Z-k{gfU&z.W?\VY39k4 kT8BYNYRuB d ; ݗ 3`M#LA 9<#9ȵ>ŻC3YCTz3!OnƼkCQjHz{tv-司 'bCä䓨<%Je[ @+:U}Oݧ1빌ilYы֊Tq-s~e$vY#߀hmux&Uj8F6Q1#'%-7R"J۸H1T?+Xa BYrfe=#ţ#* (ʓQjU&fa&#]\(؛/MXXAe/ g{Pa,d"~ dO ]%f'yHM?TiWvqQ|A2t?Ojtzߥdf/0|%$׏bbqcNKpv!x5_6,+ aiO + `7bp4/`RK?y}˯s1 "}-.ͽ:J6rGw]!qfl9cu 6 \J: e=d^R[pP6[PRil!'U GYInj]m"mtAf_Rp )\ u y ̣(W=0h0G[Q1 Gx1ZK]]#.5Z]6zW.:95%giTs puR|IZy9$Yj/2WET&D<]Mp憃4o͊%-6ȷcżԌOvU6t8__6]"PDt끹gRVh+iUz%ZH mthkz[ߙįe/N)61ߨWp=b - v<^rP0і_w)1g1xX Xk"H%*pQ1=^-EJ2t)5,=i6jl*)cX/`Z׽֕`ԲZBBXn3(FŢЄޜ"~r+5 1yǪ;E1vcB, vf6{3:8# =u8AcqX]? G ]{Z@,a;(8[V'rR=1l %}wBT^8h\xGe2ID˱1EM gt~:Lqvn1^q3#Y?EZ 1t w"%/fCI6J}~CUhRB^OŎG;Fga;y(A!96S5,=V$L_ReX!i;$~ĝE;2Fˋ" yЄ>UR:,J9 bF"'(>Uv1fߑYPdG-A6*NJ\w2ۢ 񤢑`^ҭ=?e];]'eH^k 2Ê8UxڃXȯry) wYɻjؕr`dŝAʎȓa]ilJ9S"sÈooɦEnisgN 'd)6^հznfY;iekcoVZQ8Cװ{q6 9 x{WFE^C79y3_\HB9EEXy U X͇|eCύfRYF,n|\[ p86.JZyFXCP0]qmny ރ/(Xeٽ",N%Wn:hoq$n/IV*B{Ǒ,P6)_*|oH9pUC#sڔMs%%Hğ{:"w*0::3$x)O81 0%\"V MK܁4V׆ |z6ˍO.@u)y̗_~uP>]li*wGOc/,3^Elqթ+ ZR~3T٢8ł|D7q `?*ښe撞_m8!bLRSKz6u7, jxP*i++AL)q'NqjWVaƔ'Yh0ME8 yQS6q4 QCFo,Qszy#kՙPS4蔗8:۾[ v8ѝ}ܞ)=V[&05ɤ~im03E"M ؑ7ĞplP\OxPv| ]jFġ= D!Dم϶6Ơt)-~ K.ӕ"$.0Db8~q=ɕaa&M&%D!YCFN1nk˞`!oiN~Z~sk+\Q]i0h1]RclaW')y:M_ 3׳6,FOMB,76A}'Bك b)ĊHX8Z([䢥VfU*\TF2S.-t.nFE0IſFҩ"a &0XDqc%jT.soO:o4GzPz<"%%'ėO prSJAvm+GVd*oPH,eOqTUY/Cj!wލ{ȂZ|.vo61 -[5 sHm=c'|o!ȻuVL) vIlI +F]3 YOyÓQ0y+Ŗ3(%5P|_])Q k D4\\v?Q>w\PC4I̗cx<ç >X/nlE Pi{*\d55gCŮSj > ҁK" 9N=tv`\6) v|IWR]f HCkʦ,אZ]I̱<:cyC2it뿧Nq^uYŒ'xDÖ[2ZK?(0)RzW@X[>1\I;g_0j_KyczĝeJvxq{/ IØ{7%B>&a^H"VG>Dr'ӹNNA*:o [$'KT.h6dTC_7ҳ9܀Lzs.~"B0 z&qv6k| &=lY6}ғNV\ hݚ\I.y i?Ac?mzGTJ`3$rN6?w 8|F^ߕY ;|Vkحos4;j GwkM} p_ dTXG{&)H[eVGdOm]sAPOrj[Ltr_y>Y'_bZ A@^DJzXpĨ@lh Bnsܖ:M%ބƺz}"rQ -R@Rwl)̊B?LRB .oN|\gy2-N^Ih7-oFX4ݶ+݇{-OAnFZ7ZNd-:#΁tԢ`@7⾑4ğ^.kg@@`Nmh@S%yVKNr$Ud'G/Rrdz{boy-tm3( ohwht'N΀z@Ky'P]`ZmfMw?~! y?]KcC *qru;a]_㼷Ls}vi6{X2Dؕs_G[3ALB$ߖb~֥ROR#uz.4~hJ"K4=36jd "*%9yQsG/2(LPN,1%\ZgUSMTfe:b- (<y [{pIM}JՆogѯ|Mc֗H5lȬ!LqiȉTCFLeؽFй  0|2F_f4kE3$ 56䯥u&܉dFz*a 7K#6~,}CR}͍kL^md#_23Cv ]#MOMARHITW-wZ!,M;PL,")RHM:[Ւak?Og9w T?#=~Rxy)lw8+>yֿbt*pI I'hki3| A =n9郷FޏGLMt2E,PX(#ERWt0(6שq+d3[Nt߃bȡ76$-VIsFX_U0^ceTNU@>xq"޼:](yoɐ^ǂ_ qqzR-!hO~]f-#tiga D8;~9__B<}6<@OPHHH y~Nw8# 8##t7:x 5 Xx,,,@`0g YZZ[x@ ~k>A!Kkav@~3} C7'Pk ؜ [ $Xp@t'9P( Gդ#XClTFpz,$]@)1o=sX彉Hqv(kě2U=X>mҺ^؁^g6n_an1 wRaLRc.y3EޛזptPB~xDouCr:6~yx3K6kp ;"awؖ=Yņ%{J3T+,(,sr}w&Y=yxKQl|5\ lEM:*={^LǶbG T^wpK gS_ 47~VU2!}O7wWRc#A50=xd?_ Mα6ܶ~QRSQ= l*˹aSnc'FYρ%+PYW|~Q/cF:Z ܅6&w-ދ~=%KۑI 4j~sNA~8td.![Q[9lHꮛܲw@fa)/ .׌^UqaĉZ5{ghC#&H}`M KEHwǖ|ļ/MQH~ǟX[GO]XgXrm@u>\`(q]Yv6DcP|.EdFS~Uwū dD 4A7F3ņbk^u7'jLLG%5=G~}FML̓]qGE6wT854GCwŌJ5 ᛺eVPz~m4+v^H#32Cr~3*PuCKWV/=OT#k:So!lSR_ i;y&e:`xxNJ5hV;Mu~%̫!>Y&ƣ캌5-NZe]YsE!b\^߮A`krU_m(yM,JRu臰ƮmG%u_؞&s1嘷~45ăVi#& FkNV.:!(eiθNI{[2o)`i%Od)V LDHM#DQPeDJt}* )H&{ |,O?\6ȎUO }QX8Zj {"rpMCD"n|yG^\[ERV&S4\) l\4Y87RFsfZWC8 zws 0/6$-F} }ٽ3vy{=:GmgEVf{~ o`%!ϵ+{w/y*ounO`Z[}>Mc\5C2U+z`]i]s8L6"pVoաJ ZX h̤RL_ID Wz^ߪҒ6-$R7|2a0ƃˁ|+ЪbL%^ (S򃧩 SjbLqĐ+Ӗ]d58)?4!s~>m5ڬ ly"? Nf^7yAo\IO+GR݇0 Emtw >|T3*M*s7nfĞcR/v}u䳨!inDPlv .o':b^2 N‚.U5OYx 3R̲y{~vYٝ7O3]\u)VXx%\$ɷխKI%?zPىHIS!ff*&0# </.YAa#UW\3Oz$IƀYCGnT&qh1WD!x>W08抆%=]¯Bp6DAlpvWo)WOB:M⹺*m;NX8@_?[։J]td;)aT**dm0Xh1k}-|͉ eZU5>BJcF[_xۇ$="%u3̫rR_ͣX1ܜ<7FOz}Żo*yç//Sdx0agϺ*pefF&_ 's{{+-Vtl<vG& ˹ab&+w$ARL2R}7 ^Sn :>z_?,Ć@~#F~U[ @MbH[Ul>?|qߘE[=Q\68=hlYjQ6ѽ\s}il@|Bd\kɓb/OHm^˦HW@yMawnQ2wZF'Q\Dv9W.MKT@? 7Fޮ7H_"1cw"0.t: ";"'p-}jB5L:ǃؾNG 5(n Orn^~> oȂ5., =l5JY%.a 6Rn[Rq~!Śɬ4B*:]jK-lģ#ؒ7vB]<=B ޚ\9Xh-U▵- g]}΢,|FP!IKɹ/LP TD.m!12+y>r ]y#B  сQlv;vEIj ձMIo5+{_ǻe 7%wЪpVULlM.*7z-_}-Fe\Sf~-\ϟEnI d恊e $95=^3C`:uGUmIMK^4$ iS̄Xꮳ&Gk*XﰸM)Ɲ;TgT J ^iJ.uSRO/#-l}'LyV0ţǍcw@Q/ضw*籩8( o+ C㎝o^ .}֋S6(¬v(p2Kb 񟸿*+E)HJC: kvl'1zV1\ @xQD&vg-dm64ASuƻNT17EcIb֜:;CG'&0'݋VX܇(mF wyN1U9,{w߃0}0]w_tr "gU/zєA[c+ -^@h-F?:G#x*Y4EVAA%a H1_ihOJŸ!!W]JbFI7;n;<]x*Jݲ0ɞf/y:f9̃ qM$5r{!r#hA\m \W^Itq, TJtAqFa,:t;oOZ=KD}US~46GQٜRŁc4+猻R4zKyi/xnk:5Mr]{[Ũc,&w쏴b ?8b疓crpjL\T,l1 G-B[qQɰ~$5MIm!T.=jhͼ;PhIFZO*J/ٙG.nVC.GULLr]eY\`c&pcБ!/+,ܭLIt9T⥤CG,{mWTfح4gy%GrЯ9_^/CNR m %$=>;s0Y5>#.Q:&~& JHǨ>TK+ ҄2i~X0 Z̓i75>'w}_w4-ŝ3я_?X>bI:h=J}y$-O'x4 +*|3|&N9p`֗m#]Ʋێbs`i++]7'Mdo/\R\4U)9Pw+cIv([ }1ҝ$.Ix!3tii2hPl-{%^ xDX{ƫ^a׀')Z;W{?h>杖3@7|;ny{5]ȪȀq{uY%qkQ)ca̹]CN!#n;tÏ/T&ңJAztm09긶\Z2C_EsT|ɏ]|uEyTZ3Es;oj;IEVAum^HtvyG2wänҏx$ϒKQ}(OϊGiz_vn z_@bedc8cV*g47aU_#zwQõD]r&.sG6[wM *f|gCRw\^N}7r-wbZܛOo:FD9cWK hFŜ$az^'ZX٣J[r/.!{( 5DP24H*eI(/^ I8TiK L$^B>S>r/J"ey?`kW예bV4/ʷ{%hp0v|tWO sw'!Ҵ!3L=EO>w.M!.Ǫe+߰f~&FQB*ټ<|/ Mlʹvr3*)noFjYtߍcl6h |5$Ojﮒr:ּt>r,#;ݲٓlw!\e$ 'q̑_:bJ(~2i_tfʟNQ謿7~Y[˔B:RXKמs`RAbx۸3KZID NdaÚ9']o}1yIdxYOb^L0r$ӟ0I~<˨X@!^A 9`$ApZ0('P ({z'?/avKEYgEAH ʅYIU=9(4?mw) K/n΅#5-ivN .+0 sB n% j N⩈)WudPZp9P#Q&g做#59[3(k,PTUC][QYEA ai[Q{jrӨI[mQuF1,6(ʡh E2V[Ո] GQ59' E Qs@Q˩blX (5jbMBqX&gP(ZOQL*{MX4P6EQ,(APL 0 E8"Qyg` BqRsDg.(ŸC( [+3 (ʁP\G٣N(V5% wAqEv9uDV%ڢX0QE98br@P tBjHUTET (fEZ(RFlPiP@1SFeUkB~zeF>]!H m0G?e ȳ.98OZc/8kH'/w4dU~Vi1p8o) 6?oЏAV+3'a g/civ½1|wvVfBl93m#8rF[AN wN(7sBְuř{r?3-\2~@P qN(L^?[ڛ8!nHg8 m^gӌ9#wY9xp6܃gZdrwð?3xᏪzK;{%Ybg/-s 0N{gߐ<7:;3r&m9iDp:@g4gnG؂~ /e5;NS,➾t=]\N N =z6%0,L9"c" }PwK[:+uΠWWL~yGeu}(#9\oqr<$Q9H?ys ~ztx6_qo?tG}7_%won F "aso_g-򴝂:*wߝu%~?5lNgե_W2cNr:;luS.7`8<;JrC>[LFdkO15XWnprx ]IhY6bObia:ơu!{rwN݈v(IaRɈ4sV 2.;eP\0rP"ufs`R`ΈE4j($bæ"|-憱aL螝``%mXij1I_:l4a.JL+z$oOqEE@ݚK WaBBInj%2 Ifj|6`Kq뀌\6#W Cw#ܘL;" <kR3l=H]'iO;M\Q!X%>Nnr؅3y#JS& q'`/.kxG;FꜰmFkR;OX5:_sTRD ~YmSS H0aZMpë֪4y q UO|)R']C"X|T/)T~'ݪ)((%k(cN (3GI:ԁe6sx]t0cHihu;:@RU>tbvUIsMvW?1E '֑Wa?HDNᲇG_TiTs45ٗ %S̹!t oڒ{|` u'OV[̴+ jyq+-Uu >mڲIMOZ,^ҙH8/S₢G.n@Ә[ @k데N38@1iQzneDwyCsw%ċq{z`,0)Q(| }kp56:ʄ:mG ^s pkE^, sK,/2hP?(dig@ϥg1گ"2˝,ϹdSgC_{XîH)gUm.YCd N5\U{ М2)}6Y'Op~*7/3uK8m83^'7Uv;'sSl=S!d3*1%}W}B;ܮF{ݪ9@m8}{ c5qyBdΣ z8ecKoJDh Vw0 zM"B&v0 j5 KˆŢ/XdjS\B@ɭ϶tSϣg˗8  `-1U{Vbwev`N&7 C">?~;t1&Yx^Ciin~>~,+z_6m\Wrn ]J˗oJZxY0OKH٫Y˸W%7~&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ߎ4![عx ӈ^AiD!ς`يP7wY&D )x;E>^]|eR$a)Y.w.]:B)Bldزʟie(*kFڌ-y'?/LJr$qFr*^Z ^uP|T0TZ^W+ekRe7^*zMzr(U[gb6~oW1#N,|:Ck[u*hQ삳׏&8|Y޷ĦMw?ܿ˵qC ;y/a6ɘ^NF]?˟o0o?bwt9詍\nYȞkU;Fg_vwWjF5]<:s<3s_5P3ur6W_zK6~(3zQìMή9 V`TQ +*RUGiLX YW2xw{~]=\[ŞY/^/%ϚzcZ1h "雱u{AV0Jigx  V?QQ봥`xǥq}CQ9 NZbK5@k3@E{DZ0LFf?|O8t)x(~{>wNeTQh̰VO8$JFI]{h4eD h 5حǩAߊW1$18N-Sf_EIo8u ݟ8VvdfquF&31Fl֣f O,aGa[m4f0CVbL,J% UĢ$"x`f_@jcl"ϕw@B f:^ ;G8?iW]djc 6 |!J{l򬇷qF%bT[bS9 ٽWÇ8!J.3 |#pi;Aj!Qh1Ċ{ų}]YULt)2bCr9'-Gmge^Z{厏l}B{=}wa zXVrOH@ht8N!^* RiD8\Յ2JfժhVIZHq$ j@>BXE,Jj[H"SpH)!NmeS|@e \pGhNx"W[dSGbVqť5(H2c}X  ~=zhc M1\vJMnbK/ --` CbmMh3Anl ߑ7Qk%šv!:dWF/j< Uy ~F>BjN)j]{hƞU-FipN`ZOaozE?Y:IqIb݆@2(3 ܽ;  8B+;4@ Ё8/ (\?XA 866Uh6Z}_[cTq PR@ݫ7^{)p4Y2ֶ)__")t넃seMveE^h7q$O2bDc>+KH #9ځAl1d8@EghsU Sr__(Ot I۠=P:p]!ժj:A1(KtiNDVH iR4&"ÀIwj$ }VA"Wn< QT _uzJJwPQY*HIN;p#I4B8.Gˊ(z)5/&~ ~Z$LIe%z|IבIM5[CȆxGiÆ@m`MT!uYs< gwn܃@HtFCـpZts67@Ph HwHrA,8(.M`V:#oDT ˉ#e;HG. 6T du{(0y7{~Z tعIuy4Tp䊬t]:QlM:K㸬,u>3+U2:| 2K+|3 ^b :%hДE+!6{Iν:%!~Pl1zx ߃Z1ĖrmɛiH++I<8 .^QS}B" b8)3J4sk~\KNpA,~UzKp"=LTR@Vp '}&YI rSQe02^mR{GS,Ԡ;kOm+&V$@MW B ym:o;`9;pƨGdK<\pZeL M]v+_z,f ?"HZ\VBBW!T*^а0.8`0i0V ӫZj̗|yZT)w >^?8V̢Mw8GbYڔk2NNKS՘,L~}R}=.a{DΆWVT[ |G+jy&UuZ_/obu-slCpBLtM,f‡]noo0/Y;vwy<yIPԯL\gՠ4Z֒9]+hC ǏMՌv,q5j.Ή&4.=c /o0Ѣg5>o۩7ώ~Եi^ wNj[Gt:iڔ1z񜸜%+Ukj뫮o>I'[kĮ8bG)v>>2{ڒ>U]OGGƦdZ]`msq˷ڬx1k3}'dcA[Dת>whvrX:M ;Ʒ iV^P-ؤ>qLʽ{\s;,>gp՘'59؏ޝ8jo6oo ^~32x_}sO3Ҽ[SsZȏ:\MozhM  WDhUg'[7+yx֪TV~ü-G-8fqlxc}xw ?+sZwZjOى!G3n;?jɥAkug 1f`K[W]oŌA F/#T_aue.mͧf>i3}fX=vمZㆌn|n]pb6g7>ZwWNY3Z`DK{vm&ʻ4l[j{JΏU}z.%]<:vYT<+޺Tn@dZG[Rx)[޲̽DN]'&lW'Ԛ}T59L_ܿRH՜}]M,=Ǽn̓gR\=6򌫍mj醘zEQm7~t5]p%CtI{;#R}!?̯5e6ilxi_}ƽmYR8)M^__=L$;J~%n9On1QΪ78Fm/d׺lMxZ7g>PG#?Ta{;қ Z}*h-jvj` 7S:m{8LakӐwV^0_83Q0fixs+Yƕ2ntKc[:/cۡ &M!{:O7Z^gW4ލykO 0@m۶v];}ɶm۶'l㜋scZp=a^eoleb';at}I` h/:"HH̸^4frv8>l = JDZ澧i a  zAs rRÉS\oZOPw|*`/~iWhƍZW=9Ndh)k 'q|'G'JTHҩB/ЕYt\RBFs:om9po E&{]E Mta{Wl\xZ4+y2\̣ (+87>'@ڪާu7N .oDEPnnƤfg3txULACR#rViƼ~g'b1T̰)t%ZWE-(r}jD`9csBm&ŷc׊2ˮ(MfG|1 lE$>nb)}Q\ș.77f@hugk,;Gmoс«C|n gy4ȅ-]AndtOfC3ǩc[lhхK[pJ=AfМ2m2lX6+fT2pr+GD>;)R! QRJ9(Hd\-zV {nu IM uاȝ£#3{ ʂU8lHw[mE̍K33|wQi%}PTw9q2'tWBLk3>3lWfiN4$ތRخDx`zk{zo]`sCgL% "2FDnQ&R? G|ʞ}W|w(N*#cΪJx6Q&ɝw,$)9&Lf A1ԔI*b%pJui _R AG;|v+42l$<$͆嵰ONgov՝5<)0zn_LLMWtª3*d4#EQq9_D̖MZ}Cpˍfk/F4ۢQcʓ@m }OBv@7c!0id9<|(S_.WPvbZH}kϔ].QF,)fmWoQwv Λ-{]*co0GXggzu 2 ^{g3$]]<-Q^b3j/!vꁞ *j6P O&{ڨgoW~P)jMV($ܶdL{i 8[yL-|}H.^Xz~l'.3}5Sf8%f 'g8hZTʹMV{ 2&!x q+js/Us*6n_3³ CЗ9M&f( PI92l$$zB֕a ][GisV N+utTl 'BڶekXiIƛē'5iyUZlZ_&T5]uZěƣwVF>k 5ұ_=7c7?Q:`jtܧ\ŝND`t3}r`y~BifGUwXlW [ cW-I'Sw'5eHJZY{ qBSv-73d`~d * 4{X_CJ'LQ8-}-!><ֵ |9)঻8oՉS߬ZoC4}b/C"=ACKW'EPtGl7( /\ xz(^иApVeѲ Y?U08rjAeUY=w8 %)% Z'JE VQs` y^C .6>\qNYQ;aYyigPt|6#z"+A.4ϭ 'rk Kɻ-EfOwP1寻Q2wM"Gj#[tJq(YsuAT*f_ ѳ! Q9@\oݝ\3pg) I 3˙09 x|.s b> F9,xjLJ_C93M~9Co ./ꦕt }PONc=Oԙz31wS&&٭pB v"g8^ + \ p,[j\Mu t[":QLSWYcħN7-A撚jK3]a5zpIO=0Y>BP\D`KD[%kDw1!dEgDt \FxplZɕ`AU'Y ƕ%9q1hq%{Ѥ$(yZ`J_!Ut؜Ϸ2ɵYMyoNi;_FXyz};/SL,]5Κ;)FXi2pE_ YQz,#9産uNUҲb˜VL讈VF"}OwH`]o7-3/Z37 ӠxrI>~r~ Ș+˥231{:FfEOD9' P%׵_=/sM.gO1v ğՍ)« yQK\Nfٖ֏hkӐ6)1̿*V|7YSvEt4 {kh2@r?H3 e8q抳 3tx?Jj @dR_Q;0%6X}lua\N,1S!ҸvK~L xjRHNChI︿¬ӲL,XmhZ%;+iT~( iγ>[gѪd%w7GmpއK٣d(:՞% .vW "Z?B_1R zKװe=d /'8t[ aDEQkbS 0I7)?S rHcfާqųd[YHtJ<&jʙpB0PWwvBkIG LE{ݽf4}[[3iw&=dw}1T);CE}x}s|AY]>M.b`r/Kjɚ~+,J/SJAauT= 3r.PkDyyX<xhT0XBgjn }Y7@HZ˷(ZXgnr:ܯЮeMՓy |QTMqYOr0g 6<8uHFlu'FQzc0:O'T nFir,T ;*ݱ"𬪍/_0=lFa G1s|Gӳ͕*OakZn|\(6f DJ8h =K _jty'<ӛ#Ti\TbRY.b韣6#}kb0E?wNw j~$4E6Mǃz< `rmۮ8mdR絠vT]/O#KcnvV_k`k+WlmA%sdcݾm]UZFtfqDiL2]ӟʆ`шz,H(%& G"iXE:L$( Bv.ìAF/ wM^!^Fdy㰑]e ,cϾ`YYF<=ddwwE>w%8(S0N@P)Dw.W4>ue#b[i";~"sܖ=D]&r7ci)SY ֬\H';8|xes~Ngp#ܜ?mT_VAPa_9lಟ4b.9[$ +r.FpJb hCYEֲ5u!ϻ,7> V]tU *a'/j f ).d[Jؤϲ٧E̥zMn&wX.@Ǒ4yd6稝F-sUVjKNpE 6WŸv.rv#F=beh.Փʘ{NH0 yLʌBޮgZWP#,G PGe@:/u&b m89AGN/7L^tlXePVojfDԖd5@㊧jfoH+m9nqh`UoL}sQ?_`jvFDh=x647WsLW%ʹ_)բ@~Օn16nUlsdўRd53ׄzI(0arik JQ< 7P@S>ԉQR-4 GM_m84wljq t,o/BA(M2C{8LΣ_Dt jMiX(!%oP*zBp>Ae4͆NҸyvS$f|{Y1FS3ғZBc$ Mm{};]xpc6T^c@qVX!p##K3{ V>^ÉhIī (V Xy%|s̬0^;ATB@5Y7 1fVH7jO[s1\R<_PPΐR*ZĢ[4WXR^$⋭r!SnϢfd}c*!r_4m(}s̟!#$ʅ{hzŁ:%<*"j߆)I~w[s:ٟJ,*$ho>>#WKot4.P&h|:Vo{#PKe}gN@<^uqyWA7ΖϪE[__*EtFq(.%h92_lz>$QOֆ6#aVmq*/#uYO` M:e?d@aY&'fzAAb7`|BM_͇ԍ,Oley;HXshGJH+B~s7dK}rZrQb$)x~Qq6c3*anfr}x;],|iw驏 JKo .SgAᛵr}7U!Jep Cx۫o #Lm ^ѡTy% ַi' j!Xy%Xމ! ZRS:w1U#K^;17Ӫ[F뷔۾r')r22hyK\م0q474d 1S}5*{3-CuԫHmoc8U/BW 0:$WYMmՔ-vBoao1#*5J08ixGw^MGAnc23q}IGc'ے0$d=nb82GWU ˏYsuYSHGeUM֪Y͇^I?eFIQfv8Ľ`k|2CFw4QH P;!j(.R"=u!V۬غ\ d[5"̴O/}A뗘#MG5TfYyF0p-w@JL ~F?I&a  aei;zEg QwƼRiCohrһ'M&~S2\K! FFFa餤[ @G&°+'tƱ%ܛBh{2Z) A"PTD>1M26}m}qUU"gU*pJ1?(̧{FuX6Ԉqc~IzIx"/# l+`@n3; 1}>;zE¬Ϊh"LٙɺFr15cW`CG+u,aX"_3]fK(;g\7c_*Vw3<s>uۨ!~ +wˬYﬤn@W3X{\4Ryd9Z+ um!᳴[? ?5}ڐilHBoJp1aMk8@HMc٭JG*\S$$0WTE-5숤1/#QJ!!Mw[Si9~aǏ?~Ǐ?~Ǐ?~Ǐ?~Ǐ?~?zx'xHL4JNL4L110O221RFFiI@T4CCK3. x?``^] TZmZKn@bXj Em&ɐLf\i[\TZVKkg*Uf d!y9$wIe0 gd+P^AVʔjRTd>zYc||df|+%^$k|t!^\ϕe>9Ix|3ҭ-gC]L[1.(JݮY9ms1Ǧ )[ۃ6L(+~Np?seK~{qҾ#Fyu ˮRf_w0#VZ^8& ڝ|GOT-X-W\w馈U _dfTe}+>"tNtaxQE>@U&ujwCRkҞO陪MrO,SvRx˹<4`ͪ7'T9^ 4Q̪7OնOr1HYΓeJR~OYJun)2@V(}W2_­o9j|dL"*2=BzR袱d< qftuS:F- S$:ј`q%h 5I\2Ϸ :MhfrI-M%aݴO{嘐ܦ4 6΁Pip*T*2 TS #RQ#M&ti:)SOP Be d3!@T@Q@{f\< F*BeJ\46d*CCcfM+dK&dPYʰ:*ЁPM* C#P$D 2T mL8 Zg3u@5.T-<*i-P% de"é!K'ty>ԟIhPU C!)SZ[- `j(i3% D{@T P2b@rg H0 ` :P: ) ԦE{ 5`7~)"O0ssR$qIQ=L"x-43*S0nLNE# Z@=*ܜ K钮11F.zwEq ] cX݉:Xt|jbh*Gȫk3܂kO˓Y4 D:=5:3*p $Dbir 3z(0D *FDXy+`4Cש#ޅQ6(vPk z2-Xb+.25K9sF`1(0<|)0V{-B{&إXOTuEm6DkvM1q#c\"|>S`nѺN="LKPZҬF{1anɳ]YUM)idEyOn$,8#g9njljfԠx Nqrv,a5T2i3ŭi*0rBhۍqqCxAk E$_AMܩoP I0 &6YdY0ABNN:HUBEpFt$':%5WRTABz$wk<<,(\n E"y$zDa"9뤞vJ,:B!"bA1GqAuD8iRSEPDm}A!I!Qذ|8XST9e]wzԚ[E7AŲ"A Zǰb nan@8-9xoH`;$ Xwz]$L0rmZUs1ay"XA@-aYґBM Bnɲ Snou`w؏K;{0vaI.쑥AQX0Ъ6RS9ZH3@Ώѩ~~M 㼶R=`pN/Ũ٠Sf M \^g"b:d۫SS j'L1=US lY!'hݶؙ\ I `%L"c*„zD(9dgN%LH5?vh%&[{P !VOJoan``õm&jX)O#pZ }&YM bSQu02.mRF,\Ԡ;m䣏mKII !-V/H8vA()] Mw;k2fDxn ٩ыQu?l[kS5Jw` hNڪic VpՋ 5(ט9'l9Xj`υPP;@+څ;xV:/D0'FPFA{H ~mAז2_YR4G$ZҠ;\ kV!`wǫs.JeuIEQ$AD@@x<(T]Հ[rF3¹*wG~am;8q4sWY5pϸ.O`&ktrl$iG'%.䀨LI!GD¤aP(24IԣgNii\&r9&Wkz'$6%(6ׂpd=Y\Q<eV. wЫj T<%Q Mt* % ZG -Y #w(* ^fA-P:Pנ%s '(8? ,bOqO@FY-l&Y'5:Tw2z ~!б|A-n4(tNP< bz@d˭@ OT3D;4tv}b~E1{8]=.f=]?«2(ze~AAAJ5\T+d>fL,1>>2zӋi_)8#8Gh8UNR*_q{ӗ'9e@ҹP_q5iԅf= F~~ epë4|p,KfdFLzUGASMAڞ i$`iȊ(Zߋcg$]z?Ag|}nu_t76X76Q݈)M ]}XŤKً9t䃿}7X{چU/ _{ͽyi.Uv {yº򥋚yڵ1׵f{nrQAqrռ+4&۽T1+;uL?w/x ۥLsi-ʓgML?MG_QTQ2~Eڿ>|Uѹ2[sFM>ޜr+kqr}o 7.t|"OazY!usF}^x;o?ل9[~0%,*jh{ۼ=|wyȉw.e);v){{㰥e~j=6;^/[G1M3_?{axYLYrS+xs'_^qQvYeETMOlm7P׼V_^gU̷-*?|!mWح͸ylRcH;Ͻso^r†oGe.XM ƻp:lK-FwQl%J7OGxwNV'}ffW69R8گΤ1[yti҅=I\3.qLy5o/eMs{g*K_Mr]&ds0K:5sE%zbVYչ nyho _HLlEVhntJlj#*?4ī˰=[_=e#,]9ZiNVԙFxMɺ-<\Mv,*tȍo^pfώFh??5eYZtːzkۆ^| a3[gHEMwWfb> )SC􆗢K\u: sgcfl]0oa&+fĕ|$0'=zr̎}wyթ %Ωiڕ}UB/SpAP2 9U?%9FCⷳ?-?bǕށGN>}˵Jjj贔bw=z<O-wsw/-wvd(1k8S}`?٭^\g̣_ Ck3e]9l\tɲc#>ⷜ*ܮ5v?,n?;s'ͻC"{j5A;TU?rjjg79s>R#q-bZUL)}Ɣ9snRJᗅ7rڇ{ua_/Kxlɶ{ɶmٶ]m۶9&Mw7{7}snD&GX9ΠYdL< Òui5pf(9ܨ6D2Sk53%$:~dٟX,gz5½*9.s]n`vm-o=.f--|ҙB2 ]1tbmxeͰu)(:xȼ{X~7T!#tuL0CܣEE܄vTȫ<.sdm33_OlGas8}9魌 ;$-3`vV2Wӵ~L<``ult&ͦk**! [Ԩk 38]AzI/?Mt`łQIL~Tψs>LUi"hy[{?5䙈ԵwPK@"wҶVn\j:iэjۮƵ pA»I ~lL *X?HBٵ_IML1^8ц ߍEbZrδrt1;ÚNQ:n-MzIAJ 4hOտe;q3 B9sn_h@I /*j痈 nk>W #]?u­)bbAp;|Qu9C{!,$2 jӍa{Mqa+eȆmi\Ѻ@dEk|7+$u>-] /Y E\mWc,<~_H+_zt䄡m{Y;Xx-{m|esvk$$R3$#?ɨ D/u.UݓKMMi~{+% n^zt>\&re_Q1mV2/iVbnMt1qWs3gtۆϪ*'@zeF$@p[t?6@2iX6>?RIYlqdFH[@MCwmX|(B =mo܆H2E-ZfQN  Q26!5g졃^'{N|F%)De  r Z팂Iv,]'0 [s 00x'ODgdٿ(ud\-\"R"wh[jNT;bHDltꚚzzUh(p[ RxǩVu>JcޑD*{XDҲ_]xtowf6, }.s݉W3*GTV5Ed;CO>pװ!6c, 9:KYvp6 ؈Opq3Qqv`RwrO}I ÑYO҈@jI BtrcKКG?60WKl3Xrİj$|iutGf2.6?*m,`p(4.j#n,;Mκ&LWGE1oDFL6fPXUױ, ֍2coʕrxj*k N:DrSJՎJ L2b6@kٳpdx f~@8WSGh {>R{Wf}К.NH'$YG_ Q+\\0?|xdeL0|.#l܍4 $1dx󯍍 m.c"d@skw=X5Abnm _%xi̚G:ǀ ;\tJ9$}TzU"o%;Vv4c5 mND9>: z]ԊH9S]*D֤j)d9]I'F GvNW0p;UgANrȱ"82t#0'9J;QaݫJhTGzS)`f^ nxG/sY#u/-Wu?0rDo74wJFOdKlUw4i3R]\qIs~;+޺ sr{T+# Ur҅"W;. I3=YRqóhACaM߱YX.`S<'S`(yJuWp(OhVCFg_y/6 70K)! ^䈔to1ߖ4c= Wh: `lϼEDgWXvI﮺=^^ٽf^UʽWؼs"h帧%Ip($K ɞbȍAmL.M?d xXnC4ܨԤBouW7q[v/$^=V)\矰Xu67+'9oc.ǔ<造헅@K%Ŷ1hrk|SB{\~/j 3:WQ$n7W<e%q lSsz_`.՝tɮ[^s4/v˭wOm-a\J*<2.B@\\D,W݌ߨVEˊִ`%[Iy=z/_EV F3#X#ixeDJHG7>B^g4! 1PgrpZNWrȅ:nN1'w>v մ9MX/qX%ߐlxDPC&2#MQ,k+Ip}my>,\q{GOU &H9|'aQ,:ILi{ J$K dDB[ Dp?BM{e<> [p.B"d&)#qY2d(]E*q2/O-5ϧ?%ǽj2+J)G2]!<w`^* gA3¡$.psG(r<ҥxHEN\^"ڿ2$ח&$$`JbU_|,TjQAޜDX%Hr%CӲ?AS9{ÓkI$}s>">z.V7AwkDoF ^S䞞)^ Ё:^b^rpQw/Wr[0Y9ٕ 2~NV>3 {:+S,%RY% g'_yDeUEj>F%x /Te_DEuhgF)Awdxz8PÒЖgwqt0V[6B 4E _MKoغdSp*}V{Z\luge d($V^E uGlphfjץf7Qy{7]7, .Gt5/ɪ(56miej\v2f>Iiz]NRDkwMF"j".YZj=m *wscve;,W9!u1C=~`ḓ ,ya+BQCع>9P\]R=p!j;3䇮71p=D(Ftfwx(d8[M J[`xez:)&$z4K.z_Du XQ`{x/cF)ݒhM"Ez֋$Ve_50n>pEsёݦm 3<s$FanKhdqDHkꢱI+ܾW1oT顩GL ӟm}{x 0nC8W_hBD.m7V6+<]qbu T mǼ?VvbJ˴EF?nk e@|2QI1S~,puI~{ d,W\E,Vp蚯la2k|FFb/0d/Zd~`fィ4޵c= <GwiYT!e'kC\lEx7R#",6|a Yt}3xȹ \wg`E$Lƶ_eWݎݯxuo#e$CїνE&|HdvMs,w[C4e}`7D" ~vxK~]iH:7/ai@7?F_b@Xz 6L;LZm5Saf-WKL}J`}bt KĤv. ; H R⏮L "T0POG6~2ΖpJ&)0¢*8ukط9|D$m AWR7& tqFsO2x _J`!Pb=?;(PziX qULH^^bT\5 or/}X[;Rl&WE-f-F#Fw[I)'@%Z͈TkWߵ$1mo*"zSTؼgyvJ՗0g̸rÐ}]\3hRa(k!QXL\\aǾKv1/FÈ+.΁Y7X.|}G֧B=ALA2B)^}%5P5fgeaO‰"ϲŬX&ԡ$3nU^ǐ՘!PA$6vWILWpAB?Mqc2(8 Fql,Z/x Z]lg<zo;l.kȌ"^ >h6MoPC$ov wǞ%+n_>$qɓ.=ʰ-h310!e]Jl=U}+V^s)鶼|2*4, Y.!u8Qډ<=o1pG1{1#n6†]- 6AoC=-"A'<:A!0Md* d-ؑƦ9IJS~EkoXTkZĞ7t~c]Ƿv]% y ktG\~ =G)u;>M *3 % !F9B6f4jV@Lc824J¥AWhe>c>,:hyaob`PVlSK y;SK%4K~Fdžz1O#e2! pw+wI*]yw&A/cIkSuzM9B[2ZdLT~L>d%?9d{F[m$DRVZ$ɘ^& <ԟ۴hqwL+$v"!v"i]ձ<4ZGtJ0n% [DLߊ-._iv>LڠXn7wZEӮeM氣˘iFg!#tx}gRX-t |܅sbM5vgrҗtH|1wvj}k@ϰ^ OJ noMk'G_٠CL)FWTue'UqUx^Yyo fN'rvmY!,|)2"IB`R,Ywjk诤,9BBm8@ahu .lvl2cz| Yk6=W ++M$^0-0Iv'3S Q,b81Yi]lKNNQOw_ \z-0T͂iŸ]b@XqA pp -ys_9d]2=QII}X[[T?[A%Y1q2F"*KIYnq܃#xTY;S^lo(b&RSz;{ALB`pdC4 ٠OxVKc쀵 hM;/AyٚFҗqjΥɳw=z[bxk[$D>a@+~*WA>jgXe;cf|OA]ޏ*i "dJg~LE>:7H[ޯGx^5e0-O_K{ z㚮3\ğÄV J˛7lY; OF#1Wԥ:/ӈ$kˁ+ ^kb #kAFǍYq 1-ϭ}\X!45{[KkH!A4 9V'Thԏu \LsaԎ"hզ/}@TTzQ\j>#7C|`oC|Bv_!/ EEA4n%K^Ґ::(9a@T6*-:@6i $o-E*.Et ?r5ND ?!Y}Xo Vgj| +;+$!ZeТv{*Ճ!5J 6 gЖ%Ƿ_qw,nwmLBvB%DY#Y#jb~yCM/M>,4a;zv5o\ AuBŬ 4ŨZkrBpFEK-_ށkcPo.:!#7$(?<l{U=S6cxM6`U1`}̊$s$0o OOy)EDZ@F`X,%sq/isʑS~Uޮ$YmҁygJb0'w `]Vw{ǹMM{$jXf $J ?+G|wKf`dcFFFD.N"l:>]s2Sy,flh%fH4@f$_s%AO륛+9՚5MlKOK3SJ^y͜^iLVIq K+Y.i߹cIVe2"hR:4*/?W tXS.5[q8z!TtkNGtRc8m: ^T/jpg"_ҁ2̰[(2M8} Y\]~ʞY~KW-;m&NrAYDu[c#MjJ!pl}zh5#JRHV]~BXa s?NQbP Jٲ4}1FST U)u)5}G $bK'Uc㦣G. )&@3/bԅJ4"7Ni Um;4P&{yxsW:Ek\%ZmEՊ ɒ[+}\9r#F,IRp`Kd%meMG`CxCNaQVdab13 3w1'7 7' 77 1!))'1771 'w}۷o߾}۷o߾}۷o߾}۷o߾}۷?NfxI ?jSXֿ` VGSSF2 9x3( ~k۶m۶m۶m۶m۶ .lƋVZ-kDi{k,a#$-dliMri"l*1Z1Si$YmѺr [{Oʾ XCq9yeVLi(̏gY|P~ y K@U8[27E gDe:aLU/Zr)VQE*_ l @M<°7* 1 ̢ӊǤ2S02Pϴ[~)uNOB.1<Ά-7XliV .l,Q_ai`'_ Ft?Ul"{$Wԧ&nrH6OlD*Ȫ_ bd"PdvS ;EJ!%Jg:ġ $@NΎ%m_J;l0xD1E&, +,VUroq₃(jc.ʼe\ZI]f>Q\]ˤs)Z!ݜQ|es`R@J*J&Jm QH >W`3>X FC{hO@"Gڤ^4@~ݨ @Zj)7E(8&E)\}bb#5JҺUa,mN<(^jEJN'eLqѤLR;+c/DjƂ|E2AwwrE47$39M!B$>;W+zB{ lf'jj?vzfB}[~yiv mUQ2򏰺BS@N蓐 noLo+g" QNW $=aCJ P ǹ i)b<+ރ‡$UH<~`"&Q3|ط! MbSPo܀Tվ%wQ,5A+`> i+\LfM~5 j<ȅ@] E5@ב KBvD(EWG0Bs7'L0($u$vSc6%rD#.?Ac-.% s{ƑU`fT!yjT"rr(UIHS# O u&.Sqf/;H,'ߣo#M%(&@9w7͖3b U225Tc0)hpܿ!m2xHOwvPOޏHZŪg?K?A.v&[ &^kFmSVo*`g뗼Z%8XCP:wO^v/RolևDv]UnWur_.ڇ4cNE7UH;:3 DQ s);؉HQ^:["CϾj9R 6h woR/)(4(θAo fOho%_gA((I]JF\z{:Lj@\Ť1a/ #ܟD> LtG-P̀`4c[H*x9h~F\<-NdR9 _] I~!!,joxzZ :",Po#hSuN"+S'.G€@2 4>ԸDKoHOwD8!n7djOT>bd_|>E@68ɯD;\$c?P0$ Z W>17-/VnMNchU B;ͯEXqFAAD 1C*X &4("\8S^& U& τZj 4׍;';̋#{"hǃ9.J УaKs{|>Fu0ݮP$=7?YA\䍒}QF扽c #6΅go|URAb (RQ#wU)~@_K UY5gkl-Y"d]Qfˁ )/#Pu=K"DJhLh\e$J5.l+;j2.8H n}胿([8`%iJ%;z?,To%H@ T0 /d|i @i,i3(ƌo(<5<\\p !мw)=z+2@y:BVJ2 Yi?1G Hyv3bah @<]jvBVq઩?!N2=żE 惌? ~)?'/:޺ E Cb> 8: K iܾ:  l1:^&[$D pZ%f 9%z[}fF^主|; ǰa9y*?&Яmb2-v?}L:l.i>KLwvw[ךPOy-p6=Fl.ϼhxL4WΊ ~ =f/9騟xtl-J0~+3QL{̻i>]Gt61?]"Ԃ"y92՞a;Z::LٙĶqHy_yd u\yP$h$}LbhM|~n閵-2pQb8=.MwǢ0nsnDk:b"oRq6gg̳ZL>r>(;Z!Nnb^:ytKÎVkǒ]|a"ܒpn%a򩑐zM({Ǐȴc:sLlj.biא*|+!wvKz+,V)iw2ymUIʵKb [>;S#=:HcrWk5KK&{iUAJԗOvw=)1o5 rF3ꬭRqTJlNbo0V:zw;]NaFP\NFtzYwԅKyFHܞ6M^U_ϛRUi)R^/|CزfB^]SnNKἹvn j,F50pZUzԮ)#>r kX߁u\_x=}SŹ+*sמu5$ؠ1,g'7MCY_/o %\ϋQK-2MgEUUaop]NQk/J`-򏋃OE騃/_APZUUoé^^_?jtL^;\w$[#'N CY8t^m߮ 1,0i$Uj)ώ -Y),Dڽ K3حǃo٢5b>?=QB!瘏&3Tl 1klEDƎWW}*ͷcX՞'&`A]dǑ7ZJ_g2p/=DfU&g/`v%񓹫U<;g|V=\o W۸ fzd8*u7sS&Fz<ϻm!>=UycarijgnlzO3sN^_KGn.H_,~ v:ns;t'ؙ>R/7}]gI"x'fVBk{pql]l7COV8퉼~[-e6 7 6Z15[ֹ֛೏0o>j1;ц3[>QpQp;EQo 0p693r2kՌGNXkaQ?g|R[Hͺ[n(3XS_w^qq4 ^k,d ?xN:j=K$@>9áf_Фh+MQo<Â%ߧb\n4jb7\6 o>C[<:d"?ѐx`>e@?GHߍ pݵ?WtvQ@Dy.^~1.(z!_m#Z0}ҿo A/ ՚!!Q?jơ9שZe:~ڲo R!>n+(e h}Tn[ ʧټѐUo[3m X.NIEtr M0iKD9'GήMs;8Y 'k=CLiJ!=XYKbƜn:c^ ECǪU |y"e Vۯ7ОĽrݧM +!^% *NuC9uNƧ,V6uLJ- սOT|9gvl֛c8}sY ş w>ݻ Zn 0}EoOH^Wzf(2<m0Vbĵ/RmndשG#M%ٽu:gmڿsRQyNz[P}wzG|p3x[Ycʧ?ai)o:jBʥ@ m&ZJc>w&MW0H4:MȬ=[*y'aЮfĵȓzjj29F}bAkB8K!4rNg>E[ lH(6yb0&&On|KK. 4sܨwPk2UPb6o&O^FM`,E}9r?n׼ 61P$3<MZ'ҧ<^4nŋXW0uo E@Hj7}7#X%yrIR5ڸ| 1K3zFc䘭dxt#k5fzh#~cg =]e.){Lxyoa$z&|D•7%SiǥtO! ~௜s׹ {( v`m+k[$򉉦rHKyO+if b88taA\+\$˯4m~nX 5l 1i1k/dI׾ZKyxg"tǁٖ4:l\C.C GBMϢŒ?V]&"Ϗ  HOxFQ}FO ѻSx͚ξ7!"W vxp$%n̲c# \N CRsw%CEL4JZxs}6q~i:|T|9M2O}XۋhB1TF h83kaPkȁD8]3%UT-y qJ.*A0p\: KWa292T3 .ev,bn|Qݙ#O,Nd)Y4 O|ÉE7v3%gee=bBLl W)ȍ[hX) amn"}Lƴ9x 7(;7gZGf4qbJ!ɴoa$HB#)TD 潈GTѦc(5>(.Л|4tJ &Փb]&_TĐ:T{F(J4^aMbӡmR+bfC_#Zm%Z%t%uF̸%K+YXo) ̻#{(n\@m0ӆoM,R=1|X8Y_KfqY0#Mu?ֹ3b-rl{Cd )Dl93;6 wXpF ^6&YX. ',.ne0RY"֝.%DwuHcry ]2`ܤ*4 ]2KV3=Ӽ0r%6.GnvRQC@ v *ֳvu ]Kͫ9kTVt1<3xagNtJn K .E$t U ϐU<T&K^*9aL*F.:,+{GcJpx2o伳{0xTy1-7ڲGxr%%A-W{\G2eziPEVC0q %m/}-ArO%ȌIFʿHC \ /)#sy %EWZ$z-mnu`fz$K")&hE5t-]<&-/9_h>o-Fӌ޵s&@LX7VE@U]lٸ2xUeճ'ZTŨ'Ek4/cM #. 9@洗5*76Z!QM3.J hDo %&Ce:N$&iQ r/9یV(gvkj ô/8 h eV?˂yzd0\mJĊRp3Sqɒ{-O"HNB '5]M[׺iA:&-%٪;8͝W_vhsQG\ӿ4uz4MY\mm]d\cj@%KXH\kƥ-v}F6\&6;s s5foCC}8C~ 1jKFLկXϪ-%)ʘJH9#$=QÎ l6&crV vvE T תEHfCpSɚ5eP$!ANcq\.Fܐ% 2HWNbyy.|SXWe-\{m$p * >$M4~eO{a@3s;ӕ_7KpE>uF!)ŦY7-@}Ysoݞժm*M T0D5l,F]TU+~MhZ2F[`Ʋә hΨz؃.uIDumYȡe0qn!e0urTоc]g$AA5n,AF./z-vGEq Ӣ=8e]V~v`ǩ Ydr<C+{V@v3#k 0KKP9Faqt !g=֍?eaDD5+ἢ3FC&؎iu˴6Ge,m`-GR9 >$4Р+gfv0Wƃy 0@IϘ:h0-!l#ė3~ f&#&e<_ .{̦uĝn.|=-Z@!# 1iʄpΔ!E,vBjov1oc۪cL6[e{EYÚwN>97OrF๛RU:gIvY=ƯwLTjRmӫZByitɟ4@BF8|n+x4ꟕVEOzdfXA c`tlc=F": ˲3(1p5[=~hoAj'sSzVBb4kcY/NG/Mi᪏H3NV2kTDe&WͪVzQw'3hڊF2f f)}.Z~~d}N,w5OolnzpϕVTk.@3r땊w^2 M hBP3FioW UfP߼&^(ܴB*+Q̆ PZFͷr2ۧTrR*`.CԽh":L* 3\Hϓ$%_JjR !n4i՚OĂ):ؗ0æ *܀OilkW;k;i[hLj[qںn}.,G*>m .Sn[ P\Cdv[>+Ƥpo龕&,GɟK^R39Z8W\c^UF5`5nkc:m ޝЛ!MiI;cdJ>-~iN\#{bs [ 2:>MF8^cX MP>\KhOέH͋8\" :1mtPZ;Srt!֙J:q5'nAvY l|blN1(iSJX\2 J@ŷ7kshXqVd8T{é [3QC[b>ye7ǡ ᫔1 EӮ9̍sC61PܖCƺ%I*}1WZP<{+_ۧDUo13:jV}`b+$@>X >z̻X_pZ@Zm7T#ɌBK"6՞Z0;Kͺd`iIo#m}{,N-h5h⽈MhXͷᴏx{7zӄ{%Ή**)|XاA  7 ! bE՟sKJ,/9E咳(9`66w w6JWē|%˜5;I`L8?c}| l~Wh+ߊ gB%U٢6|>D=3uv=̖$BS޵ߨX`|φE?,Dڪ`hx+{QI)xz8;.;R4'g;Qf 5s%nz\\ ru%Y9k1t; OZ8-`6] _#9棯CY c&<5T M>F|NϬѾr)AH5)4́Oa:5{IxAnxCܼ&gks_a4=:lҪmZp';Y,6+PKwm@#-n9Wz cK- َW؋ `cpw![doI+iEM͖ 6)>`f4'KǼT<0VIi׼ ;7Sy- 5;~˞>6 :M#`OIJHFM wU(7agB,{Iun'+  W5Ҵҧ j<6@ DUV2$npVݴ7(#c0CiDIAQ7kGÂ-G_+5Gd!'.,FP"Ck5&pR[a9\9ޞocN6/9H`HvOWQw9'&/Jg["#F3֞Z)g:w`ߓY8gVg#Hsy-9E i `X@$d/" }sk mK*`mbrkIߏ ˯h;E#<HgQDGl}(6u$M_2NFɯETʄFx?.AhMŏwyl-,Ng>Mqf|PeM*ƂB-"jgŦ:H!ݨ~Gbzjt~\ᠭ~ lpNV=V!E*UFn4_d(NɮF&JuY#l:p(Sj˂.sX v]&JmxYU+Ҽqdz{N^ a hqU1 oٙC$79.FwڭOXAq(woY?5dܻiC%Ə&~0W/HCLamp? M62`qd,پ$[@p4V.z`qƸ?šqʚ Ga}c^S#x"еϢax^Gg߇^BI Y]X wL 9~_oz} Gp?9xA0Ѝ" K*.L3~]s>t x8^] Xe_TļpWvYXRDTD/Bqvwvwdvf@4,HK3SK#%<;4,3R?[caX}wyw?s֌Qg9/_ PO/*/@*U;*,1:ɬZ+YyG/+Epr82r=iJWJSP*}5*^ ]zBZRi1]r3FaFQE͸JzXAPb^1Q|#GCLm8; au SP+}GD^w|Eˑ5%i#dJ,8#Cs־xBPjv]sNۊ$aO+ՙ0I6VichxxdEX["AETcp6Cǰġ;nZN[9wXf,t&m,YQ~I͊CmsWVAή4KB %I">xI(j*!J@118ax`15aB8gBy4+.aAZ/m# >(ZsHu2tBZӀ( $!;A+ rpӕ| Rsp`-$ hq@&߂ +Q+ug*W =Җ߱a?C'_eJwrnC~VW Pj< Z.PL^JmG,alOU)`̉=VࡓH[&J5˥c50o@!F5zjŌ:n֢(TVfZE*p͠c$Zۺ-"\([ ?Pbz1U谈E ;`C3`ǡS@瀦o |Ќ2,iNj!蘼]@NKJx6Uià+ gfa^5͢y6[nk%8 o*(* rR<}9Gç`I. ?JprG+Hu&\g$8<7q,1 ۂ*yWۍ{ ؠl0"0"uu+D#ʹ|WPa=} !fܱvpV`K{oA0DΚ!]MӮIн(L5*"zHhXH'\Om!A` T8B(`T@L: TLqF&@0 *Ȱ@aCY钁܆ Bh2Y2 T@fLp`g kxrR6Hz)@*S.Oӽ@ t Qj.jrlv*Dq 49@MRq#c°(P@E";eXz 4E903P`a uI#؄QFZk믾ǝo,L_?<~K#ʟt~cnY=l\}f쬋حV}4'=kuxק '}uq@K6ydq[AC9/yFxD{믙~4<2J^R>'>%ŅKv]qjw ˧|.%&V%ZH[*']!ݚ/քXٍuJ_e%רq)՘4Z?>1%k:iu7}FRju?u7_ trQ*+3}q\GRTr<$F^Z${bpc^z%hjzZ6',~u3u"Kf:=˃V^VDYݯ{q]+)ޞu`ErAG鷴K׮ot@V.~(ܓ_v}&󝂡;*o{/gl춂ܽqspBhmz< P[{'yvyo]'TL3uٟ^+GCl;k8(_dn+&su+Gv0}7s?=:scߞz}BHʜγ&hoY l;ZߕٷYd{xuI+1UA;Ty.iX5p{1ۉ[g燴W0࣏jqxJ;ؙܘ/N|dǧZ'|őO wjZ^:a{goSؽ!#h;0-hcͧ=EUx?kGinOgm7Q嗖|87uĚQ'_.~cSڔ]s;zuIEd\}1_[ϔX뉬ˏhO}KpN[kji7lj6`63fH?7::໛3;{ywOp{3=fo=ݐ~dgB&1;ö|ݖ1'k&-z2dވ)?Nw^N</dSMny>mosu;bWrႺIo??cd&}v߹ZE5'ވz4o=r x>o?PS|7" i;l~O_ݙ|Ӣ3nSywrӠu^wX?Uf)[Z2)Ԧv/_:nz_ y> ظ)Xճ]c6ĸG7?lҭh_\W~}KMn΢q3~3-C-S<5Ջh;棣bvR{ߛ5ҜO}ޮzs/#o^nx]i@dukazQF?y Q}0{mߞ+5Ƕضmcul;mضc\9Uyuw7 aPEi bVպi v5oVŻ"ܖ8m4>%Y2x4c-''I>歽i0Y/°┄!w<ݵ)wbv)C{Qyך L647Ba7ϖ*}|AmG}uq>/m)tT`8sV^'{6R>4BCbS'!w1N'ͤUVlSw2WO3 -,iO|q^(p.Ѡ}V;cW2*z{XO#۰F[k _apP]Wr1&/oZ9R9=):CMqՇTA1e(«] rӗគ&`Ox>Y,b@ ~OHYzIAnJ:4!޷ͬpA^?Kd 'qĘz& k}b?[I}J?t3$FKo ,ܱLoqw0ILilczy@q++ %KDՆ[h1 cq|DqtU [ܜ;ZyDLm,Bl\s3nF= /h5ԇcqz ]qe̋xƔ;$}mP=B@6&P6O#z,,VDn9J%g3݊2׊/A"3dtvBք9< 8˓4xOt-c9m<( ~B7V0+`"6r>*p-_7pGuh \~KXOhFU(/QOw6CX.i92 vR #øhĈ>_Սr*O/ps]|prv @םN/XNx q֔Lj BLRL{џqjbנV~UͳvS6㋤/k]au?\ ьG(yNj`I!ruB֙!*7FehǚmIcM&{i{JU~v?(Lͻ֒' ⤝t۞ư^z5sFb3H!0G( :i8U9Aw=v.n4]sj9"Q$0/f_BT=-hUEX ӫsG=:")+xQ3pgYv|}[Uh&} Lӕ'i a[D|CIY %!P=8x "Y(U; |? DT8CV;*9die pˈ#!/adB V\xY4h%b/2aGCZh/דW`)6F*I=.vٌ|o!•5C!P<$V]GXS_%`4VUrR_#GԶ[UN/槷)&!~0zc|~PDN:)UoB"d śxQ@۞ŽÁsG'طPF{1!4zHBT꜍cQlD&sC1EzQҦ碖JACqgv 0jK.*1i) nD4)U~eVM"jmx6InVZ  4Fw cmP}1:v<*?ArUiP!Kd07?@EЛ3bJ0F>PEO>z/ d2zoO=ƒUYVɿ:9{Z5B,6y#%4E(CZ: 6S cQBbSNkRJ^N&C\_.hh W1Aq%8uxX69T#薬>Mݽփ2eR(~3.pzAax:~>7"`YpQsW(&&Li3n3^$BR.G$CouXp4]SG=9.n+,dtqgd6n{1&}Cs<6?ՠ泈sYM2''a)6)`F*+B == U7e#*ogų"ÒJ>12Y1A0p*;v30:Z,M1" >(R1,p?9s=\磡"jlxnץo@@f+=DFs8u|gV̛׳8o]FA~s/8SmU,;߾bmY (? NXZ\*U|]wifW|2gH4"uRRdFMs˺3  \=Sא_((OeT.C1ӯ6 K+:o67fs^"%_?%{Rn*irn{<%ݑp)3-Kl@U5Y ]󍤦3k\@n-ycuߝWzdclINYSl_j㷬HI ]3v᭺֞5CYL-c#7unwA6Eɹ. 3 ߝgVR=>?94 " D(L FvYËXb}](::Gsi- ZIDž \\:=I/M$bA3Ńs׫z}٧'2ٱ^g%Pn^yia\=WU^aL_qW([g8a׍&ͅ r/8ɲzt=yd0TRBP܈p)9489`Om>05kPpN[3:: DΖ;r4 rhj<+2&px:E+:m/h,Cѭ ϮrxnFPRk;D#&;ZqXi8ATD ы!%&Zxd$BiY6 *W&62!+)/'3O8Ώ?LY;/J zN̢|JYJD9TEnNac?y;s _޼JnSSu^ֱ#f*W O /i;~m`ߞXB8|Z!d{Tp?Ӆ1q?9qmlG2QK`wfҬfM;l NYHp)s9^ P|&r ]sTjtKNUqM̔rP3!;a!!'_|PnڠI E>~!Gͭޓ$>֊ iL@t .g AMw(=~{=,'w⧃FQڽ[#zׯ^)d)g_rHz`s$*q=xQ_+k !բrŇ vD!Q4Oaumz.ͅ3Xr^5쨧)]\V;;r6"Qz$E׫t{-m6_#J?4˦rņ6ބ"TJFyyUydžve8goH;kIAZf6k#s评VR&n/H̬Z7sC{\xwF/{oyjZ*]ZK $D!ia-3a) '̙ 6ISC@:hc,w, :,؟=oW3b.jCSLjWC/n!)ȱPAaQ,UT.)SsC)'s r(K!0xq".)0*O0l!U hs1EN.]}:M^l'`)H׽M8+9%玔;v5Ԋd';Ll ϾGZB:^p\MzI< G+9y\6nZ%O#^-,T4!cv-[jtShH)(z6'Jl'R0Quhx:T744/Uڨr9ɖ@ zUdޅ!.A{@|D#Tk"mBwv|ӃC~aVrh \TX&%q ȏvquSLcRK=n|*bBncS՚o ixƆ8߆O3ऋ~;-ގhH@.trgorC|?RQ,mNgiۥרm~^+3:CݞjaB)Vf>>VY̧њp"IۼjV$= 0_ u skhaߺySuy>8"Le'|ќkKs?bRq#YgJ[FE͜7p5fzW6 橛M fp [b} #V)i* k/8&$ ̶g9~MzzWi;ͽals hyluzajL2mG|`-š/Deȫ(bg5DJhAI!*1Jecru֟<Ҁwb1nj4\JƳ__pnSGgQ7.W53<m۽|%TLK~N ,uU<@ePJeU+Jz92KqC   ̂@13@KA>P~^޻g]}nL^6ٙB%0<[,K LC,L1'ݸ1 ֽWrR .Wk5l&^㚋rz,\ӿ6M]-}TFR?CN CKίU]AR85kۘ  gKVēk Ӓ[j)}غJJi.;|[zwzf JEJ=,J`T0@B,FS;cFEu9!hGL͌AKIL#_tFEEiXIRAdBGew0.N#>+ʒWݔqѳt-ic:{c{?SަdcXh\z-zS 8fQW05dJuΆ6GU% jf K@.x_铼52֏rQsw#ʅ,`: 3ҹ?V|OS&?E 2q-3I1R87R)М;!> 7mLfD6-{r{12߾}۷o߾}۷o߾}۷o߾}۷o߾}۷o/}uNn:ۃxI i0?3]WX#F= JN>S :x9f^] TEEE.EU ED-n$$$3qfںU_uCZֺnjŶUu}Bɽ7}e2ow aI P"", )B#""ƒB E"8HVp_fV)\+e)RC;ۨ5A!!U?8\w",%8, #Ma0yP\S$Rx3KN4ra!#b qQ f-I.YAe6q*Uc{R\K0r:H 3qг&xj%ТQJ0!X"Z6 V~I =-<%("t E% `Np@#sx. fZQ!hyG`j5,@rU?"VoD  s|tN!C 2YeJ(C3jΠU+LmA*k5iS9'6sk9n8CDdrL[1rX< Mq*ҐZy(C9Dp)~g!zG$ q!KZ8/6`$ъҼa2IJMg&AoVpପXPMp^&g* @ "BZk0d-?A f10g Ԙ0Љ %4AXiVEn\ҋ6,9x&(koSYC1xґW mԀ :aU޺O`ޕ!=WLv#V= 1bb L m]Z!ѫ=tiT{8j(:yf"Ł6cN3ɮ!mPIâ2jGE,:4\%X (TfCGHG0t ؊go,< &: 5$A$#(nB‰c7pc,Xі8@Rf $&#gcč]4\ 'D)UID⠎Ve>gW)$y,fVU.؃\!į#XѵÛtRXGߒh{!Y4C'vKН=`Wϐ!d,W>@Y[ȈEЍԠC+1ֺ#Qj-C"q-ZB\? am̂Vr -8͉Ml^0JaC Ќ1=ZcvXv Y:iΟ h*FauA.lA1̏8ӌV8Od2R;5XUm!u3:rHn$!>*2?^:Ԥˢ͢/|"pPA:?.N x51d;1[E<w  ?HZYi3pEБPsN (G-p)L !,Wp" |2=Ī|z.ة||@ !>܃'{nv?#c3 YnD!7Bs*JyVM0m~Cܼe$1YH[[ୠ4ZBJIc&F/6 ) 5<\5w<I41 p gQ!s @Vks\X1@1мWVGPmOȱ"@jiqJzNeC]_hkA,1[iC@sU{Q(2"簨t>l4 h@t,*?r-G͑R%8v_T,C~@҅`k4_@If p@kb"Y=ƚp%jģp 0£t^TRnV d.2A%J'5kĤd cO gDZKaV%lrxb٪Nm$Rlj0[`'YUРWA+$d *kd@(8KT圕( XBpp0,0) WOBAc) ,B.zo3&O: F!3Z"i~J`&j*SǑF@R{6$f lh pвڴX{Bq&m p|Ih;v֒Q-#;JE(e6DŽcg071`/lht4?=_ r*6$5;( "jXJS(pPT!½+DUy`.UIҗ]L1w fsH஡c%a$] K DYUu%Xr&-l`]kؕh5$x:VC"ѩsao  ryr@nnq3k pJwFlLך t toN*qewypP#Tt!#,!Y2+xEi{(3,Ӂ\?12.)<5B\ER*YMȍQ& s-bsHZ!%rް $7*Á1Ց}QfRh}Zr~ hpS{hNiٷl WӸ.2pDJ\
3n2q TF BgC{JE l]x _@hz$l*J dKz{bIOà#YRvqvnAc]ZՏ).A~["2b>o8moN,?|0oսߧC$Mb6N%_v̱1BiZѥI٬lͽ'<5p enE5󽄁 Û6X{Pʬon|ʃ mN8]}o)Tϭ?璕o}آg~wgowMq'%iϗ`ґZ.z}> ׶Cv6M1tn˫[Ŷ?3h$CEE:SHIgX|cYQo1򱱇%S@Q?/1aAږ袹?M{,p_9v9󢙳_OP7n|1`N+mj WO\>4J>9v1K\8+oںvRߡmqmcz5X뀎SgmW:fUQ;uOY_/J59ߩ{g}2j<<];B/_ssyI3'x׷x#']paWsgcGWZicn͍ۘI~|OywYh |[:2q[Zt2\{>Gj=u21\ߞ7xD12 #ڎ]|v˧S _v+ګYKӢYsMNeZ6Ou۟zZ~uH4prVlxoגS95rXΒS̺}wǴ>j X girܳ3W]/rgnx^ϬܽpL'sczbr;ex7 1yF'<'$|tBEK{\x پbҮQK~1 :-Bg8.{8Oy#c;vR.!9^nvqq-|r}]o-z9;>G[4oՆ97x6[MzJfF|tT˟Ə;r۶8o_є+݂|BQ=_د_jWުez"bZuNz}bT;T>3- 7Fװɇa3e8A\&obqN.=hn{CpB%l{>_݄&"HvQ&LKƑEeeFk764bP&hŧt! hnݞ(!QB\W럪G +.ZӜ(dRnlϸT=`LPwePwڗ۠(ʁsYt~u/]%?'%pO*-A:.Bl4uʓ? Ju|+hTO*b{X* ˢ$/BI<#XpÚ"'NDVG / VgW{dNVjqs> 5h6mca<=˻ ?H0M:9 aRd<6Ӌ qaZ r[ ZҬH([G iyfG)qsuPL u%['/z"89#,!+H$^=Ŀj;{9zde =B MA)3i|yzc\Fsb\L85TԱ>"gaXWUcқo~as]~ 3%~Q 8TNx:@~+ \ky_yA$0䩅-w]骊]tiVN1Rc.H!DR*D(J<) ٛ+!@Ax"hsO7Iԍ~U?&{Rߣ@rkgJ2^=zܛǪL6YT%Bpv/znu&D@Q XQl_1{@*I!8J2zECQTȆWC;{pj ,9..bZK}[#`s7/Gւ\B~U.x_U})F/&iw݈("u[pi6OmMU&}zjq\ORc1tb;yznkP;vILRI/\n"+Y}J)KdY$Ë+Vlu=E]Rjet?/]ÇO DLq0;\̀, 9$1ejв2}͑)%:/%/*WDTXWJ)ϡep ?܋Wåby1ﳵn'ciݗ=9~Lc0tXDq+T20BsxNC:t|Bgiy=hgLQk>u4U?. #wj-c!G0w |(c@*g"/-_نl4t;5{6μ>A8B.x /#A4gfS6&tb0NK=e点+#0{ڡ ,H) nL&?}1  ;U҆Rg&8JjZY;?5 tE/MWm<UBn:$dy U1FN8:7ӝ'q(Vjaў0&J?4'B,2\ǭITtn#f$]< (p(W/YUG }@jz7)1Bj}gG6s "kɋ7m:P\xy Ӄbm*Aw2E&rL/wdP,zPJ:B 5zϵISL؊cR1ZMM k$PXl&hg7fbnD;|,m)Q_J;FyF~LCX[Ί^3O.ʊa(7CGQnH)A}??n#*M||5Q V}7tWcޖ8qqJ-pP Dx.Gyq()Pf}JqJ<}V@/cdHjO|TwKql)$UT$ BZǁVi &oM낿c8d" ` om5d66΍@ЍH9vWi<֒%7O~@ВqSngqN@n9'Lz,hZqp+1څB :C-ͻ!CsGp8=VI'|薅_U?|U@m*k{(Y \5|(` 58{ݐ2/ȤC1Vg!}?Yt F#O'nJGĄB"|zTT@Ox .ΡfSI(7u?؂w&O\ǨBEx.y||V uQ& Ŵ{+J)nL"OlNI1B?6*?P2uň#lݛdbM6XWБF Z U) vSI½9ޟLD /]8{I5/ Zh}$ԙEk~X/8 gj]NՆ4»[%g`z%!Q-٢ϭ, v&L#Qt M:cLP*݀.Ix z/(bl֢/Q͠.#PjWm3ydBxdžmSӇ A>.E`fEœIdlyaC_GTFNXm)(SSVE4[v/cI eLLΛnnVD52(Y}KYՅu3 ף{]2|c!F~:YTDhE7\t"(s˷? k?+>XIc =D4b;ɏfbGÚM1 '*ZBܫ6~]6/U ӹ#AXp_Gnjn=>ă1CY1}ڤu`[ৰsPX(Tm^6S@<3UF%>$w#=or M06bck#"2sgUI8\ha/U9Z`Rn 9=Gi9xc6ԣkL)ur vqK*w.< 뒇{?pW)u|DH!"q oxCG@ԗ^H];dz 曪K7>CVʻyc;DzڀXqia+^*Nug#ѭJa=_:M&kYw֚ʿ=-EGA".gkSlRt@SR+g* 8,yi" ܒ'!tD#%1Wf'bDEg+&,PK 冪9f5*ݔ½&2Vu#3\rvSK]pJXyrR:?XDt;a^%YH#b NG+UЫ#\ 5LSߑ&Ϗ;Zg(N$+x(Ӆvd@*[`1|_<%?ψ KA[֜=UvR I}8#I6&W(#.'0Nܔe~"jy;f1FR0ǟ]GDW)4 WMN8 AY";y‘sX"60@U$?3Xu9RrRÇͬ1.EMYοAGSFg4xQ5<FDdosR1^g JxE?OS:ziFU!t[/^p Sʄ<$f+\?a8so: { آn|犧hL,sjrY[df+YBa~0|@@@Zt7WPc9Xf狔_N\DYXN9i ۀQ߰tmXKLٮ:J.[s` +W]A )&dTĞpwy"B4,Tr8Pa(,^ b&!׬W$POguOn쩲U/ kU ЄP"S30+'7*N'aL1IRhI5P=[4 *{0U@ܥ%=օ%wrnI ÜqEQlJQ/ : PD'~X5Ow#* ɉRGQ@SCOwspg/R$AbYޙ%,懆\EYw -mL,7JZ6ˎ`l& Un)#.r̡ g{Hpp#,TΟz$%' TeV'}0>T8SDF#NOFCk),#6爔%R@*: Skwޱam.(+&fE?’0τIih3X8MfK{GNF,v'Y?Y99LLlƬL8L9Ll,lF 3'Ō`bddffiymnF5? 3w Xd‡>S2Hp})CR`]S]%R AC>$W 8Ā;ˠS\[d;߆Cb倉Ptp[BZMs,ҦKʅ{ѧZ^Xu={m"Cydx͆$/Z6F,}Eo7cnFVلuֻC QhM_Ob"aN:۴i(26d8O/#ihqs/3aZ@+K9DR,Sz`'Je^vKyqAH+|+mhWÑf/3?2AUy2H-XF(qCNwώDA# 3 M[CACs*i `2&2ZCqÔ@P4lR4;@ݖ#5? D2OdzRwx"W HF|K V{ eY2+r&W¶>ën| u<5IJ5ydŸ> F!$,5~Q*zV@jw-Tz I!\09MPPik-XC&VQڠ Ƅs<a3 6 I>a7?Pk.4&>O(OxdcDZ |,2DYs(>-jg(rT[}5J^(ɆD =v tp:jZ`ʀ3k܌ L~\(Ѽ\hp j3(-"vn |u<cOq Wl!>#XvO Sǖ,}Ň-sM^+JE4$ad#t>, bboȌ$ѓiJ7<}Ȭ P0% ۦ:T|l[PD_bwM\VKGpTB`o|X͢tt̻01 k̝2XW{#bR. qvqŌ[CK-hYwRHv y/A4EZ unpŮŘAZ'XlO<'˲X2x>c~فTLA_8TBд50~ju8֞xGf} DaSrW";ԐEKHuj'L&PL?\rARuRDž R{Y2Em3N!.#Nk8ړ@yZZr3=%vm@ QRP-ɰYcR<`8/?Dt`)ףp!41cHYx_\YSW Ea@a Wo xy{M D1K-U/FRJݱ(4p]XYB.H*}"}3 SE3=#X3!ʩeG7B7‘FQFi嶀q%ށpN'/΃-h֣7(skZRn4*R5Py<̈޷' , %#3 BXFUc2O)G:0Hgqg߳~\zbb65>+|`\#lM/GxAb+. rB"+@1LQ(nl9>~JX[Hʊcʾ9Fa(DO]`,/CƀTKXj܂m*N cW`IkԣYB(7똌ĐdN콰VCz9-l=]䆼/{:Um ddL͠+ 'aMθ?3A])$)h®j!bml7z|)J[EPnrjљLݓؠb ā?X$MH4),.(&j _}Nȇ8IX"0,$#3$F$b|?i^C089mUuH*۶ :`H@B\/'lEÚ]:q)SK_@!h(En)yz9~3],?OVkBVڞ}SjxH&DjJ Bl8eld"r,dRoDhP5DD]W|ы #@r2P d6 3ˆbh>DC aE3*r% (!9{+e3WBBSW@+S/s&j3QB[s%,L( GN Ru) @S6BF+B)qP@+BdHdx{-\rrrU~xh[qN !˂g  u§6vr+-ߛ O%HMB&~Vyʁ;#c avNժJ;4Jl*62y8aT) |y<#oHU2z I01vt.6OB 0~÷d19go)3a ,&R 1&c$9s`;<58F߅IQCzԴf-[ RT+4!&T#˰uKc{?9(?# qOŸSSIsYɝ x^%):|]#L|bӔ^WD.]mPhg܈` .z8J7%ӵjlʇĴgk9ڻ@Tq,fn=9>ýg<<:u[^vҹj,3]_}˯!24'.e\lGؠ^!rzYG߬ nEfs[[oBg7p]uCrۗ](>K!IgD|_V3*e^$N4-wkW!{{:ˆ:n~xξs9h#|(1^X ?O m>t[Os59Tɝ[AFt~[ߧ<ykVUxBxm䖫\IL,w9J>o2덥V=G*&9hNf5)½y^޼ l~睥gsF%@YVU7-^m^d]Wk6NcwAӨ6jXn|7uJ?)/Hg GhVw4/4خA˲.A@o\!LV2f}u 3o]__uٍU-8bGRٟWLl͟Zz'7Peo. x }_vTZ'_W҇Ċsĩwd~NR)s:،Evp3社g?8ms׃nuXtG٦곂7XeIt̳2ݻ:^4VaI>ZP.-v^0]3˞>:ܺë(k΄~Eoa٥gp[NR8c2g "5-p acɒ `>FS$*93:ѩql)[n*•NSZr΁ymo@II͉e;acSR5Tյ{sBZhf.i6臙ݡk0nGʫ *A .7܇l|". R".9N]MŸok/ y}sPԥ1\PmRMBxUK^粎FTC_l:(4-l؟mAjk3,@ akj f#(1zLZpogv) -8#p>w@6T0wV!sE4-mbUWsYe,jp|fHJIav L0[q ˜wK+͏EbL}>Ç[(u)N쑛!ckLYt~.>u-^HycB/n0=;n62'E_ux]וD{ɮϦyjGYlZ7 m"Nl"g[J%AxfAb\B^֧dzZ[Gv N-ݹ) ܦ4-h.dw71nuI`v&'iPߒ"4o~W]L+n2I 9=];ݞe-[ ~U2Ink/? "4 ?JLO$G_~ gж6u"ڸ Pf#Wtn8=8"E 8=e?DŽzk,UjmފƆ΅PFcd'_倂gA;&ΒU!*$"1 #& ː).ɛu'.Dh[YR!8w?Kw +lI⍈607}:s6<C&xm58C= 3&KuGʫ`$FJhΑEM%qZsq5%eξЕw9/*OJI7e(-%^gŤ.K$J/ 1 ^+[k>Lb4.e6MJP̓}iaJf xw%Pغ?)xϙ_.9^,BG}fBy'Y['} v6fg釲A2ctdEĴ}wGd$M#PRք>LDBFbQCGyM;ÇHgt䤆0xCrNflEssPp +K/1 a`!3E2gG")mYsfԧvHi,5]mtTeX;h"DIw+z7?(aqU&)!=%\ `uc~eKl dZU"d\D<r_!1o'N.I՜ Z3B͚ŧOٿSf"y2::?6WUMI?., Ȅ,?v&s,F8@5fLSO!d9 3#ڬzkigcU95 |0WҥS@f^Vt'\V [E9i-0b-s$~0p>ݡRFշۦOČsjhRw"qQ&GS_V A ƌ,yKRm9tָjn)JxF?EOztm6p8HL. %Z% BW2?}4x5So$ɟ ٮؗHh޲fmdsl8upuZ2$i:)%]Cm?Z\]\7Em5VOҶU #Z=Q!k<8ixSDm#sp}I3s'Xy}n< PE w5Fɢg1=kE[4hf`NV)ۣ,#+~ݹj0LO܍*PӴ I6`ӇZO%jU .asͪUH0o%F4Wo2?O&# qJ2/F>nЧkOhCɷ [Ahz7 rU?I hԍxzcM%D=|#܏a c0j|VRKu¿ axs.]oRDz ^>QLx6E )¿ioMB +Ik) }Ͳݫ4_BGqKwCժ ;\q0U0V"iטrXHqe|D2,q"fr@o!MWcSkdER {^Hwfy#_{v3h~2YgU ٧ #yVóf}ED|кT%&:&yP$^-ߝٳ.Yq$x,^L5??#$_KCCHٟ>Nniz3tYbi'jsEw.&+^szmc [ v<1qVp.n5&uI⌈yJ[Ksa]VKtF([bՙ.h֕ħ[Z<ϢPABq$_A(cߘ#-d$Od7Ă2|MWѱ6r6`2*tժ'h ܧ6H^vT0glZqNT^]9sЩ6{qOX:)\1 kl!7a G̢)zXqY4c< ʀWms5{ߘRhL9)R#΍[bD;o ұg\ӦD|u{!dXyC>+ϥZʞ[dmBY +Ƈ9( ,{Ve\[ɝ8x!yy}3UgSd4* 5H $P U'_ ;7B:-;LB544*!bS1L`~rRi[)CV5,5;3W͐\S'/ dD"}!T q+T 3ֻ>ˋSiV lΊcтe"7<+]Аy^S֑7EEZ gER cw% cI+1Ծշ]/Y)?7?GȽ];h6 o-G&~)^V> eeǭB-յ2YJf79H5›%ecBǭ9K%VYdeb?5 %;@s{g##UtE3ۮG:JUUd$kveۖ56|v"|\dIZ|I)*1{ʒ0ɢn{\_ϕX; !s@ΪK `|;rL!7{͎Ұ^5~$ߐVmy %M ?]6?Pߠ>m~p,?ݞ01UW1!3IEGk ۩ulGe?̰'~PG+ċhT ad%J~]2Z'd}Kjߍ0oR 0 '6/!])) ZvMjѽĒ Ęt59$m_^TmuRmG7";;q80ax6XRT;E+KLW髍W:PT+КKU/L6hx]-||9Mr={< } R77ztamrYȨ0qt5Ao.j_朏ll֮SlOwi,02oԤ{͵!-*wt9$9<_^̝n ,bd%j ~'tINXjKB.A݉-WPSP/PQ((k;w$ ~q'{kY;~H=9,3Koɿ0٥8}@P%k锕Km T7|+q1k,7&\+]bZז ?tl7vtZ@beMZ+"tVC5h\\>&i8%l;5>X0qÎx:s[v8xe6SOEӷum9F @5KB;WIތ'͇v4dr(K*Cl%C{%tt!z4"}4xS%̀,*#J5kERӐTn,έuђCCk j5nGMBz5])/ΊwB2HMZgh55X(w֍8~Ż;D7D>v\%,rt}F.wG,UlHG{ ļ9{#er@%Qz'Shy7HlO{ % ٻO"cmCFm3@DC䈗Z׉> \˅3O`pMhH8XN6GT2fPsERi>E@Li0l66j˦Ȋ %L5<$|Uk P e:_K+C.[Ojm'TՐlD-UJnP1RS F+EOL@䅴0]비k#] цc^}w uAE %aO6>e0y'j=NX=\Jo+X*$gu`wIg;i;n%/o˰Ca_\n䓋B!h=%>%Βt` h l.7 삎' ɉ9 gzR[`: 4fa/LEJtp#4}b91rVă%й5"Hނ4R\w3]FDߤ5٧yAwtFa^xNpNp5F΂[ @6%M=OdBE`RR*5bGSuviD{pq찶[cejHcGYKvB.5+m%r%OXx\@`(0.X_X~>l,}4"tyV iĩf4^@Ck>?}ɲ^_@eτUjZ۱"gW\ck8` VF# O!הA_+>x$ɖ4!0nz6 V ~0O `+† w'6Y VovQT$g0t]p>|Lb ZjATGƢσBvw*KHlAp,.jخ4)~팠xDg Rۛv,e^N^'X/f /ƮA[E<}lf-X^a5.A(H"կ]Ƭ{r/Y@_&&'~@0mjNq~]~:~~~a| t?i^<x z8eLza X*TI|G x7pE^]8߷٥cJ, pgȪd 3lH2{~y9}]|?} bCFJjU\VZχ4؟fla` {/<6=;(C!h?ſ?qH7_( m}KHJo9Z**I(Ph^`8\T 5CCX >^.$U.Pim,::GYfkW"#Lʀ?J~9CSa{=^űZŗMV1f4pg!x ɖVwaKY0@#|xY}&yؔ/s=֌Um,b)ԝ$ YyL|bA4Q!;y SIIn&>2U4N7qP>pB!VJ?.Tl60M,;pX#%NͲ;'_ 7r`g1yzEdS%Ť4IógΖ͋L6hZ(tr\}Obբ¦]j]Έ VFK=}[J~Z"rpW;n؁d5SE #&o i;1c o(xJ Ϝ*&Rcy~*t<~VPUmB#{GV`cclGS{r>>X\8xV~[OTh.ۄ$eaCJTbV_U&=_&}|uY[m;)SC^Y V6'޸m6?} 63, \dg$B-t^c?VȒg+{447b67݋d( ~h%7OiNbd5%`>k[rdf'grZǪύ 34׌h5ޒ\M/d buIWPYj6LXjj}a򱒛5ƽ+H+Đ X>.O ,q9[ ۰MpL3߰MzMf&݂g8p&@r՛@pT]e>XP7^IMeIO[/?ܖ[xWb%n`xC%[ړS MJUY;{m8fR|XHiGmɏSrJn fd2t;m:1n[Kꮒ% {N\:TyAZCH}ha^[.tqܥ}rvuGs(T "W?]c~344~ђe"h*hnb);挦&<޸Gt[&ejz]_y[0ÛQ׬M5G,&nhhcfx{4zhvH;W`Yd'!Gj84TtU5Qd񼥜(Rx~;=bäMnqEB7S+&C;pqG3ui.2żn0[%霂L7qe =azF?BV8B4fޗ5.OJL+"'o\dl/="ut쳋2lÔϔ=k3xw@/<,ꑰʛ WҌ =,Gr"J| b'/в{#ej>}zyxBi1[y\P@%7af롐|E T" l]w8 2ޓ:<}ڑ382./YLJia9N(x\:qsqw*]Oiټ2ܾgkZyf{@z9OFE7]d^qy+7uVx$W $J Ɇkur\1$I zJG2= 7e;^Бz|w|b$LO}BDLwAuQGө,OQq%к11Vں GJp7ݾyt0Oi9 }i6O B>>p93Tٞӎr6';M<~3SUneMC sv4X#]5tuG8i/P>G Np86MyH)iёvۂvȼl녘;mwԋasaW2C%*72 [g=>p _Pk`I^N!3zb%)mS &b؈wjKt695܌`5CU~w~]}3=^h=1Mdc_5n#Yf/a8/eNqn]pJ'w5%-tՐOʌmQ%.wNgo8acuƒThlN@Ōޜ/r3at~o@GፅgG;4On_ 1*m(,qBmL>ȚNzӡ|ߗ$4Oeui)O%y}D/iy!}3;42%867ĸ#u j)w2EC;"C-jN֤˝z"RTˢ?/nQ{&32v/ Q[e8xy!qZD FÝܳC߈GAiK=w+mfy7!# CҟVf!6nsV}*X)tq]x:wA%K/Yx'$T)UgE0%._>0  P27jGk]fKRj[%6z䵔q?ven(ZJ-ۈsĒ y|}{ڡ˱R#KWnWAXwPtrA GYQ D%}ֹ2O,Q>nvsQOpsQJZט_YVmfښ8nnpY9Õs|8SЂ8͊Z*eC-d?uQ= cˆԘsT9+w]sP:lg+Yds|%SڎMOm9ꆒo<>{y9'=Sikim[" 6߉m\21 \47 %x[ tq-׈BjO$6 <ʤ:דU(w"ʤ zᦠ]Ewsc#/Nnl169f9ͼwaL1`;pޝξ1)q^m݆N |J lA>! \F.j%PoR]W˄4uy;ze'Gx؏tu ]M>w1i,L" 6g?2`4V{W#n1u/xJPV[[l9, =Ύ;P>MoYJ^ēU_ve>k^z\-)_(Jhc2 Khm|EYQ(L)IF~C~2*eG3>},ix'0}Z`[x"0(({oF[ Vh"hz!8Q}<j,3:r=|Ly{WF6 ި(WԷ a+2ɿ8߇Թ 9$FCzjzs$$’QuJ]Nz{O Ppko:XUIU7>Xwn`۷ ("5õe~hu]|I{Ve Raf5QL,g]&c07xZ 뗟w:}CoG Վ/O}y6=WǬ#klk1}IIZ($zVNw3i/Z|-l}Hv،;דE E %>*f.8.#IJ6(jl> 4|zxڢp-W;p"sv?/yVL斥,346[Z)YV("$\􊢈ljghF?V/Lv9*~L-! /r}xB<ڢxY-I5;yW4P_OLYZ>5L-@Adzƻ甊\3dmM6tf>9OPn}q'3n7fɩcHpyɹ?OWtʪKW!1מ?def5,).YNBVs>-i-1Ѻ7vfcsM^ iv> #3>qYCyWu~dHq7j9<57- =R˽tMͥO[qƐa|mby9)ΩGz-al`LzŐyEUL*tK8/ H{ YᦻviųEY{xAܝ;P[X2u?E\ngη7]'Y.,Jgx|*.NeydfCacɥsډhuTH}Sc'A|27lGzhH[;̳=oBSuFz e܊[ThD`' z~TvD>[okqѲ2Ǚ,aooH[W3vhP}&S}>)fO=-җbK{={G߁լ3ߪJ-uM,.k Y䣬=]NKYݢ%|DɾW7nˆʨrSmlo[_ߞt.lRi\zOC'?mڻNԶ zZf)| jY$wN44 {Jot2Ž6xG]ؙb1kL{xHˆݛWKm7/#ZUS &z3\)SH95fY`$#{%.X$ҫbNwLC^iIvA^$=Ģ)z*U/ I(0v ]knosoN9<'@y*m: 8{z t_֥L\Pc!w%/[g&մptmś<ԀnS3jZ?obҟMa{+U/Ey*9 wn}Oh`C,;R$|-6)wZޓ3*Xs8=htL  ף48gPޮlHN2'i2-{wQ/* %voK c/ۦa_Z:{=cӓ"iQP _uDU+9K ׋N*M;XfGeB-yZzT[]#R)sr-uHN9xC|./DwFG :0H[[=>q G+өsiI2F(0| ,W& zs!}Ek6PX. .1۪9-ͼA!ÏnH6%l䭇M&wz3h/+6\vn"ml HcWi$wӪoP9܎㼊ĵ]*)Deܣ52)wpc s~,}xcKc&&=/ŮkOzSXv7o6M|:BU^ŌF)meDdt{2A0(*l$YMb8æYu[cŽwh売+9M9Nѓ" cU9@[I7B[j쉻o͛oL/T*!KBzD%n lW[籹8YiŽ,c)%p&n;R{~OLsT%(\e54ښKrXO9m߳!YQ.5&kFױbì-Mʏߦ?taPnstm'wYmTc[X sx`XTo9kJz!EEHP}}ݙ릛 $] =U6.țޭ*scWZvTBeIi)6n`Jmϰ2xЕ 1RN~qeϘ&n=lkMtũ̅g-UިKws?[9t{gCsB0M6JĹט ?뺔f׳[.&!ꑾ5JBaӃ}?g5nNuj1+hSPW^>dži*'|=BrO+xna%vV)gY5](#􋿟;(VpƉQ:ܑd$e<+Jvp nbgLhձ5JgާVI'#mgk4_~IbEqե g[5%eKn*lʿ RM9weɂf@9!,F5+5CUOZϣ=Bp{ll^UטQ1ָ1&`H)V2S gwZm`}p[e( tQ轜 Q<9-[> w##$gtEn'=QvMp S`s/y|S":&T7fPǥ]95^6IOEtK$9SS ÕRD%G {M(4DD}pt2*s[INOSI}??x aIDɜqfڃW&?Xjv8**>#d/M\I`$6S\LJRVo 'uaX, iAP ƿHKɉˊҭGPs*FPYGP㨚ơq0$f|~@X(Ԁ}>lEF؃PKIDȯl(<@`,g4jb,$~/ I|hy3O 0~ 2KxaA?\.?+f ?:? BX@㿄 0 ~!~-S[SQ~D\ "37(??P 5P'objb5@8)œÂh0ca{L$l+D1y\UI刪 ♣X3f{< L">a)_)y^ ,"zg%N;=!q-iكbhWE cCBP@e[#~V`P')a8~l36+b Cf Cp0B@P %,ɯZ+K_YӋ 3s!`<; ȣ>wT Cc :6Y[Q8$`ַ?'%s]M @8O c EbvP4rW]믐+*No[!Ѐm/W5mqHq@AX30hFOC~Z;IkXkXbsI`=*E'ck k1Jph 0b>.qV%Z;'Pc$̍?}{2k5Z]c fE3C`>oB&s?`H,FƑPWF[p%!q2h p c~v EAApap+QJU( Ws6') ~ǂ(A xEg q"G`N__':o]!-a+D5q3}k,EbWvK#9}bB#@ ̟%0Szѿ|&&|k} gujM5=sЭ5\~` Yˈ &!E0/lBgOJB``5hwwX-dY ܝ,@1`xX3~tGQhl õjh)ީ,׷fp?o}A5rj CB#|bywp[  rDV͆~?"pNH+Y;1o);n!`Yڦ=?#[Fїp)?1 AV^of F"p|蟹'`UzƢ`;k>|@x0ѡ?NtX~b #Lt?,7'g&:7gs [|o?.lc 0߽SuD]][nts5 q0ߪ0va^aRu8 p?Pz3M8, +=u~Z#k0fJs02^$p#z;W5_ b(Bv@eֈ YYMVmo5xP"`hzϐkܭ@P0/606pHM"!ʔ@UC-,V@6`4~aADl" fS21Tpߞ Az+Dy*W9 $FfC}'S _[X-1Њȯs}Y݋"G'%f}<zW-A3B3a;[Or-4 ?RF0s@DxM/@WVPw?^'@r-Z~q?@kû_4T",Q8   V`k | /P c,A⫙x* _@`.{l߿P 6t`1=&;cDX [0[B ދO8FZlaIOh~~g@VD &9h%$OTL$.b x34CeAH 'MD!RhZ^ Q1+d"h*  C@0$=HgFhof'{f)a|A7?NHhdb-#XSC=r[#{0~ t+DᧇH+͉ 7 D77'?((xO@X`mJ](?HjQ_ 110Ըu_c>y!w ǫ_a C2z` QJ~ p꣡߿uݵ3qE%G#"%N 2CPuם n>1bb'(?dubt6?q u hf 56cXj9Q_x%f}13QV\Q8S=>B iA"QU=ζ>V&"X<^#v zZRCsc 3g_5jbg-eE~?@ZW({є-H 6j_f NQ2WYoAw %Zyغ8 T`*,*~h4P9Yk}p@@hqրZ$ -y*$!1(? Wb$)$lf ,Q 2{(Bf rBelh{ TP0Ĥ9 5FS` P2 7  ȿPfԉ4ݐ́uOҸ% mXQK GP`!h<(4bH:5UD0ְuN(WDƇ) z5)Z@bݵ<. ͂䝦P@jiP.H4ed@j8f) 93Zjwҽ=\jlTkO]~ s=@u* eU_S௮ŏ׿ſ z( ߋNȓv+w%`(O/o'M4$F$۔4+8^~Rh !zbX:D"Q #inQ zz WDw.:W]{n0-"mo`ީz|nFd'yJn7~h*]?5'j`t- wPRUUq[Aî {;OvkxϣtK>IUv0h0 Z9~{q9Ok+IXz?3qʲHLHE-O^\`u 3o,W137Zָvq_"+Sfbp,2yiia훐=!$нO/wVax 8&Xahh_$䳉Zv 2x.9f^>>^vn^vNνWTQ= B7{GN.n~n)17 /7/';7c.@n.c#>1/ ؄Ԉ[>=v@o-;.⡼{4rl_YKӆ{ 'i~V׸D#\f簾ekq4jTܽp1Ei+z(dx{).nlK'TnJՍT%C]L+9zQ0P XjoPiX큜'>dt[Z kȥKY~6C h$1X5X3uK(r\Y hۡ'n~tLp}a斮vxPMe^H_cH|y 1|(lϊQǩ/r=.A乺₵FkrFJ j묔 V׫-*XM[_IJzJ{lec|ZNӜzr^6<)/Rs"ekT8"usqzLT{smZMp1.ŨP?Ac!yR"-v3T]en;9B:J}dn] ;8qՠ"c?A /4 e2kC\wGN/>3%Ċ12W{=.oTX3I:QCWN̲\'obb ۰n\Q\]-G~n>UjA}`?]8/30 ĀS5Bnkɪ2v2m@#t"q\Yu Y m<{F֗CvD (]}/v=y2T*n u^^v! )!GKEJ55Wb"L7ۜx:G\_p|—t"8B7DIpWRBE]ʟh^⻷P鷦|tG꺘kniXEQ^9DBnW'_IѩO=R+\[ 5D?mؾUjZʆ\[ |]i1ؐwIgzk'G"7T)w|ev:VQ}#^u* .G0m,%ِR ϰ'.Iox5vSЫK5q0]`JHK:f*7q!M϶'K- jJa[jHkEy 29ےFC1ԹU-'3GYњ$vOP OL6]h \[cwӸ|SY`(T)_~<51ˡ6f845o$h?#.~#3X,%P6 xϒE|w䄜dO˜ 2Jx@ FoCڔVH}} 0NG1[J%: E"y{͞ޢquWPbK+oEW6t6dzt7t24Q/͚;B8γIb.篴q\7em)yVR'(y1"ig"V"TvB ]Hm^{MN +T[]Az(:kJ`DNީj-Òw>_~E.Uh3'@o D-FI#&y j5[t QCRܸ 2A+~Qs, C(.ߤm ($,K- \Mg{!:S}8%oDV(VE"N\IUZS:UN-tc=37˨.r4Vb,3: Zsޛ~g>TX )]EmXQFӲ&׏TR.5 [ .j7) +xfNNUU6Nb #ΝU)jf=VޟMXu?xg56k5īREfG@ԃHG[;(0$zkAP.AK 5Ps bVߵb@gDŽg=/!nn9xHROLSĄjEKoE+kQo'&6vL_'i@fis%Pы`>>f)kSzBs'{ʴ*δEh JZ8e./X$WF\ޏL>s}o {obl,[lm`/^ڻ9}`RtZ19y}#a0w@eUi{7,U&ʂR浳өPK]\F/2 7o'eac&)ݭ? [/Ԣ ,x(u|3EǟaBk6tѾ;OFQ`ЎY~aJHMoӛ PCmQ|14IfV)ߋʹu6SR}^J!|L6%g=*eic'Xs1KF._= L/qR.Џ%{aA-E@U1\Gk(j%6 Ѵg4֥/V eL3]k(ϭ<3kB+A(E~fTUǑ\L7R"`Y(!P.U]`4<}"$`{,c=M[K'7Z$osQiE/N)T狵Q֚uS$Ҍ>鞂g`IZDL >8- S[bK`fN(@@iГY#9Q[޴p9#Vh!a;_DقbكwZig E1f KoPC%P|NeO;6epLڞOu="kZ+'Vpjd-,?+RqQEg5) !77R]TsBV6Xn0+/ٱӟؓPZ-L:Os9nB;B5׮S& YT\D[Qo`3l+x2+Д%T/]R~kbh.z}{a d\Yc ;8zc|ڗk7lȍt-9(fucUA9P+CmfZ>=)Nr ކK⋶^21k8nL&3MC983#.*ȷY\(#.<2˖xɋ8u'"FD֝%=?|{Irbb񲑸qW]*P7z`4eӨb]z~ V\ۻMcϩ0:w?QAq}"e'H&KJ\v[|fcx疠]m dͩ7:-[E>2WRߔABK:<_M$v1'9*IStuII-8Ɛұ e434(L h(b:6W8I?U$M% lq -O` Ou_[UlwI\<`yGb,UTK~S7x^Fӳio4jW' F$[1=pÊ zl dRK Skv%~7wPY XFBλh{c qA&0"1R>->fԧ!QɮץiXg$5ϙ@:'sc&lm EwEdT݃X={bޝVf otdi'/}7ѳ UjѻbӨJed0')] qRc YwCQqT̏kÞkO JUj!N횟-Mtʁ(|F9[EpG0L"K 7/4z7[2gҠ62Syx"UkX )-k&[W|+h bE߄ۤusj[㷝O*{儧8h[+X1}i&yxm,p돭.b7|H;?*xb_QGP4V?={+[itkjM 4P 3S.~uqjdv|Ͻ,8i8O%MyVԚE-_I.F˫DӝR(Y$>D}YԪƜq%JmboZ>eWDe4SSgصJ;`ץp/Z, 6M/_2N/}bY_|QUK庇,XM k voG[kAbHw(M88fw}OP|CiTl9(ě?^wKYm jID8_Gp֬NMITj29bHI 55]t&qP5Y'9CNq,X%?;~ӗ/=YKU4ըSjpԣg>يG+0H 4̧ 1[e\4)}W:bD;7P: J>[gCLM7uw-IlQ}'x>2;\Nnxzڔʼ79SgmoBbAHbu>f:{Ϝ7lK7-n98ŷ.6+`EЮMmE(l+EP-*0Ԝq,?)]Iu/W.Mޔ p,Nu=To;*N}i^YQ6JRЪ~ oqp\c-5]:dv۬l͹|we۰;:\=q.GF 3i?xͭ%dEA\)&N4Ƭwo h?ee[?eQ=..iRZ"%z#iC݇=/d)یY p^ 0Sh:z[//%5eAl;~v=]xvHV>',{ƫngC>TtA@[8=(&Z-u=|UPB4)^q,1L 3}g_? mPL(1t}G|QiNELhTWo{6'ZbH.C5&L}v||_g:[֧kIn}ډ [9uk}ڤס:S笋J Ucy *gǪ\UT|),,tJ2H3](C@#|PVW=I܂?Eaͫuפc:mYx3 VEW*Z2N Pxc(YvRl; jˍ^<}qiA~\{[64{@{F S26-TN zIf.nrFS˗I9RIXσU !~Z0约hE 潵5: ywETADO "8ZxK{0\<;TQEɥIb& :QWŔΧnƹV'3]\~֕~i'l))1ZDܓ^۸ǧF@Mk̭ܨsD6g/^oT飝FY')&.ǭŕFm΂Q0"I&&О6C 2y"2T%t,Ys'ګVz[6Mt)#\Hn`sf6Z;'}&2Q9)Ҽ2n;p3:1њ L"aCˋ/:ԡt1_KJ^=ĒJ^yJ,!((sMUy(VQH9r.Kꠠ'(o>OL,Eתu@}pMWu~BsJċwhS/jP^ ہ 1R.wLq"Q,nˬ:X^}^m7ez0 5eNuXb'R2,&i|v܇!e%L4bjbs`af^%@MI֡*X$H&$ؿ0Ulɽ0jg,-Iۻ9Y|WV7EoR.}Ee3-]n]gCcv3:kL٬N`x_jQ^D4dQu 厳R*5śY;)9>j;C/7Tk/ K}Tv*BBbU3Df`s$_+mhuߊ8xE7!ļ7ArT&D $B.ׄu LsX7 6aE ygh8C&tmˆWU~K 6ҕS!!B/su0ǧV06nm@6|kl:``\]Oz#< QVG`Ԭgh ܓ`~E- tgݺAF],w҅x}6c3s>*PQ]̈ini\|p#R4<@`t"TLuwG&]$lcm /'?dӝC9#EwʚL sޒy~,(Ec J g5wM-nZw?%L&7,x٣VGT˚5B[i7I$ndL 7ʩg o?`&/i@vCv Vs䋉DW1T 6n!O!q@v 9f5@A _C/0[jD-Hi^\~o}U[G\'EL0+-'&ǏHޟ: DN܏t#BzGt"G{:GrPɏCk=Oo#ojGduݫ%u{Yj>(OߐM7~ED*R◯H~}( C!`=CA`P`"E;EDbq!r}a0нqCLGE&YaGt0c;l젎G3a3r_?ERl?7H?x`.?TqG-h7q:OأZܯȖA{*UG d_Z¡"Xv0=Kf @47aQ313%rm㯕?6PQm0/¦qW Aa_!Sky؛@jㄨ-+9`;"(5۞p[]  1ܾ")c#Yqq6EPXljrFk@x釸yH؇KBܽs>P]LzCݏjYP;0??={~~A|?2?KG}^RZѿQFNudFhspFuDPwx}FduHCWaN'4'7´_ bxT 5 Xa?F9<h3Z! ܓnl7;!Aqaoz}oorO~G{_C_CB~ 1Ce]Ɋ`W`+MNPfۛ"۽T `iyS7wj ^·$ cf` v[V6H~vo Z!c,#R;́j /#+ ͷt{Hǂn-,{[ѿŞn`ɘf̿.g߷.~o;Ab{+hoLbu{M+{K܎z@ 9io]0D`_C`H Qpz-p~ԫ_#~+J';#p%6)j=8xA%="z+0e6,PDNIo5^032``[89fv_Ι G͞0Ęb5?ixE {(#IM 23lv{ 3$ @_ D.B#9+_Brv R*Wk V`D[~)d~- OFD~:"tsp0Gf'"s<{k 9̋b hCJ8p#;\7S@`SFxL/au; 7JB4Ew(?XG,jY@6{y? hyMa [Bm(p; pI YPwujF^El'/ `/T ȿYubet MG^[A^$lčl[3#V-@dBt ]?4L &@8!FQ(rrh&ё?A (@ Ad6|ۦ?R0G ;ȋxWYA(BKo<8d + hO4D#D_k a~jO$;wmL|5"E<;5P_@vx}9,O G4|) ǓdNgA.Ma{>xV]);jW˧;,j|ZOS_?ojIGHbamXo,avH18dןsf(_Ubn؈>S4EV8@? )W똙v:YFՆBtXq'NO2IxËdv!"spӝc|!=>mu1E=˘&"v/iD]^hal5uL5HB n1@2m6h1{"sOXYV'Bܠt-4*Bi'يb$sq DfPzva}Gqo3a̻4CJȌ1*+VPQZY>HOx͂䢊 G̼?5?)[XP5BQbDزADaQ"#~[~ͯ&&.(%wyzdZbzߎq. JԠ\"G[@7"[%*^rY8-nSq$CkE(: dgTk4Z՟b+'5p;{>m_Ő$;IMvRxrI;oHcnl3޿S( BP( BP( BP( BP( B w]Z x ՀrH92_ En$V"乜G1U yx9^XT Rҝ"!!5t#]҂t03t( J E HH"Kx7{(g^k֮u bKx)"%!ϭKT\D\ KDLRJJJRXRX KXDDbokB!@8E?ZZ.[ 3ag%:>q 59ɰdֆs}X$[QIiúG5lDwUKIϳk63MtNA@9 1D檰(h߹3XzoT?xM&v,UAO̧$ F6t t!s5iDz>N@ͬļk6*У>4IoH.1]M nuPY)A iU{;LGYTv<1^~(JTƙMlq:F^ nnl. t(Kd pP |zMf. ڛe jʃ$Ob–?LxA^wVj]Ph_zxAlEUXw*I}lAa~ܔ#KZ%EgKrW<5.i{g\/TXA=Öϣ浠S'%N'Po_ǧRn½GF} 0>8&6w(êG1 KzXGĭ˥VǫZ*幱*1]Ip)c19u?׮ilaXڱQʓӜX.z6D, lwuԁn01UL֜('rCﺛǦIZ/CXң{WYvk`5nZvsz>63zmE,sy/m[r;7C=.l&ԗ^ޤSq fsrԥ86r`zґXq ":lrL5w:6 K=L8%PIBY1YsIOE>v bZ4EigDbs}\j)sĚ! eg"$#>Qaq'j XN~ŚqLk٢Ou59: fb("xyeߍ>UwjhwX mIWe'!=:x]ڰc&Ϗөt.qznx`Zŗn ])mO M/Ԧ)8ǿ:gS|)-G{x?؅h~`CfA a#l}Zty6yBli6:jNV9ys$xn~4OP-?H?;"[<1_XubcaI)VՊbf4TzQH ֔U*ݏ!XQ Η¸ѫ؉7 nt_%0#[30JZ;?*؜( 6eSE9wC鱝(sSnn8ov Q(QhRn5'P˟a]埵;0xy %򽃷ga/das&O`dEK˕nXZq62nKfAC(o.fȰG.ON_ ZNHW]'CF((<2vc 4gЇDОsɃZexNOHvd>(x3PO!7b3ee]!t9Wl 6Xbr%|˝'m{U@FjrUj"Qޝbbjn7J~rҺE=uX@a őuWZ,?BRש(tG]+ld7ϑ?Z:}я])^;bJ 9YR7j'Qwy|ő&LLrן -]jE9Nrv4H`E)r#,+A",r'Z>4yՑ4Tx]7Dx#$rg+?* zMDi>~"鎵Q "FVP Ǚ \n NTDu7. >NI9;=^+I'eBX nv _MlI@>2|yWj2c4%xUMpSms) Q%$s=+(ogd3xjBұE)V^fb!Ӏ9" I!ZpY*2\1wiOy3kxX/R}H5d Kϸ8L&!ewJN5VAb/butƍ:wTomKdSf2Ζ5=sZQ!"]qrBGBcm45XSse*2$Y[A5 R)n\PSO [^{xll퀯蝃xo΋g_}R2~:n;3t8a\SeZ. 8ΤM uef%9^a_N68{]isB{MCgrzOB3řNas\Mn)eTql@T:waecқtc>^  #P_ѸrXb2+Yb ?2Ru`B_cCr;ўfA52**Ϫ|Bp(*6gKDQ'qS/ 'H/h ߓH :j9Hay;Ӳӡ/.< hPu=|%ӮlPl&kMBb2,:gհ<CnYs[uTH]Jrk98?#'EoUsuDpRvn9jL1P0Unme:R79ep9lB6`*c.oYdqc+%Xl圣fG"ș e1TK5_[L NuNLZ"EfȃD^B{kDw~)E=\K=@aYڮp ~Df[c +*5FCPHoFߣUyƯ.Jw~ŠZ\O™P4ŵqkSq=}?= yFAl-ҬYkŒ7F옯I7߮ slrPG]`}^Api bmݸJ!VͰwhzæ1pE,ZR~GMϞ ˽5cJ͜#9.3O@NNT^MiZLSAwU RzܙG~ڽa?RY|JIlY$صMg!fuUTإT+BT,k\Ƌ -5Ȍ|*GC]7_uArg^VMb7ґWdCrt ;n@@U6%6}3!yՔ湆g  #8^%E(_뛝T>}$rB'J#miV0๿j3'̻`7p/^']c.^2HhLZ>}7כ2۱8uODVjXRᬋ8طYsf+e-8:K>>iN{ Kjf^zo i231ST7V,C.CTo-+9@_c3o˖`)DL -HVRV[4U Xy]Osh;/09+3н|$ Ҝisu:Vl4VWpPDmC$ilD'ɮ>g^5Z2=tI^b ࣏Vۗ8Ä\Yy|(I4bV7~KΙ|ZT[@`t K̫pQ+Oݳ:+NG}q~FF~`;=x=h1eJV,_c1~Ǐ: W޵5U 5 ~x,5Ni`Jc3<11>of.r^59}B ٯ0 U#Fy)&yRHy}Eu(i>qA/ξ?r\i|jFs 77hp#!ޅ 9xy0  ˑ^o>^Ҹ4ҋ$.Df[..K d_RqF13yߙ.;ʎY% pt'BVl7K>&?oV0dy*`.QH7ങj>d^aFCgCºGm_>3RAz1|jKoaocOp.kUtZHUޔ2p!Kʎ+/ $zZ09.\nzf[-&$=ijHNlo\O$4_Z;a'6!=]Pv_]MJhee<)a(lm:fIbP!P& 2W]#uv,.Xko2t̫#!?&Junvq.?iʲU a(NJ,7|}w; bb ̨efS9FYJڪ՝ XA:(NৡKţ|CgϬ3S*x].Kk/MУpԓ>{vs(6۪xRx7AG9* ޓ3kAz8Xq!{L-=IJPoIGbSY gf}|XbP$[)'RQ^,K:N/[4ۗSnb\lzλv}3$k TpE~jTW6jދWŢhҫ:uX$Mc Ƚc4>2"VN{xQtHr\꾑OܬFNC8mJ !Kt8iW  :_9IsbHQ Qè`wC)LG玨`Ui[|s*r qHNxB=lsrՄ;'CWOך.}KzZ{])]C $$듢K+Uسoٞw ZlCP2*6,n{"㶨c\9,ŏ+Z#ŰV trJFNU,َ tkf];du 1O?m{+kqZiF>%3$`CaywgE׼DZևrf8SO[K9Fi9Q{x?u,Bw}̟Ǫ{qM% 紆67/&^lw! y>QrΙa!2\fqڗכ,zhFz_jsV\5(6W/ ;ʻ?+`KW=hI_z?E8 dX:;ǔd6J he%( ]Wn%X~ RֱiVly&%~5!t\@E +O0}o)JLûcb84"░^Jc<>풽 >/S7?yT:vpYl >on3k>igs/\^md 1JE6DC,n,L o}~ה= &_f\|QW[Wri僳Z&>R&)=ՈklQCFPUcuӡ }NyA\^jSC3 dKCkY(E%7>v"sṮzB3~Q]ճlzidX`nxŮ^c,S_ Q*E6UM妘V-[TGՌZ*,%ؑ}@?ːyYFθ ŦƏE7s[mE愤[,q![KkC黗,߽ԟWyo:4ΩRC+'It4Rb>x +uRY1lیR( z~Äu$]/\; 2c#U%A^t`GӺl\Ϗ:>#o2)?-dWx}ɦ,( ?${'Qhl%\l{z. %c#k)QN.B]$\* g x5$X򬫳>!%1E\˫"f *էaR9\O鎱J֙8?&Ju !D+j= uA.Nid6ˆGHF'D$xg.w?6E*zvvb ul;%(-w~خ-ɞXɝ #/ U8ՙ]oG{]L6;ugBZ_&~r5?(TckRpfMZU'n/*JpF<E\"N,^<3%:'eǴ[$*x.Q9N2}x.4c";^RȞJߙlx7"f+3ĸr,M=*Z1LVąr:O4r[uZ)\i]} LP*7C/ǎ9s!Pnv{Pu͠6Y?>9?1\uFN=6/sG8nw9m_k$2C[G[ePF5:fDfB?(+YX M憧3 _ݼY |PAޱ(HՕ6h0*vYElaP0ʞtsC\ac=I)Pi0*Ɉ TY|*vu3a+EuGg/yYXZ*9kLUsًOTxcJz@KwG$hҫ^]hs{ i$WhnK͈u [جXo?5srYhg[q',j9o&<T֜h`u{}J1m}VK(y:`Hش2Qrn}j^P"=[77a4(:aS}Ź* U@ZHەa;+R~o=+=$iԃQWƹOyJXbKHVRuK#=E ha_^>p'[_aa}+*"&_bԫOX83[yFZ R%.Eq:{h"&D]!1x8yB@y[I@+ z.s 0T]%n<řkP}VsO7gY,Ln$Bضޕ]N|\͛Ҹ5:5]?b}xΑ|gbdŲ& ݱdž2U {PW OS己|SyeӋOI>ЗɎÄ96{%:I5,T,]cm.>UCZe֘LđO]>1 nܹ ,wԴks"VקwNSg/[u6eBE%$(o_DXO/%/.Ii:;IKJ8;9I@g)V߈8K;Ȉ ;"2 0,IZ7àaa??s/'w_D\RB w/",.5a F $ uA  )",(*,"!SBD gHwU Yhk j(0/ [zZrA8> :b C|p+ h @.qw8BbHiA(  ,/y10VɽvC2{ 30,V!=ګ|})~=="!A'0G#v 1Ӵ=#vOh?`Nf\M~} uA 0'hWmw/B寰[-> *e0 Qm"ћn1!ԕ<@ "aPg˖o`001lhy۱0hQm3A cAݲ;¶: uU]g tDѩQp=ݶwnk v.i0Շ?%W"Qm\0| p '+swi "wvDc>+@ˢ>TրĀ`t&ttwPP=ohoX_o# w'$E<GpzO8w{ mZFnh?s5zas;FjG j @8kZ}OؽZϱMk*UGa_RîY(8ߣ|.|h{:۝{o}k('W-ibUڹ(!$zjm1wn$Dz+lx(_4􄠹`[ %8{]m{)j;1b߷Bߒwǿ>GioJY+' `:u0G뻜3[tvyg;h ݣ]g0?F}vBD$=MIߊ'IeРA@N`  oh7o6\aH pw=vXpzn ܒtDm͎qPwٍǷ: ?M8a˨|*_>]~> |L ۷`bg)FV4C߃o`W vP;ݶ5E?ۭW'pgiyߩz5Я-#f }Vq' p;i֜H8c9x[/;PV ң+vFA='em9c:Ʊ ﭅%`~+3F3دsfmp{C=Qbu+ܝofn{=G#G 4.:]/Wd]7((zk lq{}Ky_ypٟnݮtzxl;<Tt_-s@w$Ӷ;{͗-~.g'XLtϼ$Gcܕnw![j#cn5 5n$t1e·f.]?lc { |+oZ~y'V/% "hN$a3< _P_0_?>9WYڔuĘC[鎹/ߴ]^2E׾6lY;`ƽ!_h'HpTa}*RҨdJ3&btpr$q_=M^5`L:<~lW)UPX?^󧚰~J\a,":MEEE0ڠ0Ze/Q{Y4f_ۨ/5zx_e.T5y*q䛃e ǙsL}F߰S'5]yqGWxySt*~ƹg31[Z=-k2{>}8zMzIbXqqs7~qv:sUe=ۗ/w+,e?Űkۺ5}aȑl\ݜP鷱-aE Sķ =XTh=rTT<ٽw]lwWGe{9sʷTLef>om ,;'м+)egv_^Q|V'2Lxl c6n_;+55QeeZ==1p+zmaH€3?ۨ3UJMXdg#"88` βidz R\PjJP+U*2*Ow̸ a쨤1 #FhpFd|䳊1s9:tfa40g!MHѫ8CIiDǣJи"F ~ =-<%("tb*U5 `Np@#Vv ]q]> ;B:~}zYl@v9<і Q`9KhM2`!3])9ȚVJYp X84`j;TY,xNr-Dz< Y# x}zfn q1/S8/(Q0~CQ &b߇K S< У>&Iե Yx%V Ez* T6 si-8PB)lg49 Hh5WlJjDȬ_!$ :Bz ]G=8N2X&Nm4e]Z5!k\tiԸ8jj(:yf@b4hdWMN(QҪo$ qaQs }u" q:[bX:f(0b%!)FM@87v9D ȬA}Cv FI<$gepb ?gXd-Gae!&Vn!Hɠ Y?qg8 f$s"qPwx=tzG'5l ɠs+PFa}JWZA h@t,kc NuM#eb 8_T,C~~@҇`k4Cp ix釨DLf4nhb] SLSc36 | $n(,1&XIW7zr]:Aft*@v Ɔ~ P *dl҉EXRI2]1'gDZKaQ'lrQ,>IJUJ a N<РWA$dp*kf@(8Kc,(4y`ED{B$IS#T ?깿LQh0 ,LaĬLcV\n2x,a- D`kf=`+Dkթ5h< ř.%A۝H~Zv[KF.֪I{Y.< &MA⬉⧇$Jl~hn@ 7)E`@ 2 IV8ݬ{ MRfc5dPw5(qnjr S=G4(c !Y43>/Cw p~-MNװ2zNuY^5 a\nWCmxkm V U@'1+"j\$:!-8nu>}N/n8Q!=R|ǟQ-k}X:f|7θ<83:sђv A*^QFc<柡̅Kp 02!#H 7ʑqi>Cl _9$DV8a5|}} `6[Uy80!0&/_=JSQ_oq,eI(-{%G5aN8 z ebFkQR~1X *¬ T6ʀP1@tؠL~hO ܒ Bc$#=H $-gjH@F0"@NF2S@@^XM F`,Ԁwؑ 0$b Tv@~ٌE: '3bc I ԨK@J: >qЃ9 ƄR'Xc De란Ҹ HF5@Oec,d,:p4 ĤQCǥ(3Re N8Єhh; s-? 4 ƀNJy( uoF@4q dV 5O?:)G3@hj6 gbJzo4~G p|xYZN_łu߷Ed }Wx&NEyN2 O Gaj){td*FTE+]?Z Sɔ*J. V+qIˤR}7=C[Xmp3U!%uhAQBCi\GW]|{CM5뻴k+r,IˣT+i$Њ?$#?z8YwT^r cz3oޟ:7yjʝ& _** <(fu^| (Kcqg4j3Bbpz;tyҷ-{}ݝaS_7;i=>˜1)S^~+wRЬm-wO[bknl.ȋ>A35cg(㲏8Ú{`%C*չ/ 8q2gWt}*rwaCE;jRϾaLw^qOק0hcc=gYvɗe-qqvƦ Ku=zّFs׾Лy :r#۵]QVO˙=Mvwl 2[0,7(&鶽z:6>Ҿp}@&ߐ\W.TT:#>Ywņi}y;*[)dz-l !ͻ_c~kxyVomfBN?.&}v$dAzNLPLμҖ'/|62h ziŁD}nc[i'+ZKyK϶1]+Zd^ߘo4;<ኬ遦_ܽdżOS&u:ژPk+<$5kl3Esx۵f&sgo[zP3 j*a>٥'?Xri뱒g˖t]WYqTi-k,e빺! |w7B7hqT`bٯKp|W'_Z:7D0SZϽzl~؈+{[;pLoS N=m]6! WVlI;ɢ7F >ĸo2z]7'Gl²aҺ/AKCu[lx=6 q:GgM#]>\ &%t=s6Mz~$-So}9}ߙeI~eySp]sM߹%Do|fz^r1g1=6Ք[7^z V0xJerGGZSң?9Ŭ5Dwv*dNQK|$[uz=o?ߎ)McOZ/,V N]ݰjƋ.l1-ls JbnKOG}i[:.GMؒkt]ON8s1%=.ܱK['G}QZ>? _`c9ؾMmu27.L6~&drmӧt_;ɯjv-pm&۶&۶dMl۶ytu"@s[]6 Y|eB!1/{܁rSԀ_=!FT憭L(vDp&& i kMNtFqJU ,#:SdJEFNt^j=H mIW4355X4StYjwuNP69WS0̇g#z Y(Nʨp84> %N29@ OeelʋV6,*{e зh `lj10wg ڪ ؒ Z9htΩ?7+:}Be +K4t؅` mPn7?rvHM책_ uHzߩ IaB~Q&f8Ll< TŨ[C#M9i7py~] qy'Q)KH%=C{SrQ7ͳQ籽Y𩥔𔤔ON$x3&_zPS)d*ڿAZO3i=;U͟adRYcưdMHAJ}/ow) +doLDטkKf;6d@ QA}<J66gl@-1(ʡE wN["\}1{hS#ab5" .X7w98$]"E xC, lOg*9)Ne/!B`Y 9M iEB[SPj3ƮǶ5&us!Y>X/ 0:tk"g)9C~Rt r>g=L(!=v !Z΄#Q\C LrYת栶DPDDeSs^Yn5 1,WjGdНe`AY1xIg%ᤣQa+xr#SSbr&S٥-u?N)ߥ1L ,-kceDQO^}J\h)1ƕ7-U.K_}o\(#&Ѿ.,dQi,N?%WBzVzkp>${ە PץL8,y^Dmļ)ŽI ,^>vښ]ؿ$5VoIU?;~w{byϵi_ MF9r.mPn Ҿ~{8d/a7TݺKMSwɠVI}A|qeLU !sy ,r^aޜL12 ~LKkUSQ Zd}8KfWJSRTW(CvgA %?3WCp & 0foLZ8<AУj=hB>ckpc-y_iBgt|śgܘǀR%Ѭ.+t3{4HjI&،>>'(1-xpp”'8T务35#RSu (|{u!qPRlMЀDM*H9`֢xi#xqQJ s(?tɮ7%"; ^ui J`[*RT#KN(g%T'P=E+'҅cKr 1 n搈"'wiUxJavX>! ]~xt($L;FX?}+D_Y{jJ"#s]ҋјܽ'>+{`n6Q-%r$N? 5(Tn} INQY c9L32:-OdB׉kKk6XbNh.~KMF$Fb5#h𫅶<>` uHa{d {D4?&eV1?(o (˄-nO 綄IQ =>>f%h0 tE*{/Iܥ;Tnk: ~a*88&+8OsSbۂv(=m1;#PKDh7OcNJQ*N--cf:2ޤ(:ډzn[kP1>}@x}mDߑi91uYN-]]I)ߚ5M5mUdZoJBE"M UQh[F)ݾ^6ndT롪fFw =UFRguU"P x=vMT]nX!0$j0]9n]#zgG?Q(ބ C(MJ7Ϟ, SY Q2Uk %n->H&υQvR|z5{Q6$їzM=Duz)1Q5:*>nHN*<:!Q`9SZq$yKbpkVϸwbjآңFkrJReQObͶvEG>i'USqJ H瘷)Ht2¸h.$4`C, ]3b#M@Ujv s\1nw5s E*WK~53Lz A={u8C0铋+ NhTzW4K.:]0tߑl'rՖ&{UCdPYzDieOql:T܇P5&ѼEE䅷L>j;R6c 5͒c飅sUK)Wyp _>KY_ >F9o/eNvzp{HoP$ W؁RT gՊ_Ƕ&JkҤc2 9V__̆Oҗm6D%6Њ :FO2e妍s_Jh ū( HrR5LO B{W^ 0 NuZ{YyO!d{_5 Kv7[%]yaWlz!,% D#U ̿ Wlo*GLZ5Xj!'HZ4/ R٫A^=Ct* 'iT-Nl,ƅi_1wߡT ^c*?Ǜ9IWuh Ϣ~K|(]Ջ-` vq=[ Er[IX( RO]]~tj~"?/xⷫYm{+B7PyDz닟cQCp=Wm#T!2[߬zǖxkbjP3*'F$XrE=rul6t)dʃ%Civ62 C#$URzG!Y}bݪ`#RL-j}~!m N^Qa.QYp穄ʀq`R~@!D9dǠ8&? w{$D4IcrDx$J"֤Y2"L㶪Et3ºiZ_{^[vQ͆GP,#;_]r7Ϧ>$>rd$ԩ29凾tE4H:d kxtIs39ǣO4Clҧ$=zț<8N^/qGΣBf ODq0FϣtW5NN{J -$%Ap;H_JS{^Cso|B$WH@ɘmF Բr8ڒnZAUgt =oF{GݮRujKxw#+6ZfE546o6|53Pb :1g2䍾9H/}. zb@1Й /pG 0)jW3- a2"}"<)DOۅa=E jNPt;Zz7Et(HmQcc>Hz\M@RzEl68X6̛e&o^,"ViU? GvOg;L,@4Rܩab:`B|B= ~I`G|WKn4dD[I޻Op &fTepN5t*K(~Ӵ)NwI:vppfݨS'[keV]M*J~ 6p>gəq0~69i^dLHvjQ+d qZ9{ٺ-o-_ Ci.j*HS9p*S3e'Jީ)\bk37o\[Ro@2j*WML{ #aFM:Vup@m܌_֝8 MBPT Y2? ))\\!K+MfXF Ur-#7#ͷo_fDtֹ8#uUm&Yɩ;Ʃ;ˉ5S=.;ڝ"E{(&xhV'TBש0qb&X Z:fG3cYzW5VUۿ̚L\'K_#X H!uU{v3i4z# e)bIO!FJfzwC1/]Cl',)oy*v(.~!\s,A *&u8J " ,P _lXx[.UngK- >3tythaLmm1^?ɭI945 { ] ˬU)F{v+1c_LSSRx2$4u?7=!TKފѬ PO4m: VgճGJik@&7*oL Sis236]BLu=3}'4a6U+9Q`4s&*ٳ;8C[6$64nŻx롇b+q#sS [{FYD啩8 ʰ-M>ۖ99.cԩ+ܪ g'4K׎wqVkk]%Cv/ z'y*72VDB4Dö䈀xi*y6fj0.!l}M(#rmS8SQKߏb&D=L%lX`8**S#&2V<+^F.y9Ǐ?~Ǐ?~Ǐ?~Ǐ?~Ǐ?~?Ԣ&5 xA 00H m/awiz %[C.QYL xCs&ضm۶m۶mvQǶm_c: V8HdU7s7uH|Qt]xhXW7yhxŃյܚOaWթ8537;;ތ/[5>:gʹf_@>7wJ]Zo`s\+2PݵޟQmlVm>N"|EkD;<=goO[9a^%Y+L?C8`. hU،|lIp$U,tf ޾ V;1ZM&l`t؊k n{F nxʀPSj=Ypy0zRŕR7ɟ4hc-jWa/"y XLMAE b `=a䐫V .Ў,_z6؋8fF}Mh-vU,H>>f-g=kL 4Uq&bX⒬;0FUyCHԜB(sFAOZL1Hc.Eխ/NJBq#3$HAhC]V; %f3' ńj:oh7}F&!$}@g]7 9]OahVb{&WW)7Cs˗2!,juBޣ1$zJ{BR?WĿ@'x",E"&yAzu,yU)J*;Dm"ȒrǘLWjjVl30 noW"M'lsZyGpH`QM Qi8|<-Iz[[4P|U>u1eN4m5%CcXkPTTab>5vҍ|2%ѭ$ݠ¸]Ys\N`&dLa:T4#Rx˪OzIw.&sDXγnjlV!VzHuiy ;UD $Km"8'4CZН^D[4ɰA!ӷ y)=& E=Art##0$, E)V)Ot4X7t9Att nMgb cĝQ8J[0b5#Y8K:ƫruv?%\9P~CS9AKts#A:cV~FyV&- C,TyxNwqG+CZ eOMTLi0ufIoDQտ긊q <AL9u:=H{c)6Zdž;gI@eΥ|G+5E ’ʨdƑa$hgͩtEk'1,Hg(!ZƋIǍ0΂)'ܬ  ]a7 ) 9 8@vєQ-W i M$ҷ% s>ح DP_i%Wא r y;u[$n]G ]''Ftr3QN0z̥lkrȗ#dliO@%r:_%< A.*q{>Q[- ?S 5EFm2~rD!PBOO2&J2EEňpT3DbXG2use)CW[Fuws y,@&SE1/U(ۂ>?@!eC-Y j]P$,񐊜U/|5|}sφG/ ! a˭CtGM4_储y 3@UcIMǀzkZLH7c;9Pu$2<+W^[Gy=H Y8,&-7xO>.f pV+x#`J0S.3>_McZ`[mvh%G}!4Kq?"KD bH'ax@H*+Gh+7$ԫH!Tv5LK$jA|X2럩P(*\?&zB_I7( y~e0[TlASm7=d-99.,{?TB)_č0i?56^Ѭf-zÎdr0w:AZuoc78tkѩ x齍(mCDT-E{QtsgpӋf}Pϣ(!+9*D!|0{! Kf.$NyOdXY/޾9ה"w֣[~|\Ikc |VlϠ!:uy' 4״yYqҎ,qP>%ЄJ$QD<`#sAԨ"DxX. }L{0v4LNg- ]p5br{BL%hbZ@RJh 4RNY\u_LHy^.ɰI8y' OMdb_uJc{0]1o/F0['-"@H}Pm8c}Haj:ŀm)~!ig5#-W6:l 9: PmX^3 Fa#' U-+A Z$C>2B*P0PB G@4りA\.vKbb% Й$@%J{\֜I R>R14#* bnE E5`Ht}j1ģDSz3q[&G"zB b橖GaTx=S^+kGĀc#[ڱ!YrM-Eǘ(;G=\X`\H%?HZ:VIUx'n| vv*;R2E3|Q-A2ogn'"׃) X%4'mhO(bG1F< ՠܜ!^-Ư⁘g#CO-e+j$4"D tJՠCptKNXכξD"w tia_Mv¦aVSلݩEJ%v ϒ$nq}GɽdwK&g^>{mB{,\噶11_tm#mA&ɒE||8?ӔM]=[k+%V7mw^/Wgxd]^!2ZvQYˋo_ =ǞV-zE9on~s5|}4:`}f/2ׂ-ֻ<=.\^Q6;/[Qu~6jś\&yW3*x8SD='GSVQY{iE6gt3Oߒk=*&4,#wU7WڎPOgg }}IͬYmii9خ}<45K|̽n/4MO*Y]  }oL~W4ZgNGp?&OpZqw$@k. Ԥa><:\(YHYkݯ\=\v 䒏%rk>5o)]J*>3="ޡlcPw7U56 }^U?r >ܗc +ŋ F ,3 :~*4NniV;kHz~*l Ȏoӣ t߇q76mW@7/.:b:X!Bv*+͹Bnj˙Fc{JÆVmob&ݕ;cKzQYQEP›uqoΔmfjgsΏa&{8,|`JWNz۾ᇵIW#6KaS_`0|4=?"kUgprTe`u:> h- k.7d81bWPۜڶ䲄TY8לUn}*}[ bԏI~kf" h_ʰd}55G\I ;+'P*`T2,n(A;@.PhIl\kJkCg2ٞevmzMz0e Ȋ[ w:ʍS5k:k*V"rSH^o <J]˥*vQ`uxhK (>bw"-tV.oJg`؅iVY֡5D-Q[d-"lιA{4 Yφ2s QCL4Lbę ^ޏl^C 1J$^h3Zq}f쎳Za#}mRh#ڶ 6.tyy[v ͸i.0?3^2hmtosLR! 71$)21Jc(11N@}C>iW:ʾ B,6޽,>a`'Ĕ͑9|Y2qI8i>eWO+_& {Ai6\D&MBk]܊ ~OFۚQQO%E+q,i ? R?חeUR /Rf.>2Ң<4UЖ.Xl$L[Bz>fɼ2й8 M.y1*vk\aɺz$F#FUF (J*\)ސMK]gF+5ߍ[ lR *ݚHŢ\曻$XѬċ݋OCVǼZ1i =Y 2F+#b5<8\rvCB'flyD%V |;( qK d,eJi:/ڌDUșy_.ͲXәG,b1ƚbJuanb]玭^|t3gNe7*VTI@s^ ++"|THc.rxTi~W6+wg>0˙t-I(ľw>RW(\r6t8#eN^86Z]2&=yZ />c)8X`ōh v3H $r{lFL `&ߟˠBڎ|"ҥuy><$-9!:){9;F](,;OƬ-ΘLs>94й~p2ԥ{YΛh1K+")Bj]oR6  8AZLHF`B ].)-_f rxW b`TTUJY({֙G{>._ ] nCE6O rR 6>.QSz ˾fYԡkyyn aKkv)z)$b>w Vf5#eNv/1!J*-8ahudݕ~@c>^D/̆'#KL"a7"L*j$ɜ8x9.:'eGR :$֪}ʖU( :p! b"`tF=$`C`2nZ@.r8`pVYC(\qW`gV 5sz.kx8wCE/_`gcӸ\èܔ=)h* eLצ`H*P:k zNd6!g*pZAv©;e'ݦ Ms *KV zkoBqBs0s_bXZW: Z=ڪ?S?vP7D6VQQAv{@%\fWc9-A]l9ߦl/j"; U}izkx1ν u$.׀XgCǓzC-|#o]?E!{ _!PpW 2t DmZ P:|4,M-rd[KZrz!`U5;zmǨij70mxq4ixiJ覶[uk8pݮtW<5 |d)}߳R UH`d6PMF{|& |sIGi ޾yܱrլ%C7pi0P߈ꃚjBo: CQԐf#wpÞ.Z.:7BI?&59Pdh{7kyuwAGS+RUs*3AJ]Y Όw*2žu:j3.땯(}&1lKE]D/yԧG!J'=cJh0Š+b?=L{9.t |@YweXtT՘@ }ZP5yZ4;yQjd40(8v WʱmfRkVٯ*2D_'MqzId6O}جN^D0/ :=s ЏX9r{ZPQb. aDJOX+˘qkeg|nN xiK[Ic5 ,aȿe{Y0h(:[gGy Xf%#'j3BUqr.Kց}C9if(uߟD m/NB4SޢBЪ_ϏlQgQ'Hc53 8bOmE~_$1a"jfX쾪樆 V8|1FE<ǤCe//rPM0`nfMQ~FNPu ~-1 ȗmD+Nj&e̺ >`=:ڣoZ1߼UC50oSnE-U ޠ&=*򃙨'jًY4Kڥn!`g2&(w;Ov D;ncM2i簁B S%r2p0;(&~ۈLĪ4lcX ^R*Ӡ0+>*ZH,>fc(kMG x'7nh9hXe;kcڮ h\ S2JI̜E!xVA:eV_|~zh b՗xNʨp!f89Mrg@tz}">Pıkm6+7sE5wFuʴ6(鮯N$JNcRS6Gm,7LMՓ4qײrnqT9rbwTnRӱ+ )1k\:gBJΕJ*oGMBuD8qson7 e|.D߹ \+ 3he|T@a:-F=r Av-JYX`|Z6X45/w-2kJ'aϛzwEߛ>"&{a9-{$&m#-I >6RGMI$oc?8V#cxdqbTf5LM7C=BAqС'؊ĉ9|a{IK${rcԪ1CS7a;jޗ',1'5i6Ί讜X;@!4~"6P e\j8ʻF\8Re6LK ÄX P=b19WK itC1/hJ3j"~=JTS\Bu3:Pe!w>8ᯜ~ a),:BP}( qOGV_\U2 m[qEpgw,K;-<hm _/r.Cok{; 7X5EP%ُoTS6r { ɕtUfw }\Ib@7S*N;hȷ냪FUa pSZ"^dŢF(F\7x+' ~04nl/Nߡ2 fH ݒo^:e=T/qs@9vᮭ|f8 CtHoW!-:*Dx2VUUp;c聺H饙N$qeV[:0A@=7a؍~h1U AGn ]tս1? R ;YθNOg˱$vI.vm he-:7F<%\Q.?X2ihNjV@'j$)Cӽ~]}GBwٵNpTp"|oCsj(B$)'$#"#m̴! {8V #sstQC71ykE0n0t||V'L>!z۴U^fhxĂb򒩵4NK_H%7V]]$ui>ks?Ȍ5^Cz/% 2X\F?a5N7, ۳pm5)󙀾nM˦Np&/j8ܷSE{[1 $oH j;_pǐ7$K>m2 +O+jdUOMg%weHJLłfcߴ5 PNi:zk3Œ2]*sjs3f 3{\$$QU!L 5@Ɩ[`ujّɐl6LnuY1-r,yt2Iq]͎6{X$NT.iF!HXп&C`]y[bgfollIgd\QKY9 rmƀ8!SBdfvI<jD$?D+W^JV\3ҋq*ؗsB߬v`))IfmDk[vlw3tNuxjBO7[GG{_4F)МʹU3kӿ~A(9\ƨ+$R&Pw99,ދ@r -]Bk^ ^!3$ T@&F|v)|KXk-~>kBIЌ :NsEtʅekp hrBd'lsVM:e,X6'nz)E4A+B"#' ML#rNTKHڛ7^ؾNT]Y>ѩ&M"d/xh4:dKQ}IDAOv&a*4ƲPTC,1h7Aa"U<QJMiDf@$#od' 9NRLj$13C l \uj8"dT -a^IdX8>oP3M{) }U@61X`8{+v1! vwH![6sh V(=9 82, K 7[ sEKґP2!e*UikBi1gf"m7@sZ1LDg81?>%ѻ#'|Ciվncӣ6:ΓYyW"Dʔ@*RJV8{ET+CwP+2&-hrowZgL ~ذChp}3ڃG`ʽqa7&?0; %-1FBU`AteA(nT"#> B#ULA EOdƤǞ3U7f'>6SsU&M%3<۬$,+a<^UNnr#Q?ZZ]AM#K[˿Pk#Ruj}hURwSlc'9hF9a@w`AjIR0bIC>2d|!3P^8񛧚 86~Oh-zbġ) &$p6mJxQ u{0u=G) 5 xLa.،(JX=0Zv 67zϠv\M 8Ҋ IB7(t oa)hp1h Hj`dĴP".7×UHQ(|u[C_T+F>2D!F :lBc&f͍:$VPkRJ9@`Ann~`#<0JVPf Յh+p.?7"A ar4Zp;”/`y\F8U0Xat2VEj"`0b#FsZx7PԠ7@D'.V9at|@_qޗtH5RYEp[xL!OOi~!0,k*;^dwpm&m06 NK Z hBd ->7@y]NqɉUvQ Tk ӥL Q| . 셅C^ +ı*lR9,ІmJ$H{pLT2[RpJa`).8Dib(ru2V)=wqĝ KГWB0(&˘X2bJ QpLur᩹Wf@JsEy|k튱zz|aR19J6hbH+a"O}HNΡi0&Bl :[r=Pv d?:_Tx5Ҙ#a _(d= \q[B`:$.K?8s@ lka[4" @3 *7\TakJT B?F`0g_ P!k+D [-9x!#K`x\8 Te 5 PkB0PnhPL!P2B >Goq31}$ +>`#%1 V$**y {eC_eHI~XWyKXZK=&F84&#H8 \,I î0q RR%w}~̖ 2ahy]#pkHf gwy[Yho "'NDEL8zF2 N6]CE_&.}`mʒu.1rLL8<8\$zW|#zz"vQIlj4SY)xâQI8g'oToOcz?A|c9Bc+1ң4^?zf庍,3zp" }t ^t&|C%w ;h./^ s((!.ńւIҊvb_/:sV+'Mo#oX FIy/ƍqJ<7qO>u&>8!9: ōsxlw[N>/dz5g!otjQ7]6]S-d]qlF6W˟oq.߸+ϵλXG_\K{i릹wSK}3vF.K;c촟&Mo;P|VkVc-a&eKtha0xȨGsf3NP?;$}=~sGjIxMT1d<^oeָ~Og˟V sΣXu1u5*ִ|,udu*2x=}Ѿ_ۿ^-aNkV{j臩m\m]:}v-4R._dRhyJrrξU‡*xu[ywަ7wrȠ.{-̬w<h&OnְسVYU^l <#Le+Hڴ/qZQ|mTκ sVWؖ5δuFe6MmmڦvFsVg0v0+DVAoV{ٮՙ`gGJZy"tm?n\}y[_F ٻj  h cּ{gSRm#r ϸ,?܀!ǽm(y$B$sOf_~@CkYtE?ꨨHZnn3aHgyRsp <7^W8mκ8;(qċG9e2[6c+oX+Oi57ۣ;u[}\}:`t,WR2cCd\[﫯K#.dX0S\.tf=(j_X=}L >>zt].ۚ˞p}g1՚qyŤPPJfsXjɎĎ|ypӽ;.V ~iý\-T#we|O* )2[R1}ӚkĻXpxP*UMqBoK̜h}(qѣϻV~o":PS0Uq#g@WmxX._k| ޟePY.>ofGKZ|'";^xf[%rXk.MQyV^g2\[]JYy. fwmЙ;7[T^QPJAmT>>ĝJs}L7eIH|}Gdh&(Fhƙ5&:SUc>?R2J+(N}d&.v~;-VkuPh)mltP4v(-$N;yƝ9|Yik/ S4S#"b#ʂBG/9D;4mOuu%N6UFd\{3:QE!̝>0iA?`|s!RAi>%Oed@˭=jYHG`ҢInZ|?E!4il~l3e73־4,8s6ZRr v h={C C?c}2 7#6Y \-JMIl@RsqhlH TLu$ }0H+#:p@mͭiڂHBt`"?KťsX=|0]rUc^)nkWYل˰HmeCD;Lgdȡ{`f=4|k "\5ښсK}#<.Het҂WK J *H`4ٟIw=s} W@8;PIghdӧ#fr7:158']OLb +K" /3Lt2vV-]M+pDJbQme03`aU*:a;LI3tb@.qw 1-SVB&G_R;j>0j=+]G j9kEBߧ3lXTzuKUkR@@z.W}8 *=dvv]D !gA@qds )Pa[zoA6rw^7Pc+?SAU$ҕ#K~`; _G#V !}Čٗ'_8B~< b$٥!UJ)G>RVT|dTG {N}v )$BvE}$B/.n5B&ȄZKI̝{5Vnmϙ?5Q@$GXbD 6$ mD6'BD=[@۽ֽv>rOI11sNH7!w^%i:i֫WC pU{h<\#gBt^MO5G Uc?|vIw[-{Ld([ Qn98bV4nH+G -6PfzeG:ޫHrG鴲`E ')C(c3W׊{(Rp~zz4Dq;SjIi<@u۞$:y[gj6}!اҫD mt_#t!k4?HZEsh]G w%]OzֵE}+COx]+0h>T]GvO:apcDQeApGT7jyӧ~wi !{C"=oޚ꙾|ĖU![(tNɤ^_eG{l9 [&LxzsW|H]VQw>L:x[;H/:bOMHY-& ҫ_]!:D`+R$LJ B(Oqq:$ͭL'cq.5 u`y%;Ɗ`Qr$*YR_9<`+ ?X>Ut8bmMD/zJtW힌rsJ3e$X<:1=+]G:P}) sR:!yypdih Rٳ<›eKvb}: Zh: c3mQvR@WR^[Q ɥO(+W]ו 1 Bʯ,vBAxHY|IRFKlʦָ27n{AF*:%׊½ aA6 ?G,|N_Ƞb"w]o"kM[chCR&(rrN(W?2cLLn,^q cc_B8ߦZ$7;! (PEI¼̹̉˖-(xVqդ$WQt r5%3\ >ÍK;j?εvd" }DyEe=ffբܶ; SHu9*.Vm( Cs85R`mv庅.,^_wqsF>Zko-HY\w ː%o ]@4X|unWN]!^, GV/x6^k:}#R=CpftxG8-bAxg'VFU8d ٢qk#Vͼ0F£ާwCΨvI}- ٝ4h$SBKL|or(DX锂"*q8v4YWw-2\$|}EG, y@QYa:lO"pA #rq6mJk6Q6)%f'5I׽5E۱Ҹ3*Eh)j@ ~#+pKC:?h zb-?_3)-ţu9w˘Ұ{Q#}<`\>|;w&3G?E3Om݊d"E/ph1kk-,]yo׮6D![ꡕTZւ#e%2{isσpQ,9%݋I"HNfPDT1jELqp~{1SHjw5Hψ)-c-I4me`js5*d {~5:ubP05u D9sjf*N##NLAOSP e(]L[EIB]tr]TunSdo3AOh=h.͍wl\$>Y4zpi_47 %q--dD?MoVzP)o#Gl2ƺՔ*mZw*}&|q7W'H.kF5{NJe$$CSqē 7U`7AZdtnlqJm_n@w/wΐ-]ac0>D_B\}fgs5A\ m҉νhޙ#ENsR~]+\3{ymTyfZ?BJoΤCŽ' ,t))Tqڟc{ ?c}y# q*P) sR'f[/ld`S^C~y:_AZwH?=ҊT~0zao ^My9 |QTUKDGNYU$ /'1?9r(wԠݲ`{'4f_X@EY5\rY9MGb·DzveW;TgC`dr#SV709xR( q|og]щgp!g4>/rEԄs %OG8KyaL09S.l&¶ ]~p,3&ArR֮=0eCcs.HȔr~D~XԴUQ[[/?3<}_fߞwߗ<l?h>8% #ԣĽv;̇'H *P@B**?z'\e{ x @'S8x&_$ޕpzS9 x;>^\ TW {]R51aU[("*.H'$336wEE.R[ֶ~*XZE]\{kH y;;9ɐ{͘0,'s䏐 SϔA2U`HhhhJ,SB2+*<,,1>>2Bqr~WG Ep)r8ҳr-hJ V(JPUʀk8k3(̴RDJuOH8t'1 & TCB 8Ч "gH`| ȖfDJ F52'dh N% ̨'#W R 1& qj4H@SYZq P$DK(k@m ;"2|MJAF J2@)ҐRE7F _ŏ5@u@{z0JGzGt` 6TBP`+#@f@D61br1@O"  #4* (qq5f瓖hJP_{eqeh&@d,U@@ 6bW#PII^1?҇X'p.ر+Xj73rN<Rq 4h80I2.fU2 %4414´o3/ =R.O)NsU1mzc[#B8f\dzsMrU.v!]]7:IFmvlB` B rJTMPZqN*CcV8hNnE=rlc8c$Mvab& ?;3`B4Mal IAZy mŗiSb<8:U1q Ť\{C4&5&DX7#c;@, pBP"qN!*y '5h*G'XAac'q]NV$f,QO:tձ4̕͝jԏe2mV'!Ku>3NzPs&/xY,/W a pXЦuI E\BN)!aV!hV٘B c:Ci` #[_) .AbR%J(6Wlu Z>T9C )+ԵGGa1.Q`s[ƒFe\(7P( V?U Y!ٚ.0->#Dd~.˱-.KO:W5m @M4qYlahrJ=@0Ò$aj笽ThXЖ~grZ8.!Z.N]hT{QBc%eAuɠGajPrOt@vH]SoJm1-NZ%d~Ђw x =J"@x\~ߢ4Z`4 - vpERb6,S:8@;-MX3]D(>E96ygUB 岁X€XBJ3NqMBom1Um[XAY*l ia 1[Bm7kd -xv"H0,sْa [.opĽ) eNjtݧ2_=K˼_#tmyq}o*h3s}O}A}gxkԷ܏vک<6.$]-?۔]c>ܓw>_Яf,Nj=-C>Hh-)_2ZNߞe6Ľ7wD8#7kkң-n% (wՕmש-/MLTp Ռ}[RvǟӇV;WieaJ5/^zs_Ac,S_ lzeQSl `.8tN;?&Nhs6QiK/}FkF֭mД[5H،5d?X+K+n+폗EM%X;aɅ9O|Gf`|FO_tnTf z㵪擉Ɲ[yq*ss4iDPyWOtg i5(XvfͷFo}ƉsG󎟸c#ês'ii!X.Ms\7BZks|6/zfjRLhIkFC.fmYӠJˉ3,ט2CB~ZmJ$vHZףw̽jnfUyq;kߟ~g]6w`r!=պw4dDU6^|Z]9lθyWzIp;>=Hj Ysc|HysJ-^lKՀQ/o?., &ラmA͑Ïk49GU]rj_,o'ÖiȪ.lLySR)˚OZ^#Cvs`AGb#9mSI52?J1f׬5pl~9?ze-6~i\m-5$5rφNȾOZ3;^g_:dmZM ߽|EO7䷭ƃ#o~?ҩO z4kz{o6u+W;^n z޻ʢb=v<̙x̥L (?Cëg [x6)6VkROwڧ&Kr['_jEf}w> [k@Μ ;iͿu#FEܶ}ߵ{|UOpָ Go]קpTmGq4Nus>ٵZ;#4 <:]rofvQˤO'|VG;`꟞ǫ8HY2Kw(pl(D2/*}D,.{LxE IULLܳ+=:Zuz/ L-ZcD[!RDP!dD t,pǂɎ ,SR䅊ɮG@a`tL253}#٢xƼ/3hJ,3kj} (_@6]Rm$s`TО±U,6C?.뽡݉/TF~==c&KeD2q*_2,?~2|lǢz=R-B#.lUWkZ7ѼmQckvJ8OrE>}; 2bܾ [(_&8V x6eh0gsx Xؚfhui9 ?QNGͬ$|,tTJ3o]OJ 8t Gb+򲳹 pSE滚)yDέ7z,cޛh3lz rFl%Kf)uR-PlXMP8_P<#P& CN{lC:Lx)r-PyFS0 |=J#;}=N$co%%H *3b8 JaHlTk2]L!$T=6oo~!ZD!z釽봿f=Sv%QiU`gXXaݚhJ! V@|mYWX}/UFmd5X' NJWT_|T?yg +`HkvA#O3H(^&P ;sl{N9~EyE v-z5pt6^m *kXsCf)v>FKU:Ӽ }NQVMXi|G&[\UvSJiw(FAm2C ǡh+0}̞6iJ;?zH6zuyqH`x@-%MTZ $҈UElCwR4 M0E nw h#^O֡,l$e23eޏS$OM ^>J.Ǫ )iC˴,^-FL2c%R|}=W<6 y ]{.I%*  6,O2A&L^sB؃6ToV^5ֻ dxj$yLw㓊9O۸^+h1y;W%5xM/9GKdxf }\!wxehl&abs&;M>|*J#MNujp@0/5ւy9ٌD2eϊ%p\D><&;ͩ aPÇ!%vH6!WQ6Eݴ R??*nЩ c}boӍةgVOTsyc?\~% mRf[ӏ~?<(_qR0Ve=3t;lɶwE0ܹtH R)eH"3n"vGxЧn,'3GhÅ^@ڙ?vw d"(6O&N,r"2pcaf!Ajh}22321G-:,ȓ~J>a9'$%,nۥ..n15[C⒄0x`p9Y~TB_w-HN "iG \tՊ+(S#Ԗڶat&Z'h IRPx0k3Bq&zό_I>m*R"-2#,gA3DžjvuePu+I8`mGkdy=w͢L>h tcn@aA#&7_|ȒT1l0 oqq<7L}c{XarŪئsNRB>w-S4fR`~BE0{d>)Mlzf&{Ƨ) z/Zoc~!( o`Zd:dB~@ȯئûs'O4#<944zW Fx6yEsuN (+n"҃4,=Ԓڳ*zfܝ;0,]}uXEE3`LktxbJwEO ꭘB=*u %SsR=[`@}.Al(9jUdvz{c!|\9p)M#Ļ*bKYJ1L2T #o2OyhOD+GY'㬜c(m/ĸV|O, [e8R*2s&ɮt\Wxbh"-d2-w)s^mɫHy3:qLGZ5 ADT; u m x'_6D7DcAV- <^#"KEXzA\oɬXls|)očFogxLw06X‚`s.޺ȔPv.Tt9=}CVjN&J᧭ny\$,[6fU m,IglSs#.qZYu} 4:mE!]D5 t:h&fO1C}HOY DŽ:p%H"&E@S]]zmVvQĢgB OX-}J2ZR :*Qg8vՉ?13Ó վR Ûbtzct&Dx.Nɩ fI>H®4q'X ZVay=8Йm[,5^G;QE}3dxx[Dž/Sх<RfOJrn~_޸N~DdȆf?_*H~^: Ro]Yg(~wt3IfʘSRiI]LK'@>/A!O(ʞ v*7iNs(Nd8[Jcpx\5o&vz>Uȼ\Y߯+BU䅵D,(xd0^N˛dCSpbޠר#[g{r4~UrRʺzW*z 6$P&Ŝy p Y=[dҠYH'\d~ɔ4GzlUT 2[SN3\:k%4q =㼒;U2>f"O+ͥ2 Je^;JMY2z\ģJ̛ki3 I9@# b85ꁒ%Wz&ez{kؠ7rZı#Nsl%7^J#h9 lt"Z}D?$!KriDoAJ[urDx,9L;[1D<$\;&ߜ4YMg,Ro* ;㧵Z)vVJbiUdV¨S1g$y~@K΃Զ/Gf1qYR9 ?[pkX/ $A{،lX(Oܢz%cѫSxr PSDo@ qG[(Xױ4% Nwb8d 2_ V=ԷL:A2~`}{lDUܒȱx.Y])~;F/[AƹwzNXإ%E~mD0L*ER yFd`gd0՜_v. ؘ"IP7-G\@nڳS?h΄F֬K(jy  tJZ\&ȪLPeP3U!ygc{00$\7Oy)"t3fD X &Ԩu !q:qp,L}`S˿Y<)?\|[8ҕBWWTQzNXgD+^H5/^OW 9J{@@:cMtӗ"` |Yv:!(`yNZ}.neɜ'.S^h EW:' WOwoD FCkx ٻ bmLsc+<ů\k.0((r K}!oiD1A7˻= nx q*Yl_EnG 0c.c+fEȩ-9K2mB@O1D zѬ'a]5J>AQa!ƓQÛ0).9ͿMp:OAAWE^ DǕʴk1Z}$Za 8Soy"Rqɸ> eLaÎJ )JɂCh$< '-QU9&/,l,uL'jˮFyT vGF 1<Ҫğ|j}Nt~Tp?Yܛ!OHK +ğӦ(A~ˊ)c Qh|IM5Q5?a{rNhpO?4BN1˶:wĉ*w]`U +w+ƃ&snYdt =D}n-WڗSM.AOJh٘/i0BܞB|׻;14vؾI0Fhre'CW/#]\ojq/ UZ1G mLmFݥ$Sdۤݕ' 3{1q˫Qg4P2B6>vBRX7: SҪ Z0jJ^K{"ͻ'|{ rҲŵ%YgYӳP&g9Ś՘A17d u1hǑvQ d9_$ ^ـjUOlFk'/ͿaAt0@蒊Ȼ=z]~7ZAc<&ȾS2|jrPҭ7{b"կt'NC}[{_Hd UeYsZ 0@NXֵW"K#hZ?6٦o+|R*#ABy]4rϨ`k}(a떸F-ZDCLEMVH< t@de.An?G%$.rcQB ؠ]ZuG%K*4shg|S՟5><:0^BW1 {끙Ѿ9t)t$GH& eP48ZA؟-_pBxv%vϬN/%y>1WU;-YɎyObtt: ){%`MmGȵ!ܥɀ,#aN8}R_n݀Cnk0 :u',^^//$)^'6#\6(*'͗$[݌Z. IW cB%5uaK` 1``[GPW  Xk4(RexG;IZ.4pî} ɉaB\BIL@^wRAOja{:+lY5t ^P`%Ewnq ;6{Q!VTf_(eX.!Izv֘Bi$CCGW? qvKXt"ahXOn 0n!cZ5yIDd D{P# gcYMpYoxh5"CP;awK=8w Ɉ=`4o;Y>t~"ɥVUNEaQj_AHM23H.ր_vS !6,k)PN;h3 vOS0L8>:?pRԗa*j(dguf4}+SDd;}6A2Јbp& l[ʘ<5d߬,,  )'7+1;?+ 460f51XLl,<cVS7Oc''s* v/ GȢ w OeX/Ov߃Iaz̴nT;n &B]Tt .[.yByAa#4kZ QE,jwYF6ny)t7>rt~󏄚Bq#aS;ehΪh}xn'ͮnܝo>=O'3pU>(jQꋐ;&snlx50=Am,6@ԚPw{~XK'DPF/xZ;:[>GÇ>|Ç>|Ç>|Ç>|Ç Z{Ox  u G0hۨKoxڨj Hl x ;^] x W߸4SѸV?qI)vdhJ#$Mݱ3kf67[(-^?*Zq%(u)( IvMb93#;y93EqyPGV+VBο3VTPNRj42JUTIvW=Y n)*D*TToRR)C{m(lRDJLH8$1 V tsb~ 8 DI6s921Ŋ@@fA@ v Ps@IN% h"+W R 1V %b"zGzf (v H PڊNdT@Ay, ,@dR !@Z| ?'o7(m(E<9ҁ(ج@N#J XQ> 2#e"Y C( W} V !Pi@ /y@RfQSh5_R>h5Oj~pY?_n[m>/>/he ;g߅OB~p2|2=`DX??h<Ѥ}nu1M܀)?v89Tn>/[*yUZg.LIz/;uuGNWׄɊZH.iïLo9Q:櫗u:9S7lX5OFvARTi8 :c,8|uW2.ZwFjG7iFyoROe*[i]cW;My~'zI+hkY~\gJa}5cPnb5ſJ:;AUAѪ ZMhhc^*NI Q*vQuFuHNeTZbx^gu^+~|:ѣܮ▾db2;@vzR\Q&sK]9gu~쯛A|_ꓙ>1uLʓO=u`2Of{qa3<1(^FE볟Ĭ92yZ =5"aF S͝b/uF&ٓ/zh;jm/X:4KumsvتKyoh.mgkqS??˚Lrpڬ+#F35̕ ߿{#"%v`M'mȓwg<:xGSܕ3d[M{Ib\+ܙ\UFutq,L[nZ\}nUfIm샺~SgWȟu5FE/yK+&9Čոm缓j~6;ulֽˏ:!fAW6)9t8/8wN=r}%rܘ1~~W~)3;q|{ASO*ґŶot65Cy-tiQǣ ,}iO)s1wP'5;=z=f|SIx3: <^y&O?=pÖ[n?2--߯L >[ Wj2WIZ I׮~gŦ%MMƆFr8냜Զ'\hwmv< nÆݘ$.^p߉a7'ߟcH)w*\OQ0~Su5_a׎xPs#txGu;ԍ,w^~Zdgwq\`÷8 ڧހ.]^7¶̢{٫vQYr|w)n{g&'&Lh"iʵu-=zׯ-t&_8G&;yҝC|-9~aq/]3M.]{ܪ0vd;ۘ&7i/cɶ mu:7qŻ֋rl/z)A\ bnpp;Z]-Kz&AJr2X+O-{QY xa_)W2ٌ5\ֺ瞥{a FBtLO43royhREM mUbF㩹Ow3 }RihH/ _&#V*jg9&%QA(>M$}22`lՆBRG!gMq3H?pxIYOd.01.p Cr .eknkm`Ϝ@k-=Jug@j<ƃn]tIy{ZA-CbFFUYPULǣX;\M>"vV^4ũfNJȱȣf 4<+@QM_FH .Z L, rC[b޴ץKǒ7zC4M&\[Uԕ[G!y/p3ePU;q"Rmr|B~ɮ>9Oj_F:^~^W,-`Uz=lυ¥it\ӘjV9},1IũƃLd}jxIv5@ћf``[eQvfM}(O zBͷ, ̊{;H7cA{v2kB3q-?Jkbj aOޱ)Yu 7+{z K`pv{DK[Rx7US+KO GhƬ=HKj0[tsyXlw~UMnQK݊A$q+w|$xT biVgu}L)2Y0imF +~K9K2^fUcd=%ɃSh&nĨBd d80f\. @8˶L+Hm/}J*DmVvMǚjӉI@g΃ :jG'JTmVem<4q՞6a $,\Tj5 ;md7$]>@cO@?raj%/4&.ZR`EA<} a; t^ ۅiPh]&3Y_npd+}Tc5A>+(v#$'ksiD:\x frgј_/L>E&2̷Of%@T1'ݽ%3B𧶌UMX=QMUД&o-./lTJ𮆣Q^r!`x/RehMdd~;iHDm~pa[G}{9x+x3S=o1}3OOcnpj*-u#2읒U7jF kS`țs韍!_ r2ID?EHzS(Y@x˾䘉bs<uțʭ @lvЪ> P(QG=+)B}tRM 0bK.x{#wD9 W!ݫVXmu6tN)Lv_{j&E>TUM8s!Hѡ@l o~\Iё00/KhFwG5}򽜡Ҥx\(.`/hic魏c:۸qYRpnL 柙cNU5?r̰&|"z[@x #w"E@O vҞ# hPwxd=4I&fJTg̕^\,EӒQ8,ޢF u8d4Jk 8zypDtzGֲA 1JY^ v1BJ|`H[rcw@ ]k"iz ݫM OgVR!줆TWПwK|\}~𗊹yֆm<%) OdS|,?]X{p>X#㌥8R6p ũ'J=Ϗm Bhƒ_ uL<$e/n"Mד`> Y1ڎ3ba@.4 p}/WMW,!VBj6Kw)vE,\d(ڲƧ܎0'GWblqzAi(tZe{NPHXD249 AU~饐Nwaֱ?~׼gڷ?.h^iojh_9 YEy ,$={'LΧf0zRB\`]p#?oT$eƛ)3`D; m^jY3$2޴*ߴ~ciR7% ſ w6w{ y֟l[-:"hKzl?h٬GIBzζV)<^0N4^B@C%ZۚVu[Dž55s0҄ruN9j*1/Pڙa|\!?0ʼnw 1<ݡ{ِm&MCB~o͗@]49%ًIޑd*\@v)lt a]Js; ƴ$|>3@f"b4ƅBf¦Ym}V#엡m2e?a=2[ܿh<(r\>`r>DZfL2DvŚ3l9iE=ױU ~}۔P_\V| e~N\,7k/?X+B2qr'(g")'|7-W&㳣ηQC./{Ӭw]ɧ23[;ǥ0Wә73U[YkGi0~K>.X0BWvݻ꣑:Tű[D'r^"Y;J-<|F̗uKȓb̶th@NdͫH`L7y fo7 sb m۞·Dv#"%b6^,ޓ_qfJY l+h1zH'oh@G -/%rj//DڑNaz SVQH3ʮYߩ0q'Ơp<;&tW%aITh %g&OXW[jFڈ;_'Cq54 TyĆ,ơ.b8,Yi 1l*2f!Bݔi'0jE"r[> .<6N y&ޕ[I2Y2gjk?!b.xztھ`>uI\0_OjQHao-޺o]9Ơ7!%;MIl#id0\&#)q,85:ǻnL=I^r~vqEeƔg2^m A8G50s$A@&,xw(=P>>sK ~!'EZ$S^eGO8vpDRE? }wo~9*ء`W C])=Ml'KO"udGO\c w r#;VʛV M+v&/q67^lD_Z{`mo+aW3,ة7:A?W3:D8?0&ZVEoշE_Ua0$[`pIE|]-ՆJj~U1, r?ERIOXw4S/ѣ\izq\/m˝m;CdӴ*yKEI,^"l_ogR|NF{G[ޗaU 4nI0LL}x꘬&Q8"Y>ƍ{͜pfѢX>OA'΢r q􌭌7G&83~b4(Fd:W` GmίFHgOgEkR{G$O*6_i݌<7o|zud+bđjx*b^d ~^GwTWlAX!`eQmmI$0I|!wXRVhY|a#6^M-;'N/jRMW/|~›L19TzK^HdnG_faOrz9$i@3~<c!ӓUFOH3Wnf,.r\ߘw&qŚt#V E2tP2SVq[ K>ot0jm锾U." /Mp2|NF*i9 18K/cF}I&C bb[ʣC74#N)tBS|BiG)Xz1T D,W4trdT'D>w ESվ'A%7tKQsR,(٤{CQ%ٞ8Zz$̎W2Ɠfİsé~ͭs Qኒ !IP#؄v&*aΌ8$ nHQCsz2,6^/*dQb5¬ ˞2 nw0#}0יuU."\h7MgN $,s-o#4I K:( ev60Gtt2{uSCDڳbQvx$uwQ#v`2|YXFN:? ڃ;oLllޏZ=)EvgD gcBxPQjeXo|9temh]݈wln4}LETM֌g@Tdaܮk{.kN/ܙeUwr/)ٿܯN}k7hTVUuѽh!"n( ;7pŇUOOIFz_Qs50j%>̴|TWjx#C$jOC@7!+Q%@#/Ao BJՈ + *2id {$\ Gl5,姭xڞR"qQ CF﬏AM/x*ӈ6"A )?(t鑓B7˻ؒYKjz:O\*gmo%۟4_cPUXm17$A ɎCxoMݩPȴc!MlL,)]p|l\?^XRMg^ߕ󕨰%Wf-  [GZE k_o{Z&>2$ \CA+Azu)RX ϒ)6ք X½^& w#걬5=I{]^l"`|{hh<qYe0/H⿔U$+lqةI#*?i7@k c\P?N]$Qaʘ-!xF{ոRRr."I[ť;q/ %~ buA`q}eϪL:>iM@xX~)F?l2Oƚip~2CypcƤ>oà@}Pbj\TƖ_ *݂5謇hxć^) z;f^GH _1W1hWSO xKP |ׯDM~t*\lorDkmq{Uƿ{e),AH q%[ņAI L8/;HN;5XJt"k 'tr6#$oT(:n=+E3-5&p=r4ɂ' ' Mϯ \sقK/liwHU#71Ŕ)o p}SYVoT鎒}i(1NVr^qn(PcO(ueO"fJiPuGwqGtm:Ϗ!RqZ؉Nm/16bg ^R4𦅄!yA8LeR4.cijwvd$Pnd8+hϕ<>ΦУ|;3Vk|ȀoJşdo9<>x/I8 VAݮ@td[1Ab^ở׸U֟&*fϘ)u87B =C.Gɨnk]98QyL̥NfrbU0* eO 4LowmPLz`n ]Jk-H iֈY8RX%#S{ǒc7 &u\ǩ}%JvsAt*ͫw {A΀pŶaK)i22o>Q:N_L Y=mZh'&vWEΨ0ݖ[=`^bP݄"Å{.7 X V-Z)xRI}@Ed)Wߑ*hֵ Oq 5\XJef)xm5>B֙3 ܠ(n챗Thv瓻lIo:^[=:L 32nr#KHLjrf٥"~qR.Qlߢo1̈́4a Iä́ 3&-CCV'MԑX7^`gӱO9;a+.uɶyX0RsEfDhI:~lqzE@{jC8B J϶TҐăWq!ȓ+mCf1[}lN0+ CLrZƸllewU ~˗/_|˗/_|˗/_|˗/_|˗/㶘M}$x  `t't0R T jx3( `еm۶m۶m۶m۶m+I*ݜs 4u!ݑU@E4O[) o_ХKPS(KrH''d3\Q mRNJ&+  ՠQ~mKi{F>rk`aW9RkĪBCCC-ZRİaWʿY+럀&>ש?PyYa^xIX"=$  .Y8`-[BAW?\4$CMS>ԐV~8aHMx@"@R d㵶4~-ZlӵJX 37G_nMXske#BmCl7lK%c"'KZnL} .۸B,8& $p3YDo_ X_O$'iaW&F*hKÝLN] @]pc1 +#flsN%% #r2n`PLY.k⟼d3;aeL\l.O;Mb X i6&a,?V<*Tdb \4 HMǴ?g2ŦB:; 3IF)m y?:؄I!( 6Kl2I,l^^:~ K.Sb!>МU"d چڎq3ΉyHKp͊wP_H>5f=sX P'HAE!Ię>Sz?P<\S cK\ՋMwxٱAqVRL~ Vnk 6Mr+ *gfX|WD]$PHYMSd݂FߺSLr@}'ON#[ N|z p&LJ9ۦ]!FQ4\,d ȖS5V bRXJ1M5˪A(<ؤ㚰UPnhIzr CGrVnU2h<:g2qUӼJ !􂩃eԭ" @qڡRH:~vAyhʫ{g"*/OV =ivMŽ$آuӁƬP48Ѧ&BRa;) A'vg)ݘ\r@<#/E=Qgm[B5|>$dZj"Q0;z~UY(@:fɇ=) dDHy#HL1F=<s-E"J53XA ,~XF8#'1<uNk2*`!B2@ `JF6ѥy$r%1"%?3dma0tHeI" 7aӯ`V[kr004)yd`,9g0d^ ~1 /\aL?ʼnrH=+#G7sGJd(`sz>B%>?3  l?IZ yŢ!{zA(؍ia*~q˹b7(\Ρ9Gkx#ȢqQx ])a8-c3QWL9 }:6N'%1KQz0ǧ ^p,̀zhQA]{}=Lur5/D5iNenH Ue fqƝg8qc4uNEQr%^] P UwK!|M8y+EmȠ!MKPGV$fTa$ԃaPYB-TDApɁ1G@I0:JqE%j#:Ry-RSՈnK{*ݥmp e?L\ 4ðPn%P׵, 07|~[!L3M Fx(^5Lo0P BԄcq u x~ {I(ȁB6Qg8(Dz`}pNBo-!e6ܨF&A=f)cwFcU{ br:)-JcZOZX>/%E0R qHE*/l;f@m}OH.T"Ǭ8=&b{@%T-&WIH҂E`S!3ON^poTB=UzfuThpR]@0pٸF?OP#LW???g ?l1z!QDs9qO9e$5b>S!LB::'{O:7;-/& hi4]RN?o@\<XlNf@-Rep$ltJʞG8p'Daўuq|&^^gχ1tla큶޿aKU4aw 1UJ:AS7J ͯP$87 Rsu.h\Wzֱܗ-S|W!ebkK T+B7uރ Nt8C..'6 OO9_0$#n~YSժ OEG)#eM^( ǨҚ"#ָq|{J;DB~TNpR@p,?Q EЄngsGqY Uؔ,Pm6ey=ZmNl)X~ga 7 gE+)/(]8]ʿM&#ږCcT %SOVGDKqU6!*N*vĤ"ds ou ,cqD9D.Zl*(*AnΒ FK;pj5[=u1ؿm:ɄH (z\ԖDImM<|lSJhN5`2y^'mٝ}IT7 #A!@A*]DJS{PCpsX3sa7ާDRC%62$N*aZW"~=W |K!\LFSHUz«O SfQ /ī [/~5KXl NlMG&EcTmxùl-h'@*\RŲg#P8{(W&9SR_|(xXW$q^/v|@ͱ۵+pn샷P|{̢딝k~8QCg벫F.zYl x{R$NT;8LՇ{>Ky{~t3,}uuSuh'l򛎫 -?L.^|gc& p\6ٖ9X~kbltt`5O{n0aM<j|c'c$8̗SZCqwK6 gJ#3g]J/vFa 莹 0Udk:z'}M7؃r|A@C;*!ʽeYqE[>5#_o$M|5oݻ6os<_W$ɥKμsr JX &~6+|~=bٚȓ3zdՄunzì#6#,iOgU{= nz.'f({[-C:߆mw?Qv%EqtǛ'M6wI?N8aw^WqO#eiot'sٲym2׼|?kjdUӉAtJzi`tE^&vUՖ[md^3?%Zl.K0_oF{U[<o_4-ڛ=V{6szؚGBRoK\TyBuvk]L},T|X 1α,W\59fԞۭƑP+=5c2yt?ޫM̦&8Ħ?sY'ο:bV S_y?EZj-Rݲ3hA8tJ6t1~s6(0~K0:9'Bcl7mY+CV&Kuғw۪DO-}]uA&ub)dx_&RYSg# ڽ*K(u0G27kՈb~w_NJEe-XY ־8ҥ-]VU…jq_bOecbk+4U}vv" ľM]b3=6,GB_G@v,3} M?J& o kѶQ)ذwk<9{՜7j yV}yo\/:48*z9B1hp%,“97<&,.}ۮi}Zn^gz]΂gjoX]nݪ)k-Mljd-mLy4#xVk]%IsɊ48wlNG/*)ߢo)fم|4Fb>i~7㡃*ss)x7ڕu31H 3}rODJV8\e0X@)HjN LDNҏʞ5$0 jYS ߋM)UZ&%R =KsTa&Ty"'_e:e?6lj9Mw'٭D'-hQFգb2iiB(T5 ["\g+DAx$ Ykšsl4x0mѭ 2-~f#Y\cyÛ8#60{;RWYqyC]FJ4C2{D^'2 Qd5r w;VhZAqptF>B F۴ 5pA1ȗ6[ɱ\Hϗj4}Դ[wke$hOYT7$05lq8a)WƛBAY꺱'dy) 2~ Pr`# r%+@ExSn s8 5r8& 1RI7Nm2G*sPG]ʵ 0 .wT ;_L9SnE½dKRlpZ?P/MIab- * fK:DWH]!|- \˟`6xPAeY%VZ{-B>oMRDSQ e 7M84nPg# ;jr$cbC,w'@NҸ<~|yIƊ6+Qxc&< u7߅}83IVX:I1oi,b?"Pz3n:6{MdhS Bt2-_Bk+E;d5nMb_,0Hu~~!D^Ȭ̮iԗ@sd~Zh{İʷ$~YhpDM]2yWX0nYSsSL7I>QA|4y- 2:ɥ3WFPMȖ{n@yzip .K 6+jCqޓwMvo;ǃDҶTSB},ƶRtA%|b;`~ U߇Ͳ Raw#UXH {8N2["q̿ar gQ-I9VTDPҳM:Ԯѐ@gL5f;@'ۛѴnnUB![^kasAI{Hdlc{q7˭2[UR6wJ )cou"3kYW["$jښ Ԝœ*»a^j[-Ϻ@mQ9+|b1I`G2'l"i7Wý͉e®29'Չ$׎=Kn&B&!`~hzǼqtQt$;#8a:4  |eO8ˇ#, )$Hm$yGsR/t!mwBhh\b|C Ui3G.zخrdZXJyҶj @ohD%J=>׺Kk?J!z ֖69^Zؓ(Kmk8\o%f3BtKJ9V6UNR|=aV C'is!afM=#Cr {\/(zW^>wqć&⽔cm ;F)NEj cmBgoO# oؖ mLՆ|%2O=2UvTḠ$Ӻ %gxI2MxooUحLJuXsKA@d60;8?D;/K O!XqrOp =A\?ߢWÜ,:x$pMvvg4i t4O#eEZثX^;x> znL0[Py,7zRya.9h3Rg Kˣ*D6DRbxTkE5~;0?ݥZ9VSNZ`{&$&2aj_~zx[Poow N4 $V ' G` 1[1JJ$"}1ٶ {nqjzgbbsx &\T&4O-gF%ZW[)2s|%3vxk dBG*0-Պ7캰.jYڑPbmx=O[{oFVB Yfm~kR#q)ϰ[[: ohzX~睇p1/~2RxUQ-K"QI'|VȽZ=;x՝END+tCk&}/7A3HD@9:2 P |j)i0oZ;qB[Rp~gYׯ뵤7m:Gu0\b(1E Q2< eQSJQB~, V@@6HuvFTjnXǨbS7r_G_*9~`XtcG,cE :޹Jt* R` OF6|S~ ]bgس7C(qX{Z6!(@ h{/p6b^7֧ ?ε'fOZ19_IܳY=DUidX m!0YF!G#Jfq*+1b[CN1Aȫ%aЕºN8Xt k1A%LOuoׁqH gNXMh $M$`( ,82:B7a5HJgfϾuEHZS[& Dho{6i+ȹa9"! ؕ5B=%^C ,ǹ eoUc)ra^D$b39:&{8fD̖;15Jн(\e98H%zͫ:"ܽI˸-ǖ Jܨ?J%O7')~(iLۃߖaN/ȳw4YaaM}VSȥTZժyM(gƮ$ЀU}w@GlYX^wmx.)WW\IC(tSC񝅽c!;qtܸ"vp,cΜ5c*#87Tj ed5BMn|~HMs +.N"!gU*Icl1SGN-4zFeL,l Xck`p5C;[ ^o~$ZV+B+h7erApCF/sKٞɐ?g%CϾ|4_╒͂Tn>U8o/1w!ؾ1,I`'N)O_aKvxWO5ʭJFW5PZ U5HiH ٦)%D X\NP,G[&_Bl{&tc)A-237`Uz{M{(s!]ctD6M REy {%ļ"kF 1Kd<=YQnaYv -z@uxJ \gadÈcŇ375D~7$Ľ`t-W3ˈ9rډXRAw](]ŒqѪzaLwKyb ?H`ubrY pe׹ci9`aZcN\`)8/xnؠ,rPc9]lm̙/a~'QTỾzXRί=뺿"Lp9{oNFx_zxqZ~|.g<șFذ=D(8$= 4h(h._(;%DPm7fO-RO'fj¨\N^B2q#cP3"UN`wzI^Ls& IPֳ{?7>ּGӅҏۺm蚶߮*ʜvRqr%LQ( .u. 2{V 0Y "ըz_:>%"%,!mU@ܤ]KJx.'ir^= " b[^.`9MO!QĸM@8E-KŃgYtB\Z0+?uGm.q,]sxs͊7gݢg:[2%ǦfsƢJ\ @NdLr![h 1H~>KZ]V2g`v"8!xHsXeBypͪ;4Rܶr˒PUKaY0&+"Qndw_rN52t\W6Y͕d*p( ~O EuTZÀ~IgH%ZV^.Zv!_> R)#ː}AB_5 /29S%S#Oda8'_]_f;eĺj=l IUIHML浤(,܀Kcp*W"Cd8fC(!wnFR˕BZ) ;$OqT]C/y$PFy5 lnBcb:cCq*xFJZЬá!I03d+<6꾾tыʎ,jC89aQ򑟉hIͣceFEeT_s*- aO͢[mrݵ.oJEt#$~ܖ5!SU*i%ņHLG)|b̆fqB;p߄*uMԀ?qLV5t4m[@9%W I8{A&f`ee='|R6yG,*HWqDș>{̇e#nNisu|J/7澃f^UFs(SALj;;d-G4:(g&Vw1hQ{~6I!"t\qxI#g0ڈ)*WQ@[dn˟ ؿ: ?\^ \WT)(w pxnYX CGztYW3Nްs ;OI}<{k)ϋ~[cy77=z^¥[^4@J.et;)0l'#]r(:/B~f__G!x iRqwD(g %!=>8 |xb%@ѰbIŶmN*m۶m۶OlֻӞ=YQ@z@WʫqE.q.*UV}\JOd[H=K |e  5%RC㢼Fj#cIDp|+tQgks.e|ߩ{0`m w7W@?dAɷ `MO Ϥzh3AI3{u8W{dKnN\l12/79&_rSg"v}=_ox!nFF+xe]8`/m㥎e:xM0f{$ْ8G3/nqn.1Uҁ.b$F&JCs7)aBw) "8T!#7v1cXQ͊P]uΤŹ[p~]dŲVX+T9*t ̻ [/bxM`̠ϱA2׍ WK3kLnLox\if6f=g=8V'v7F̤s|pA|=VΗْܼ (͹x,vxلG(/[;q19]3$eP=(Ok5~龮wxaY{;%=,goU%\Mr/N@ {N1it3>xa[^lG*Q¡#XN!ySx*sUtʾ`! 6@Hʁ'#Xr]ȑt%z‘7(˃q(_ P87ifYJlJq>;#'4d`Ⳑe9X/cVX|On?TF|u|_;j Rkأ q|Xiwf:~^òߠ$<c@*5!XM!fKer0*Mk t^4$Sb 9d]gpr8CsÐjCR)LBC޶$C^w>YHV@/T}d:KN,u%*EWpC+僉5";,75Y\T'"qta0&427/S-L? psju qe/S<QyL( .!Aand4%t$)oO)5}n_d5Ņ[y/y)E9`FEN2!8X\8|(f]J\䈔k$j5e}Rl,?kPGĻ mCPs.Eo%No.gĀUXwi9j_D_ܦ~%4Ėwc6 rfV|n`EPCJM,!}#)M79/|vt`R_>z ߑG^%?=-hE| T醣 -(V4޺v*<5f:vBWsMLojp,! CAt ?/!(LYWxcl ]j+]0H]6:7^ `[+I{hyR[Z޶z}hU>]BIw6F\h"qe4VLDD{hKy-_!)䵓V՜kW4s_E a@Xٵ|$4saȱ|h>frzI֙tOm./Ә_)/Xj颼j&4TO`3;]옵4E39Z& W!\>2>M$M3zDΗ;Fm\cJ2k?D9_s@zW[׫KZKt[ᛄn)m!͵ޭ@,^qM vWKh|w3^v 3]<{IaFѮ>G&H$6K)5R=!ѢEnt>fpzz>Us@ZcӨQ_70J{1C_.?seg|?̓z>E/|O&%/t2ECn48w .C)NuQ+q:!f,WImHv؅<\ ])>f/Yyεx}=qBx>]|).Vyօnjޒ1Rs]}Zժgfl_2[geqfqU 'k|o}L[}ζEf5ohR*a4e]\ z7J,]ĝ~+ĜͧzWX>a~}w,R4'~f%|;U&4L#PtuU :SqW ޺5{V|ܘ*c ᡰm g2NAs}ZLJGJEe02<90RXMnl%5?V{9} {YS0pu{CX&v= qnZ:wN֮Van[5;b9iRfe[vMuQ?0U ^0T;a*Ɯ E}f"MTl~rmt/XF~{l \7JysT>3'/6zo&{ף~;a8# /ʹe:%#_۫zL(bfg9*0y^Gy qyɡetMiKY.K;K+ȹ1Ɵtu{z?zjy`eNC+5cu,_|x8`N(ʛ7##p0n;f0mJګwYVy{Yۑn};c9i&Px-5V33H]?7_ߎmQEo>;tEVϗnV=v ޯXRőbz}Oyr*]Ozz:gļut~Ev]u"A| fKl$'a$]bw ӲN:Ztmdۭ|bȃy9^VO{`\ν}R]o+- uuIۻl낂!oeL3)3 j޴T-q3o?LpKzHgM'c)nпh%;*'ry-)SKzfTdb:`[]K_;MY=+.XGr]κ7l4<5"(lPRE1Q]jom|m̺&->1pky胤0JNfX^h)To3L0 d, F5 b _IDH?wA軇#{CnP=DZ5qPV] F0hhe zߵ+3qCn5YX|ױ"a`M?|$Z 5@on%(b،kS#!A^C;n4oUmkZZ/S%6פGݘF(R46|c)D T㪉o̅n4rD Qз:Y,IML>Xuˤ(M<6sw;L8A1i20vJ57bʮBGfeh7dA0WPb4 D,*pD%5^&L= u}-+YZڮ~TxǤajV6ABnWWB1/+@^UT?:o̭3bptlD=T^8osd Fwmd`=ZMcy;d d w].2sBb.&Xq JĆg|yUuro.%v5(rkMKFVxԗջ'>dQ5UVab\ˋV]ϼR+3O}鏇`ΨB2LٟN= W"U Z {jTTWnUAbBAlh{Gk㜝+C~;OpA; 'p:} ,l}eI%?&X+p_fVrޚAVA}b;6__7ԡq2-ڃ6]ٍt#u Nd/,+ FN-p=<5ފew؋a2QA$] #6,0בޙ KE6ng.|Lܬ9|ծBL( z{OjGgPRhcN2pZ~3ԎU;SfLԠ={UC* 6fc/.5Vy9=Eݭ)N̗S$ۍ;a5~,QRh)қ`+\6OME'62Cgȱm'ԵF]y 6i|=uJE]d@4 сY=쳾xHǩ, #oew)u-aB +x I].X>H&\*q)H][e<" eԠ&X7oSfz|'YUܚA5|uCq8h1 Eu$g:Z"!=G9 SHv(W>rU)@*a>5B/,9Iq1B@y&n~RNiS"Ic&8>`hHA+yFh0c[8~(/v/<#Qg[t ]DN(PDY+ (! l?D+UB wGaWx˂@ ( *Ipv/H_ʍJ_[br&;UsK?R3p^>"!=󡾨 X0jP2!V.p[/<93È,еU}OO| Ԣl@'{9M+fV_r|@F t?ȕ]9U]*u[p0f!Ƕ٘pOCUoķ51~>I5ߵBܙ*Ҡ|=^5Za|䆪vOLVy&A>bVVP"R(rs90(1$v+hZ( iqPC7ھpsL6҂/ i۩`n߿>FC񍚓ꊃM7 O,>r&e¨^ m~Nδ>'_ 'N0.?_;͎fb :=A~BX8:IHsĘjfݭNT/U|$VI}nkǻ s|}J- "Ӑ׺-qXlc}H__8xwVHR3nLp`Β2oWi[(' 3Ccv3iI$T(4<)ka)D]%PySoiyᄋ^=[ړ 6xОfܤAUNTԔ=8H~ .gI̾zt (>!EAu;70V#1ݷe&*s=ýwQTFfgObP&}g=/@ {Es^˹nZD7lO{H8"-MoZm<#lF+>5zӱLʁY'EұSΪL~@pK6Cxd *r8[!J;m[ m$@Iͣ~ncۋĉɄ^-m(%ET>n3b2pך/ f7]ԥozoج m>ڏdkưWw=K*"=^cw%WGrҸ$hhJ#p{0X>kGz/zyyavR8M݈bpz^HF2ϩ*< Q#췥0Kb6h' &l֍qzوYEuF8囆%jM.Ϗ["®7d lML[ ĎTchHWT@.$q_k!E'Qz)$ V WƊ;ܮTj_\~3[y sgf:rCWidߔ`&[& CU2$&یbtY7Qk_(%6;O 'ujT}c^]LCB;܀RH }\WOOtY4{W̃Ҩp w&%gVW_:qu>S{1diH|6e>ĺj,c%I8MUZմ\USÎJn)Ju!֔~ڣ hv8Z]+W!|!7n;x׾T0ގVa0I^$^őxo.J=~R'.ڍ\])?'F/P] W WZVU{ Ғ'{nzz6\(Hc M:fn $]$݋ ,yKܪYKNy8/s XT` 6Z:/eQ4&O]TuJX -D?)< oƨA!cZo>Alk`>LDϴdo!&*;L]/3dG !U eb#ڠm " 2 V [ņHٕH,1Ux~b[@4*t5a<91LwfbU` 6*ɣ0YtVȹƂ6;ȃH$2n*7#_T{$·LRy׉½EG\AH#o~n76deڦ.P EO,{XMJ0ӏQӗEŁu=W異'0Umn%`}!.U5[&EO8ąoU=nZ 'HÆo6k AU S[2Z/qN SVg5b<`9?z:/{Iu#LLOj= ͢ +Y^-m*_qX6u}T$;֎TqCdk2vp 1BRS+vb1_7 `JsŎr"/j>qcGcN nϻXjF=t *': *C9$oE*K,vy{_%|Јs˯b='WvG5I=CP4]v9JԘ7|˷#_jϓhd(bsAo}֧-cJ_R0EdUe].:^Ԑ{TҖ 4;f>ä"vWJԊ[L揵Ә<|qYY1$ gTW}Fq.]3&~ɐ¢aJ)+Wv_=M^ƜRᦶ·̗C:BL)ݒ +I0rgb'e=2#VHg@t?aG|0y9`3SUl(.)h$5sPhXwI&eL>#kS'Saܾɦ\V`U;MuB~Mۨ=/I@mƍAT -~ͮԱil$uʠiԩBm|P1Fb@"!d0D=Cd4Ww1\[)X8I%rTvIk,%1"gCuqɶ2t=f ;YݢG&13ۄ-p7zExDCX sR<8yxO]V/[ӈ'=(t& ]R)Ql`RkKBPwZ- j~7T${*"ܯb &1)0N  }7fD'#\.^];T-Wo[K{ ?hlIȱ>r?ɕNӶR/ QX 1.BTC_Ľ?7=M4tW' !12Cy (wc45L;3I]3eifYgQ*If 7Ec# ΃\3$|AV&DNj =TS򟕱>d(Qm P~+bVJ:ĊBY0!Q f‘k}z&AWlU\-F}wp쾔"H.*9(2 )"i>A  G{`+e'?8e\e!/[!5/snU>2 3Ub_6Ek* [ 50q2.mx* 6&H&n1˿ɹR B<o4C+pRJҶ[G& ":G7!M͡55E]U`A Dc^oǧ6+e}ɠMKUnJt|M._0;ޤ`#A)I`Xel}%@s @{x;s ye6Ml &+qt{J[ ůĆ9fOh)<1s+BfKt9|lG{Տ#F#eEJ` N.Q|;DBƂv-LرzuK@E?b#kg; ~fdV܅.HN ;laDuI2*J0"hh LP f1s7q֐!Z~L};q[)ڍN+C`,{Nt )!-#A3酽¯\953Ph f5knHjӸ+S.;O.UcЦ fn !OjK"qS"a!)=ɬsiŗ[OٴV󏡨A - n'k ]2\F[4y;]bQ=r^)x2k'@dN)? ~SDml% 7p R^Mņ"TuR &L|N6`\UEy!b>B-oձOL+Fɭ6`mQCnώ,foyx~fs~?_=wO7'?Y-~0ٿ~ll,n?e7Sw3_ d@C@W-K*f 'cY!=ZzKhE<1Ҷ_DvӠ ȳ?CIϛsfE5iY&Ο5vA9#o;G^)?(+h^*Si_I o>AmdH]i_bۉR}"/~̻2rjZ ,q: Дr$+{7-vx#]k6+kx(mQ[np?\J2&St:(=^߽&) W/e4AFsA>qf߆t[~<3qa J,D /ѽ$!3`掄sOg"q`6bUV=M 5R$vK͏P2 :BJ=UE3&YZ+ExwEVx]vϹslFCĉnTF̲yL67;U yS29+`g};=$Mm(:mz˩qzS|tlyشI'oꮕ}PcvG XMTtKu?G$j+P8-\c,UjAiɳ6\gyA"ZFQD5ۅ#g>ގh{_iI4-iGo҈x=sՕqƧR*[U'<88[mTS viWJFs '{ظT)3]Ɇn`sk}B h)EPiuU+VF$gsbaVX{By<\1rFƮƍӨU[f.9u>=D*}[zhĝI)s/NybAqsc΄eoqiɹjӄ 󇙪~"w3\&_=GƖ݌ҙ6Gֲo'7}L l (&vKۓ/[ro$هjYі|иC$ |Qu2Gٽbe.C*?atiGa'4`G,uS0yo)L!Sf:=Cp"=-;Xhzڵ8-b< ?hȪs.LG^l -7Ni@~4D.Qv=nŇ:~ 2-i~j,A֜nj-A$Jp5gRg1VeH!g):>s roJ:2@GRuUf~t$D{llM`mgnH wdq CJQ\~;%)| sv)& ÖM91_R9wv?|TR[Uh Ű|-_1gÔGqfn{qے91ڌa?n3bU3.y,$gBMdtRS6$_yJSB?'pbޫ{Eםǖz)O ]͚n+l/xY=Qꘀ؅*/R\w4\QGo/HxaVQ]q#~߶OѠ0}<̕(8,(_ꡲDSz,9+ [['IK\Ry:׉ lw@LzL!ueR?ؽAR.߫(HW0r_>1X̥KOHKS^5|ɧlDwpDynP>ӯ19Ȥ4g`j0 e̫-w#Ω]б<%h{dNnro:w{q"ϼbYz48o\:=2qE-,QZ[LBtF,2u8qQ  ɠh/w}a)1&_VCEO +uD:Xۚ<yboV>ވk!~gfb2}xŞ #;y )AEu1͊9t{iEA [|*":*w.V}Tz=r[`4> E2>^e1ajahHхb᱋R:ق(ksXjyXMAûQL;)!횼Oz(77]Va?:bM'76暾G>^FsGt9cе(4LbXlƧ(I<^s:nF-W84AK;#zåUp]#X*4.5qqTiέ''=ٕh\Xd^Oauh]{A߻LzEe=̩[ '27Z-_Er bz +)mMKY4.*n }~''':vY4m;7C՟Vcw:qbWЁ;r›k]3Oi3'6ت'ޓROnHNo%+ɭ!OƵe^0-BT%Ѐ$mIqݤ=˟1.bQͶOS |H @̵wOho5}At6=U#-1C$te'y.S67ư_\$֑&9#i(f$PW}Ay psnt;/U@M ũ5/9Iʽ=t#ln&afV^nc$gR`|LuifR<1̥24a*\:ô#ckIvmnuo r3a[a?.r!|깎1NSn]\͚J[isI}w)eS `@G6}/a9_POc iNow'K;{}S[OE3w1eJgE좷;vu0-eGrҦi:9-ɛ#ٞw@.Y,:mkD)9(@cD3nx}4O>i#)qLqR!1ӧ1Gn8ͨ=# 75Y89$1sNiH>K<$gÞv F̦ݷqHh]8[T[AJ'~qFG 9m"%v -Meצ\rӝW_MRZ'u:TJ{ .knĄɓOcT~K\J,ZbP5Ϝ'4MLyK(Zz`雓tr@ّ!m|QkA_#˕XHje<yp};۞SLzv%عϞ=Jb)y<..[>: s$;*ϊ'37hU1Oe|LW26!QwUZ7]:vs{%+uN+E=S1<0ۨ;`bܥқQ.~bM\Jh>Qjuߺ$ k/ui\uX,^ +# ~VFù4`% A @uNy ٴz#QZr<&7&nId(C[T;cZrcMͲ猰/B$,(vRe}f9[m|j1!JC٭sƞD/Ř[`r8h@xLaXcT;}(F'C!W@) 97%9sZB_vߝx@S&',M`h6"E3aO"QSD&3_d=E~mcADN滢c_]>s`hoP N&q;w^I=3Saƃ{[BN?}ai_μ ~z_҉=ceUBqoktoV'M)-$>|%w [ j:AW [c4fЗu*6 sQ\mckOyw8Piڲ.۽'Z(amjyYq?m[ve4$xwQO?lB(hC*s/ŠaA#Ե3KXB'׶  nEg^<rg3 wby<wAyY!z&?V| ⽙/TN d?kcˁβ0G5l*A \}l.FTsS({:gwt/j1}>#iNj[?d3*uPս_2)BDr$wFfmŽ.iGZ\ȈދQ C=(eѲd}{O'{GQ37?8tҤRZۂ@ L&:zrbA~,u5LZT g-Kv3bGTƜX3n^vyʨ"8`fJ(S"42lS Uמ87lM3K <ܣ , 6ԐKG38ޛ2/Z|7iC ɍX T M%t.;;Yē--QT\`Tv^lfް Bt[7=#`˰GrƥHI;16M1LF)jv~3E}'u+uˇ~ =)0>m'+ _/ԑ)r 5ۈ[뾢~EcbIFIHYPִK9|\hN6|꯬|o;6<˒!ћlJoW(c$yyod? >'R0O4-'zNCBJf"dam7엲 33jɟ֞'u4EVuzg1،v<ݾQedڍdʪ [G(cF=plDrH'(|.Xf[Rb{k498*7?*k~{Fb۠VP(2B3KZAJ%-tCHYgYmU몂ލͱ)wT$|9/ּM01شd ҉玈5>.xrT|bވU]3޳Lİ݇ O=<"rm" +D5َ6DhAp vFЩGeY9bєuemno>V޹V憔Y\17.C$LIbJ~¿>z; en,-lyB#$1i35voUQ1[CH<%,,仁PA.XIg\v,#^# /BC 0tc$h.$*Tؕm=`kvޔ< sHp}n RR>*sr>31~~U!x^G tgd [M9KneK/f"hӞ.99E3 i2rz[]{njQ5y܇(Uﳃz*AYz6>G=Z}Ňs$<Oז=nfHAZ'SkbDJFf WuI@)=x-zA9`M3s*M;Ao c}kuU?)*HL4==R3Wyw Q7UKs<X?'We$Ճ@񦷥F. pe(StAf3 !Bۘ_8{-XN~K2FC0 s?v|De@G½M|䨒ġ%|cզNE*y]9: ShڞX|ri ǺVIw,YĔ󧎃1lɯ,jmEp4nWr]bs1+C}@=hr8_(=z89[͖ޟ7$عY4d,7vIxSq +뮿E^w<ȼV8udpxt‘Ibm׏q(؈ۭ*4kxf*LhV W~2 HO!wsc.tX6=87-l4Y3h60!nqZJm-d4v=r ?HCgi0C_BG%P1Sa@.3mSb^>V[(t29atlԾsD%٩d$I/}PDQȶ-$2# WR&1}΂:{#3eZ:<̠MvE+S }\} +ͫ+D}u'Z)R>*/,6c^;o1NӾqvb4V}@q@fG'5}8+FV,L+i:3h'gfskE]> څnzǵe! jєI2 SWɗ? ΋JWcsYZrn9=rg^^ݣ( OܺgIkٙ]Kd| Y(ev0yVBU)5#+jlCgO8*|UFL(KgӐ527츧+ekM3nJPͱZʙ,i3$Aݼ=(RZݷIbms)3vė>\#o WAҨ3>آ/Qu )()h":O×>d[<+7RdX(;)s9K"CF6 I f5K,#U*^sNhuμl9X9ޟ3g8O=hb u4fT|{-C S cYe#lU۽lw6*Ԅ]abGHM^}hY2eaCQ&CrgNJp,Jj,,wKG7M1|O2ݣ.}ۇyt':,x?iM(-T<(o}ϝ"<]Z>js)N%sx^̠pY";[2M KQ= '9 KԾMqL2hCMg\m ʿm9-?]"=f3wl6g~BRf<$a'x#}D`Qof@-Aָu46ORSS>Eئss'ģ '4S?uv"v 4Fi<m"s+S`o9Za7UC]6tbXGό2 "#y'84AV::z[E\ m'u߷濽tl8P]҉^ja|SU;[D_NOd=ܡS_q!{1K{bӝy=pGp[y@FfօYyY{j$*W㵛 e]I)Ts?HZ6eb?6/=d ê܇ɗD':ϲ(q7wy\2x#Ky*ϔr\S^p3͒ ~] O}ަYiӌ˽oW&-TB~9ȕDHΘ&.yLxuĖT WwtZ)cX#x7$^UH?!Ւ/s0}d=Q1w-yq$@Fg+DOIoV6ݓł->p9).qCzA\?I 9EVIA"%J9;;*(+HHHJ PI)YyqqiI#&݀ ^ qq__?Et?KKJk;0?Y(p/b0sGz%dDťE%%dW%%dq1YArCxb0QPOgfE剂B0|:{ a@~& aNhEփ¥#~F75'8qmz/=˯$ #GoB0pg\rqD`n F>W6rO}WHXrN8&l 7Z @9@ݜHO(@ock>+0~$Pg~'k@D4hH_Wڸvo~O_/ثzR~\_pi#w73xҿ& $,!!h?b|!_eu0l& _H ([>} aj`yף O[@z=F"`VG+W wpx hf3#7B! @5Ȫx@쭴[ fIʄ/|I8 17<׿>ޯPxvgJ?񆷰^ Ix7 _p43|_q~Q*ިgξAx~_o]7 詒5.+W+ٟ, 83DQs~_pR"gھJi% wvw; A_s30鼲go?(EvB@ Ca# pՋo>% okh8w]{j(_~.s++jpB0$f׸Hp pu9*&˙?,=j+n4AaHG7Q=>nunbHm%roTDh> ?sr; 낄"˕Nx'恋.h$"3 뫈D?DI0_X]Z#h gm0gQ4t/+^fc q 4c Zm0)c5H_)8DďUmB+5uG@үn m}oNbe ^cPZhOy_ øa(|fLs mJAW-BBceq;^bb@z!`$ZB:`CIIka 0@+|wz~Bwln[=_ 7B^ sL@m20,qxҟh Hߎ:H@uA"BDj Osw 60EF 6778ͻB0@:1(N 9, q" PցBR1 (Xoܬ>v63`Py5  :C8RL`bkP 3Dn4 Et9 a~EB6x2kS3i`T5(;d)+%B׆9!pG'zݥ7F udd=+g 6׵J> DZU4=/`ݕ/ /܁ ]߉^0R7j#kmgS77 c>ƺ`r[_9zl',AZap(S(vl|{}$Aj6JPYAwYv_ ˦P"c4T xo@`rB@*8K8X)c~@i27v:eCᏰ'Ҿ7 ϰ84Z 1`B앰Q`s7(o 䍆P0CWdW%dĿ_-2R )Y999Y Iܵ[rxhnnZl?A^t3rutHL#6tHxK=XK*c|+Iq6_骶eSD%ϨBv_},,~lfk[fvC:ͅʓuXk)4y,kvXv*g6EkjM|Q0ߴG&d|恨UYDrF W+ߔC&Ex+x T9N&/ Ie!f"Ũp-v qxS:^] TޏX*ZU.P IAk]Rq}+NI223 bj_]ҧV֪EkU+⊊ZTo@{oN=d2w݇a (hwUt^2U6::ZTjeJZȂ>^l,12FqJ~%Y,EqeƿJt6EF\9L܀JBJ+*#jxk&Rf謤DPR٬a E[p3AX~-gp#fa&$B.K판2e"VR4&>X=Щia]G])_ t ʕ5dz[ t>6N%̊ qߞxŘt1(HvbAFVpƶIol`KXSV ,̓r쁷AH+@;R9hC uEG,pyf!y(Z\'h0z#ha'$h* *<}X =UIihݴR7aiXtP AFXX/Ȉvn n 0y2#L)z4 BU!7)x9Yo( 'y{[8N8z1~zDT6vTŬ6Fi[: br Y{%|Q61F9ApawGE u @E,4Q2r^қ8e4m+' EG5c@iMNjĉfB]k%i|,A豾I xo~1 ?q|8IgҌI)q쉧1Nsj!(cX3F*XDYK.ur mY)αh9#Hf[ obn+cC:E5"ȉwpjHWNMp9"8'!1>rr(|n=e;|GHi:.ضfRā}"ϕ)樆[vԁEpB W* @b=&BR{*Rs3?4;SV'Hz Nn@{Fj/7-W>&Ua>O[]`A'*'++n,+C [` ʗ~>[ݨШ: sBO|GkqhQcqS%xEvFqB@3V=@G$8rϴiIF&3vPޡ eKu8K)gr6 k~+xP2:a^n$1YaYH #fihl $4>SQ+ğ$OSpPK0l<)PwuӄtzD5X{㘕%i}\pj.l&uu34Itx&1Q ]1ρUx0En93m3@:#aӧа*DgwBbv,)'t6.wHX(~HeM&A>cXvH!J$߆[1w315cppRGjŽ$1%і㩘TFi!xDTep\@a]ᱦV.yыKa ] Pl-I ]f(* I95l2G[aFLvt&"Iox 8,+b; J-ShJ/l0R^Qp'QS@#Oo`Wz`D8RO=dArL63t "8iڮ8lph+Th6 t$5), L|U~tg?b?%(0^j75T:bGB~[[we;˛*JE-"p&@;ق=6-H[Xpy =^O;IY} L9~ T1IDlC{)zG(^zmM.1* Be bc@-BeR>DR#dtsҀ`LvIH@ܚ }@#>{Lxd # @Dte4c, ͤ@F]X36~@do=P TiM"\@f1s@uqf dbC PCq  F5$- T PƁłeFֈŗJ:@Tq$ekz@T uTR|oe҄qc{V@pldp @֘*(hF^Ot@8ݜNOX3Fmo|r. 㶀c_a1И+iZ/k=e8>Y0o$ =/|ỷ JOxh:"x%RWާ:h9W8B/Сsi*g|Ju%f%^.>h /]3n9Aio*ye!tcYچd\ł}s3~3pG'?gY J?|.};EYR_ּDǍ>R+5WaQjUFG1AkVi Fm2hQ(2ZEHbIqǿ:Jto4/+kF3׃#Ɉ38? (?u3'MU[gŊgL!xu bd!Uj׳N~k̮Ox?xɡ]V#se{֯|YWTRZ0=k髦C[ 'ц#6Z)]ۘѓ_1+uF>pb'vV:zOF7L;̲;~a$rE)!>9rّKM-U'vezi[Rk:h顶kF1CZqwK6^>l/oMέqdкn;'6-vz|UumL_o_9wKڄAdoph R߹jϵ3Ǩ.Ol`kfm[^cwΒkBZs/u|ֺ~Ⱦqnne'u]~hZ;[~pisɧ3j=V*YÅٱoWDau)͏ih͉خˑ)7uSk%nZL'(X:%8sSWv!>no~tѩ۫3d5nVE.h~ChO6WsA=w)ůM9GN]~>Dͺ#Q/#Vfλ:YyG5dw~w`ԅ_Nye~L9w{|0nL3W%m޾9ayVZZior;nҘyykF]{/?T;yg-_5잿I[*,Yy}ڿtq{ݠUۿr-w뿤JK96r@w5 ;T䍗^QbxLJ7~ ޟۍݻ=w ۥL1Q6YwZ!a#'Ϣ&o3d6k=AC~dnTJnڻ鑌K?jAZ@qoW=uњ7^ܡCqw(.w)i)/qw\$'L2$'<`}Yf}ɻ]g©Ʀa!1q,܈›whPHLZ6F]5Qk/! 3Q4[06QA3dq=^y/ׯiM!#c3}Nt~[R*W=X^Ϧڴo G` ȥRGb"A:]-yr덲3ʿ|>oaOs s}qqH^PxSKwSx,eVv"v|>A9&%O"zK޾“`J"´c&AƲh?APF^i@lԀ^%#5UQYEdz0!lp+7bGu\B౴Yf;FB]3hУz:gH~eJ!Ƨ9A`rhP!5] ijkdS-ulmg[8oIM=#e wb)B ؈q\?~u{Z!enF/q'?L3.#N,gOfҭYXh'˫&d/]Krs+j ׺CCˆhoFۆ.3_,}\,Zޒuݦb,6IDU:V=ϻea*3'/F 8Cʼn싺4$}iğ7qÚ/?ʜG ;5;}썃䔐1srgxL; Um8#]ǡ:ڕ&kvk֜൒ WZoT ]1#{/.r4.݌go𞤉Zꎥؤbp;1l t2\T;k.vw_b,d{Jۯt]5 Īr̯2YT_rpwg cenMz}5qr5Ӌpw6ULf !A؞ڱ{iB0ҳwiQQ]"QNm.5 p,wȩ={ӒiR=6ZIW9I^cǜ߿4lG& zw?M[Y @(€U9Msp[aаlokpnr˚7Y{Ky:x> .lrJUʸO7n"0.B'w$y۸kvҜД8/3^[hGmZޠ!ˁ }-ʤ/mke}A_^(uU(H"N}^uu=L/&f 2xEmӹ , :)4|k Ag\,`쀜cvub:F;^`q棩. 3O,0!Ny[w_t^E stx[8`dž/dTl1]LDއERބ>5QHXZ=kU$-&<.@N0 ]sEf9a)(ɨ0 Be;/h[iw3r_% 6`DZm˒XS2?ի{qk}F'Pm/"x'y>.)$3 &D[SΒF8/ExD-%䘏[o OIi[ YWץNLɜS߸ln 4mD xɞqJuѮWX㮦l?3Kb0a[E1{j[^hXt:^;*7u$Ta 8,Ѡl&%ؚeɿ>t.NW&-  ,g6C֤AYho/^S{7"Y4";Ui9'wSt5t؎ӂؗyHvn\rۛ[@4O4ObI57lzDtIfrĹp{laoLaqcW}߭J5Vw'uEkKJWv/eFkċ~ž/JcNm&գ&ՖDҳF|tB X +㏼/[,ľ-*bi&}8z쮿ucS׹Lv9I~>KTc!G`m$Q1Y/z]i+lZM3e1z=+5WBj3 JH|PMP(FahnQw>JTӸCiTÆK{Y8ؗ>5 |0 4zdd}LyDE\1ZlIF?|ߢ%VJF~Q\N#* [[eU x_hXT '.R<^Hl/1l1+P-] ȜﶺO-ku:} 8O+Ӄ #-lry(ɔf5C)hw0'c_ kwn:ldmc .SL_U'_{ _iIC $nmdzTy>1i(nsסSO1zmPJ4vL&ߤ 8+-fd$׵=ZTPH38o ZAW)4ǍjE{Ȑ"ɆMe;y;4~I eUf!&V#xj"]+4ϓ)SHÛ_z)!V-蓭k3 .$D퓙@>OȟcSx0JLb7"]Q5Cs{L㴡gTrāxd{M7~{nCo6\="X8ezJiT=ZB{Q:f;/U iV44R>ΜӜZdіR.A!ZYjKj<0;nh= U^,(6!tX΃9rJʭ|*`9iPri$uv8O!LAh^JlnN1 O*nZk8*J6iӵZh<]lͩL $Dӝδ8hٲ}.W4) kfߔ/fJ1l^KIX>d3ogMfxO15 T}@2XSR/=\ 6'ݞ(~0kp`Ťrh\:<( 3X:/ͰQ34߭B h~LęEK$ si#-:7)& _YbcB{U2 w}g6vxu$fj&|"FL5D4ݦ iA!s{ʎU&*-m@3OgP:Wڹ gCJnUK,HPPu^:pH i¦}Ku-GrVkÃ;q7Ra3a.o~&X3 $Dl{!nb\`i^Qx3CJ5R|Rc4Vm Pm.my >WFݺ%ФX@wBYG%}m JXI +@R9to )|!SyJ0"VN܌C2v[̸^#8B3"HԀ^YL?ty@[a&[;]Ta;U8Ӏ> 𭸖u"'u8 aD^GBiLKMrz|NL3~dѺىbmM [&$/aR>O*KQjSO[ mT*61"$N+l_3 ^'R@#튎a1s45ctfPSMx-Oר1ѡ cfg=dmĩU%5)⑨-!_d73;[Uƴ 2 l7f@A \P|2s(7rŠ\tA1 7ȉ &@Q#R6+9Uwזl!0IYLr_1Av4N;)) %П 71=ܼ ;:6<՜ _0O'] +҉ÞE31}"ucvCvCTT|q5d4ǍVKGnSьPyϹF -:wʼf`_#/xPKàxtGE\S}"pi۲YP`Pq|?#vR 9@‚cIF'OX^YT=mH8AzA&uT\t=^Cp/a`mma륫P7!(}K%;AM1Ll1&1rľkޗGҘb)N=hju҃e&DxKh c 5aDAxմ"-@KHc-Wl9Q/ilAU*x\-LK uV<öNՃߨC_v]?OBot3=rٿS;.YN,CK 2pi蹎kN룇~Qм滯Sn? Ns"ZVCߛu5Jۨ=}or#gZU=~b'+1o\+4l=FVo9҄'XF- D=b"ނj u6P{_JoLJIBeX| z*1x+B> C!}x-S(g.ЯZDsI " *V2dBZeÙ=n I1׉/)uy>Y6J¯[.԰>7r$YXXYcS/H(۾eQodg/_;FWWoYiadӔfdDm8֒A?Fׯx!l,_x# Oܾ‘9A p*cmP2CVtcDF93Kߓ&Y_hйu!*!w|3C q:0oZR-=-4KjlBšGUW̖@ȇ_+)N%1I"?!*PC1(VFfuo Dvq 8 x,[`@ZnlaL dᩀxlwí䫿~'짵ޗ-mntJReE.zjNT`vpyRۆxY<̄:5/ *`cLP q}f:# EP.]? ɶw19]OѵQgV;PONܹ8Xp:mmRfDR` l-W@XS!FZ>E^@ =6jG9[=1z`5Nh+a7жlL`V87dKnK%l{FbmJDl\pvs_ :pn19r5O/TО藇_:'GBhئ_ۏ{GʹxiDYG(xS 56fJ3C- &HZCW5 P" d1 V# *5>*ɋT2:U'YoTư='E]]z6ThCb`!aZ s!4d;RFGphksjaZU}7i.ǿmvk)8 v` ?gpFA 4Y,b(n#A#3#~3W9P@w'`ֲxGwOMWc>2:LFL/;3SIRi: n●1Y]߶gƳ(Q] w;BAJb,[-9Dj\pvIڌ!6,RR艷$jrfBL}?xّ$y[}/r*Wx_k ҁ-8k52آr Ǵ/hy.?wښ3kPR\XY7DKq2L19KXI8<bހ=wdN}.YǞ =51<jv~&ԭ|T;/_  V▿R_"X7OZWM39SD.!}pCFebD!OJvJ㎶kNn$HA1 TZК25h+lCvzvabh}Q >#l'3.wHd?N?#w>l=X/-Tz ;RP^wt`ROL)Eq#C.j,=s6[ز#|G2c~|H n̮c6  /7PCU)At*M+bC,q sQ_ܹt|Qd-<縭[0enK]D\:PO"}qk-sØ=;+KcՄrg#jf7,s>儐d߱+bfN8?^ivJÇ]0ԛMgx,8G J蓘h$es~(յC|WX?rw2vp0wZvg?Ihu}+ԠےF6X1O<.ɖ~O5Ԗz68.Nˁ/G6 3/me%xyv) ꖵr)$?{y}OָU$~w9mNŮg$XV&l :"~p/OMx5mk,h=%5p^,:ZW\]$3O3ojN0>l87hyy?VFLJ'w  RDf +?j>W31k-0l[ww Hm!+&dǏ,=k ְk'<#5n+k/~ӧO>}ӧO>}ӧO>}ӧO>}ӧ7hKJZ/xI i88?3>.)Pi8P2* tx2:^] XO $@⭨ ""jI6f7n{UE[g}Z[U-GYyH6yyg4i$8^#X84J.hCVojEJhdq<(l:۞|/=l4ɧc$m0NXS)C*Vi<5nA+9gtVf"i֊lVwf,DMc,ad άT;H;z8x2a$)B[бf$YK*(ŵ4n"XXyA",Q&BL=c(a/F3i2@ ӳAsx bVIK 8eBFNVc,V,X. 6V!i3dhg:@;(#2 '\)b{RbI@4 ,#ىESXێ'!6[8.cюcshOVZi~,CX47ʰ[(J@X)pA ]@+:b2 wG OkKRsmP+K @`@p(Rc%')fs [7 o|DxJ'(hTH@F9NPa;`ʩ9 S- x9J2: Q u#)ApU8Do.>Eg)7] =PjV)AB/C XJmE(M䬬&t#Yd0ǭ1ѩAwD7}")gB++rLb4.9)?b.Fic f!x3c2@:a aҧ2*D{1.Y#u6.wX(~HƑd#L&Q>̊D9RٷV̝L,C<#L{1" XÂ>VӍJ(->z$5PXW|ՠK%Rl'eq¯C;8z #NQEebYx@ LS%=N?D5-a g-KbcE zR%KШ()xE4x$V "@#POo`WzJIp+꥞FȢ1NL>=t"re*WLŅ0\eZQ* y9MFqEMMJ=aD^&+E>* t)mH/@* 1i+<{+?{[ZN*rCʆCI2\?)h [Ԑۦe#8dg&p 45UvRn ĨHeLT/Cc<[1U2B@@mtRpB BgPOQԈ,Ü0 ɞ)8Ez[3 OUQ1\2aVݓR5,8Z@& &Dkd/Bn4S|P3,q 6z$mr00Cx* z-P/bBEQ "b@@ ,3@ 6J@) *'[@XMً@/= 8x uH %@IցjX 3褨XeҘ!=w+t[vg Tc kB4%wO3Ati@8Üԯ?ao3NӲ7 9@z.|SjǾb`p'VgӴ E{=Ç$)$QֈH~eN\Oz&x%3JDz~ӵ.>yLB@`Uq E`(RVPAg)1D՗ncSx1hu ]=n[mAbY.A R/Wँ"@(\!K(c[pW#')|{sq "t#; )վqB|*EiM I!ȄɳHԢ7$i)%qdwX>2aYit=U0҃WضwȌo¡b0)gd .\5P< >Jx`Є*mXUB4ZV#*U:Tm&Dz 9{Ce ?>83p6xQU_j^?qp*Ta7 F^Uࡆ0m'FEh: ZmZчvC5}J^mE-!/9MQ7{n 7E\&gf=huczv6lz>Q0+mf~_FJPGL4fSի8\oI>1e{RlyiǷ ?zj,' bѽ10pͽ _O&vka:s7*_xmk O.u@Md՟ѯƘ'zޯ4a/ݘFl@bᤨ-whj_tϟfbm١`rUts/浫;VvY gYO]?jꛫ+ l_݇oFYoxܨ9KtLYv׿Tj[?d7{T7} 6Z9Ls[rwRؖV|S6myۗ^]c'%A=>|=2~vP?ZQ0ekόLQ|܏ v(fk-=4ۜ*QIbSo>8Eqՠ Z^4e//c[)X 3i4?*КB_٣iOo=>#[]𕷖't8; ,ru7Njik4ow 4z΄=^piJ~ Ͻ֤9{mqf1w~w6a wRk L^)úv|ضڙ~$ۜH0#mZ];bێYwn<"gՉ +7v^i_{9ʷoN՝#:-}SmIGaYz։*k2U[o\ .h8c۶mwԱN::6:;ԩS*nVZ_zTp攥 Z gpm*SKY읖Ίzo8\**+JG 46 o/`0ƾ.K@^nQ4vd#^SnHEQHA"Tk(;7 nVS" ~Ȕɦ8$= ys4!@ܠ)3KUod#.ȏckgF;q߫6Gd169&4AR`{80eFb.JsОy[D?T-dƻؚ@BYϧYAPώz廝W|EM/p-ꝛt94!-)8^S]Y~aoFY߇g) OWA|y^owW&:5L>#&v ՇfVƛ!Եjӡ?Z-mR[Zo6\ %iE'zz7z ?_V" V=[1vao Pz1$c&ޓ.jo)"{c11^?lǗuf L0(Ojg/;8.ͣgp휾ҢJm!EhEo. 0/JgoNvk "a, kZg ^:l2sҠNt6k`flQCt.Nf؏icahCǒhJ"<;>~fyH-;x-X/b Z Scv Б/Č.MNN]];;X^oҷ/uRH=(({rRr޵K0{ӆTAyc"LTѼ!%w,]E̤=i$j[|&Nڷ6Jt,ׁ%lr_H }gUכ74:؇ Ndۦ8*G, _~ƢxpW;jl[$_hv6}Hc9H^F @miV4aaҝiH+yo>xw7[c>1׻>{x?TļSd6(J*0 ky]^ HY"(Cu3ctPTثdQ~7&um m8{F1!)RXPjȅ0V2?DDI }0Pڜ%#_|s(_5&Eѻ}hboyDI lf5HEޖ֐+x|;;D"`PngR'(GF+AґUi򹔻9I,WD3JIIz nP ⹗9 9K̪{+usqʜ-~d;W eS?RDKAdyVN"Iht(u*h}D wNϋ@c^j78S 9JwLA,n[wt3П:el7;܅`%⹋AuPQkVR $RlU)EC뱝~Uj73m~] '"LzPm}fIa:)Ek$m#q6vz%}@h1% >ʿD0,UI }ѱ@/K-mDD85R&9`lok@n4xi-:s90l2cHCfQUXnkl`E I$ʌ0})62SBt &@YpoN]ݏVU%dC@o5ܯȚu!Wlυq$X}AҤm&!_z˂߽ږ" r%8I={d:]D!2)hxˊ=xv݄(8Vp .Z* ka*ufPЈފZ3],eMq7[q5 Z#ĥpLqxheF<;ȔZ{c1 mR:d|<섒KoC cwd$jcGuGف% j FLmo΢gE,}RX%ܖ p:Ù9};|BoxdG@]0寬{LjHB p&LH*X-a [@;Q6:7N9Y>|K]'VOa(º?`Q}`1X` ;IGH0 31Wgn/l @ h#RqM渔L*>zKK 8j#\ݽ TʫƤ⒞ƶ"4} tV.wJ.T%ɰn\pQHN#a*ws3.*8 O9_gB ~`(!j%יE >&ot}M}kU-7rP4v/-=gA֯ʌ)*έR4][X_qZs'>l^5"lu X< c0+po˱1;tZ򢒎983ՋQԲkk 0J"O Hnf{0TXWJ=2Ew!@*Ce3C0dZ~*ɚCiCqڥ 8P3dv+̿F[@n t;CD !øRmqh3kŀJɷPsb+9wJXͱj=8c LsԜ}<^緦^NsŻ,Tfw{fK-X?`1:l;1vSWMp1oMKP9ILnyPݣaӭviDA K1s̓*ܺO6Bp={h[2iH,̜89x:DyI+,gț`ow|axa:@uL}"%*ف.POAR(*vQ +Ɵ4ۅ~lQm๓kc  RXϮs^q(7|kXd)L*FZNٷJl7- +fMVx(Φw&)%3kdua&5OѦjp],_l˸!.Eau2n)uc #4X{QIx~9@EQ :(}ƥƽձ`KCDά?vn>6ZN8^d'}Cz!ܯo%cMwS4NA&Wzw`;;|$L#S6#H(L./APxǍ\!җztkHf1'eIaAC;⡋xDY Sce~~U TO>1tZ}/*%qLMZ8j2$+ suHC{Y'ڄ eGcҠz=9g.Ig< :L~9m_z ^K;r*Eάۦͮ}%HrL@ۍj ֊q -+ 3~"[̅@ xvCz0\!f$78< |b@Oq pH=L^5gyGfQuy@؞ŏ rFu R#s;4%3=Bp0ZU02 e갲$W''TԙEL<"G,,֧)Zfdyt'?O̦QYVe=o3+]Jzwc[W# i |E"SY"3jORBA:pŢg}*`JJ!7׆Rh&޺~'Q7T|, }E #\!z2E̐? 3-LǪ0aaN#b&Z"<0|RZuǁ㘃䳣]Bih˙;?+jfæv]?UL6r5l]ķX;{vtń<ek͎TWi)NӶJGj@{m%)_%x,#PXms'B*"0djNr1VTJ!SFQ M+MQ+}\iM9l.?u !G~ %GG0:~99Ԑ+~/\,@^U+NZv*6km \?JG20P@eiEYNdLhޗ.8e\*4{~/ȕfj]}8"p[;N>m@Օ[BHjۦ 1ut=wn 2ML&6̓\ޏvΌ^pL6˪05ڹX$_`X"ɷB y H$ʥ(mۃ@Md~qQ&*g|V %IcxRsgr&Vc)#qxC_j <_佈x 9f#NZ=&z2 rwWk;Va庅!kur f X^wV!vUӘ=3 LjсIбnjF9X,b>n~ߏ.}Rtԭ PK烛-/obN)Vk^jk熘bwl;[Jkq񙂨2s>8-M3R6hl{Zat'K^'j?(g~T/oJGtq|_\T[:2;0[l73϶ip)l=#E(,ffe_Zf`!KDK"r~i#W7[YaM_"9"]#j6LOgצ/YB_e9!tb%yZm7k2ݔ&{,.f22*o<쇖@QvQNE&}Ϻ!6aLk^rIo0"{yvNlPϸw)*-~(®;QdM{*,=/14?jW_)/&_yeYGqp2:9lY 4rm+6T#ZhMb܏RϏ -๜H,0qS1T6 FitT QiT b˴;'f姜&$!wmN1D'X>!K%,RڳmN%ʦA7F, 2i5'N^AfjKkσMJxXB\%YzKrbs'h&NKZJ'#fA:eľWR40)(Y{pbVIpJQtsD^k¶x$McSGh 0+d8`h5lIvKyA&."c~,^->Uc厫-@Gc?I# rIw!5ml$j鬫nMꏵiP4` F᭙rSm8vQ;F'h=C7MĘ̦U4sV,b߰WmT(oAE=s=yE->>7yyHH$ľE{`ެR@e6X߾UN{[- 1gjG䉦75FzNH(+UQDՎa^΁q1ь?X%8Ru`+K%.3<]P s_ggM{% E+41DoDDjd /Nl8ԒXS=`4myu"b6Y%.o"ûa݌vXLʓ}򠪯Zic]'& X v] S@4ϼ n[ݷah3&Hk"{]_+xjVN Y;fNjTY})A]F .24϶`VzӴ GtvW?EtHx d0ʈs'jӺuB-=3ϪkVUjUqNǾ2Wo6;ԝ#W~`v3{jT~y?6"TתvYD0bFy΄UzsǏl1 W`>a mH⊩ F*2w [lNF^ ]Ub.*[fO,] _cpN WS4"KUGZ'?k|nSWǞ| G i_`Ƶs[eCN=P6䐗 xiw!YXSON~;q!/dS|ʔէv\ofJа.W =sbciMUBqÿ ֽ7V+9[ل(jxZ K<ΓR&jIvEY 7 3\C "aqX#)8-*lD7.m0X4R,%>WffLUoB ݀3( ߋ?/oOa3̆&nhݨ-F?>&čYHw~[#. T=LJTHg'lHi<47|Y~l~W{2&/ne_-Eۊ_`!V>&Az=WI6ȔXn[Bq;X\Apߗwѕ,8MOuL}׍:PF+WA"IFJ]#1h7ŭ5?"畸pQr pxS'L EPd捥$gRŒ¥MY|+8׹Fajvԡ ʿ.i]C"ԟRҋ##.&ڱf%hE3-'V˹lcIB`6sIƆXq͡DA EuTTҁDzQX(P+(cM@ i??+˗/_|˗/_|˗/_|˗/_|˗/_m/x3( ׶m[۶m۶m۶m۶{ˮj i(?]kHud8ɞJUA=W%ZKa~F 4.կÀE͇dK-reݔJVݖ"KޏWc;+ƍ㿬?&?Cmk2nx'=_׻Ń2ro` ```e_˃N/Jͯ+lMu]ő;KW"j#_묫'՛18X$i_߶xK̤4|i^#/> )=tuSL /̭ۙCQ.on==vW􏣔.YqH^h:TіW)-ͼDHAқd/*Ag9~o;7?6#{D@ 5VÖ/fN8v]bފc,қٖ;lZ5u+iv͎.Cb`]??FhI.%&vY;Cd@-~mO,拀nl$qU~e^jJ}$P1i*Ex5p_8d$ єLJ'gZK?7cd}D6t8ri>_ɕJ"{/g߾^QZ#sR3Yi uMʔ!Zq~D΀%UhgIG0E01$DvH\+D֑#Em5LtR7SL&DLdH, `ØR,ac4ēT֠\T,OccO"͝]d1kـakcXCV=Kq "7Zr^ҨAs=(nH4ǀSԓBRj Hձj8в^-K2 !E? y{{> Qs*Yn 7 ډ}tI&߃98[IJNHHfX<Hn` 7y$?JqW2d84k/d 8MHSqŒ-Ḅz DDEc޳%|.E$TO(&1rϐ(vHMsJ6E4RM##[,fD#GkrS<ׄGb̐Ħ>:',^Ȉ\Y80ra o ]j0El?-WsZmcS5wہ %m$;15vqf ; &fꚦ;\8HRMBx@~L;˂O<ښ9-4 >0e FT9+u<R>03HȆ*R L{?zvo8([\!8<Ktp]AJNkjl\N#>ln%uw]{½GC1%'[QpE\E gZf"Fq\ZPe}`6a'_(ՠQ\yJ\j FTk0U t.A|v(2&ȅnq)#H_ݪh\D=4%k{$]:QǙpTTPaH4s b f- d-0pِIw ] !ꂃ(ίj\3͆~bXL>ÔCV!@ '3$O gt^ ]sq4!;('!%ek٠~nU= P('a&=RJ mM!81|aU0C}j+BBEh@`Kf+ xk89pϟ.҆ b6N'|7pAI!Ua@O,1^) xBd 89XhdNoVUL׊*4>r,!^EAZ/*lxGGt6%[+N5Z["Rf3kUJu\ɭK9$oH+4X%WQ;8*}pO^yhI C1qN%>jFI 8,xI`W$O}18M}͠މk,HvB-FQ*xLx@-CUUaJ0găE9 B[ yCjYBIsU&9{R8[=7{Ӓ)E'l)e#'p%] x[M ۮ$#M1>4V86V WM~MoT0%9M C RM]:ˣHΈM &ҩph4.?B(>jZGg>eU'u#;ZK: -^ 9 qحΡl=w3bʖU@.irjO-ۖVQ:!ϩU}e_i[PiUFnxh^;pt' yНΧc^1$VnٜoKBΰݓ#OjgfNtA~j:_'ZZfWF|=d6MPI.υSf۫y ܞI4Q&4(f=nL*l8U R[s+情LnMRH\-l7DfВߠwO!/YHs^ YkY ],ݰ/G%m/*yYEk[܅.ϳg7Nr oh\VGnwGgs:NzvW;h=lfz_^zZVmjzs|ݒhnʍk.+v"'ed@Y/sKɔyi˵;ڥ4I]lpFK`/ BYfFI mԋ=Q(.Do[)._Wsy*-ЛwsUW茹\MݞUpmx ބD~<݈NRx>|Kꕣ;M %kWp\GAr_A21w Y_6&+RwoJnQ5YꚏL.vե"MKB!VۉNyƼl}^tTUR9H>ZbWMnwSƚQ,rXP pw.kn6Ww;p/Wǎn ڐۯjVYowIHS 8̋nTiƒU*yWݕR/6d4m.eђ"!\0(-qⓕ&op/{_Ts௞ʸ?(;lF+ 7Q~D<ǍVƃ& raPY9Q3ЁQOoj%j;G5>:!#SX{Á De88udx~7un9=-~YX@4VS쓲t#׺^^߲F%7܇}/'-F->-vR X NE|2,OY^s..tj떞z⿁HD77-ʁ)PV"Q U33Q1V+*ʵٸ:wY#T/[ؿz}N\"-~ߡ ݯ ߎ-?:9f3X*]9u SKѤ lfvРXZ;gm7oHW``QeFZ(FWh8l+@9:_2ҘeK_Qrsg"#o?b]{:FY?H=^Ty22mo?< /<=y¨˕M9ErGE<g-a=g٩׮%'rxVV(/C/íVMzۜ[K\Z ΊM>`4"'&cY*|VIBWv WtzCQ?&&S䱶{?%mH/,a9SZcQ1Ll%o/ *"mJcu;V~=A{ٚ?]xKq`K"g;gju1Qn)> &8ocsg/eH 8=ag/FV.s9;qMkr<>ѸY{0ǚF&k|f܅=RhVRg~J!g) I?0,! c×Rۓja3 SD:FCƓ1O5o1U'1CH3%׏. 1=D2Q!$f*?m?0vKm8 =$7EWo$!)Xֆvj:zA3M KoDfR2[ K3>x)\Itciz'DU]]&p5c˰y}±gWI7JI3~n%9"+yU"IW1Z(6wqFV/8:H2ITչxo-e H>6KGMeSZO9n'> E5.YqX67ҕX̖z5yq&v-zykP-qtFN2"da:-r'ӫJPbʴTt%wc?yC+ ?߯J[V\zj0[=QMTCo)B7(])dW@O&D{h `hd\iQ$].EƠv|(/^Gu}rDrF O~r$g%GW/r bdTE{xT"3Y;"}Сoyӟpޅ+&P!V\IIޝZ殢$ط<{ǾdԜF4`Td">H#w|C^ڵ#q]VDx,(8U62pd !*Gc4rWD(tg)2rĉaAEeɏ:)}rx \O:[򁑠{QF%>(ɺP܎?\MCeAFp-f.É 4MR"cALtŻY)*q=۽*/Ae>o:d/8^n9+󹷅 x_˄[:&N "<Λ)OثoN="ҽrZEkfbSs5LK1A{u#X̄OhdD 5pd_|۲Rԅd̖'72@%o-y"F'_~b#{1x"zA0xb)  z雱6YO#-&HX{7td0fgA@;D0q*"{Ks)0أ+e}zNJE~7-O m:b@IܮB 5/nTrhS~Wg臿7}dGˤيbM/] Q/5)X|H<'"h+G,1T2xM L~56]6 )0J&o=hySlI؈1XQ7#CFٮwK7R/i'Yk=ܬ!Hsٓ{aDX 6yR1d{oY฀D~1b#]}Dɓ[bniK̅β_8c _Ń#Je%'IFd8qWyTTNLfVL%h > lC'8>%}dpIɞqH LNmH+}>-6]*q})Q==.:de_JV}'=kD0N{r{QmNz/c0meJk&+oagu$C;O!u `hr@ ͡-)m_/ uPfbTjM2%-xoÀSH8`_}լ|G{6Kqj}êsCH3i6s`x \?C: E_VXFZ?}|jٸIy2):  mAB^Zb8լtlYb)Q0ց˅C FbxE])@ҬSM!&@, o3t<3e}N}=AYB?;W&<h:d51Әu%mw.kYp1EkSl{ZxR龸І4EToU&lS0F - MDkA>̓(W,pX!lOA$y)wRZЏF{Q|i=CuE1e'֫dսٰar^0V5.t `PPl|e`]lV75 MvzW_@A7X>SpuAnTX(1pw;t|][pҖBpCBqsz`H͐I(84B/SlaV&DWCzΙgL5B6MXBH' ݒ(qԒݱv \`b#eCNy Z ~v fxDـO+9erBIuFMD)_1n`kaﳥM l0yVj4*_h#뵁7*jP0`~z9[!Yȥ`bN$F> )|]݈O3/6/UUGKN^܉5C$`ؾs۵eD&*XH5+8P֋g#\3U rVOOáKe\aPs= BW}1=G,6 ?J_ n 0v=12q\'ĎTwVFSΊv-Ty[V8KyOާ\+1eFa:lكq1i|@kqCOG y!Bg]$wۘf`E^ؽ݃!ϑX!gh=pW ч>e~h1cl]Cu'(t\5y]B.t YHKnq&P=dM$w? *ͦ %-l:} -gO1BMfn^78v@8{rvͮr p_fT🽖S]*jĻt_yׯm?m%qx[@3_pN$!N{M_+qZ(^7>au/{<-#럙&c܏=e_"w؅nP2gɞ l~Ic4kap^>H H4EJõJ̾3S3)>nu"ꚛIea*qL.oiGMrt":8ngj,΄I9[ه,ŏ)*OY>GGUj._7~;UznHg/(7y1.et֯lZ)&BĘWe%T1 ɏ3YR229~KGRÍC:>${a+؛yդyCME4dq$7M?a4N4 խV%eAOyptOD/GP%cs}[B Gy ;ch+z5.ھ$Cy u׌#zj)P(7|a*-4NԤ7 n/Ue̼kҙq5| 0GGFV ,סa8!+ґeT ]׫LJ CNzGDL btk$OB|K?Wt/AgefgzFbk]A%)C.XXOw8Y6_0UxٴHϛ{D g/'4V&%.j@gļqκ2\I4lǸO*(UjnFv"sZU4j4ߗ RGaya{o(5;jf̣JB0e>(j-p;z޻s^4A, |e<j{"俎 AM⦏*IP> E]/;λ_k؅QCi׋>"g"Ł w*cb[=8P/VA^0)-w?/^{ ;da6Z5sDif%kXAݼHzFbh2usNL0ٸsOe A2| >gjJ*ovxych'HܒTY.c"vy2}J3j3֬6 eMƃpˬ" W&to}zkɥ 2y[AGREpHƦ@2^ t[[*rh~NfPJg%7$m= vU@%NlS}XJƀ%ɶViZ@ k Q,E^$s:A"AqկLh]:O2Uu u.&ኤwXLYBDuP5Ĝ}t] Ѹ| Cg&U¼+Bɟr>i).\Zdcѡ^ HRG8Y[{ fiMk(_G9}ml;VwT!Ir &6c]Nrt0٦s;||,>5?݅;0wϝ[CjWp#äUQs}_I~ZΙ9B-IG2]N0Sz ; &է5S"g78Ɲ(@yfc&.c4Le[GgO̱_+`n#'sl|!&A@?7guy/?7t!HR]V0pij\;Z;LeM rj<9\FLJb1N,2|LK+)dJ Mf<*3cJ~)~'tŞoHE&h v>+S*ַMLQJ˅΀Ǽ/}{!6+(uu+4n 5y,JylcpЩ/$bEìMMe* F-))tȔߞZgh`{k@S 58')2=hA䖪}AUG@.8ZMQ|(|>anccߔTjb/X BU8)yBo i=E csBj_y Oʜ57E 'w *MMo`%A?m` 3Ȫ@Jq2e&Ucd3,uvu!S./E\tzMVxAo@sCݽ|9bc¶ r<."5Vny6U_E&@ûP =8H)FƠMcGyy{z /ju]s5@:_*qUx#ơ'/N yl9qXQŮad\dQlXyBypYt (<2n]s!|9 Ȋt2S 5t\׹& #?󒐉1a? cLzv(3QpCvB@t欅FZ xV+fvOUo:KA`M@ޢORb.p0>7lTj&#Li1j@1xx=˲\O^{ZPfȰ>i sh`u l9i#b\Պ5J.L&TxM¡QD5RD=ǫ[ї=UK\Hfz*UY+>{Nm{Q #{A ۊ掽BG%7К6V.%;SY|qzCW.4\Cp/QAu^0&RG1  (tۗ%=`OG1ej(JH z),ӽqXt1$ki+?2Y S̏>*'rb&V5'YakGbWh-IaUfRr[σԏJ\`7qzI pORO$_FRkxoJFZ 9?f2兙OS{o_f3qFpjA‰sX[`B^`ɓ߳h#Llx7[*Ȯ։K^C@k!Xq? C qjSOcZt#Zk%N=PL'}9]gBy'YJ2ڵ f +}p{~`%xۜHQ {\`Xg neү6> E/4l1@F~rZ޸bO9|w}"6F"~1ׯD^6hb3_wx"N_+y8K @)+s-ru%2LPR1A/BROONXMMZԮ-@v+q<=;5THZf?;OWeXd$'MU%bvt;[#9OhlnlvFYhp($es6ΘZ(5g9Dw@Ty^U2n<}pv?P|5~3O)Nq'p0/mG˾)xժJˀIy'Sk)L8'G&lp/֌OWjmٌ^Aj>U.c%?A^U &~fUK#Kה*bO0 O=n\kU4L_?f?Vpf2U6pQ?߼񿦿?1 fG FG +& L&L {,{,Lf& &F&FG,,KflƟnルQǾ? ?A??A~8Oг ;|tZx0{, 1 \T)R x@|^\ TGjK"n(( NI223XwRwZV"jU_UkV Zwf2$s';sνoI̡  poHTD/wEzEFEEEDDyExUfˬ6|fM17*3>8ppUcUbҟ%hՁIa}>ZyxE0Km#7OZ3r9*wׯo43pS#7_x3tkn٦NO/=)qS6o*~ɭGTr|)=+J%ϯ}χ1bcU;W\3sds?`ߝnVj?*&&?oQd^sjC(zr3pIݼZ!K}y>iÁݖZ'?#~ ,Lzׅ? *z1uV#Se.϶a-+5 Lu:oNjm^1}ˈ) r^QB G %m1f=F*[l" U ҈*ha0BO+x#$zZPڠ4DYyi$d$ a8D.0ʘP9`#z\,s˦k4I"QhQӃemZC(A#(0Q%Wb&]JTd]2N0O͒M)튫M"̈́V냹G4JBJb#ڛ^."9vB-rgMc)FbqoΩi:dk4zHbAʅF0G%a!!!6dYzp$p/IRO)ps?99.Da HaH36s I BmpI ֭]+,3Ec̷`9ߔZ|ycέ#CYhh~Oa,1f@i`+ƀ MlAA⚀A(]k-R4$P$ ƈ,F̌"ϐ4STA<h6 Pף "Fjuv 4qEZT;=(909 lp `r*x/K,mB@QҳA0̙n6*gGdr2C. 9m%;S5\:\:؅Sl=suFf?r@ɥD6,ѽԃb0SQ ̙=;}b*n#s@Fa?d˞y ^dgv:eOڳqv&NܝRhF  S)ۂC8 >ݛNb>I9*!\?">y&8.N40og'ݺsCD8frJ.Pڐ3J(t `[˽{kqID+ lP+]`odV3`@hvG!7vE j[AE-w^϶7AF@YE҄b!(x( JՆIdrpLo`ŰZ0 (#=f= 0€ٽB#z(D4JMreL4AY7[J>qLtzq~q(g!|JN*hGDհ"H+4 R49TC. !.K !b/KOׁ%K-9rY95ne4<&L@Q;,WQ@] o#eb ҂J]iH:p d\9CfSiIlrVY Bю{^+1FɾO,\׻:ȓ1)Kc1 Ҁ+=W䌠gT.n$6@nfq6)xv.Rf:Χu8?-Jg1)y};nbZ 6 h@J٤b@d"=\#\צ^ЈAx,p?ۂNHQ!Ojjc@6cQ(uYWƛFq P֒eǵA Qzд8ԃB/)~#x.' , JbՐ;ba4t[qs[Ίts:y $F,5֞Xi?۠QH'&8 Bl'"EL&!YicS&BRzHD>} ILLJO.bpXj0 =(cm kɳ6BhhBD`g06=`L࠶631)>MIga&NFXJ'11v{Bξ')A(M3{  ?$G%8,>zζ6p'VQ/Qa gA,Ay (Am"+,؄ ÅZe6(dTCT9IGC J3 40 0d Рj"31E$0c89Bu6PA`u`NPYقFiʦ2R5J 4ڎ5 M"*ڡuE)[DL>a]>1)4 }_,U܇lh0Bpz>*Fd^C&kXpLy e8Hbj2I{lb\iX/O\3>OJ4U2'&(u$2$,wˣ,ZKĴ̲#b 8B2i/y/?wָG<8L89'|@M"%=[$h˫b.1L=ɠ,LXL{≮YR.M ׈Y*n;[#o\c2nPF]-v)L ']I(RVLo<-_Ʒ(CCD ~K A4 Aiu!:]ttptthtNDwD#QmDdDǨਈ2Eqy2?42$iDD-Cy7#)LEBBGiw6nʄ ^5jVtk⪄75Ӕ?awz5hA[eW=nOV-KRy2!{ʖC"ȍz.]VV648_ˍl3١k>ŹeRU'}}6ڼs!9p[q;"=屫`w *߰q3\@ߑ-dL'yWv(>ő=u/\P{zW鐙_{9o;Yr*.T4\s\/fSo Ζ ɞ^b>?~ގ鹋zYO__R,pˉkL(psS^&M[.cOkZ鋡fu-F~QL]mՆ]Q#)}mzMsŐ?ޮc6볦=]J-/NR3eqj{ә3\jٓbӖ꫇Y<|4;{}c]"~nvlMVY6yߔ|c<,v᱄#uGgF3ռY>f :w$.ѡàMǭl)w2j^huʻ6JXx:cſxufok:<}I^%Ye^'iun{όͫ31#V7WiqᦂBDp+RK)[,ok;'xpm;{ekF:yiT}pt뻴_zWτG$n*HO}kҊO`!jl>n'^+aC*[ae߻"N\?uGj>Ug}Mow;7G't _ Ǿo|ި_&tގ?QsZAع/z5_;v&zv{Z {e-ڷmIK}<-ٹE/ڗwi^mc6 -6/,ڶ,~֪5u6ѫރ&ޛQpJ?j3yIŽb̜jm7 %2r{ನFziwᓙmlU~~uojB~[^N]U;pu ?,rz]G<\11%kVM-'SʦWȅ nA=s'?oI;ZAPHo'9ھ׹;(+_vs?zλr}^=e] ڜs]"!/5λgn`rWU;_>#nރo=w/sJw8b'^]KW9>=5gEkm۶mbcfv:m۶L:Wgj?j_x7V⃳4( 9 … X'Q ΪT;|{[)ƹ R6M^]~G$#f0ҋyoqNEYW0!$Sc̪ 0ЅX`CrTC?T!2D2N"#C~VleÍ+ZU{(0B'b+\I/{w~;~GF䐿3AZ%vT.f앷]B qKCJJKcpN+N G*H&W3A0>3hS҄42y!aQ{@ќ6iUn@L"IZ[V f|ٷBԅCDZquCTuk:&(c1_ƳC@itYU8)*.뵗0xS~6hN[JEdK684ҁ9$*V1&LGccE?VIl {a#vd6QfcGqX.GnĠSv즭-ysZ3$]əwMNJcDds/Ng+I\ pM-8AOzE&\~/_h"jpH"`fЦ1.qg+R AJRa 9?b`,&sBjE9,ít\BŋHE{%hub.40r>wߚZG?t8d^ #"L5@'(dh[$%T !(U 4@lk ޝBD[v/SJpkjU?Q8X\d u2s_i~XF~#a:hl(8'#tF1ȍNX@2ku,or",q~$.wb)OTհ[oi{weT |Wkػc9IAntOCVg@yX&Z԰@ZA u;~ZXؑѸp;hzپ<3닱Ik=9*?Bv"kmN1;s`}Nqᷳ6_T jaOF _ gI0X&".( )R[硿 }avI\8Qj* {Q\ h2PiŤgɋ:C{S|ŝhɞAT/1~/z@=J_}_ OKN[$e^ ID=UΕ^{0{kď'& JV;s8la{\[1fX5F}ًfrkR2ePqlZdiU1fvJ j9Kbd@Od%"a٨czZxqqܛMd%MϺtMZ ,ᥪU Wc)h3}dlɝhHL{<}5z7ހvQ0uT3:|c:1<{32Ҿ㣠/̗X (f85aĭ鵂 Yʹ ,Yύ=@N0?iKВ8d 8$*V*,EZ;vP(5F ;,3 @GrqA<%ިH;XݓXr2>c`$rZP9V#)d?y * "5K˩wD҈ִXo5J9l#51/ZOr8>Xbz8ʆ w |G[=Cxb68Ə )M3ǸlPT=Z Ǽӣ ţ7b(/:gG@KKGJx=63'btΏNt'+DZʮ}oZtF{qEX B.}]SSR1]#9JQr=]d'H1},_|x>W /dEvCz5[aA \4~/jVs7jfkVBw]&t4dXnGP nz1h08ϗ}X䭷K.IQK yVMJnU`Ye`vIza )({|B64Z2(֜yr^!;l\ȻQe6$;SϴVaf+)Qc]XD9j΁œY&*&ڎTU(NL &C8(ɢNeKA%qi7j/# 7ej_J;0= !f(ִx"0O_Z eʧ~"mrV˔TLת"SN\8) *pR">(͙`i Q+`M)ZJbkc IW5`n;D#Cg4IxNQ!L91@ͲxI1bN5ntfBtzzO6*0c3d_v2ҀQyA4ijZOoT'h1בC˅O"v;[-tyZhc^Vf3`ʣZe_S)<(Q7szW2' `~m_KIPWw^ao*4 ND-KV6XW&p `HJ(;x-ћXXEmN;*u~|>1pn=}5~gIV_h9v&yB{8)<_x+Pcmû|MŇ݇9ʭ ;jkd#]:Q`gIYջLܯ)}T)^<'`Nw8 ~J2JG@!%6r/[PeoYӷCJ* 6b8ԩsZ+F)opV~GcN;0{\86)^6$pAo!AaVoj6 ujWcq:Cfs.7y| ځEZ2dIzߴVI[Ya('8`*F? 䲂5aFjt|KP$}mGGl:\%ҁ)ԁoP" sA-[V}0n+DZ4k=j%|, +tZ/!GpO,GL =X`C.pn"pIrx`92L]rWmhS>,QOb'g!ʟ%%;q*@f'~ *E , |plu52p~W0)ٌÑ?,`Q PSvMCeHk|WgpMRhR[p$k _⊂L˯`m6]-A2 +^L*T9];%dmGT*ir D L$iAb' T +g\K)|`ߤ.q`gydC`ei@Rڵ'ހ^ܿ Cl'L4֓a+j ,~}pybJ%ܪF2s:fR +zj^BAӠAվcZL='+a9'-j[]YYeM%h-$ea,P}_k3(+m d7{gbcC6k9Y'r6/aۑյJ424 f7pCؠ~ )a |c?Di׮dOЉ]|š7>dMٻIud݅TƣZᐿi[|#h:-P#Xyy{i}<|[c.5>ic ="Qx# I>LļHm(-)dE % RzImbEimd!zyyD؆BLcV*&"L9$hxm\!Y!m,Wɹyg^B &oNCN4Z~%8+sU!mRg@J gXN,Ae6]ZRlV?97 (j /pkI5ܤ;Nn0t"p9n2=ULNL(2PyyB)צּDJ|;|<94'Q^X-riP4מ~k-$6o\nR%Pl'u-W cǁ@}oe?U`hLѼadOF j@~Q[s,bp$98*5B =".n䗯C=e,o\JMBtF=Z& j7 75)d!¼Z6D'C^t:*(D:i܄LQۀ6a/},>Hȼ5;Mb2ٶRU'^FKxJK9=b. nM˙a&!敖啍&NIno6)⏹?FEb#aӻ7=e\!&QzC]Qy?C}.æ̧ xE)"lf,l nb\9+lE*vHY(kpE &ӐR"Y0kXg߼!-BnCntݦB)L t1e:~L 18UttDZG-v)ˆUɃZxݔSzHcsnUHoi7bk t%Gq 'A-FA7. f+[dh{K r.@c3B]q`eHl1)$/s) #VP8 nBr J̼7F =~aCstHD5d{`%x}̓(Z 󘧑ڈY0zw6UmPQCƌ=μYƽrf^ڱKXrሯ!p,'S$݈#^7EmyY;&B \R|9 OEy듲BBn6. gktK6[Gh`mZXūRT *0 _Yk?J=懶.~83 +3e [^Td\osPK(ѱ/$FR/1"\wg;,'Вqd:L3fʨkdd5+nEEn㊌餏L1?MtK ?߷&V7JWU*lA6y{6vv,E~>n=HهN:"o>q( &n%$18^ԩV+cu ?1Cյ +9\C+|lYprfV W+ZuHCwOR&{"[mIhD*⯦z# Hm7Y~lgħN5΄rE?ۦnkzE[cUKSxf^]IӉ2kz71S9zb'_6ĩWsS5BL{"Yjkڷ%f)E:)V ku7H ;5&io2n[GiP*y,L] }UbSJ`(^8xJ|q^Ȁ3⍾MmrBRxaUvb c8Qn.{OҋkOEkLID5rxmFҮ(ee' 8-ƻ#zX{ƉF.~bJؗt/_B>yLm9 ΠYfm?XNRyE6¸4Kwxb__c4f: ˗^o)+S `X>ѹV˝Cͻԗ#%?z?fhMvG8p>`v`͞ /w!P\8+fуo'3I_/(oPR9^;IC2[uG!7&f¯zBKt3BӃグܤV3c\IIK*i`r g,%S\dY+kk 3EM >RǻMTOsdpP@rRɫ_Bu.ff魦 JbլdtKz 4wɟ,Rk116>_ySw<(ثsdf=@&~t+pkIۊSWv41ÞbD$OO:NN =F aifρ.5=?"W-nϮg9SxqLqxSR>fU߶QH9y]f5bNr[''cWe5k[_l {F"yPoo`1;H [{X*3AUNjǡ eUr' lQ[O";Z)!}}R=HB_a.w/SZtʙd#jW.FZxjw$ՆW(Ƚ*K8M$ ſE\Tƿ튔Dqȹ,#(XbFsdv3s;ߙSREDpߡQJoRFDE)CC#oZ023,Bf5{yi oJB7 rao?q5Y/ZXP֩L垝RKICOj4<|rU}fjY}H-/ח,ar*MPfW>J?8v7[7iVE/М5'LΔJҺqfw;n|klZ8'o.콯-XLg2 ۺMN{\?2ö1www@]vݵfJB>src+b2*~Rb'S4˨nT~mMx4}߮/ƀE 6C?Lv#V*;"T4Q*LPBաڨ(pZd6"<4Q*}ӡ &yx*QTąYRr@f=F0 {LiTؾz42eY32+LzF+e4Q 7xDhiDa8*GL 0ڔШ>`#z0<4L.g4HQhQǥFC( Q4iIWxh☉jvwy@"b ^j=QOfBqqBƊ|uͻ4PG8@!#n-B1"lwlp^L[-slMf$aar{`i".3"C]i-v;µwNbb{CJ ;õ3?F\)8h4C:f=Z9ElĽjKc t^aB"3N©N2fь%(8/d> B(4@RB繃, ! &q_ FeAYiIaCE i54i::(ʀ>yai1dU|g e1k1REδZƪt>zC͗1M @.H՘YFc 2i +bZY:iC" 4Ag>(!a"h'ЊzYFhɴ je-dqNF>Ԁx_4=Fj@b%%@hƀrΓ>H)ZN]@kL$I 6Gvo Yp HIB?V:{+N,.9C@rgPTI6,IpOVƂtsA:Aah 0hmqMܸ2({Fٓp^`0= %wx7窼y{p dR l" p'+W;'5`}Q$F@{g38FPV֐#Owl|t..8 \E) ^bQPHj@x\$pÌ)k̺Iqe#JB-78KK\#txuH 7`(YߌhbӹMNH"VFs;G^lAg0S ;M=|Ai;sTH+$g+B7Jhr~hzv8N7MFDvZA;@dr:D+AI!ܙw''RFM$X@̠@&]Z'McZQíZzSMb]CB܂?:`v$a<]F^nozZ7q&6Ŕ*~ wJH0 4@;Z!/z`v0TU@'EN[̗7EفT9Kbn!(x7(jr?G V KC8Ȁl$Lrg!PF05wpDP4ʠ$Z .h8Xr+r3:="(gf\'iJV;ki.2JMq71|dq9A&lC"d "vFg?g.,Fcv‚${e!sXh0nNˡ>D$\fBY v%hrV'ƂI8>'p $L)E]F S˭L~M' E|w_Om֮G2Ԃ( QhX  0 % + $Ro; AB^:H!8΅7[:e,Is8mg.[$CV7h Z& |ĝJ,Q*sSw|_XXYE qȟ+ARj7$90 q`|j:Wq ͠( sIvˑKw$7q5  >t~eE؎m9^ns&!ܟHͷV*4rI6w늵FxPHap{M}qTq7Fam0(MCWHTCWLH%pg!`,r#lM$ᶬU#i%: 8dByNoo ޔkZuߦV8^̃Äs1I;>Hpp,(jA!=@RƲ<1`0X fȿ3eJyl  ^> n?["<2^PF=-nɼ 7zIp/{Vp&?{{{.-*UTE?qAJ4vPNQ TTG6ObRfYr۲?ʢ2F*T s,+CV;<Ư_ώLmEO뽁}Pttτ'3DvOIYۡ_$^kX{{\Y{K)mһ2՜i$~FyjXРV((ǫ*v^̾:g߬aGIv[˺?EyӣQ.jLUhw&Ѧ}v)d4O>_fozԋmV|N:_N[y..gdŬ%msWƟOE?U,ԞaN|@JuJˇ(Uw&^Rx:Ujs|K ͸mk;ZRh|,9p]'~K?mYi?&xe:':ދ ݷ|_9WTn06wȕVmO6$hj7QVI}5ۮ[ǗU%ҧZGT؄s͗7 I]GS= 덲~M3|:,pʦZ?<=rg|`gc ؎ziwvZ,SZt+)omDI߯m{!nw}pa} Tu1;*cߘWw2(gbΥ~ N5 ~jZMnw7O(ٽiv9%k5ݞwͲg9 ڬ돤[ *T :I}y \ZhMvi-t\e>f;\ gO.9J!%0* szԱщ2:0_ +^s^T[lI͉^}`˖*ݞ1>mB3r{EVyJY9為0 yplci*l3nN}l VB/zu 3G-+[e'H1HOlSzTˑiI –5IZ e'][_KAtl2Igc>gpYY8"('wûq8۬T^j}vhED1ܻ5c8&Y@l=;oD+\;I*%H5Z=k[P.{==9X5 It]1@ B #o&.ߗ~XҘCѡK*s"xBF+.SYO`15v r ûv+Nj /22ʄL95皩7_Ʋxڱ4avB(ə;lEZ{Tg6O.칓 p/I~ /tт4nbA=Ǔ%MP30s: 2ݳ]BMs0pG@37>Ö(w5>'( -kT9'1[;(.Ⱦ(5w +ؑe.SDc+ֲB <8`r=M&TG|sRY#_b>$M梖[d : ٫, Jd+9RH#I?>C'C+4},U8 X^n:v5*T)0-kyE+XXR-Hzj]#N!lGADŽݞ-nCO,1Bh`Dgkrg˘4[ZYʓWtպPd*A^zHteL` Gqj֊c.TE3jPSene{G&B]GJib lkZu hart# dZDN9w0w?ͣUvT|7Bj(IZ>̦#㄃.{\m#Ե>JG?aTa`Z/ޕ &b0ʷ. D`CxQC+lfPtVyQx4)Ùךyay$JX!cq|I6(FvҚV-V:nsY,ύ eZeZ wTٚQ Y,C-wMJ쭂RNFiboqAHef0QLM.,)0PvƬ[1 Vr8(geų-?Kd%؝[;3sϬԪ h | JT7]"%h<"AU;q{ 3dFIV F+A˵ӯU{D|~<(d\i 6v  :Y& -jtmLGҌkLqfCÆpjRa"DEsAD۳\j&N㪃+=`_]-Ob;vRSm>qA' c8Se |>6  :*vh3ĉBs5'""O%DoA3[uoNrqfLW!fߍu7Tu(tyY޷eCў16Mxp!v -ZaS=^XbYhZk|=cV|8=dLA)egw2Y ztj屭?)-l<'Ժ{-[mWdmaYN9bqKM3S?6]guo,' ?Pkc=Y,6]KnyF$ԏE MСRp4RZO^2cIJoۖU V wxx'R%k@8/ϚA6o.! `/C/FLqޥ=sjJZI_ZF"tvfө8bT ҟ=AC=z^ϟ`*ֳF`H?,`i[nuN0mJy6م#VY,ՠ̨s:M}7>Ǚ{߱y;u[go2AgKVfڷ*\i]\1$`ՐQ*BU}d4 s"=um;fik;D 9?cЁOH\KԈb'rg--5ZEKL,z\c#q!FAUCeTt%8is;KeЃ&W.LXR :,W3ԪۗS@7+Ak+:} F.`L5ЖHa0)F+OZ>nYa ૖*#D`be}2D) B{x5*0D<a.]?F7ygqglsXN_'.„DJf(?oˈ @xsKAvˤ7lkH 9f6z WhEϡ=*rkXJd6]gܷUx(8u!\ N]׉"CyH@g V2~FԢyb۽0! ԳIąPlj!9Wb:5wꊀ nC9zeYIP}.#zwŁOjIzz0'E[x5q:WMd_O3bΤ.Ou1+<+YY"z6; cER~`G1 >:_.%4i_#N#(J +L~[&p7x PgR5١R䥕)jm7Sm&t5҆k GpTjdvYt\JYo4ɃCymx'Slg40sk(}wfr=9aJ#^X$/EW*6I;awQ("W"{2!%BULr*&8 L5==;ɪ~Ү]j67%$@/KPpB5[ͫKt_h+찠C22}+e8 o5^m,~+ gF+ sR|Egvmp4al>b|2Gh}ZO}ķ6+L=ei)d9#g`Olr`:MQKt>%m#/wLŃ.>d Xy7:.a"V0VY/" &HsÚ@:笡?'I B&*N"lsl<{tּ/{l奺ˇc |5pJavbaٽE: AB|RczU-+K7ȸ0"o9|D,f,3N쭽ԴLLI׾)p1@>;lm^rNP,<8#ίڡĹcM")#Kaz%8b5Uecq"d&y l".KPGoy%x@/:m 18}:޾A' (clR }L/DsU-}W\ue5UJ<PHL_##j<_,A%V&90JTIX>gS CL:76K8ٳ}hugH{,c4g2!UuDnҸgKv 繍1WxuE Lτ*W6ş5BZ.㖈l_C ,"gaJVK?g]{&Du%6=4*Wu7i3Hj<3O`j5z^t:3K EuA*+"I!oAɷPk ? aR̆(3B '~^1ۡ5bXu MMipJ } (Q%'NdkvaG4;BE2GW lxQ.R`LZkfBoo{i1C@4FvV C("d;fF_E@#}b;bEH(H[^O OA;S*Igt)Tœ*:p6Aܝ;M΍?'"eD0ݐJ--EXҡg'`/ m> q^w:V0~qnUY>AYoKgn- 9 sr9^71G7_E;!0$oók4*,Y|_RS =DߚG6<*~hϣ;sUVAHNҜn|0*xOU,b"@ #!S&H+|YȂ?(=ٸ۔87t &bNf`ˋ`f jPkie}r/YY2C}p'߸9n"5 כ{kx~J2⤹uM dġ|VdID#<QyDM`aTX'0.hlJvR6V>+>eT/G [r(U[PuScEm> [.%GL .Qr^ f[:ho]v|/{U€{$u4(m"GᮋZra){b;bp52;馒gR"W7!bJ%i.pUbJ'C:%t?i(tǨ߈E~ᛶu& Oxvc>(܃[νkcUJ]o|$1ԦF(rTf,|Z㜩rxrH8|h+;`xvlg>X|+ˑS[Qͫk$}Fn%!p[`n@?d˓l9yJ$v '6$<4"+xo&p_[^e>ޫL9~XܙL-8QD00MQ/TI}Ki C"iDa4%.JJVα⏌Htڭ@G V9m:|[DY4$Ƭh6'j=5%0b\Lnz'ZЏh×Qe +nYO(ٵ=[/6nsbS)G9KPTs-@hfO;`fѲ8yW!c͍g%+U5wl;/lS9(0hOޭ(XmimNa srJByP0'VI*ќ&5ڪPÉ|B̌ bcW<@ Th(C\-v0/ycA-(:;HWP'1L,;IO'H'u:B 5/]5rKcc оu'$=Iv|(8lBcVG/#u~;fJ0B gHÇC 8*J=KSZOBoF/iS&xi/S:ߥ6#r$nSgnvRq05 q{[]W3ss5KOg-D:dvH'StVn=[,SwD_lyڔif'yA lѢGM`4NL`=@'g*_[<D[AViUo@w\Po[_eXH/}VCj-C:,۞O(y9impչћ+rgZ5+oڒg̚~JCD$ލ"x2f2Rott Y_ftW[6L2#E|X҂u-]lK@WvaCso٠"H6cQ}#严ֆ7 D}|;=dD735ENm fqw.}X]m L C|T x Du) h!XwJ$ ~X&o\hE_wleGMc*#mG.GT˸CBfӫ{ tJ!p^}ٝю(̼т~iY]'>lܤ&4'#ۊwt})/wS3!1vp!WQ*8 I8P{dǀB C^ rf.K ̗Y~sl@ϗ^>B׺akYQ~xߌmr#;T k0Oں" | #Ҏ*{N')( 5f'J%&C,97Fsl( +\+i =vZ`z 5[EXw0BkQvbX8N0)et2oud\ HNb #m p3a3LSo/<#ʊwIfJ TRilg쟞6-ӱ0+pºN} u3e'{KRs8&۹E|iricAT[={|߸{dDl #_y;4Y\%v%8?1Y0noEsyH±_criݓXjCHzB\v@-^Y#%o,RqzGnUPijʾl'7jWԣ5wu#mUjg[, :20u q-;8mPƏum #9u9I~w 7KW+[ C5¹=LQ.L~M+6@tS,W!XDEhܟ\d.N TrŎpe}]Hsx8 Mz2\>/L7%t:` 3uÛ7(]s]* iN0#q襅8N֊)+O^q3eq'AϺ„Mb7 \xIeWrɎ,)%4]i }j~}W:MUw"Q2I3SFTOy\4zW7ܜ0,ߦ?SY7LIǤx9#!42 M9ʅusv;!{+R.kB '&%91\7ubBY\_A'x¸VBYRf})U8A"{?gDh7j"wNAo:8B[ֶ9"1uOfZ>sy#X*,|ZBAi aA; raaă%F;C #ـ_MEv8=0 ^ 7Uov77=V6e.yx@%0x:7BwUjNPp«.= U[1SбyRv҄i+t כQ.X] [vg@]L)6"8Eh'mnnA^(>\˟$bei[9lQ[1 H`k MiQ,x]9HA=F]X 7"O v߶BH6HX*+ ԥQ|oFKH%L‹T?D*O|n<3/"@^IP~;v{0K9OuĢ?2uaM,`;ܭWTY".EϿ"{os-rXz=TRgyd/ԖجpN%'揍z `he碥lmƋ'x7- @@6pykQrͱXW={|ꃽqvdyS nr!e&;rWTF؞c-q.&MPkc ( )H?6=SJ6./^u?acY&5K,.D}C/#(h߾`b_m2~t]vkXrDUv@u,Ʈ|[~|'  3*@$|fBٰG pqwGK*aXa|Օj{XwGhlDXoԬ_R[L%Ɗg;o & % WנL)BT/F19`A\{FXl*䧺yW`CύM^ݙ M$+odECV|R(ߴÕ xSvj\\IkhGX"pl[ȼ:xۦ78Z*X+)^u@yUZxJ_.`#T%WJVy@/c;2 %.J 6/>-RL P0J9՜p<9EO`~9of TO`!FO cKAPx \hkjR`#HwI1MDFDNQq˰215"P M &$݊d 1r**ڈq/ENXr"li#s XϚc ]f.޲Wc-v3sL׺;sRwWh%$ٗ#l9ֳn5Yຓ-ӂ>bGBO5]bzOx/R%^ӟӊo\g)-w񯄹uQm!,FB)հ.RZ|ŕL|=M"667IcHC`ɜ (={qƤ%X<8'v/eۦ(Q[`]g劎3s}j[tcJ҆A.j߄\<ᘌr>Xg/P3n"ոbj^r}גjm '̧;w7O}f]Y8`N=b'.oVnN 忨7r9N&NG(My&<&\l, VVvss6V3NsS.^n3^6  '+7 /dq@ G ve~rr2Y99 7 "]ZY33CAPtT닀v/4G9_h][w+$*DrxH⸴1WF3 4P2qi$0*b׵G.dn6D띩R;o|N4;1"M:Ǡ=^|%ob Hch:_ݚ77zTxf2 dȌ/IE ^;RhDdy*^igÐeiP\06DQʌwksE}2cYH+哦5n-ykC:0y6Y\RO<'b$'r\]:.c_v+V(Z1p|j|pέ;xc+\.ejMBݷD؇1j tOsOHYg0zaU&Y:v||ٳ]Z`[ Y]p͒RV- hup2de)cʡ]d|<g~W\TS@.(ʫ-MTW!+xAr4o_W,`]3u1 Fָx:S2wv"{"ҩ>',`q,e҇mktP7e7%OEssEN颫w8/!̺ڷ,UV-8-sNC:,4-ײ~/>lӝdRp>X79Ɉp㢉W j '@u2K/pRyq*Q N3ٕ^g|+gS~.(]#*GC9;kxA6mL?#s^zM(Қ,.c j`+fy}h^=(BV6lxo>y+3S\+n ",fE<><۳&XNiV9.?'Z?}.@;\qwpF:9J_ڰj˦ >ΗM<֤}YOʜRC'vH0s2Zf"=08\6EGkw7˾I['l^Qkjx]g qi6:!]P{CMW: l- gOcN-p yN/iX|j=dգfhAC.Ѻ1dw{RGQ5:W#ކkP1  ZUm~ŗ:&"q]}9U_Qlmz6b J ~H! +׈QOp0PDMhI>jx v @ xdv JK136n ;El'~DQg֥tz$VW]XmTH7`r0eHo,z*nL]?uCTs"os]7Bu\.T1|vm>녀n큒0:dϴGYy؜/P5]۞ ,7-0 H 96g>B_-HS\8ADO Q~zzʎI"w(hj'R!Teɪ_6^\QFraL5pۺ/@:Ww; L&#Zѽr>j==]Ʀ}~q"8|s q#գHl&oJ(yqHކQB{[pI3F):,5bœh×yOgvc|w²i~ʘ%]7X ` bw6Eo/z@ưlO kO.\Vlo@#qy<ۺOt*j̞o`r6X݆̑Tq%qTb'h+-T~ȋ)JWgޖ-y+wtz[Ȟ4cyNz e|Fgs2$S\2cP. =MtO7A*{N0- },A#ͫ;̞Vς50UO0&/kpJlqֺރe3v^7)71^ 3pN*Un~1-UEo,.:gfQo~l=h'{˪؏ݼ]=IF O܏a ꖼīç2$n3D$.LebhL#/MdHͨe҄Ze2lFTAyl fzL0` /NJ=‘4Va2t<ez:2>ix#Wf Wvià#IRjSq7VU|UʣVқdTUZ9a⟸/2ƶ,ڽqgPTeum^,oEx}/ ],)AS^Ѭh=G0›ImXj ec￰XSu6#V8"b  }ooꆊH`w̓ͻߟZ}+I' -} 8ץ5$,^{AhWDA6~G,bkyYtދE<TWveTj#MS*U2܈M@A `,)*XH1yoAv-];u<[j^.U mnäxAIӷ)t[(i:P {F*svȬΙ%t5J"cI*2kοl[P)Z5^ngϨ1{OCDҮ eBV[o^\|nKda̅cܥi=HR[2*`je|dθZ$4EF,LXk,>lT$Tl!=$&'GpyJ\l OqsXzӱu;ܶ#2Ժz;ϟ.gh<ڀݽ3q^,l-"V$gr@/b U]«h ol /;VJCf?Q;3%GJV2sSӓJ3&u\YVg,7Ȏi02vhft[\y좻rUrW<5]bYj)BR!`fztcJ銤M6K:;NȖ".RQAABLusUHcV}Y'f78,[D-IY;}%^c{/ԣQ{aB!2tY5g:l & y+GnKfPV9Q+]?G`TR@O>1q.͈"@Au).Tq{?Mnf'nt/V*zsLW+s(I${sg] \cz笰Vtqq17񕉨YuzJR%U<^d=t,hg h34Lna̎$\rc c5]Z M[4'sfd;Zx㽒5DIΗ+ʅJ[ C bQ=2S<6v@|cKLw^Иn>729ՃSy^w);1rC|Gf>||M(SqJmf\ȀbƋRȓchDwaC!a⪧uJ*L:ҺȊaWޟ>ui5ZxᶨI';|I3S&ASjk4V22H^>j9mȮ>͞;JR-Uúɿ4)CBRTNDE1C dw/D؍8vu eWԦy6N%|h6bQpOgM0GmǸW[B ^L]\orA;FAaR~,ưGtV֞Tudu)F0?Scڴ|n&ش! IftGD ?F3e+dN%}ҺaŠ?+oSp&Cl6#\E˄h-!voV3۫ф.d 2-'z26Ξ0yiK |ȠsG X a^Sܤݳ|'Zg?HnL!0 F2Y*c9Vəsm7茖,GDIMbڠ LKB"+iV:!lB)(Ԅ~u+;FNOeQG U}#2É%AmMl@!i㩁f9vOy!/Z.S2(1mUN X`(*fDғ<EL(V(\C={/qV]Ud= KݎŒ2LQZgc3mZWi씿7$Ut(7bCMYEwAzI=t'g7Y# q uIç*ؼRǯN͌&}dƺnjp /aX5ǫ/0j_QW++ !-M\"]E]L/ôP|O;f3M#m$ha!T =t%{bՌݫLJn[`1-tK,[F .$\dlpջyNSƬ}cXg[ %HܷzYY㦮)I~-.> q6TǗr 2MÜǒ.)ʧ5[0?&ڻ~ FBxlLXue~qReFC"fh< 3!Q/Bnͻ}5Rt=urv8IF'npGq ,s? EQDпj&X$]CC[qmGS !Qz,ߔ6<ÕG)R-1Ǘ2BգI9-L=-$CVIlay7> $NZccغn_ᅔ1&TS6C*˸=6ysL*GAWE4fx tinXP\|iQIN%ګQ )nq)&?GJ$Ų2+ʲGY̅mT(/n/<ɓębC. /HP8X:ju;[p7E-ͩ l!Vܫg 9~a& <}DM~-t~cE;7P +IeVEOdx.5Ri{tsۅ=џm em)7E6OOD+=ؘ##3utA_wƝ7)*T !]=R`B Ήs˾>=&>T8@u jV;o+`qyoP\,yΎcgCwgN)d+sJrb þJDv`[UUIH Ϲ=0J<.?z}Ԭ G)eTЄ@ԭn)a۠?[{]vٴ!r!~VlNY$4'kFP}U3>V31g{jǾv}`#`BݺݷӔ}/f/\U4XH}u7ʌZKN[V7Z5Ynt>\#bxݨXsNݚwK>&vCK&\pﳭ-A9n3ju&2ĀiҥyS%fL(s&c\x :%ZF Fq#([V⊉hF3|ef&ﭬx F4dNJ 1dIq4S0B.~B.h@#sͽ}3ky AZ61DĘF;4>n,m>ݧ-qkQ9ǧGmٚP4 mr'[hC0Ir35${n&BPR6HN c%K o1Vf.A<Ɨ;ׯLd{S2ϱpj1Ռ\1@-I<@2HQ`U,f\l}T$ uWal䫡vJ pgn+je,aqzTryB[ yFfD][ˀ,·fL`3`bdmV29< ?=M` =NM#oZ 4`dd_H:Ϯ@6׫%zI zo$O0 )r/_wQ t ۘNbssaGt#gjЇ#kMri0;N[VQ(硜PSR|b<$QFK:&&,qTVċn'Ec-7"h>g>`,2Ich @a  Ŗ>+.ذBɾ$$Ӫg@CoQ,>./H./[}\l%~!YaFj9[-i@DllR,+(ORV&,0ƒ//e"q%f@||'YvAR>D|QwZ>Jj[y=Ϩ |7Z3"4q*/Up[=rK@a9eQmS42ZϢ&?_O.G' 0TnZzY*ĵ˴`<Qx [AƼ0Y1`5AK{sK j1g,}XLFP{'_9arRSn뿸:9ژ'($=WnW$p_%?u#A@~[QKODWgܔTvs ,RN3wDJv`MbgTQ%$' w~zotNI_$~K A`gDꄚ+:zP 7} 7= wW ǯi{xf)OysZ"Qf+zJ>;<*Fy}muJ.vn{oJ 7a &;< x[ژ-SօZ{gk%xҔ[k$D(m(7frkYF{eX> г 7:,B-xLb:ħ#$vc3>5 dҺ*afL۔j$9evB ~q5pfyf ƧQb]Ƅ~A8{Mn.TEs1.dު;2RMv< lAлvA[J;saETC({HnAYr8z@m79,ݲ^)xWAYMN-\r3vFTD%GpN_,ko=G@ ;EnPѾ\ZDЊh Z!L%Z?Hw^p@y@kܧskEodH^FW7S5nJKNkؒ*DOVsKE%Gp8ڼEB4Sd} _arU%.<ͤkn SX2| Py6n-UD O,)*li,i!bpNs$F*FW(kͻG^1H{]ؙ3mJҏbk/mak-/j\[zޠ~7"+٦q.+). ^N^v%֞M= ǰh$oô#mP䳳lGC WNPn_J$OXE'jk,t#[ ~>`'ɹoUuʉƧ}F4lj\ &W,X{/NBh6"bQUh~ˊu@S[ϽZ[W0 Q^ft`}-Xy]撣`0dS[AK:yhi,\l6ͷY+ Q~=Bb6J'K0̔ Y<־Hfk]q*ρnzd)sje~Z*?~m]`s*xmܨ'Q7yj{9#5DdBg/ܮC׽,\0rF]8mc#*3n+z.S.$,wtUfV{g|pMW).V~xAP``3S{Мa& ] l^w PNuDdscXYͲ{)i+:*H;S2˪JU}Pţ |e^.`Chc~^A<癋TxB{> v>P#WRTsnQ ֭8!S;TD6]+E$׼b75!)o q:dW#etF?Sr3]u5|K>W$jЕ-7 ZbOf~ɸ KE]J~C3UK'KoW=t^R (?̃x+sWڒ0eΫ8/W!-W3(Sц]T!Zz1 Ts9,M8=' B܈#QA `ӆxMVtiIO5{^No+s˻|,PQil˜^=)GgzRM[)W]Ե Tؑp8zA־(V W8oENO"P½(8 uDlTOcf)F)rݻhu۬̌ ;K-6vK;B.V #7԰H,U gbbzwg=gJU BJF+5ɕ.wi^tC7".Sn;)ʟI^.Hd2#m JɄ؁Xč~3!:,FJAKҭ vhIS&QHR ᆱn1cDcx}a~qzʐfc.ާ%ɴFoj-NHn r2ft3| s1MӭjWTuN:er˫i/–J!-{Ltش'oӎr L-ѵ>m9椏ڴ{F ~x%zE3H+q񸻆z;+Uԝf&y4+g-#.ZkFCKG?X{K?`+zy@H<`4$v+#CP΁s"8War!nTQ0U$QqC&ϕ۟ '^8~\pB,b49U47u>A&MCd"e*Trϸ\إ]M&34zLQ-H!1rr\%uVB"K}LF]~w`km晐^JO=dGk?z FC2)Uf@ UƟ~?/A" Pg!D]"L8 ̓";#a=̐9\^:v'G bg/.~̻ōXV`*biv6c1ć@w bs/$Up/m_qvk㷼c4#߼SѼwN<,#`\f]#k 8lkmlfg^;1E[NIrsYew{_ rGo5(KWnh]!cOW[0K Ob_Ad{nWt`[9'Xy"O8UUBD\A <Ns{99I~ʆ~}٘/@{p oDLv`&s\22;` XX_E|oA\5dcn+^ Ʃp= ƁԿ$Ͽȩ9f5;Pw>~Fs*<0 \ba;',8M ǯ'L0/퇟LЗ?>z<v_<F~}_[_ͷ~U~qNF/I5:9&^} k܁4ׯ/g0 feZc4s:(a@{ek5qMˑ SR֑Qb209(L`_ G5 Gײ-k`qrT0==1;r>*Ob48Q#l#ЖGn#39[x #&#ţʣGFt C9Gu&bom:Rj#C̏-8im,evG]܏4u=2}H}-Y! y;C}W;T: 0_U3;= Y "').X2~}pOZALNr`~^?ldWÊ}~yr~t_APis봟}M1%ໞjw$ne>!ӾQ0(,l?_ L/Ȑ?s?徫՚/C''Mp!=rΎFd3Odjcd6r:O"#_ 0qH<|gS9Α?Kſ-Gw|_eŇI;ehgo+/ UƟvOTG?G?G?G?i(r3x 0 T"ESvE3Mi ?x@^\ Tu[]⒄UAA,EqL8 ]qhjϵϥj]Qqi]P_+u y3LNCrw  ϟwWxh( r/UG aUPALhl‡Q3͸y?Buڈ:$,8H۹ҩ`]sj-;#4:UHDD:T SCd\ӕIB*O?,$X#Y>oGTy#׿:E׼w:VܹBwomFPJO_سF˪JIswX])bW|EV6o|׷u2=߹csEs^4ˮkؗg<]ѴtE~6{p],iNk tsVcY=w]|<~}ryOvq/hoZsw^=e%a5Z}ow{Î%GowߺJ2qÚS6]'Eff~O$3%Ӷ?.?zQu}}eK̷LeU}~XԤ'\FCt0E<ܯUxg%иAF(ZoÍiS hʭm9 H2( nQVZ(Ju + [:4fB$&@(Ӳ FpZB26!a $nR☉zvOy@bE=j3킫!ML0qƊ|7=ͳ4@GA&´#ni1"˗gp^L-sC]`T @_4 !ԃ !B4T,ŔݜN=bG8OILRlogHIt98'1LGÐ{~-s[bY! gՖ\1V<kHg9C>C#ɍM >2 Xc0 FY 6" u Dj^jAQOc4@)K#ҒBE ΐX3[ prV\0&a"$vL0ρ^0{}o,߃ Q$`g#!i2@$ePI/=N‚5լNn]D٫{NA%"%i 7O\_i9͖ шn ` oձM: qO*6&2U+)8&P4(=Vx(=Ļ9gMۍ{@ 뒲uWP_\ Rlװw9#ycL#FE0H"xE΃-qILaN fj*]N[԰p 2r˳M3S/Qj(YZ )ƣE8vC=\nn (@nG\M[D)Q E8G^lAG0S +M=Ai;rTpxWJtV7$ol3)B$q#/Kt얲nR.䉮eR\WXa)#Zht8܂DkI!\w%'R8bsVBJ~E}D8v]5\怬噬'u\$h.q8$D% ػCtzhC(mә.@m-u'rXi8/@VIiUf0|5{-`AF:SPD' 鬍 A"[r W SIM`m6@"ڡ K&U-2a]岸ȘI_߄DYxMJqw3 eX 2KU,yyJϐܶeSlex2`v'shy2lid&'M>1"]Yb w2Q.-$ZJsDleWL&dLr1_I~);Zus7Ϊ 'dv^UĽGaC:@RnbYJ֤T6"JlH3aI&0]nvE1!Ǟe<,?u{ z\I`/VpFfziad*BUauHof8Y;ٲN$aw Jvn\jK:|lP@l'K:bSY٧el{eף3F4smiQ_\T/ߢ?Fi?V/sd-95mQ2|ny/V6xFX8}gyͪN>vޡ֝.ʌK<@V<[j1d͂_wnk\Ah{O3Mܧ**W`>Q5-`ˮUyb#電jRZ}B.(7 p(eYߗnPmŶN,A?Ws=z_Zu D~poF'7<ͩ ٿ7nn7\4+w.}u ;bG8ŭ9)1ג]#ZaW-Ã[nI&iӓ FDW;^zԌu{mӇە'o-m2-8Dq(&p]Q%jE򇑲v8m۞}EK?]dͲoxP|Ə괨rIG%I7>)' ILuG:Sմi> 2~uRlяgWYB'fר/I quaC˲{k_ پd꭪qUWE7ܜ \We -յW94nr?n~펳|aa-xEg s_SU'));oMC*K)}9^`S-OM ~p=fq庱ӣ&eJqj@r~0qO'sO Bv-pgK旍7MvY۲_k'6>]``ǎ{+3m$n@!bfײAȟT~_/x߱uT]eNzk~_rteoYP\yTģ;]it\+?k61֦W f]97N|ɓQ=Ryg1EN,_1m+v/Ad@nob6񵢱~ƔO^t,i~ygchu7ZI ~{V n%?Ӗ55|͇ irv;iޖ% E+]<}LHyq7"Ag-1dQ 7OL.?CtkVj%\73Z/fwF_Ltw̘pJrQoQ yU죕 b&(}QA.ye}g{McK`2L^ɣk[o*zsfq`?>:;~7)vإn7[gu>w6.(YkXrg O&8W:M=%X"aoݤ~8=7x[RU_7`R h{LQWwD|Yy6|cjiD(_H7%O.Z"->;Q|\^;+!zlz@J snezXoS|抦t(sG/5FAyP{ɹÇ.f%3O4?wk(x+o\yiLVy7^&3o8KRR-}G^\7%uFW~pL‰{gM1Nk=95He?4;}ƪbFQT_h4SL[6\8M+7Y*T|цV_寗5tXE ?^G_շɓVxۻL_5ژUkjcm۶m{jcjS۶ݞy{ܹ's?_YU1e(J{ ?X|ؕmVGyw1#'s@:4tI"$_mT,MRΚmH25qTl 8B\ I@Vz6^y`0gZkm!%C88Ԯ6e U,?Ŗ+1lұ[3.@D n`\@7Yf` )ez)Q3 ގE/P!xs_z>CQdٕYR ~sL% .4͕R7*([~qyLu{z0f}ș[r CшӑQ)һU|}ǯ,jec + xm]z<>yS`*i(=:>$t8Ҥ\e]%ޚ/ZuX"ꔖT!F.•G\.D=ѳ؀zTegבDEH؅ LtZ+)*`%C:ն~vNZ-570(0[VS'Oc8r(ibV7B#蛦{ܸ1^FC <- pX3|aS[zeJNb5d $tQW>@Ǥ߳/9_:+LZY+' ~0BY4esܰ0j.eĶ!#ŸRCQrp i1h%*Fv,c{3!pR,v,Ӕr]ťf [G!`KF4="sFğbmj#fR@Ud5(ڧ#dOOFKzriᢅ~~TȚBz/'nO 06u{3EX~;ҳ_8=`۶]r tcZPj+$'z/2Ӡ1Zs9h[8$yyA1Glj=FE1%-/uנmQmI l,ς5 & 6gWlqy$SDy V AlY 1`@=c(?hkP.١?&D1e sh'@Cy0I\mtQExreiÈ>6` n ? Ohbzef&3pUu QQe!Bf]5T 8s F:)c]) ,R+;)uBҙ"C+%|CN^7'Z|]";audx~JRU3desS"ֽC$ޔi3SdP4=Г+bT DFQ ,} )—Ԅv!gWLٍcopeF+5NUQc- g/jzY?^ԑ@B^S=K~|[o;R|*P FRDP;^nocr2p iyz2b1gi7Z%Jnц/_H +*S &L`. 7WoR0rtj0aNra_@Oy)!|7%#Mm+uýmctt .e#QxO/U j:P׋e L2ny+O#B#ޜU7P=ŬwZ>eǘJKOlGL3Pg7|Jf?D砕?NM-< $^#ͭ8 ]I,¼b>e*;D<&9$W%6R2>Q-սX'>%a+>)&x8 IhӃ!%RJ!<<@3vV,!r.R*Qs7 Wʡv=#u&! P[PL>wK\D1"߳,>r(%$Qt cɊ-Ma9)lX 鎷"bШw ƊՊΈVsKzNOs.lT)ߣm43=2 ο-,x̟OˆNB߈}j]8/ kN>Ў-u'Ƽʇ#h L!zze uCYO!G.տ4&[S$h#lj=_re& F~׭r1h|:\9#c>X"a(w\ SoJVnED21Z%+,"be1d'¡Evo-`#dNs< kT|^bHKtk`NcSFr~MsvZ ?ZmR\3S~s3pSx"P|DzJB@+Ro:M?JlD-Moy G5LJ7\NlO<Z6YmM -dpcU3PIWƶ4qTL * F}[jp&E㸣@NKZp>=EJ2\KPCv"h-߸[K%Z=2~{iZ."MvKu`VZ|Q4meHao1S1s =l%"Ha7弅SMm$xa~RV~>` ޕ 9qZXRZ$3ըϿB"1-.z?A"=C;qTl0 Vih1ЮHZk$0 F)9t"eN2&XnZ9y;AHpItli w[x+FVq9~(DߪlZμOk;>D9+_ |Fg` QmQ2UyۋU[:N,eP)oAn>t q5uvSXaԊTl_h[n5ƼO(IJiaEJ-+BNkra4p([ b6jjRs}{A{h#Xv*45$Yp}#(^uV旨t5ǔŘirm1tZ0voˁt3['Nz/EXh|r}.Ͷ c5.1l@ˮxCۥ>Z3%չ_6TTEd ƒ>dq: hu_z@1-DC 5_G g3M]Z uа_A,QԥC⎾l%R>{i}.RD5#V!)QOg[]}_pp#'P)g7$mĥ.=uL:~a2&/z^U{sP!9%[ɳc!{ QĬ^ ,&D+sC)wcO /$TMXJv+;^sqP/&ˡY;3d\Ӊ6b d`p̝oi,So@*{6Vn7x脦 S}_BEA1pfe&ŃѤe sF84`!Nul4 ,fs50 b vK=ɟ N"4-!,/:5rjҍpS./7#d VGrSC4lmu bWw^H-Д !P^xL &13} O_v|%i"v^XGW$A &sk|)RGWR5~pUEqۄ7J-X_=2XqNAeb}!@\P9٪qnďzdHoOV%$x "(vkj\kG~3"vG qZajs!lMu\.wLO2\W&Im=;V]T\Rф̷Q c(ӛ۷\Irރonr>Zs!9 fh?p#CwK-T!uZsAz^)fuc^z9Ƌzp秠TJ%iXhfm'nmqI';x?F$CcJYq!i'α\ M0sSI̭2Uq6UЯE8o u۞|y{%a /33ZM)|w2<T?%Ů(,:h_+? CꒌW>D/s;dz7>~pI6n[@WUJ@ň~˜]3=ՠ;QY_W-Jb郀KH a8zt(c>U]:3ZJ6HAQZE賗CVXik͟߇Q\#4@K/ڡ 4roA7U%+2\yG׉I fYiRƐLhs ܂/SQwOq5i gㆬ૟JO 9 1mt(E[># 2yMT|_eN  鲧4ҷ_c;d=gv-)O FH40x*}kf Wָ5=>+.& Er$keK7aeypp˻&-\2Z#.[9+#j1 #VC DfORƓ'hO%{Fhy d=MOZ`jcġZT[9',3Vþ5^ W,&ԨwK/$ !vhL`xes[Ƨ wu-JfCyb.iE!Ն):.ɇ3![a3NB>e ewR=xҚB3!:{h?(_ #2L-Χ,*4_1@u 5L+.K@k6c KFB ]ti!xŭWB7umG5"%ت2w|P9p' 9~ON؜`RH޿SqȒƣ5 JĞ.-+<4d,SEx 'XDsRabu}QMq$weV$Lh5JO _QC2rt1NCs=y߃O 2djXSG|AV_aV\(_ܠ+qULubqgU 㟃.FsR/5X,ɩ;wFh&>vÀ |_@6/;Ҍ,bNK*ĩ) &d.ϛ)w;A<$M90hAi_)jm|!+- CNyB 1&{כ:&z"UZ:Av{\($hՇ'RF#~_pKٴ|5]E9E/$Z@,Y\Z+Gk'pb6{GĹ"r˴4ʎRiY(3fP GP#mi8xVXp#u;WEo2]P6>C(Q0o^:|ew&1jQGH:vDQo eCq.;1 暅{m.QVf~0@+w=5|SĚyoY.hdQ`IVLY?x-%AhYztl0 ˿r,`)hE)<ޡ5+suq!cd`f\ E=ѹ : ݻI<ōx0^пXEҒFc=c9ͱL;KolK#I+c:0*:Jen}GgTLL^eRzPۇV+geD~#F'AqrƩez{GH7JsrN".FJ/˚$3=aI!hiXv}Eŏ&inmMN`q;dx/2ez HuTs$ !ۊC>o|{ǿ>U:L0hKlJGY)ŝuF,w9Go'Dq[ؤ-ź0sdXҡ* foI% fei9 vsJSew_0~Hd=]6I[l:@tVHxNgص؈Vю3]ӽh.EwWoxXȕـNf~U2#e{ĭc۵ţZy%r/ X!I  q Մ2büyC3Q-xͩ̽84ٿF.U2\ cI$Rԥ Ȝ @Ǝ2Wr5$/wg0+iG)[JAg.4ȬUK 0zEvl7v Iy|sI%odY~Dk 3/9 ckx$ԙϪkcajծ6nAR魅v`jBߡj:޷Q7;lG1oyeeM U24/N`r:z_߮aRf{qP*!goG - ׆Si A3UlZ07ςZׯYW70Qţu| ta%VW@* iGe};Pʥ }UǴuLݲ#ԄY]b؉\ok0f!x?q%LlZ7nrڵ fo Gy546qU{r;( x#A>pΥ ?CB 3!Eqʋ='ssh D4,<0:SFOJUZdg`%&>0A sMuKHo?[L/n9BڽBBc -&䫰,;0&籛M=4#R-I`t G (! CE>8;zi,A#uND^ 9ZQYHF% :2]|}DΫE_L~ ^஠0/szaL0~s ucuxWp]]rʃ|nG)tb&g 9#><j?QͮIB{mYa># $ D,5ծZgf ڋDh N`܀vU bin1c<;olDTBs}4`r< U9E#`󯊃2v=Z0g+Ybqtp:DPCjjzF}hfϲa)9N7Pf?Bo}&3fE]fqC$*C+qfQ#9F@"RN}#<d++^DKw/^Ɛ锦 @sGC)Tdl왾bU6NrQ -~ v>wȳbtcq7QO+蠏%KF]lA|5Y"#eV:1wϪ{r=;9w 8rV89ɝJ0If[+Dr!@/k 7P/9]i Nՙ3pL hO1j#42 oEfKQrFU5Pc`pOm?1zakj7k\<,Gs lsd5fr]1 :z鵈 xvJϽ)1bSiKtLŭn7-~}͵= jL R:^MǜJ! ۱wyXw]>V}AK'>U\S)҄)փՃG[%], JDzxE7P{5 jVmݖ7"|XO[qlܚZ!0X3Ai iOM2>KWUa ?tJ2g &-rV>A[1|H! X\?k&1|(WkirB,oϿ =C'$E~2xm<)U`4ՠM6e'Q b4PK0T(Խ_>iD*LϔD73Bgw 7& dG=/rLڡ"VA]<1F?6`% CeeH!y = eǀQmm3ڶek^3ƌZw*Pz#3#P۠|_AHiPo VlG>C#SbQlV'mciNa;ۛ}8D,D@==rw󪽉bPУ|Ι56D57G hK &/w21?߂;5'w;k_@?߾}۷o߾}۷o߾}۷o߾}۷o֞mVx 0)pEH T1#mYRjZ x@^8?n+{Q)콒= >88pMfPȦ";J,rT|~~g+{[ $Ƿ[oć+ (((- ȍ#r뿭9'PL (!/w/A3f@3!^a>n>!n.Ssna^?90[WG $$`&ooMf@=?/7???߿?Aգ`Ca L`0'' h _o^Ĺ兂,r.UUG!ed@ $*"/FknRPCSur٫c3 XKM.,z>]Viprw,I$C/j4$Tϴg(Èn$bp]&czˇ-#&~<:4 r*J12[hcxr6pkįW>1u0DY%jAvCf1Rgh qOF5>JZ $yI%G@\fd"҅B3kJ 0ny#|pB1V:(|GcwG P wiKpD%l .7eJ3}l'\bb{T;Ip^ʀĢ iG-T=(ĪHluo5́˯=KQCClIQx0[)L`t`snimy-,". o2t#ןrIzuFf.?P"jXqo69մ }61I ؔĠsƩC,ScSUto,lUyh纫MB|C2G0ƛIOn&NJ1f ֥],0HeFZZ}%fMŤ n<t\ F_Nֻ:v?+q$KdF\thm|Is)ٕeٽ9%UbMOq[|VIEd˃I+"ʧ?v|8VֆM OqE`7]@텸I,MR|qb]^2.jmj \-n;神 \z:ږH/sq&70e.tI_@ +WK{_l ʗ&F40C0 <;>I;ujHʯ/V6[+gZԭ{Pc)@Ll0H41>&s߶@Tz.cw,^5_2 o|SdmuX{^DŬ6aD8ߪSz4T+I? NyNq x6N^{,$C~PEnc$eClnrϞo ç\ 4AQhU`[_mM0iߺS-|%(ZĊѕޤ W06p\G:-NkBAV~ƋPc[\[MqD?ʔ\B@8%|Jfy,'/UVhl^VyVO ]Vpk,EsCɜ"o =޻zᕮ~pjRwW݅׹zz]$O|zZ,,\Uu%Oe\[nO|a_;P*4E#~0&w嘭u=a>еڼg$$yٛ=n L{=* usVOKDmNs602-a%?'?eP<ê\*a++coGZRiO0Tnzֳ6A;^nIU| cH0\1~v۪Xi^za yE4ibCSI\h="<~)zJ)귖A7A\B c$J~ŔfdDugM+|eI(Yb"$=QBuՓri4K[4U }O{=J}3kmpp{Ju(b-+I1T/=#_j.mtQ$(ԣKX)rdU,2!䘟efFaB8lFf,DN~4Ԡ"(}{ODϸW~a뱧^G;^¬SSf7Nq?=j^!b9 GmMۆ 'UƔI~:ւ+0*MC~(V=5% ήZ)LstТjNX  _0\Teq]!W$j\jc]WeU^/NEj= >;~?NvL<'IN8>NL^D?5,&~w게ɭSo 82zaT(h+ l<`=|$\==u ڢTڰ&3mpiBX¤|v7gdY=Z{\~gU_;P7k>gHzտ{ΈU;ᑠV:Jg^Ⅰ<(|6}vE~'& 2]t;96q=Im1 f,ڣ$z-ٺ3m+kEE,/81*db'b+˗[2J[Գ}Q?ng{E^꿝65l\)8;ܻTWCڍӇE^k7Kg#jiY2u]3Z-Qqe"LK8䟠s{lGQwbuG^=M,a}xX%5!ϛ&zdSrv3xJ<}CkE]nTDlS^Ipr ! {7̝zSi6qcbNV\'z. f{UNSd#mN'B7ZX\ÆJH2Si_Xʢ㻷-&/d3Lx، ,)!y #N+zDj;Tn-'Rs䩑*qfb yZbzԵpiE}<ڧ 3N'YSf>iF0GwbT<rAs^EFn6)s\3i\7tVOQS>rR"~f4z`U0z)8~x2匍mwRͩYZ=5@ѐZh=E0P15_#ZXxh&ZfcX钃4?6?Wfp;| ]QtHۗێ'ݮsF^(a'wRtS%6]mj%8)LI2rJoT*cyᦃO`KbunC{7>Sv3gqج*rKyFB5ďF/K>MedqEa`[lBHҥ(_PC2{E4Vuh (BlϿի_a3 q2۱1tÁV|]o]U ðҚG_bO Nx+>KE.mO.=[Vfpf`w!s ;&|@6B Xs uk1H:]T>U n:;[ ߖ]S=jRKikxƯ*ITmk|7Z'F{F kLQpi\T0S}}Nlm/i#&7/'Y4{"ћgSqi+PeLˬ;v)$GXYK(ݬbU=ciu^ *vx?b#y9xctʬ,,c'CZ]ȆM$/Z^)ڶq;pL-kSu'Uq+]3*FzB?2*g7,%f+K*7̊&ap!|9|@+f'])z{Ey}*xE|YX~.M+a쎁 HRMPjZX$:0vB{q8%BC hW8bY5{ ʲ)yUPԗ ~d@*[E>tQP51EQ8y냶6$" jj%jN*OP=WGjݹsJdMckg̒Y&惹F}d=3=<`~CTgcմ|3uј&-7t9ϵs78GIK"ka]|JlJ_8y!,׵(m^K̈w6hDO➟y#Kq> rR$1QKQÉN9kY;sy@,Vӓk'0É] [sl}&^hA@ *\9 6iA&ΞTUY&*;!"W*SѐWE*$簝ӷ4pO_6siŀO=x_Wz1˗G+WWnc1z6{q;1)RlɷRl!MDu~JK)#5C[Rf$'= N:D]|]_Tݷ stޫ43U `y޽kʶoCO2rXXRҚytKylwϣm:*t[1s|%Gm$N&Y0jRcxF#8]v:CTw/r4JC>OyP *4cgWTA }χOdD\}9tCS@\VV8K,JmcE7)w{|(+Ⱥhmf3>]H/uf}ED-!k.^ Os7nJoVm]xNk4Qt KSs5԰4.b9_1aykfMqdwB-9j%V+>>ğiVuBlZ;f&x/^Q~-Ԉc@0`#]~1wV TJKH* zB2v4 @Ew-#nm2XPd%c c B*;~%00Jf+_aTt\5pxF0=p(<4BKD G*r>8ci^G"=.!o .8ʱ腭}`0WjxcNړfx֒H,i ¹bGϖsb 67}/)Q6!7b=bZ{O#޸idu2YES{FNϺ{7ac.94N|K4L A5ä6z_=b a"v`#p 6O߼ϧv0M9&izj32S5|bּ܅B8;d&t\u׾eVē1Ks|c n/_*'ƟҠuNxOSXP  M}t TԛḚ9ƬW71*eO` x<6OD\d YlpdX[R?Hv7h>_ufIAZxMSQϮH/h^)nAܪfUt)W7 u= ^R|qYy<+ʼm|YD Y73֜ 3@ڗ,Cޞ0Q{ڠTS~!mhFv\ei7\'_f2m~S 7 HnL쳊/|OH=SK1l#̥Dvzu8Y mA=U\@֔={2'[N{VY״s7O\+uQz_+|^TK| +4+w CV VW7k! a.>]yj!H{Sq?m͙As0nD<:Th2)\149i\yJWZY͜'mH~~|4٩$pU)eKc֡g&cn+uf7V |^rCQT]㻮3z Iwl>ܫ9~hAڻQWWftcbG0hE)Fu,ەnIZ/ƸZ>3@z1ΉJVb:]W7f,cf>6Vn 9E'ލP(~;+Vy>ⳣ zޖ!މ1 tcblgs[(K1b׍N^%zڎ{d 8TדQK 4 ߻ZYD(|E[Y r(uVZ='O|WLA(b$ ^-鳥juѷb611a,&lbDvӦEG/<c٩l˩8B/[ɄW$'՛:l!{O~EWOP"ca*nfrÖE- '*ՖZWZB`1\](L1+>21t,0( pG9yB:_is0>@*\ {Kd[7nipz(@K8n=3˦^dM9&o>*ד)xyjD` g \V* [f*R{.M=ǂ>MMGVbҎ̔[A6&D/_h!r<)ean{ZyO?t'їڀL /wN{zE;C.'^rcHW82 ̶u FoEvtM &{e̞$҇^[lc3I ( j{]drM fkJ*AcҪ[ZK9 ?&^:k3,ZD Ӊ) +. ksw؏_ |(ӹ/v'DdY?@:ҙZK-pK:NqQKe<[&V.ާ$Zuȱ-TKG9`XeZS5Öm'Y͊icB YJc̊XjRD&^=I@\3&ygdgrSomqC_C2~@?uP@Yّ|mc9"GIe`―IJ,_pIOzR@{T$I<=xŤt[ıO}l2OJt9&D"0kw6ˉ*|}X/PP.z%1el9o~;\a&Oc4D˕2NTSƵ[&~*<O+k,;Ź7^rjo&c}rf{KjUNtt-Ѱxd%|5Ynފ`HOFhnq60Ͱcpϗ~`v%܆>b+8ziy=Zy6[:lA#Yas$O6&Sp MH7AǼM/kc_Ⱞjk0wkOˋܪ)(RW33崯KN6,&:7cr33F7܊񙚇O-T2UQ&']f#k)RӼqB|eb9ʥV;Dm[9r,o5xO(]6qY@UN}ԕ%"8T7Xn02 v1#N=;!pSg`ZM$3kǤ|1 ZUcgMhHJUVMF 1g:~]_/ owWjM; |{d|ez{@ځt3JX[j@Γe bl7qتkT ڨ-񄒏8ݵ20(BJW2EunΙ8os*}pߧGy]|3t,W7Q|V'㳟rL>V1q |b^ :*pfPXuwE4춴ⴥ++gѫ!쓥 fS9t\eINJ^f`szd=Sjw.Yaj ֟sH'o9eE(k~83%1ʃC<P9ˇϸ73= %M)v9'.{ё"څa ?UTy:KgI6)X<"Ax53Xԓ-/` W]}X6Xf0^7aɄid1>ԦKQ47 wpr܅S]df5v v<meBx&IIu٨vnit9ㄚ7$<'2 ~;~N,3F6MSTD|e V i7)3PͫRVy~Dex`n $FѯH"03Lu OoP}{LE@%TڇS2o_{sPpOT2‘@%'FJn]Kkss;b0;1~Bxy=A:l.z,`򂙭 dw֢=S$>]~B엳)b'[}|\PJK3SNt%'0KO='2tg-]%Wq#Qs9uQGQ֡Nfb޺{FnX:`fIrrg@,3WԖm/WnʮlƾzH%ykr,73nÿC?!'&8%auܪ})qSK/v2jofY]fpj-Dnv#V&+ƏR $W4@,OVެca)x+jMr?1y2%N` &{,`DT'5dm=S4E -G,(@y0QP.,ȿ]N!Oky$5<מ/#t y U.YDŽF[/<ƀpI u^R?'CΜs=y]tkMohyENhF^C=GL4(}/l1Hn{Az>f:'#OGɤ^[~T[zqMc,Z|eDFErd;<)ENYfmx~NMW̱olԬ&: @ }BeEĵ,AMG] 1@1a^h((jMINwSjܻy*d9lqUUϷ掑SVAOOwk[yZV۬fVdal[g3=Zh2s>v89T+-OG8+td+X78}5*-ԽqTߴ0iqo4[ּIG82Mëd֭;$(~ngP%@ّ3F!!5TlCÞw#ySTXe5Rl1j*쑵`Zi-5'^ @1<4{p9bkcBm*C~jL/5]0=3@}լ {50Rh8_)W6yVl=F6]7Kf*J֢Hl+.I`oajk$(,d́pf1}-B?'Ώdۃ pv3 p֪ 0`*{ 1;9lpLs QmsYVRFE`9',p5hD j?"Z@pkv-; n ;<vR0ܒ}ij%?h=ڰaHa- %ôbG.bCf{ - `j YX;h7]! - BjAc3U!AK  CνId}3p8!s(X 88 <7r 9lA.?O 8|_܍3~e@{5{*q:[#= 3,_g[I C Vd s CA h;_6{aױ ⯜uXHC fdw; ay$a{?xw:U2`iܙmΣw\v@/~.B?/,GG T`98{F:G9yU>= sHA3]wRHT> az$GkcBǝu>`᪽kawewZlK3! ?xz[Y6DR@aw}FdG޶<Ēbme\*dZ s)dkL1?vD==XxK$H0s;Bw= GGc0[~w,Vq^a~`xx8l! -{O;!$ !cG }p ع]ح.?wdOsGA ?䅿( ݀`?yG; GklC̟L{k5HdFdd.?Kn0BPpr PJs=0~lz{L_#57G.9-fC6rXcwmQf.$[0|7l1D8`r;" D9 9 6eD3@ @0/Guy{s rܹ 8 u|f':8̀~U` P=bS'п}#uw0ۼ8ol}ٱo_Gy?d g7@vhĨA:!=cwB̞P'v!q!G8OLH- Aa sHy%;ȸN6E Y,D#v; 9;#vb. C 0v[(bg 2G#oA6@0b~:,ǾO8#fZCvX<}|/@:he?] ="J'i0 l?Gr;sT~> Df{4RQQṣD߹Ņ @Pgvj_[cn I!.c_:== S8eaGʯ  =;:?aoǾߴk`G8W);=!^dz2!wcdyC ޽!A!9-,vvE춈ϯu dSc؁[]HoP%S;ȟOO%G]LM6o<i:Tw&<:AH!9&W~+=8 b;)$Lmg3f6bri}wBj̏ e efW4B`fĮ]HStw@oeQ.|/g}z2Si5k p~iuo߻FBm* socx4 w48e'C?6 :Mwl*{A,t+fO/߅iptK|pFQrPVy(J[ @erYfP-j{G 7|+CN.[-A&Bg|)[Osl蝔9[qKX;|Kþ%\K,@>[_S>vm/qU6L,/sAM%ԻjTdJkN;*goݮ Oޟu?>ߓ~5Ko?/AJJ|I;Χ}o᭜ysBww޼\0gCie>Eu>V3Y\=BBjUxǽ2[ô'Sc7f-oLW)[52_n'}߬QBo-9nl64|[{Qu|fZwoO_7ggWk-sx^| 3xߘMg[_]5kլM?9<)j֧M{s{/hn[Oe[ZgxDpݟyfUx.@񳼃u_o/۷}J\eVϒ%_+x_]&>-eXx 0i8)?BmՐ|S4Tݖ Dv: x@^8?n&;"#==338ǖ"{gQR +;eo~FJ9}w}?}?3sW@F6 >xyPxyxPyxyh:}'8`OK`A8GT60613 xEf<|@n~^s~^3aS!Am'2"6~?xyy<BEDڃ,` ~捹a _nt_//$4 X-T !b;P΢m⤒Պ PWY[xѲ~U@VrIXlԈ;DvCcg.9" JO׻c^e)FS~%tV>Az7WS wNZF櫳rYźG"t ~%9U0؈iS`FJjm5k MD*4^=<8hƣ&yP0SJ3<)" 9/XxM{ˆ4(ƱrC'>6J#o@ l؞6%Q1.pR;98Z80P@3C+қ̧NtqCP:5K /T:O"(~0"UЭ>Vzکz1A2-P\w4]|D*L}sG=WsHjrqk*%~w&3uZwD$U]F:|B9p -  ݙ|V1QKkZNxA+ת4%vqL\4$P~>0N#1 *u xK 2}4R,a9\&lj\U<5]muq<?<6Hؓ:ؔ-L7vٟIxa?Roܢ~n!a8:2+G Ģ"rcw/d$oK1+R<cxLj +9A,GK8ϟ `lAPcy:{)"" ~>'X</[[N\ kCLNtGP+Ѩ}?,2fYcTPzU&j!3bĝ7jĉQaɏm#'j34:ո|atcxؘODQiPK13 F`G4t\bLhF ޒU"|LXU-PM>9ɢ[jI9<7>Uܕ`ri{{g^ePiZjBuKPs2e&%!8\1.+ lIjUDg~Q\wREzU_책o5 (6YyxEGqGXϟٸT_O?'a qĂ|RD՘<Ϻ V*ߩ.qXuժP5AY_Eӓ LɄRq1͖3rQS[4"u+VǙ/)H| WϦ3: )ga,}gg1JG*k]Z0ؓ˓ޓ rPQ]N9J`쩋+sA-.E6u4+!x~Ī^ӘdIq⫿P=jW|Jc#dZ֙/WԃWsNh/VFõIdfV>ңf93UthZ K9(9GE{yY{vyVoäȺ¶+%WE\)oE{r֓z&=ea/y͛IKa춲*0 .A4\)u ;i1WׂX5^QlmCQKP8˓Ws:oI`h{DWx];̵:u&}:g<@u;^1$*UK)*j LٟɎ=*h|qeJ3g"[ Y^Ri͟ӪWW+{t;fr22͹wi%yPr1ˇ"M&Μ!x^PڔIxsZ`87pUo|"@Zؓӹ#'-~t- guT&|>Q w@yI蓫3 222I}O5Ğ$Qo>f}5$6w+XIDZ{#w1xzJ-jNtS4iÓAԸ܈thҁ7HkAF.Oq?tsU^էzc)ȿM7;GK;R3#Ll%3cXؤ3Jjx'č$ϟd]. J'̄?՞3|P[!:5p =R GƧU+j]4c]2?>PtYF=޴sa,B3g?]0[f@BAuRˏQNea-gܑP0u|/+Ϫ A ę"^Kkϯx ѱ+v_v hZyz\Je( N\wXuڬaaUcͺeН7eqJ}(d{$Ǹc|h+gf q)(P={)S0?H 6*B+)/#|{xkv!YÊ Χ0 L-n4';.i\q%,Q/3ꯊji0Z< Iâ՛˺jK\N7qtBY הy7$A=ʻ`%ec%(I1`Zs4]w%VI^ ?%[ɀԸRҞkHL*ý\U{FuJ_gјCld #6jbu.- $nYJ ӍhDN57o,3Vjva}P)t}౔!p\Y^̙Np|6(?g3NZst/ӆ+lT #fch|Mdveɲ5¥'+#g2/}U)`'6z$"6UƉKϋmv58So๢/a=> /pĥW0&Cl'C=R&7S"Vlun=Os2c FtNɢ/$D6tTNbWDЋteF4m_9^Qg{*`vQsK2eRk.ΉFyR<{QO8T١(/e8f Z(DRK# B_ T|*T\> M(6Nv0iCR%8=5[g9L})qID!+tx㼟;槄w]L[f\Fj=xMZݼLf*YW}Q&AEbUME:+ #TWPP1+O }8]W;Yx&K7:Ίi]qX=SR+CՅ/hQqQ;+Vn^X똹nOF a[iI>"]9w!)jDNy>%Ňl= WGx]:*>]6ͫp_dJ7JG138ouj;*\;uEŰF\\$D7+%o KWxc{zlz}7$]t=B' P'vՁ?ڢiT6=)[=,2ЍTM.-&HSHJx+'gQ}cRڮ/:|VVak:o,{t$LSsP?p?.$?CauSKUK&zXdFzbnjPp+?,Eo͚ټ&iJ^LJz}*S*(Gm5ͳ<\Uv57پr*WF&aqUcEj-VA(C~Ѯy0ȪU%u ͚܊788"D8Z15Gw7"rS-D6i=@ "` ٔˈ%EI3Ǹj3_Cs(b Hwiܛ$=8\,P Ů+L9NWCҩ'8g{n_g:b}ܤW{h%{w'5kޜ-{yk]+'pmi5/V,}\q(]~D]O |z.lul5zVWbWZV[$_Lp8tw#6QTc@8u|Z7cwwpM'eJr6s&Zs>M~<4?k۽kי}泺 ?5*},˝x&[m7'pJ[6QA +ڒyy\ϕqr}o3)-Qd>_qjΘw4 Qۣ p% zՓQއvfѴ? AjzexƁ}uU:m@yE_P|? >dC!L3SsDS5+E GSԯ)lt^DT׉rX6+ZLw‚PѓuriNugT2AVa脹)F}^=ޓ{g_\~yflP7n-- |XQPRB8m81`2xK녺FN嗘NS=@fݻn|9&eP Dٜ: n(޺!)&QoĝT/C{YW00bUA>nfUd~UguҀ۰&pgR/ \Xٟ@agްF#vlRQ"cy%0 qUq紤e:EVin nL*]=c@VpClP5>-Yu~}y~X5ܗr=1\4&pot} r o37u&]\5A¿U&e?!)qLg_핝+(:j AW~k:=E\Ϳ2K ,)mĹx!y :E\7ϦơҬ\~(zbKP q@zgj~pt{xл/M7S_`WcZMtze8q/qii_hy~Sso:. TZ‡Hðg3g+g珞Q]1EŒ|Mrc5g 14.yV{+Q9I\2@oTt[! , BQF1p%-.11bWw<26}RNݳ¿񄄍HjX~U׼zhyl`BG'7}5Rjc[f{wev3tiѽM*_>/+'1{|q#r[Dq'StC֔:E(ȭjj ^o+xNLSO[6*pҸύI^\"d[C(tfz:(S.yQdE)ń /T,-hͅQ c'{HHQǧ}-o7 Ek1|g&ض;2b{xeӓOOFljV_ s{ȃ۟+ݦ5UT  #UjrE"G1Ӂ7h'KޔX<&a!(-tV)7Vb/l8HejRaNK+z Y/fQ^0ŊGr퉜ݔ!nxhLm+Opu.%&ss_n9ŏ(kxΟW˃5 uN~kׅ`-i(:IWM~=n.1SLqL3gFoێ agūE,г:md@|nݹqsrWt2 \kbr_gg1B]?W< tuvImaҲKJԓQu=oe5;[ab\3`*+=bv][{V2^fo@79|fQC5ÿ,dUǨlz5K!CEX"]raCK̚MK< 1E;lKcX5dRX"Q_D;^~r!Jκ& ͔J}bfd 5zMXr~䬬߈l]t͆pm_WFY)坵,U:e|`qU$!MzB^F2y}Lpof2kH,߳M=!4}>k5i̞e|0ir_CxVKD5CEJx͔Q$*oicr[_QD j ˏYQlqnׯW4p}ٮ*OSf0cjtIB7_nz6FumSqKX^zFTRՠKUW.E{$e>zo{VbǕrc؂p иP1vYvGHysB:f0`FUmCC(Zų@uU8T&L^?+g&~w)٬ kMg"GeRBtK>Y(zgS0a-d6O\S}ΒN} HDgz4lR'']pD-1jULd=EN]Ĩ.(:-$S*yZ03{ToflE{Ŗ{ȅ\QՌ8KYW)Q,-=hyu{ktrZ터= kc/dXJzFSYYxQJX uc?;76h\z$zGlY}ص(̗vJiS<гb>`>g5dn|-^ |Mw 4%/Ex<2U>qs! }, W ͅA-*Ik tQ@&ddaIeNuzl3+&"4 AդoYX \w#At˧Œ*>z.*kT\OzZ bꎯ4^AAvzQY4m WDy1Ih˼D|p͔1sD2L uQׄMq_Ym>> tZ-dP,O"qv떖"O֬ߞﯳvIV*-\]uJx |TSn7$.Fӧ9F.ݘSm"|B;_sT%V~ðErJj5S$<$2[ -msT,71S?IRFOW4 +a;bA,P%x  IWUY?S"ª>ꉏmUaSb4aALnn6w]J:2)hӠwxAPxs;ۇ`$%kn~%i0.cn4'Hx5f'07)<%^[dʇ@N5xRq8%oL%i;˳`7׭V"J.=q[?.+CN[wS:o֢9N숪:"3n!uhb=xԄd.qn>QEim_"lV`tĈd '{A {~:+;P87urGS!+WmVY=4|Ì/f ޺caAb~C:a":(#4DZGy7P{6MVקQ ԧh4}6][iti?(*H@1ma}. ˆd:F|Ȳ y.!M/& y᜛ܞY}ϛET}|Eջ>8u-v 9B6X6\~}C|D'0w{B${q"-[(cѭ̮xxJ %qvV4~ _ F#䒤XA\Lti5.VanF,3FA,݃r'Yӱ6M]m^*Jc|<'ϫ6Hhy T.3rBc^O,>m ~{w9kh8?KqW(ȝ2b+#\IO_ 2odL:CX9(^Cc2WI=QGy}(:d/iyK)T++D*tfeC+89PKs[ZT9xMr ,Vlt8Ag?!TVtb!w#;}`FcYgnً,}5L/ ?MܛRdKl{= ɚiPy.1}˅}0mx*XrOT"b`]u]Z/]y=A}J:љ:O 婼-q%kE 4{qŴI6{ iFhS<BT nGbK+^sy -~:yAQji(kj:ba-OS$UQn ng?|9N r^rC=8Olv+8}u\PH l*;)cRf`IuuqHmKi\vY}P@W:tt-";h] M@"^`g]nuo؆BVcMYk븍tn -ꕕ9vAcxs`s*])RVX>'ȵs4Ӗ<dž]?p58_E~F[L+Ҹ?LbŒUο{eTih3|ٌ7Rh}o/B Z\gkd6<̕G5%N`0%xpl5gmEԫ u I*4=ft&,@4xj4Qd+7m$hcSGա Jz!Q7%vy|7+Qh$TW>_k YF"M3s.(Si/qlqV76Fݼn̦u&hw x8B*XmjIH=b֟fFѠŚW5c1jzD'C% nR_EђkGd%: 앥k*S wgc*7)ͨfAt`k |z1EIZ(Z_=#k9Do@u|Eӎ˜Mӯ L۰(O061GWo_pYH.:}5Yl-iT{P,:beL\nqHf1ui*,ˎ.WrtX#,y1ǃro(qz2؝(Kw~jPg$6!B tھsʟSK#jMi5FBB))zeSi0t6"d'98_h:+8oE]p|7j8s1$ӟov^B#V=t>5mDMNWWDӇ y.*l,MO;9ޮ ~͗XI |6'k0mWe K8yX{FV̐C!%S@eaӤZj GE~z1^(3Hּ߫"!p~/v9}1].d,u`3z{LWLwGka\&9VP3v%iYx7觶O4;(~2YKso׳r+Eo=en? ?[C hs@ۏ,55 !"u$#>E`jm(meq#G `r w5ycR-6|7l' H^yû#yȽh<0˷8 9؝'/&nvZG;t ǝPa㯐Pk;<7]9d0B?u/;/1ǶFo9sth"[<~4@v,۱z)v;Y s=j`H{8gOrw\@RKB|P{ж d]'r!c߁ouH;՝gO\dwWޝԑ  `0(y [rwZuXKhGZvZtd|c'\H,gZCv<}|/@:he?]؎[΃= l?Gr;sTsh` Df{h~bGs ?g'?H/,dN;'~~o!ߎm_0;즐t⯟‘?eCN @7p. ;R~],m.Wo l8xMn8a 4?*e紷8ċ,ZW&ڻÝ{,~CwsȺCġf*sHή2@K˝]l[BdmeSc80lYpf.7p郩KK?b戮.qh&X4nTw&<:AH!9&W~+=8i]vRH9H+brfi}wBj@~UG2urh p(l![NӃfPu>T$]u8Ҏ2(Z}>=l8#G쿃:wڟ9qv^Bv62V%Pj\9Y7z{<ʶ`'a0@ VзbVy{>{amʵ1yv'e>%l%%o >շ_t3>ߪ~ fjrʲZpl 8[b_{w5M5/!b_ Α~2l}!`>;LdT%@$V_MS@[{󾃡cgTݾBuW~_}V`#k =.;{ L5t_o6bl >b>#`ikLebm+`߮~\;b/a_&ldw~͵z(#s8W۟WΫ* ۠{Kē׾l{2پݸt~Wy3w_?w?Iٿ7չ^~gW}SP{aqjBd/'4C&%vt8ēȶNp_!4^5[kc5wf;I~]{}}woS9Ӳ]܆te2?m]mVg=w?Eo->-W{=tf ?}ߺ8큎HI!aAݿ|"B?0/? /iV 8>d;G6)n>u_Sï}xd.O|u,Qէ :AX~ I^+m DH\6If7,zܺxs]Y.=M!4sQ {-D VWR[WUɶE;|SEA47r[[->[8/ɕbܘOn9>NIڨ d*줝C[NaԈ4Hc|a~kLhA-֎Wq;f{T-־n׬ClPn3a?c{]!ĭ@)߿,]_kt2KM˻)-aâӲozo ܦBb_!K /'';]WBc9 qZ8pAM wHZ'qu=᎔m>Y$zdܝt}×iLjI=-쓃@A|B9ܒQB1/l >1lmL},a,o 9)1y j9;_zg˴uW D< `L.(q&JVwTr]CuERWRq(c-U73 ]fgÏ6้D"%(ůuqkA>PiYfE]EB% El6fAD#g?](e#v39i l95|[+B}׍B_fe94HhHY8irJo:Ci C]I^(,9x{юyk)NR$#ƆZ%(n!W|BN 4.?tVuZo{oyRb j_"zG7ƀEOh V/JzstHճ %D: s-,AFL'ub>}w L#YiQ |CB?y @r2Am M2]z#+d򢌶pO9q0z>aNzEM1k5e-*'S}F,3M:ss1馯q[H;*z_=fW~QMŬL[Die<Ńaꁬ)SWcSV"_Ksk6?9fm#UsS&|j$?kv{KVgdN5޻L9,d@ zؼpw/,q۴DTk(^V/.Y(߉-?u8ݤ98KdA䌘s;NXVRsh;v6ŵ _,oN+i}zO])hޚU|<қXXܸO@ԙvGa,kd[XL9Ĺ:g݈@FA׊ & R \t[`4,ֲ)hGWl^m<)`sz$u %`8Aalo,e M{|Igg&1j:ܯQ][XOJOSŽS2CC Q27"3:liL .63?|5"QhīgD*\ R0u}A up-s-sسs淢j#-|MZ[j+(>%KH?'YaAՒzϱ&/oP,rԨ,ʨV~y2:Ü$_\űYX_{Rrt{xe}:3ˤ_:oQ8p\K;wbb[|M!d)!Kf|I}H1_ÙӕY jzVoN m3gVԽU6*W;D&ucO^ 8dڈsnK0ӃVJA0ZP |z%4k_]ߩq iS~_aζuF<=40[eo#0Anjk# ]ob&2L L1*C '[t.\.QY g0H pV g3{+ZbNuZ)z{,}&%U >r"0eжsE#".J遴qe{x'6J~* .udj"1 'k dOdz.؇u3ldL %N꭯i B)^T,jvL7fdr~C\N$O`ejN+s'SfIy!5Jռ_g\Fz a}^?(UgA_HilL7Ka)ڳ&qq)m3adm5amy_;Wc8b,^]uӹTr-ܘ)&!##7jTb3D_A^5HWzR1KmByOb⦋O,KT M/^%#e]00#lLhC.k6Mi5#p~ uB/$z4_sٝ),Rf[lHNb(SzN)}W1q8)M:=B+UG3KAi3kKB,{zwi!jik2ֽ/ #.fTp>-WOzot`iiɢQ;.ld;iՎB:[fH7VYR%oF|u''ѫp: i@b}[))wS8MM n >xV/0͍2E@ZxsNE=*ȏ==F( !P/jIf^^$T|Wvp:JF3 @ "HE'5}DB7E B92I& v R1zɔy煔˅IAlgTNNQ̶Zկ^-њ#s {m+SxvefZ8w᎟j(|?|? O=Ґ,fgԷ~qӆW4p{8Nk& B':;v)|<$Vɀ17_^>r|L-[AB>Ov5KH"}>7.4cF#"lf*@B3fܿQ!JEQH Zrp6W n ygMj_ѝvES5)?mDixJ[~c'wT?;O:| Of·YeUk9IJ\>բr:>$٨ֆTdfîqė*Y7lmR ֳ8@|ثPTͫSP=O;׃A\6͹|9pA㠠\/5!4Y}>p' q}5_ mJS6f;_`tBԉF@# 4h ~KsD@';w:өJPr]9IhnGRFQy9y]qZg7"mk^_`̠U{}D2"! Y0ۏ$h1]zc-<onZJm6TsH|5rKT?NpSpQ"3\&rޢ9SjHr$ z9C&6Bbjrx{?-7 b6L#**7$Q6&'>h i$2p8{.6"u>%sO9i-K5^$|)fE?\b1IVmR7}.j3:vʴ{J_^Pp-%R;osH)fuD薢SeEHs%|kNBNH}`ag.5avAȣ5P~QO( ,y !W1=fVkV_^"y?SIUr!%i=3V(e[Qi.iX7Ns2b5+cX+x^'=wSߣ)Gq4M0;R}D͓V/Ɗ'u[u7B-XxL:Z]ĩGјWy8grק砩GY=Ձx&>fsv^5qb 9)'8queOY(ċ+p{D0+`ֵ _V$ޞ_\Ctװh{ EXwa _?{;ylM?Hy*D"@pܐcj>7$`@nlR`!Xm'Lǎo=f#5*4n5us䡤ۥ_4rydMkLzkfil39P!{b }nPjeTHԸM['2.J_D<ߢI!59Ozb8SC9gQpRdCUC1G,)ZHv(q[7ʊ\TmQ9+ri&-OLrIyWpyT`ؘ<Ű/oFRy]Ӵ[0fX0mg||MqTQC([E9'(tu\qxݡdro;a^#Z ɓ:/ɋzU<T\2:1_K*Cǯ†LGrVyz2.c6d;+H܂Vii`rLv[j1it'm)(] ek|?'5Ra'N4^qy\4BNxv3G@Y,D C,J@,TBLODCǸZC?%2Y0:OX& e2$2!.5C~tEp孢3rL#P 8i8"C(+vn5UR"\rC ĠT|Yρ=!b0(äe+͖k6]15*°ʄJm:.?t#c ]6h8pS*^'zNreRMQ99)*q;Vi}J^{u :;CgUDBGh>rO59Maz?Jteò}CJxs2$hF%0s%#iBm|Q'ʐ=>vYgx:mhj+SC7ikjLJ`Xm Y|LpVnG[ {Cd%ׄ$!DV0͢uCxGJZPKUֲKF҉J@zp|==ilA{amn ĠI25CT8iDJک}P"J0ۆg>1壼b ɎT]OZU153sP=NX\(p%^;կn2y-wo3{2Yd< t3ps>~PPZ"ߴJϔyyUɪP]*]V`\rg=jBN)Zr1kf b%PV>=`MbJ4^f6,+lhWsF3\ژ._8u[}g6r;g w'4vD?";Ȍh&gukO8$_6ԃ9$'>xeNpL|>Ѣ+\:tXH`p銵6H<>0n2h S_ݍ{eYym9%eK,xEq"vܴjf r6$O\[;\$ 4L-8d0 n2lAZѴ;m[i_%3Sxtc wz }{Ÿ jOPƌQ_1sL-[ēOViR&HQ0v0<jmx`5fфmrX6PO)&UiTSj49u5}>\wxgCRUN5GUDY3Dnjٸ.(bit\Drb" 2':nSIo?(EL>A|L4w"; 7'Ѷ޵ƻRp9zZ&E?OHMKю;Z][(=NP GE  4Mlx߷uVΧ7)Vh3#I7h]X[=O`0=O?÷l686#o3#`X/>qz;-FqM$߽g^qOXHR "]o({ 76wO`ٕ^Rsxn3 _JPRJ;,X0ykViUzp.AzZA#j?"W4րi)ϙ8yhPi݂,LU!V)$O3̿ >+S\kG)q呐g8u1֛,}ҲE"<#dHruˈWUϹүܓ1OVI㒕 sbTKOdtUhy>TF/iBATI+Rw%O<*d uhVE0PN5_δ , yge o'6Ƿ|&)vW!nL8c)B%Iμ 5쬓ٚ0?qgQ3ꕋ1KA*/Xn6<1&uώbcHv^qZkVmg"x|:_3%X[줕5e{JĒk\6.P厱TF8.i\yVkaPtd9K MZ c[O> ]hbq Hb y) 1V>7@Nߘ'-_`OOXC"O(# GmxAܾTFI^+/o}|٦N6=%tSUjEؗDH~8J}Yح%|pZiH ]{׋6nsD.2*H1I~I{f?6KIO׫-?$J({f:xOxTp-0MHDFtk׍Y_:uq\`%.VĢ|EJ%#!HW,C)՝͟aιH0S$c yxr9gƒbqB룘5 #R.{Pj*>ߟ-iG7ð$狼kM\,kXmz kd?ٕoO6׶f zFL2.Vdz ci|[lZAۛHd9kXru'@R4•l5:_ (+i ʅv6V Fg --phc$S$Sy<*Ma|]JK= xb4&?r~ƦUkEH􋼒ahEҪUNqm&l spds6Z T"[u7RE޴DwBi$.*(lr{bAbD3'=U(Ȧ.mQ^yk>8{HEiOGլ̀³Үx`ߺVA[g]2 9a(\./de]ɾQ뢉ЙtFA-Pώӣa ygLCݶ j%̡l4ߥAW 蚊*_* 5&+6{23z4cbE9 J,i׺MQ 2ƞFc1> َT\"^a61r6IFsĻ:H|H?v&vh^KϭjGb~PGk-p P#A2Ʉ~#/Һn"/].}\a5؞8:fntעvBAad;szH[r捂ʛS,'! 12PxP⎓l6P`\,%1$M*l5WX f !aR1^ހ[o5d23xyIQ#3! r5ˡ%kj}L͓0ywB= F~Q K7nӲʒLudyԼ<MKݗ[-MeT*BBܫMO/VL)ZCu@к*Xih7VEE+ Nz/ ܜ%q+rTmc;y-+WGl'/z9[[@T%lX^A$_o8\ Q{JeF{(r8~͔"[br6"3"%!W}Tm?"هrv˪]%d%A}<}ϓh7?rԲҒ}p^5wOdud"\Qx5̈4FqB y+6,NlHɎq a sm"iNC׾v %L ;`7g6h='m9NxkA6(_v<֧&+U j=Z1pyϳE0^%zWsvV fo}ue œeV,oy)mv߼ l 5;)梔N'; kn<0[?/kuY6]= rq` ë) l1 ҭW̍zIae!r"k: S 9AK!o |(B#f 7A {RRG_u^6؟\;'ˡX)-eiIUA d<]R\khp=< >Y6`jF9zslhdgV.= ŕkCVdga3 B%gHP冀&276{Z؀ew>7IhMU [I%VseUDdu| ?0n]jhRn9A(xZ/=O׳ɻ(b}4.{ZFS.ui쎬EXSYN2a-$ 'QYy+5S$ao4!do$&<ߙ)kAn@;(C$5jv䬺 7lNqZ<>kz]+TJ,TYyO]rzKP,-2rjmI:As\u6l.e6\ ~ z)tg}fJRU,K_餽sW\~XUtˀ:r az ̺ 0P>e6# /ݚ0hg| *罪12S6y䬲1u5X9$դ)Ll@` Mk@vkه?djJж\7UFW=$>ޖ(-|%wvQ:T_f60VJ=jKB B*jtq[fs)ܝ6`c0f 16wئp2C{z1>TvӒl9@E6wb5sRut'_-[飈-ڗ2 r% k! -Hڋ>׿Ͼ./uQfq}i9*,9I6ɑ&S8<ё\xQD}͇# orDkT 7Wg}+lٲ/`` ԂQʝ,~ 4ԥPU6\- g_bҏy` sZ C#A,05lG:*Q유xo:Y"w&;ۃn<ǕIX;9⍟X~Rs-mAݩ8Tv0[guA?;!!Y@"X:A Bi?|X7fƐ#wBG;Cfj?vGXϥ?<:ca<~/8u n 8ݦr+\ G6zG%;:^߶ گ  fٛM1;zcwm ۱S\ 0 !㷪su@-,~oo]G'8 ??= a'@AD\~#v;-}#p;\h"c/~l8QGPn)ڛrĈm;Z/@Z?ȨGc{Ɏ,НJ[ $CKОgi@twlVVe'R r琽S{Y笎bw=QC;sr?nYG"מ]G h sP.?Yjk#. m#hc?MvnwY@7%Gv W'8=!?>mG ̽"]:!j hٙPnvC}g āS rٜ@P[i@4i"YP x/ǫuy#{ r޽9i_otpqYA&4,N?ko܋r̵#{׸0 dsvs-n_ ]t,qDK#Dndf7E3B;.]{w\@1BK@A;~Av=\x(0:q!lw;? |tpD!>,)euM㲷A?} KП*sw‘ԟ_iq5Ooq-D`;fט.Gc=8?ui8  s޲+rBʾ oǾ_s`ч8g)}^Dz?3!ڽ=DXC/~(9bG d#X[Tc8ƭ##oA{I@-ϊpofY3>XE~^2߽L 2wsݒ~G<Ɇٜͻ0d?`>i[o7vz-I|}Ou{o ?]؞4׾?Pnw>1ϵ_ڏK.wNV7`]C~J>Նz59,PxxB[20g35Jlcڅ+Cv.Xpw337c`uASlo*`F,6K fK7-@P‘? <6i3@reElٰ\,/j('AȌÍ;4;&G̍fLZmMv ofw}f< 5n{~h}M2 _xs f2 gic5`{sg ]|99~ܙ3G  ߥs-_r  >x 깹xQ%8 e`@!N(գCsX!` s(گ8濵1{+Q4~׉/z)ۤh(81tbv vTiL6VR+(Fno)=(~\2 >YQd͒Z^a/%F%phV2ylhlnz;2zIW.sb`5$0.nsy3~R{+VOjX9-gDN ʬ`D]BP\$+"sOxIuԘ{ޕcaK,弼yRY ߾s*SL q6YJrW~nT׭B g=xwD Erhr~i=}EEՑh6dO&OM]{+J~~y$mU+\oɕ':[&),yj WALŰ!+ &ryK ,~ѡPhB^˭+5^9G>|d2؛4*o)^y sGh D;KAAweߓyQj]g~e}W?Gxƃ&F Z1ҋoq71uGgXc\ӝ& /_B8܁GRP͇3HUa6V4q. *SLҟy B”ɼ]mi;+SiuNIRU)uו>` ؔuJ0$*JՋRd)rDXɒǾL|++WCI끥h6Sa1$5Lù +^r;(گ&ҟnq0ٚ{(ʴ >#V~/EKq'\|߈mv^Clw( 3ahhZ/_#cU<<+ ysVNHIxen#' @*ZK-;sIh6xr ;8$VؐZ}4>Hk!|#L5o%̺w)g=F*;ן|Hgze{ӒE3^ino'?]A9 STp#z LۢM*Wb&.h1kM1՘@-zNz?C5rOccun$ oJϞr`QVŠ) \h =%1yލr%MZuAN1~Xs5=XM9@Em%Ktd< Ԉe>mZn%c4Шuqوn@-:zaw]qIqr: جܘ{'gd  7EWњVVK < p!} X4E L;.]B 1ϳp_k+B*%VN&%Ӈo+'w)ـ$4G?zs TlexBϟ=-xUЗH\Q{2mJB9b'HvUfcK'>3ë"Yl鴎f~ꥈ=q]ypl<1fʥؼ'"oVX 46ŝ'.0<ɰJ[WKDOznHR׌)m1N!Hj^Ϻ( f)-'aY1B(i/0"VrO HRmu{~C=!Hv74 ɨzJG qx%F/Qq [ѤDZN@SX[LuM7?)(;viy)(V7Y5>wY*l'u$|d\ҀoNBܽT&F6G{Q S2II+gje#CE@~SNW-L_63q150⺶Z=VBU!"2!zԫ侍l%5 h]Ο|k,cŁJسK(d-'@}Pâ@O8lĄ҇pwJPbk0hΗV3ϗx3 WۆC)A : kdGOFi(ZJz/Jљ\ _}pG:k+sW2>YSc//y:J 4*M {{ȬVV}5~1FXS8&JRM%Y!vzаQc8m 29D&ߌy\$###YUԇ+L1"x,$2Yd'WBPeA} ppH0m+YbƋJ vEOEL }8R=Oo=-c\[6(q&"V凥qLw_ OB<]zɁT/y[s?8%*ŊcGzy`COHw.+8]Zu#uº#X#FskܑWۑ(A.x^홌aLx# ^D =OiM5{5ʿ_,l^9zcs +|wC?"ԔW"YVP3_uؕ VykyVV#CVc[lQX5bg8=]#ϵ͚V-Di=CÓ>)/cB}b1j>5qX+SW1>UaqqšskN=fчCQt*?dݖtCIoQ{XR Éᯌ4Y/(ܸZ|aJCHE{/}-ȓaSB7 {~"jb6^ԝlvbqsÔrg_3sIx~MaEˌ!MLG]j/a;zcKTWg)406@UiǴH3 H3O' J=!>qpXSZxU}sQxZgXexuE^ ;q3LFߙy^`,g_hԉGP~Vo%*~{jU6m c>\uWF_5ݑU4b)a)?9x5oreZ"_@?hl.&Ai@Ko3A$4y%k{_ tsY~Eܷx]jו n\Ro,]M|feHJNzjUsV_PuE\_-w=ی.x_]wNs%` %\ Oq{I.I8٥"9Q9GhRbG9-Ui/ yC0'R`B{'04BQD&^|>ٶt"KKvQQɀk),b[_>p! 闭kZoogYِKgP.ϢgHx*";ZU SVZf߽3*UDozWKy" b>asD=tN\u(__Qr )znSgbޑ͜mX7|GXƴI>,~_WXu/k۴4_g(<qPg+aJZ]Ǣ'(=6diRi!](L꾭 4u17!ӗFp_Ȍwċ5OYT֝|2~J 3nIBI. JT5Er-' ybxIZ#E \#^0ˮ}&өs)3lC>Z ]tC YO^u@⦹3]MLc-VS\m_uB|.7i25_NKm6+IS cr-}M5*@Q9B=*떅SFW/J{/iIS ]I{O_I:nE>.{A=xK8Yӆ<%T|uCs姇:m]|%6OLנi@7Pb=+w8̍ ƌ>#s>p:<{Lg,Q ~h-X.uapU:59ʘxOb/nĩy\&Kp&nem,.$dB̴yqObӰjvDo%^O^^{nŒ"Öy/!zs\V``xkD P҆S# @T5N|h51!#K&;=$\A:<˚_ 5?eiK8n31w?nܷT1c3|v$KVEPЁAC+8CoEY FQU.o93e[,%￉|LI=\ BlOHkzR.%HI3hKzl昃x['x7qғ]fxfVg~ ).KafO6+kp=:>^Q<.TNV mNg4'ع!>bϢ/z8Ҋ풓w_dufڀњg㛸kY*&Ԣ]O;A: 8Ī5̭<&Q/3Z6Z%+;oq-BC ^?k>Kȶ-5MxNȫt]լA)ruPsEOϞDkyGn̞k:FX+8ۯtp"MO<5'׬h+R'/3*yhƥknmc6a nN2!h}$7W(_p߆+ pYJ+G1TA6S۞nk"H+?Ube7$]^( 6=/#-nܹiDPBVBf1ɉ{w6!'^382Ǔ[ҕ:|=!0Sg|_RcZC/Ģ4J.?")>\ U)ĜȺYW*86o7_JP: \< P|JYbӤE;k52Wfc1=0ds(37^}ر&P9Fq;;ٖt*ik9LɈЪ#VO7*jb{mP<ĸ;1PK MRC+Et,5lADPE׷h5*I7z}~D!~nsfY"1[TXQ2.y'ɈL3Sq4ުugXģx&p 8K+z225_xU7?1rkPQ^̕.8߈:XH}VA4\c[w\~f1xW#tr4cĂzαL^֣GD@LS^G·EH[qof A6_®^xD3z9ҳM |Q5A;=4iV;bYB*J:u`@Ħ$SPy\=OfVTkE)g2JU¢wΩҠ4;FU3W .#њQz-N!4uQY#Q*7 sq[أ3kId>NW}HWjӂ:t/ܨ'@4VW([2ŧ^fYwq|@݆DjhtJ(N?ef'ˍӺLպ2hCٜU A>>C1cULsswqȉdT/,i#ybX8sJѬ-INŽO+zSV@Mo&I$u+M=o5J/Yy >nbD.X,J$Z5bX_΀^>:YDAc*uzԩQ'VǠzVWe-9#USƬDiv&))q?[ÎS:iƙw8>+J3ZfoB5QRfcܿT[Lz% ج/ ouiklMIrs[$U彏$UMT-ؾ׻8lSu NoSL?Fjɱy 25* ux\=6T,ْ&nJwKTZNWR4;TfγA޺MOUbJ6 oЭ\4#g~}S% `[N[Jn_\$ܰi#5:֠ NOfMpY,ϱv9Ɯ폸ljihyahs7uh\gEZ}XfL~P3>u BU{{08/B 29dށukGTj/jY'ѰQk-#ypz[uo[InL6 q\0~ -&ZI2rv:@TEJ=OֵOW/ ,8FChӥ9Gf|lI,s2.V[4v:*Je60t8ŠWbǸ VØ :Qܐ]%u^"Ɏʧ/b'/> eTLS q_8B@)[7]1))qYSwy33샹e0st/*~dB~u(/$hiVy"Nl Sti]M b~+P! k8. 2a8RHdC%W`'6kڥVW7K`;١[l{`eZLR1,ë*Y(9ؚVwjL$Il3dTUM 0Ӧ$/=&եurr^o]I6L1ߋ.=>j_nGs0 OֳHS.ݸAϧBvK2oSK_X:nwNUmlɘ*Ie2/Օب)&~!AM-9xDMwS]" x[wɲٞzZ1nEJmB3t@T>Z%P 5j@JalN}p)A%'[uo EQn*_ƒqI-v:۪-t Iɓ_|E|Ȩ=)ښzۏ韜3YVxڝIůRwU"ǩӿ[Z|![ZUO+"Ȭg+4 sh9WI ϱBQ<{l(,`jst-R.fWc o}zWke}$;jw>,ɍ0ꂯgnr \{W8Puf\#OR0 "zmm8fNŢbq GǼQB&aׄAԴ=4]9)"8jOAlȊOWV0Z+[}X9R0-=F`xa#, wÂR}*"_sַ~-xZU "jlRC%ɆNnBԧ|ueS8\P/轗이uIQF8c@2.Up# }1g aX6#RWy[>_W&P̅ϱ0Mݽy^),F)}Л0@豠"Ov"C"( MA!{9ǯ1:| W~[:K3tr>{g/s6t3 *+o]3z;u Ga ~2XlR ӂ9RKŔu4kG]ϭ%og3Jq#u DV&J n\ i:m9V]>X7I_\}=pe/ylbaDM,v.y-c8i5 5s*E_3zJ7%z&Yb}JM0.+·3V۾r5j{q-~|Ɖ)%V.8-6`1Y_ D+UN{1업 \jCK+mvH%uRB|ZH ʫljgP~.;sf2הPUK;ia6MuLҷppXsM.Ԍ|=-(n6>! (ztIli@6f[y {2 sAQ_χ171c^\KaWΜAry%57ӟS]HbZc|℈H_o^˽AXUqqfEaj-;k\0JC _zy؁"gHmބG'R ' &e ͗:,-‡`ue^XEB IQtYk8I)FN5&v&GG#U 橓=ዑ1 '¤p{jϼZY׃+5F_Bۈbw=+o՜Ff' n4OM$\:Jᅥ0&N8i8 ն.˗ڐ8}~orzRVTx2UFF*rKRVs_q#s =eC˸7>.iq8|@ޤ7sN 7jNuYK21I]vQwSMӮ+7Y;EuƎ33^*RgԺ(+*-Q>co񲙈Q:͚%ɉݶڹ[zed/882tlI~L`_t sªit.7p7 Š5_kb'iΑzEkݼ!]KthB6F@DP )+mM<'a>/oOxul磪ʅ<"Q~yE^׼l+Jh;UXw?E%G챳_ 3W2]3&L,xKN2 be)Go#XdpO?~i @=cxB/p?M5+r|ӽdO%Լ6Bi.3R|c7z߉ Oܸz`8G6Rq:LXbT yeC5:noii[FSPyykXX(ꉂ.Eڃ /keXsXxV ?!ja kHri3}ZiuJwV"GWmK9sԼ_K~- xxυ8` '' `;@8]j@;  U@p = E4^Uuíl 0k8 d9"Q{ ` 9"?#Z,60;h lG@` ;>vp) Qd?'(f q_|s_ XGv0i?rtpA~ya-H w:8Hf@s;amv q: P :=B;Ԅ`Xۘ89@snv=FG!kpe d@இ0pMgop=[6n?O 12 ɽ=8o dmDw8{Fe+6 ;|+#dC diwB|Y"./P:fc9[ B)08Ăq%$ŽBX8d`ޝN8~*("5@;3#uTԟcUHgCu蟿(dܙ ?ǁbQN*G @(=;%$*0?qȍ{2@yg-:0p^Z}0掿<8n;/!sOO̻vDnQyo9'H7@OQ;A?\#5F! w?Pɚ{U^$2~2257X (pr+@3:~ 1#ĿLwGki\ qD rv@;N:gydO}#4;(~2YOso׳r+EoӰ冟!daH3/\ F0@:@sj!Y`hfa B "]N0/{?>m@(Qf.Ǥ5[0|7lb8`r;# D=9@6eD3B 0/Gu{'(sjs*qoOt,@6'4 'D5O= 3b9 w0۽# 6ol}QXz)vX673R; btpAnR>Gr3Ąҿ7sV(y%;ȸN6G Y<^>Y8F6#Ww^rdu8& `G{]ޒ+צ8]pphH3>BRe;{WM?@{W.HڅNN(vޤ9Ax7p=RM+@ 8^h~Gs ?g'J@Pg~ j_! fǘ!Ck]8ui{'0دŽ__;8){v1t~CAv}ב;< G# / pRvN{{CȢeBz\>LǮ 7n/{:; ?D2*G埿u@avqOq\g-*F/v.a/?W?~?u1C3Ïl$kjc}ҸCa^|{}[DR#1욼W>o3픐0 H,m~zGN bP We~4 mnΦs4W@_ z$H0oeQ.~/gcz2s\ M}%u_z[tg۱ 9d'gaGHQ.Nw,v޸ﮞ6r[LN W'8d q=HGwu`ڷA9Z=֙]#!6K* socx4 w48e'k#r=7#t?{@ m[wS=N~Boro&@[g]f'#\r0rw @kNU;_Av62@H ,N #jloV9n@Go}YX:!*\vOjZvA,vSV@ vo'跂~[Z+CRΈV{5j_>'q ÷&o7ƾdNjv+ 1gm*/"j΁ /zC}]1Пu> dPSaW#o辒}eZU #k$*N/پpѵ/m6}6}6w̾\fS}3DLLCcpGYFzߏ.YqB/g_~qe?} 2%snMMZI]OV@mw?]Qw`?bO[cx=s&TVs3ב9; /t_s߾8ywӹf5wji'Yn46-ߔ̷cM/ ^5m;&D.zzy^χz.킔μ5ɳ+KBb'x+g9f桔}V ^u{H4:g9˭\<tI}JiVOWrvn9~n]z{s߿>{kںak̩[\b,|ߝ4/W;s?U<~޵52ںWjW,.Yu]ZpiOO6wo?RvSϮ[G}w8v^1:uˍr||{<]'*)r_gc4şEL߸^s:ke\?OWO|S_'xoyFlڂbCb5yd\nʟ,,;[u+Y889rg:a*?ky?//.& /00ɌDx J`bd\<%(vg'k}" #xp<2^{P\۶- 5FNpw  @C7и[ ]4w s{yUW]UT7{=\s9ޫmM0`?^Y8`afaadedafaeb` maok77?:X 89 8 XٹA n'73+7;7'Nv;ӈ{ vXvbL Zڀ`@l@6 ?@;;RAwC~'b:q墩uOr=- C z>,^8y-␖i5e4 J9i,2g;vκ*̉y`$|Q$]f/H+>\ٝK&Z1Ǵ?E9{d kۼv2@܃B D[GߒNbV?dk 8_&*1~tΎ Y. H~Pvng*rM"4*gT\}4NDJj]ыvKg2Ae:e?v]s 5( ;̈́ohu#PV['#xvtq+Uwi9s ϱX}vN`cNz 7>@ș?/w 4< xݘm{ fw jgd}vVL᜸UJ&lmVȦ./A'Ⓓ׌>Q|QgQ/A/5wiV7N\Fd oW ۖVKKNvf1͞N%Q1Ag[n}ٍ&Y1e5LR0 ONH{R\ioO:CFl&i%&LdKÏ2gsD"H n>%v qNFz*p8JlNH :jF?NY}%% G({pJ-&3x%`9kpfǞ[&U9q[O9V$BՃ?jLKX2tc_vS}u[uI)45 E&uX9+X)?_>$1%9eܾضAD>bA1ՔMD0Fn#~Z{l@ﶀL/s#?Ʀ>eLt~Qw^݈!->s(p4dtMmo W+c=$v}/A^{yX᳈$xΊ$D~el%h{8rQTD~vp:2hϨ=DdME +_͌#dN:P/{ӽG uis`|)u1+^ľ2ߌEI?~4+X;H\ٞ-ԋa)ʀ+&4 tvjk^Fꠊzl˜8eQgz@VՌ]#k:u8;99Ik$OGA :oO(2g`v`JxC$8QUwz O> Ff-y aڠat2@ܩ`ُ$.^5>a K=o%+g?b-*N!ҲIvbfON9BI캢F#ײ"w 5x_;5jd=bű׳ "O7#@Q@vW- Ɲp'C3f.tmӧ&Wģߖ[oțnDZH=uɒN:?{2}~>˜ Li|Y0;8ɭrt+o4< $v*=o_D",: e 0SeS4G߁J|k"N/a/V/{$dc"k0?lTe &/IHvFR"Η fXxͽt 4~^T փ`;˜l #BgYv+r9V 4wOK; W }_j4LG|FBM <]II݌'42VGdHn55Gm*c@ȺzAojpW}庣b*ֹ=,f09y2ɥ:FI,ui6:C~%h޷0HQq<֢^ OG'0JSZ8M/ç^ߍ/Ÿ5@lHDO/Iͧ>z%h!̈́޼y_CCb/wy[@S\ZzaYx{iyei ҥ-2n,UH$1GZIb/(̅(s1tnj:n,FK٩EV"<r:y 2PKwc{ՙ1%%~)E󽨍uZ( 3i -vj>[kWLZc|/ȏĈ?DX|Ѫ>%^Sdg;k\n /*_[ĽsMkE?&`) M2#]Qjj^kJjB,{&tȶxp}$XWl7T'b4-`~IRш.JgO TH.ЈnU=U`\y =?FGr*EҪ*fN{T+R. +z bgy: YޭuY'JqN1 h3KѕJhk",N5;N4#]0@0nH<;@Vt56atDzN_o9 .K f6g;,;|| LI7Jf{ 4 8݌Vh5' '"\12}W&0k$R?IWR*G[ǻShCj-zGu;NefJD8x,eStOWl;<1_`דS{qITBW<(Ē;~"-A;'x|+㟐={[yL+6ƃ)Fb>o? ?zʺD[?#zvٸ,Zo1YRA|OױQz<7`6?apD[NuH"۞x% `7ӊ.)VWBC(8ZjRJ;%T.q#M|x>)AM!A/x:ċX7:Ya8Z~qs3~>¥>]8i-"՞Q&}vMnm %Svʑ]5l>ŇX(3E5'/7HILFpfќ¢.Ηj٭UKJo$~l"Cæ$iNzÁf0{xt%F+F neeF)oHěV%1Bj"N!vpֳy`Mkb0@vc@6_7 ׈6t kZ{j?`yS0)`ry0dFyB:H4 vr9っ굗G{a=@\UtcW,OK{֙ךA¾& l(xDtdcצ+A<* p 0<4E} ?̇ШxzVѰ7ElQ:wJ5XndxM@pJܜ׋L&Ǔχ»t,bκP^*Y4}C #FIN}O õVPmiظku:s<JQJэ%Z 5U/sPgB k-74 :U Da>Ш%Vn0`q6Kz/>Jʪ<:sS|+J2?3ܜ9-}.kO'![%_mx}&/he,w9D> Q?!IxݐT^!As o^k6TH|?xJ+.Q5g8 f ,Y>DFDĎ9;sQ}YlQ\ SSdA4h0BG ! W :)ۂ'\o| Z65.LXQp?I^kKm`G4R6lQ}跳"|] WKv9}Kd\v ZsH[o̹0Qf旛$7 !wz/TUPy|IC{_*䏁G-U4 <\zC,c~%`(l؋7&RO*bkQR댘<î$PU!NsA 㙆ǗJ${F sAcJ8'ӢEhåhE'fNfM\`w]6c[ e/F^TQ­c.v0󺳡픹)[ъ0darOT=Q aE|5"mjքG$O$&*®4ꦆhsɩ 6[$ߔ\`Se+ tȮTS}uFΦ*jB{cȠF2Tm<O涇{Pfc|D3.o=d0ty4uL[Ytv+l{2!g=rx}b 'WTsD\FYq>'۷bXIЮ3^6ې̝o~uw[cCv}33ɴ5[X]+K'QpٓWwzo^(s%/pLH `٧?Q\ǴEuU FX-<^c0鮸.nTH9OsOĒ|2B5snkG>qM2\O6,B:f%f?^=T!c]z!4jJVQɌ,,8PY4I4ZtṾ֊X*TG`ZF3yYƕc"Vl|\Rg(iZp_ETHRO+SqWb >4d%q9ga;Gx]BW]уn–σ-c*UyDfARH% ٲ)ϥ|W1 1x Cteo K%TԘi"C"`-SSaHD,, ԯ$5E|kG^:"FHWze?8ly0[nկQGFꭷ !"HaWp[RNyG[4 W~Ґr6 S$nQ$||/;|65Vߐ] 0'8iiEi/W]BSD/N%s0;KYJ]='Xױ=QW S|ZqЇ@qJ6Z8w ϵj3~s#B׈Sʵr̵Hujqq+Sچ^d2uf! L:&}.{'+dsfpsty*VDPǛ*t}Z:IeB듳yP8Aۢ-9[ΰzQC^n{^b6)mq%ЛDfuLpa-ŠO:T IV^)_DP~%'/퀙4WlwV*ϻAigE I ˦%6D"EfQ6tnEH\I3k1<'8\ڲfe4&x.vp$CnxVU{FhkOy%JW"/Z¾o ='Ii/~zmG`uK+ݴ1\82H!ytފi{&>MBOLF]H_c39̀L=Op R&Ճͧ Țx__ l,|;z'r:^3j>0U{3ձ;vNNɺ)gEy1MQ(Byp45b 3:|;=b{d:HBUFV tc!v 7GJFxTi^ɻ=Tb> 勂`#|2FYhSy-]Gʉ T}x)7DS*!FjE']O=C 7̿Pv^{uM9bLz's @cjNWE.~l$<=Jsd䄑 S%\w>~w{z+'EXaNZd]PZՠau.'p߹KƎ^`j@e= mlVEDj8Tö&i 3<}VЄN祝(.z"uEp3>ADԫO1p,& $IX rMwغ`jcN&> L D/K;A"ZI IovN0K x,Dbg'ȣ LL4xccb(* Uq*-nNŅ2-\XCq+]Ռc`W-. %'CwMO+9F eH Uj)f!|JÚ rIȑxH12 K|ZU+7{zSf?\Ƃ"qn_~莞?P߄,|H3ѪWg%V]4w(>ѷ*tg.'w-ooqA$YeFhytޱPqPv8QYm `>S-UZwL;'S(M:QuSMayzyj6#L:'&* d K]o֨kOEZ<1W~ȟ%64G}:˽,}1 cS'-7tj~qWVɢ#Bw!tQ1J xDxꝼǴçsVǩ FSVň8<UkYWˈ 3x5°bQx&гucl'2&Y3kgGm"#q A{[JE¤0VL͊~D4ַv/ >>@Z[;rwBbF3F7m"!0.udB+ TxmG zc(;N\AƓCK%¾kUwG8T)pE09\zATZm[G`:a:GT@r{ldU td_!&ScvTԐk_* ?؅t\358r/*&6$V5?KU&:EB Ά9z Aaufztrhh Sȫg4 ~C+ꓷ 8og\ݶngtvץ F0 TQne;Vf=+o5q%xk):ۉ? ǷېdL6WkZ Ka[d!ǭC~'ng2Ƅ-bBpq_j)ƎAN^;I}b-[0ruAe_ڠHծ,o# #+# ed*oKf夶SxO/p 'AR!H`|>9+?NWb}u4"ML?oʶ*ZlM_E(1#~9+ {5[]6W}-pUhwpQ\K9El Y=¤z׊|*ӨE\Қ]lL+k;z&ra ݌Y#'> s+*8^0;T6,121Ou}JT<34粄{Yފ)~ؐ/7߁aeIN}-LBM m?fJ*AaN:YQ A=NW^hW^P\8=7͘hUd{I:!*_lCpv+#)4>C_αiAO="FCr]68Թ쐴po|ɳd~F~{ckf]״a^r>Ƽ(fBGd#-^{VŞdw;b,̟8Ea`zģ%.CskG2ZxŴL5L Xe`-!\B֎xLYR{nX3ߌ?c.; n Ǿ`DN;u|pxcJ}uz*dFq%J"9{d:vp[:Ϳл'V)ƐӝQHH~hFͬۗN)Xf 4Gm{(2m,YF3eY2kf#Tvz7DޱtAV'z/f 42A< n,Zrv:o8Hv-YIIXKKAw BDpf_!)#8a-N[S#ݼ%tgTpmCK^xj?I1 l kq^e[&Dߤ̸v1sh\J:L%L/5<$ANCr@<@?j؋~?Rf i`2&)/ծhk;7-a+ڦ(Č%3E=G0GV\.vMn,d[k#ULXnL/J7GLXbvmUd#kT#Ub0處M9U|Wp[BQqrz&Seؙ+HmzcJ}>QuUyDoT`& d)nS,zP@Lkwxy-r T&P} e7,P |hlA%3CL,T Ay}#C2C%j{ʧTalk *o/T'Tdk}7hUCU14  B 冞+%Tb vP *P\",$Eloq@wV!Pe* T#T! JzPuɖPT)*@󌠊{ CXP#UCP@*:C2*|wOo; `M@߼w|?nkm?{c,m=?id4O7! ,?ߩ !0φ?X_<Z_|w&s 0h{?A~5[)~?!mB#}?p +IӬo|wO_{mMdkbi`oU'3e ?OO?"M,yrh? obT߇}I0@&t4ܧK0Ol[1㽒O{W"7GkEUmU*d UԮQ,xT3nLrXYA-hU^PExU[HakbQ+Ui潗13ٙ}Dyd]yc! R&,de@52H z *?U[RUÕls+SB;g+ܭ*Čny^Q3hAӂ6"/f +p}B6F,.f%5^x~w mc][(B1lFF0f;Ɉf f5)kBoqT&>"g/@;H9JGN -:Ācӕ5; <} KQyV$:N+lݵ7"7!T}Wo{4K7+niY6CS8!fZY5"w\ULpP-zuip`2f!фSӠ-C'%/Yjqb-*?wYŁ M>56.޳>y*3ch$+`ӭ!~ôՒ:P RVgpIV|fD°Xc:5'9ڜUmtߕ7 S;B% ts.O{4Y+@VTE_  OUSL©Y "[u}5UWd*BAiJm|i29dXuTCQ [@D rVbk]^kMz̆ t Yį@[#xs/8CN;!G.(~U.ގ`X rd0HL r=CBՂU@ųQ&Cebx@ѩ.e6eZpN\U 6$I8UxSdWV݋8%.Aڼ7Gqr%:#h08p=H d$+Yo6o#8T۰aW qZ!\L }f0Msj?$}KND%z w5I@+b}gu3-%XWhض㚶s 612ܤRj4]-2;H[ UrpO.+- , vPWp"í  N-5x{dfAQyy,B8 p4M=`Z;v;N{CQ8A!W lPY*xay\rmp^R3/:֥.M}jpm&Zx4AL e_HqTBpm_}.[SAI+hu77!OF)V>ۋAam/Pjoo d5h+jw?{20 y\c_}QS<4:XmWGELb{27c!ؼz9>;BE"Oc .*n ?J:\7-ۧ%LJAAPU/It a02?NpE ,5ؽPW5`g())G:o.zۻVJmzkjtUw^ZfFל K;ш#~.v^=E0W.5pp>,>P(JWMe@2K%VsQlSI& !&+Ki5HKcq5םV?CfI 99).iADl9ș(mi(#=_3' '4O܇3~B6mKX5g@r,YQ{&O 56128L'Kr?^hR˖ڲӏ=+qL蜐LeȖ-fz6_;;g-I;nk˷;:r 2*qe{[[9?*'=*3*7. [5wM_nh9{b칣 'Ɵҗl[=-KWL>:k7ݓ81rrnyfޟ^?0>w|ÿdӕ́^b,ÜQd6}\w#eàع%Mg s8.3wR4ziUc5Ĵ#;1b, X XEvPFPSn q|[,OYh?87T 5@VHWE5Y-MDz3f0]\XDB,#q6l 1&avd]NLzsN"X$|AMZaҼ4O0ܫ"՞ &p.!qa~[54p:rîYerQ@c=gηr/ ˱r8 #aFJI1q5 Ge#NCLhdYQ@,= _@9#q΄`U'7BpBAJ&d c1A^;7 B4]&`yYoeW^&%)~[ћ0zɌ8Q{-R*1vp`uGXPgg Rx[KbI_5YAܕ 6B2 2(A,ME@6q䮤:ԘP"YJ(֋cJr#…{ V 5@:.˚"$qMCZ_۷%"P )3r5I׳~o@˵84tllm}ڴ9q7H#PX#~I A!Dhn/f}=ZbB3my'PTC1"=1NdFl..@P+93~HE6GXQ%s +^"mmr.^L~6%R$DVz X[]F/![AW*<>M^J Ee.-4;#qͲ1){@mg Bc@lb/78:" {cq0㲤,4b*W ݴb2%VWd1Q7ľtl NOŞe*^K32S~aF(C4*){eȼqgWO0\iZRuh*gR&N%q#y\$oi9RIs]#kwh ONtrCi)&dNbȶ:pGQȉp&fX}sp0r_84`^jv%7H'g9jFsOIzDJp#ag ӵ<.6ҋƘbtpkpŬVF}GfsLB cҘ%BF# s1Gߤ 2{4,F?0_fRZĜ\"dNP91/ARޜ2`|NhLh#VU|*o_BRڜHO('# -ob_Ży3xd:o!ś3Gzo 7HW8^*'N5׀z(fOz=[[!lm‹`&Tr,ߢD,j 7 <8<ާO%Aټ*^KtB$6שy1- Rcy^'&kR{GZQ<<g~KJhvQ> |`*^ȃ%.Oغ1c8"9O<]mOvEe(rO[DBo(R( kl15b~PAϙl f~7gdpO:BQ5!X=PQB`H UiP(-Z V)A!Z x3*m8Av_f!h`6Abo7߬spN :'`5CxN>ؠrr\=tEIj!h-]pwՀNYG#ݼzѲѺcUʙE#7mm[1nP]qINi rC?hX݄uMl-0$ãySj>poj;6iFn 8|}n-w8౵14u&7:BAo5k^J{u͝Ky]?儋G>[|[飲$\XA3L-m`'dюOi?bkҝ!A͆0T=v(Q~(a@1z?hr buŁ[͚Z^Wrc=J~nu~o>=ÌqGPs۵R3YGz&saw-mmB%t0ux-6/]:lg{o)%,wRfݰendׅ8px㠢 iwK{n䕹nu;_gwm&5JI>`ύ,l"&b6n2en(;;dO'vw[]ngS򮺚0{oJ 9ԖU=~S~[23܆Zf+/nwI&9ǪM{óφÂ1W6qVOi=cY6+HČ;TfqTAgʓ#k)T#((jICp|hrc?ɩ/HQ Gk]H=z{TYU{ݾ8N5iq!{J5f/iqy K,2vE'O<0N}u|x-ߋ[6]yX99QCM4y''ߎ(',Eiò*XrT&巿jxY'ѳaˮ*S=`V|'/iVւyC :߶?{ʍʛ6d[I+|+v'l˫¦ՉF扗Uu>Y\4=/h̏o~;W54\qxÍrkyl9`㉙CKmjT[ؗ2/o\zqlӧ<\9ҚokgG`4=?gv.}UrԪa:f6<5ˠI ]][iloY!l/k#׭8w`O|^9>AI[; }ayBzbSvd^ۊw_:me;}IّzK|.ğOyl =9}-Ѧ:ߊ65n~~͋7߬PlU~Ĝ=1/&5}s\u[dI/v7~FiR4T3]6\\f 4JkLM#ømCN:_{y5=n[Bцc_lXu%wMF&\^լkZzv/P#} n Ju S:dh-ydF: JtM:'6uЭw(kUxH(UP~BRf@2,i&wY~rNirGc2QLIl;iA 1eC~Z %xE`IaIÉM|v>t]M86UFɜ'o0MÜoEt!mhK6?Eݫ\D3ce)4!LG{zfDk_FwX5y=]۪X\.f>i=aB#9J">RM[t#S*Ϻ>B3* ln-OKgsWީ۸3=[cCQ*HRN IDVX,C O1Ñ7EE2W bW7w4c@=wYUK%G>J?v;Cd\.OڎZ̵HD\1 堮J60㫃$čM! $/ ˋ) 7Б/q8[KtwJ)UDcoI\q(p)L,65G[jU ~` VQIv Fz@)؊ei-mdRI+fS;~t=M(<[ y O*{U?`e{dF[ܦFoZúw/o1ocLXe8gWN'y uD՗Z^)UjOT4URsܶwpupMh;J 6=Pk7tYv'ӎ9LW_[` V,ɢE@b>J0->`x&n$iz%ZT'^R3|Os1ByWmXeK#󥪣Lmh(і7=-cd nŰrP`yh , YS*ܫn"=LV>X$~MRVw;Xq5wZCО(RA51\ta_IF!?njS!P/}K5=z>#jbgHZZ]`da4UlX ?|$qTZ1q+t5y=3 s՛Wǰb'16b1iq<8b.] GġuuA;4!ؘ9:@-Sd =+x ,r)[J Ctt@[_r@TZまjX_`L/$..jJsÅV>sDK(ZKdJje}[Z)u^#'?Df>8Kw6^{2ٽ'Gz&0܂zzXI|4?dF#>Hn{ 3X̹lF1'F<{$ T$J\6bzϳy~'PHMo5;(0В|*'7b> UbW5Clί۠I#ʝ$7׍4B@ UH_%K|3I1m9]gtWvt*?y (qHG84}j_iXOX_8EK?e[_A]ӷݼu w@s㈷Y C*9Ȍ£@Ğ }j#C;CQ{!W0C%x`!ݭþ_YO\LM4ֻOirZr]FdЁq'vQ %Rd5"]vp֡ >|qXvs!:7<3‹:{Od}=JDJNbqbAA_Ͳ#O_1xP <$-;Y)U1Q4( tu7m'Fy|v㼠V-||)}G"GrIdqK͜K A!RŖHf d!RUQj?s<LmLe塉BEwe\Q0Teq >OxúƉKv6"EΪ46i7D㸊xc,!Ru''Iq;FL ?Չ,1]Ku߃\|Ef*թ$K6u zO>` T!ǂⴔe[_{-t D"-Fg:|f8 GsStGp̈}0-LN`2hB ֖rz̯cbixoC:I.IF2R6Rgb;@Dɍ|׍PlkR11/߉'s J{ұ֔ٳ2 K'栀4&LG:Pa 5WgFCz b݇.w.dei sW,8MoBzyeC.!u\Gi/W<EU>T#e0L~7bgJjx|uZ%aoV+QEw YȎ\()I+_cRR[`qD< a*.٥qtj آ)cW;䣊5uZ^C 3tE }bB3P$0PHw?U!!Pp%{iޫ*~ҙ2Uk#Ey% op_&qc+KϸJ^B޼esӤU`eeG(N/|X]n%QP2WEe!:w [1pTxWX2d;s@Lw"j6su7`.b%a6R89\/q*|sݚzv\~3W5'?#b*.ӉEՏ1!5`̖0S¤flx3`ycQ4@6\!f/ sW#˚v?S .Z6hg\v+_&S!Y%KؐzdkA!=x'2r O~ZXЧB"Y7#>}~!u-2!\3O D$%ԝ;z7n8ӑP^Ru ptM-Kz$6Ook.f#E=bo9Vj#{x9T)~Z& ^Wl+fw#kl?5hON`71WQ$X*"~zyQ*H57e=bؑB]DBd4棼eEXG^)1柅Wj1М v~!t_w+rR; [ZgR?~fnlpSqFMVK3ZzcZ#lχV?M,&c2dBH>gQJxvjAEEDh5fvd]a鞹9m҄{fptoY *Y6>Ƈ|W9zƷ[h 'qmT~v5NDOMBsz <);9x Z8Y19b<2ӟg#d Xw$T6?aX2ftg0 2O$%[ɓrVXqd"~RWL2a؉t4haX$;M*-0}wR@CnD 7;~_fn=\U3p@--.LoͷdݸV 꺅ܒ|Sxp'K! N]EEL6BiHxpdBNKYnXlܸo ƞ韷;ށ~o,I&2'@c#m(1ß.yF-&6p߳ȲGd`{t4]*Eꯅn\Cs8@ж,KK?3|팷e$pX阓L4%mwt'|#T%H%>RyX]3䠍X_O XsLb<|$`z[FVY*oG&s`~!gnmRFnf%"4!"AgJo0we& 6qF+Eo=Vm ‰1f";LWng)ibL2X8%"38@n>vDy:s=0S * 'Sa}5E"kҕ.8G2:ʷB}zFUY*C1 4f7n/]:aZ[=6!7pՅƇ Z%{ݙlzN"JU[Q]U(Ӱ F%f=aK);GrhAJkcʒA LX8Psx5#AoV6R:i'{".񡚵;^2!y5s0v#sUreG1jXN;eeي~}A;UA潧=:en"|r!y.݆E(Ica˯I* ;- C'AFn5YppvoY{0b*c1q MAWE3 "ZE`+Q#/Tj=WU*D3/wNs][Hh2UR}7^JtߐOh4e,M|GDi]KCp޺;~Z:Q+.Șwx2cvҭt:My˂̈́IsimyA1a {B2s-y4F5):Ҥj A|GF3dwF_gd$U Z>eX m&~!g^~ᘍqNd*]`H.lyiWb/;Dhn+b"}/i 7 3:3ʒ-ǿJ=?SIMfWyGtmWp"=[iLKbN^/FjIq^KYFz ߜE6I,:@2z=y4|jCgn3KiJ+J0{?zU)讱D #;ct2{6ׅW^)3`WW,%2fT+,`ae\}±#JS;j+=ix%n~p=-eX Wz?e9>T B2vř_RESS$dmGTJ=h{7[4~YqDb: Kj HAfv._)!)8TIX %@qdӿH;<\dƽ.b0RGzJ痑~z3nPه6F jcnBW"IǴ)( 9pP7JQTo"$|z}S]GYמMAxP+#s1މvVx#&}q$O <٠l WvEgH1_.M"rB2XTanLj9پZD-Z\(>0S/g` ybMՋmg qR nJshW­>zعڣub$T 21h*)50yBޔ̸";UxC\\z[, VfDSJ[VC.0DA6_J#uXw/rboJL]}J1ΈZ0iV4RiUӝiz#dpQj⩋чKԺҽڐ=:/.6˘_cSd^#]Q07A}va~;@H~E> @Ys>Ę-n완T+n9$8 Jƌ]QHo%R^4"Z/I]"4X V7C=0U,[Z !}5UAH*SҚyp=@2ׯ uP`o3^|@Kb275QphnyED̈f™β03q"iWCX { !V,dDgeȇUDfݪ#Wx?|)!᫛49R&P:[024M̷"~g t)Po/z<>$tQOc51i8uo8-)kb*% Ȁm2&4Xbr. '%O zTD)zG%U$#p)bq<) &d^tJ-I?pPvz570̀KL4 Fڣg|kwE.c\q>oNܠKԅgTYϲ+[0:QZF'WV BfxĉԶ[ʳfJ`X7ŹKPEԭD+pwߎ#􅀦ޭ~qHF {֗ e5|*l9r{xy,\wSfe|iiAk&C%rC8ݎLқz>,` |U恌 IλdA{hB(YjуufOl!H$_Wy I[2c;Y[ 6Ŧ)@h8B+Ren<4]#hةrBȯ!)tMNӃTƏuXY-9H-`( ])4iuV;#W^T+#<с66bz>.' JdycښT'u/29*'^[H[7ҷnj/фnA`@fl8ʖI%!?S_:9?,?96T,?߁  H[rI B je(ocQ6R͔V ,ND0^o;|lO봦 :X Oɶ$FIB,B;ƥFYco;mkȪ}/Wh(u= 0H#YH|}oRRᛯ!aLMfHB5"u zq[[qg_ KNoo ^vVU#LAߧOoB_=&=PC7o KX{ylB6b)UGxtx? zQ?]?~Ǐ?~Ǐ?~Ǐ?~*| 3x լ2Rg%@$^#KrVYW՞>RSZ@ڸ&~-M*O>%UC/\5y9@rFm]t(50VXuaMoj (3Z~DĽWťر뮤oӑ:}Ns  ~}}OK3#\繂Pj8)>lgfiJU }h^0dswTmvAJϮԶnrX1ǽU^kGnFt1m=x;fz;aI+HQ e#M:mh11OqqiΜfK^`&5fdyC']RVͦ0zw q8% .84S 84֞ns; \nz(vg2jIRgGh !84ߑ{Rcګ,5fo\ H) M,U zqu\ql+K?T R=Zp#ׄʗ63v=ʌZ~6=e  ܻ3 d5:I&b\/ S5a>ͣmwTpD"V{@2T'ę,Wɵ;EPeG!V kƅSt9/׌ ll]| Jm;r͡)R00gG}qSS7LĂ?¤Şhca"ShpfQY89lym@N  6sR`LB!2a=.g*u<2'Eє]i2 g`(O lewt>$"Jaa'B1VCg*ZikIrmsC%R;]SYևt9c]/xȡ'/#ᦳ;D27MŝcVܽ5.`qW5 2,ɧ,)@mBVey] |_ol=mxn!Un2# hr _'Wf2;ǙWI)(i859^i fY %)jcѐƕҽIQo}Rώ=R9zJCT^&+,q>)*Zu+Mwghe3ӗ W2~l{IyyT~QW֯փ=dT̩Epݘ%,mgp/ri#)fX5ڷa"3)bD38l8xiqkmJn=y]ʭg c5>ڔ?xwDo}Luo>9{dLL>>ԍv.*aU5ČVD$I;InM*#zUTN Fk>B ԮW#fAN L%@«$BL6'"d2tb'M/8|O˙KȪޥtC`ܔ)|/`1 =@ŵ#w܀5$1 A L[ oY.nTÔ3-P?zݓE!o>FObZӖzdu}\CbteY-Cp c9]mWSʗ/YԊATaNSqIx;l$OÅJ NMC(no_M%+zTk9h袓h]ln }yF|: eqJ3[횮Bb5_0M9o`kKku׿ETwX´$$X]C$}KObx2#9UK L](_#&HEqI%gda*HX^& ,,^  )cU󴑮Sڽ YwEZ]݈Ξ#B%VoƧgF`%XT*\U^QS YS&=tA|+T/!\] Χ6A0i 4OϮ%p Gl0xzG"{~! 7 vFO Ͼc,J#.Q6wʀMF"]\`, {j{2c-V.D~mElo)_Xt_E='X[djz6T{v#5ߪ@dtڹ$ uEف}4*Ʀ4sd!ɾ~ na(gUy9M Ӛ[I ף^ޟJ'ܶΓ$b W+L|y_py4.[9rDGx A4psl8fV;K[qY|%.|zOḓgW::4mUarɠ]w^*&#>t-~f_jn-Dz v&hfxge0vܲz7;=冨S> a^z `**krsc<`D;WI ۟<6'C$W ȼR%+ؒҗnLE%tyc:nt!> xtm9+f/edDKAŔ8_&V(آ:%^5}yYl)%z^ 6!2FZ^Q龵v*y %st: YZ -9`:}L xDNd "bY0'{a;{+k.AΣrAUc8[ݶNE/1gBT/#D_k~&$ͷ=[kD7,F;2=_W)ߦLP Ac€n ^)#2 >_B^>-.4!bVn)DBJ T~f;7{eI9>¥/L]0C/mzCGv̴@"~PbvbEo٬h%-rZ^})#ͤ?kIٙDޭ-]]į>SجF*7 !o=LID_l;~wM_67 ANf' MA[r9q6jZ#Y *gbt'C0N++yg/Ҋb^ɡ.hYRT F1'N}N'ZG:T{,Kiw雼e;<Ȭ8Mq}}Z,}{Kzw4jݙ'z_ԕ@e!Bm:EbXȪqH*e Imxؼh=-Ҥ9^ h2c9w$$I)+ٟmvtS>rTt6ܡ|7N):@WjY"G 3Kw).)Nxo_$7DdC鼋I$5OY"}QRfU/:- ^qᯝM!~260RAK ]M@sy2)t ]譪?W0͐h[̊`2\AW8>|)LrkږL=NflU7C^ͣG+9aYxQ;$=M"Hoya$}l.aP%+s PN37mȃif$*<߰x*/HM~PvmM9pkddhk}dgzV1$|24屯虧ŠC>,"(&y?%Sv 6\Y+7 1 ?U`g|`*/:F>a2VH|ƍ_G%ŕhRi_Dm"RZuwƗ^(r:A |-aȟq>x0ٮfae6н2|,v|h.<ͪZeA`,^0)Š27\#{5ðБܾghxJ(u\)Ǩ= XJ tFFLjYv/k{8R#\%e[i,ˈʕ4̏3C{2:q0t"@ igi/5?Eys~E$ϼv~W 1أt TjH-ֽHgc>jDPjaOx0EcK2NwS$08-GO *H+u72pUM2,It$XBJzWh*"tnX).˷0J:E#Mz紃mqCxoqy!DWc3e|&]F=vn$:˸X06޿Ѩ^;=nUM!E7鵵¤7E)jS?g$. U Mvgs6;GY*q?#Qذyv1;l(RaLPy;(<8*™n~ Kij-Xy@K.gJu _li÷l$t?%y:ȣo6{eǽ!b*װzfNOQ8XbpX6 W!r$H"hsǟf Թz'7w h;O6˗tC[k,![ʭ BXMVce9QMbW)ʉfopeaY eO 8RP뫷iߪ** 4nw"yr/uO]1ؼh-Fgz>5\M6h3f62bRknZ ;yr rޝL2!wmK@})2gk0/ n8r)bL(['i\ ƕ43FXم:8ŸtFh[$~|BB×snY}vje RT_#9$d8IނTxZ/:TXScE&1Xu,tYJGV(KTp\[|8 Ym馌zjí ]ڙٝcTܵi&e5^v@YAg>'8ɞ=7M ;\l,5'R^afjJ9J/3p8|L77,j \&u 4ptd|eWexOxFs|}O&)>6s*,gP LQ~/3*|)4UvB75xZRvjY('{mOY*e;(TNuڔk)͑ge.D˦}\S|&w[he)4?d2 fB]H@.>C1c`{X?·dzWY[z+l"Bbw_oW|SA"~* ݧ({y;rgץ>7RΠkͼU:WGܳv]isf{f| QQvN<秛e>v7@vEsK;}1Oq_\Br%̹a!0 K$={5':9#3;1oboPU G%>2fW)Ϣͮ,h+tMNUj54-}#d΄IzSdmg"׿0gE_s-ƨd҅<'KA|UVn#GDzsBA Xߩ5\%dd] ͑ i_F`&`pJD7#Vq)REjVhXpsUAY]B8uOd,}n[rҫ=F|,~Ι{mnW'ö??ǜRҳfb tʲ x/D^ A/0c,mdOVNH+(cFd təL=Q FGq<͗wδko_p `9(PB:M>w8 ިOGǕ[MO`WR0E!b }?z>τep r^WV\jr.F'-AaG ns.eH)laVD=1N+\3W7bΕ+4}BbP,۱dŲʟnatm] jU7WDx٭J[J ץgg\M 7cȟ^p?tg\܀;#;)v}͖|Ga¶['b*aŭ%Qzro:*>BG G# \gTq_g^S堼PHFyRf,?~νܵ،^7H_&MW)/>{&\ÂDdk 滜-8]" DI:t/*v{gplj̮Q4{݅iH示6.d۽Q!6??YUPbbcr"nw>]#lbȀ/Puu$.|[/J#!:ۓ,O(GVGbbYoM꩛BR QhV{uv9-g$Xj%U2''^?(uNQd"׼E_@ ~q1*d=}$iwRCGF7Fޮ+z3^ 'y};da1iWײZ$(qXw:MzIvSH{7qh Y9eˎgY7I"-][W$zHV|gu\,7Š=L>Q[( L}'L$PiSgN1Sin8G$2hjXgIic!asP[_o.5֥[:+W2Kߢ6*s\ǩHڒ̺_DjL=k9h-'qByRu+螤z$Q0P_"M-/䎫Kɗ>𽸾?OZη:aB@ADd2U 3gfvMQ?m" ٭ܕ2h(&lƸc@Q]!*=_:fQQ Wʁ9rY{iSXf@^/^6nRt4a~-Iye\&OS A$piWj5Ig4ۢ}—g"+QV4$kYQz W\}F1kE}7sw몺r'y֦ND,4nƊakā$-%$ 9FƘԮCf$.+V\OݕWjr9GIL ՘Mm# ꪼ|:eeT{%5t 4odUjy~'+_Ҏ}hƪ){ʪF&jϏXۯ1 D"j@(O! B4x͇I)̐>l.zݔnp^-@Q%-n4%譹Mwq]Q-B-4kʆl"y*F2@øgI5u[KګʈnU ډEVnc gcv b Ao?=-?1r08aRXq-fOA$'e>rʘxcC&IE8jʔ Z9 55x;֤ū EmҊOFllY8[}pl[ŻZUgC6&~[*0lNȔTi2F3Pt+ޱf'%vݶAbM woo~_$dt7<\|- G@ 63 aw* 0`|Y[` ̀6P9~Ce [=a utZO(=a@m?:``Avc'~S@ 3635-;f C+(d],17jmlwfpds_|s_ gmO6h~e uscOm0 -`j YXŽk.ĆiXSfWQwj`P{񿟄7sIso0ǂ/ 1̮Zv378P0ԕWuG=kz~tƯ b@?[';^cFe 6 {|KÉxc dq(h;8,8wlŽ/c3:, NEbKvO~ '"vs<_~wh€{3-qRԟˎgEpgcu蟿$xܛ ,#eAQGNEq`w\uyH(dOB82!rČUCXgc '.8 6SAaFd{ǣkߏm |yK5 j~ߵU0S0 ?2(=w<"NԟcO- ݝۉS\a \oU?s@̎,Aoo=G$8bϟ\/Y8#Wr_yR'2ź]&lwBA{}/תʜ8]l 8_Z##>Sd;;5dswط8㏚~\pڇ8۰8`Q=I y8/3D5-`{f` 7[Eu{=c_: `¾eaOʯ  ;:?vG}iמ; '#@ NpRN{ce{?9~L. 7~+:Ǭ;"?Dk2+~눬] j`c,f.6pKK?b戮.ql&X7nG|?Oy(u yщcrM>HV'Yp#}Rp;ڰ Vـ~r[{^ bP3 2?*MM~oM+^MOˉ;濾Axa'߿軟v'qL1TTue1~i`8x]n67N쏜OBl@f':rqe}zp{2hjmd6]`@#o+ЬL?baw'SNVuv6soOy1<;IJClK Gpoz~t ]/{?o?Lu_yە3'??sBo4q:Gu)hy8]+KbFcm, ",v3(co9xG`V{ Su= doP;Vb1{-z/e=$%`n%o [rXwS!mq(U6L,:,q8䂚~Kh+^VgwV0?U8t!P ޑCe C!&`!,%@,οr<PkCC;g+r94Щv 9]췄X <+M }=c.wf$v&­GaCoL`lCO9M F2ܝHVGZJЏ.6;Y~5OCPΡ &ew::% ye1a M 9ݲm 7=+> 2#;n`imtK0ho>؝3 ~vg/n>~Gbs7 !'' 7ϜߌK ($ k'eem 17ߦU`o_mO㟓!kmy?rkcrmi:x BGp1D@ǥ\ljjۅՁi&kE.By;6-$JP A^o[J)U۷jwFod<4VgJ|wFMzD.S/fZBm2OJJUٓT)_> +zIIp~Rۦ^DPĨ6!3ۀ4NJ5E蝛d ˤd)%Ʋ S <;@Pn !KH6` ??S[[Z(;( 7i#KsBڴ$g{Sav K@mJAE,j' "( c E[X_(BZkeSmW rʔD8F%4 *.LW%(N$W0L`JHGZQt'nj*X')Lip}Ȧ+'Υ sFIqݪFq&Zbtl5^"⸴̔ZK`e-B ݁k̰UڀQd5l58%&' Dz9P60Z!=\)3C0 Ioji @1BFF=gÆPckfG=0Jp`Ldӛse4 l`E'my!^dl0 j zD3۔ -J?3vm1P{'8^ev{2NQ*ώ-nape$Fxe[v-YT{e qnZ 8æ]!l~,(H”$ebX7 ,h:&`66> m(?$ \ s"YP h7^h<L Ŷ눼(j$B XfvE2}T6}K:J dp6d` 4o@T |0\ŠHb&IŴ 7hZƭ q#C}&D"IH2Wʭ?8fYØ=賁 X"&1ɗi]o`uTQ1 q0g1hfӈA\!t) 'ȖD7 &$A(% }gJu}*L0rBt|Yz-Q̴Luo` !8KtNHIUS2yή`|` ^Sǃ%.Oٺ!c迈щ14&*.MQXŀ-z"zvdt)KU&1?L@M_}? F)n?7;n8ip&`4Ho9n~+OZPkM wASOx1]&!F]o;z]6?rcV'v.4V\Ge|2ϯ)'F;\ugL_8u.!jd>(Ko<7M[\{}bc,F3]Қ$m;~szm/Vφew\cn֡50R_>̯;l.\3 nV_1lhiV1 bf4g׭ +9;ƵѵɺT_;v'Ug_Ov˕=[>Yy\s"{7[fÛU u]6={~}gU[߄Q^u8Ȳ;{8дg/\'r;S>{Slqأ>Ucn('/웓x1sV÷__\'絫ڽG_eUsvj髃zKȚUطƸ]aK1KiP፤=W:"(ZUr܍:@B{f-L~*Pő<۾ }ٮI!)'+$8>rhޓT߶,_v../q#O۾ٳjnIQe%#zϘu[ knh۝nWU8|恀i[UNUam_VK_5C^v2k>J)V]rqWiē]ܼ|0 6B?彔Hݙ#cuŹcKc,]5vy_n}4y+u!a7#[U#^*?mwo>_㛅O9;.v,{ݗUS.y|66e_y\sk/ƒ{/ ~aK W9F܄Wx 'GXrs͛XEwS#x|D;,p_>zTy*)Dٳf/VY?d\hަ=ý*DYŝ6Fs zWN] /:NM[j'ӂ~&u).eˉˋUFd\QPv ю<^vkS9}FcG/8ڃ_k|_to&};LZ|0kS_vgm۶m;o6:6;tlkfΧ}jΜg響?pZUϳg|Ǻ[JkEG4N4D3cM20;n&%FOU|M播c;1[÷<"|1:c=T ke+TLq8 rej+F5KnH%-nzP^uU+T++kv ڢjY7SԠH.ND3}rJ RUy>&´T` ?M;5ǗE|@,)Pq-Fhpn˶y^ll6n]pk %TGhZthv.`wx̩. #O/Un}uAPf*m ţY1CyqվuZFC(5êbyƊNbxq7FEL.R=wkW8ɤ W9G(T@(Q*}(j*< 7&(XuU~U&j:u 7C6UK!-!ja$j0kn az ;W*M7h1Bx;Ww`{MC4 wDgY10ԧ[MArnAXx\qP:8.A\UCs53WdW u>;|/ȌyƏ2|Y(R#{Y4ЖyFE VXG[) ff=mm`~ZOBi%}tXz̍h2oCԠʚ|ca,a3Alu⏖U:&=$/\ґIǠM؈gy|ت2el)0DSw 'OXgjhfX0Ygܵz1J&nDYqF!/q˧D6Ot5hO<{x.+qec@}YBzZs܃ 'Ŝ` sA%ƅV0b`oyiD03y>cW5bѻU)kfu^T2N72AM dsFO Mqvw w5r:r^P6A%7HF Yo$.+"u0> v0ΖUoK-C܂!`SCI~LiuwEWtR;/;Ś'{'!+9οzz#gnwe}Ưh7m`N;<>*1#(D9GRj\Ą.DpDRZjPoX ׁf._3%nhB0051a@y^YT܆%$hJr$_cplۈe6d5E5 ZBl<ћ HUüqkj a6(G$i5ה&lA+ZIuX~ #}-'; (ؒr*P?brVFGڒJj*p h]a]͚|oo"41D5H`I?cқmЂq#n]O\ŻPuh4uz{%5,zsi>Z-?~VћGeD2ࢲ ZDYb2N=?1걛B 5uigiKIDE a s]Vv3+sPE>zV`v\o,w?k!fA|tLp4 /b5{:N*w]޾Ko粖C 2\ƈ0rזUy(ReDwR ^q߇#Xokf{[U#^1|j?b\ІԴjl x,xRZ y9ڶ`¤;r(jk`3cFjy~QA]{6ݎ@·674P~W$w >1LJb_6|/"9Bm ,uIw"pyN#;j & it\f_5"#|.v83uDɲxXpv~gƥ_se#lhI Q$`{L.*?*DɡbH$^k ,1wE E#Oyw nY wh1;\zyT>Yrɻ %0T[yj ]!r._cq%Q G`hȉzeE ex>G=-ZtE $B iף V O)h?l4WnLO{e6{ ?S$2T67b Jr/ s56=WgNˎ&dVb~-8!hٜ" A0qޡ\8JJ>Csaױ;r"۷z&3{}$.c̈nxB.>0 3ؿA.Leҙy J$@_Usԅ??E)Vx'QMc('7s4J?4Tdu ixjFW:rr^5Z|p9 7{Csoީjr~s?^XJVf3R?Ȓ:( $tor~y`HEDH( S[i@m* DP`$''0o -p*ٸMrq@uI򫖊~ ?<] d E2A[5Rd CiOO|;izj@^e5Rn $eU9 A-jW1rM25{m/}jFiЉ{Aң|Uϋnrv0"QYmoF΀дhǒN+>Y B&N^~i G2|=%CbtI)JP,d?Rѫz/!~[i/x>LRS .|0Ȋ3p󞁩JO]v~ݹ?k7=('G?&PʱH"CMd06ly$UN9ÂЖ[7M[?r5BK_sJ.emvgZ{`&;jS<$z $!\N?ZjKgHcz,9JDe/mOsE PÿlbMɯo j,A<o:^̀tV!P JZ<u}]i#?+m;X3'5튳y@9=rNTtŽ7Op6-9Ģ9,+]\[ӵA0KâNx,iNcV1Ɂ FS%Ե[a13 Q`{!/<4-dք{Ioc%7m5JmI?[{kM8iyJיer/EDMv!W{ZTj=1}h;у,+Cޔ^8P%\XQVe`ruS gёyp 3ta#fhp2j|LZU/%()4`6M:S)ČD{(,$7s3%V~̙|}Ap P&AKzx{0-qJYgQJztBM )a Z'NiId]p77T|>o%$D\5L|6;zכL޾ Hъ*3r_~GC"Њ ٛ\ܘxRH 9_%%hRv.C;zktNX#v^c]nDɝ0уޮR'>$ kFeI;iлn0`)|0TSOnjzp8x ې0ǡ_!󂋓a^&>,8 N5<4=ϟ8OEfHxdFT@,MyA {'0 n D㉆^!z4/lC%BnQ?ϖpKfKaB/{Wc=tw!,p[[ڙ3STrP*n믎pv ྠM[K1gBGw>)-m5;oJRIoзѦoRX‡G(X|>g@Q#dp'2 ]TWvc.L*6BV+8F[ j+="h-ӫuɻ䚨Z ;ꧪ2ȥ;xMV$jiX mXTLhH*>-h-Bed|۔c[,I r|x%q13JiZk^.^>3v njmhK"ma{b齥jb ]E \Sm޷@B}8!mV/nՅxnsZ+ҍG!xQ^> ;aVG*5 4̽ŪPjN)zpCJ81Eg˘()ޙSAc;Nop%Xiڃ}*_ H `z؉:^YzLG'W)RewpG=bI%bgjX.dB2S0/çt vƍVUjCsy|hL۽@5~ ;w,]%w|̑ oN;M?BVj V55 ,Ҋ/d<١Cc6' ,Q< GKxE,EC'5ף>tZ5~a^h|ɾG (CiQxWLrtGx ^48zlLz AHl3qfq9 `W=X) A"'H+a]0g d6Ciij* {L,^q+#esyݪ9ER,׋F$봛G~t&U7~fJ%rKTKНawX-|Os +~eW׀* |}^L f,B94mb)'M_E+k2r{y"1i 5tqkEѶ} g~$?&i5e%kHڟ1] :b.#@fUzkݳ&mqό^n֪.f>*cUoکMkeW[$և1H.2sC߮_bR3N+ NVLd_쮴̓"b*"쉎% M4A8$ y7RZ дj jD\ !:mQMy^ ǝzr(WĊErTu2IYӞpxdz@,a(#E7f %߀}b-fuz ! -:+q[;'XHV (5cukqItOն^O^UD=WJE2N Wn94%нv8sKuĿn.s֦;܃IL[j%WDn)KzbZ5vܐCVZޟڀg cux83C['.a)P"k4F?g?HV, ʮ֡gDy&_hHjŪymcY$!:J%oWz@{ѿRWpo-݉DZN#j;B;0V">;G0G)6 Rj+<t(r9e3: dnj>+9PucQQJ?otg#vݛ[W'A' rkC{Qio\PQ`SJ):WD$A8 o*YDX|Ѧټdȧ04c_Ca<=k ]h긠TVx˜4*k֦ߕ \WݙaQ(Z]B ڻa=i ěNR6T-_Gk#CKBh T@%qx.î|%]ឤF:x-]I\~t)t;|( s8 .<4yH9> E2jO&ayTCK,!]sX˭3 * 5C Ǭ)PN&%(³yuk(Ƹ:kU8Dd>/*b $ ҫۭYVPhg#i#*,[Cy,4gYR!Jh 8Z9=w$HݰR,u*'&<ѳuMqV8ۨݑ,g$\=i30 V,1[؄ErMK=+x93/ep.5 {HP9M Y}B甫/+;BֱFw%▴"Ac.9 e)K]zN<Lh O?#)$ K} 55ɫQ2lN6]7Cnow%$i=EjoD2Nakf:2~ӏU[M3j.ל{2&Ϙ& %3ʜ&хޥLX9\kJq{p^MūIQu*9 &w'35 hH\3g/FUX'3v?-O%?7 #B޽mArau%Q5Y*mpk ]Tf 1Pg0&P6|LXKdMN C8 g<{jLf= yFָ͖3OM,E25/ |[4-qkL1 dO\:΁h `BO<t礱-: }/׬(Q1B`K9A$ErvP#AURfD:Qpn xKo/i-+B`_IԘ 7fe$Jq>u%2X,,>I(o0iHYڳA;xQd1W ExZCBiL&I趫X#Tޒs>8 &ݧ8*7S,'A{aA&XY_*q7vQ-pEzi]S`~“<|ߩPn\ TZy7f#7~h4(* geunĿPb;'U^_XuXx𓲘 LbQQC0z,a.?,D3e]LS_[ E6C*2ܸW8ܣ3W;pIwWVK8=D!,HgJ#UV/hA pդb?id.q4E)[1?''n}Ҡ?ϼvn#|kR绹q߹ABQj=z;,ZYVNFPl ?}E(cϵE7[VYpN!mxcRwYaKm"#BJy{BH;kA2$D偈6$A#dHRakEW_(|[d˘z#u"L]6V]=X9DB.WOv[fstAk*Edag# QTlfBD[+ib&~͂`#`ܡm<f,.ӞG!5쭂p.u v%s#fץ9+Z;FZ (?3ֈDa93aV(A[pmL-Oݯn?kdf|WntEeb٧rP;a RlVgRp~.~؍b;^'T؃2 N`]qv="~5#_#Wg}̔s%pq*LK,WЈwwY 4;xt@uj`&JZ>b# |QczB#0H4w )V-툗25)Z=c:'QO~mio $>0JVyrMI'N*0%c,x PGԴ0;Vk;v0shg" gvPY.j$ժ 8 8n *ҽ D4@PEh0g1Mc)=7(g0V]7N&D -uyrVwϩ֨98䃑b KC06GN l>a,@OE_? Wk4>=P(txI(e񸯙jQc^3x j U^=uwCаW:K$dT{<;hq)3P,y/#O vw DlLPls #{Rez،f}_=ӓ7B$8euzh*sA H. \"!#! fo;h)4_Վ >VVuT[|Tvaץ.OO^FEXR`=$&w1ovZ!hsɉPcf$G ofJS\01M]En6# n jjX.~;y_qe ` ͮ˾KP\Q~"R!hWim:sQ\xgY>_?~jv|-hq/Բ2z9pMÿ9FN(2DU~ƪC1,PP.K/kt'nQ U$ pLk+yBHW  b4M;`/]DP: Kkg{SaɜP@&${ETib^IG¾4A " f4*C5֧kdͮt?6GR[,ߚÌVv739Nr؏۾Kf'샰 :HѰ-m$ hC`B1S!7ƧM D`;Zl=?;w2y8;[_ `/CzPk[טBs#{G'\I QTxk{\?P#qnId@0[@vL4"ϮM2ZrU:}q:Ov5!Aq_["]Zuhe}d-ıUǬbYd,dS&g;&ػxq xЫ9A1=Y=:1wEi \IHy!dWcüfm.}B D$j},:|5y!űl]ƁdW _ /B{+jw+bfN<%7k6N7w ,f&<\&6s63Ksn s..Ss3SnV.3Nvv63<,\9U3x+wK۷o߾}۷o߾}۷o߾}۷o߾3x@^TQ7҈tI tHKJ,䲻K)-!] J#-RtğEY=s3sgΝ B/6<p ssprqrr!;8hKKbglAKixmكlP?_?7?AljI"cDu69Mc@g y_^'[Jh~5hd\,tJWUL8##; %]zk^Mp| zx+*wV~^&s9ИU kM^v㸗7X瘎.CgĊpP8'[-]dht};ڔY>|sd[j(m7K/ief1^3y,Sic\~&=ܓ;!{"ClHχ#(cשaЁwy_<})IǰHT ׁL`yF /) Qs:TbݾUE-%nJ>na$iU[)b샞8$l_FS vDQ_D,|eBO7[" A^-=}'+F%b %W IME%lB<5>PQp~l<\v[ l mN.[nZC]4`n7o4NSuw?{IEㇸ##xIVI7ccgSՈ&Nt~vFm6wrsv,>mVh4XPuE=2ʇJYY$ SuCzԘ7?1wfm`4ߕy_!L?ksm^qBJ1.Q?Foż:k}Y+cJ.y:_ΫԽ/lǵvrX߹ʧ#بbm3sPIG W8 !w\<#6t\vD3kȴ1 ZV%%Ѿ4 @4<BlUZn2݄XRzWT.a1_TVͯ(D]!"f+xtsHҀ"/LHls7ۇE<.R}'srU\oォ Vఈ{"|Z) 3 j5ϛYv6뽹<0OjސY3o/vm4J2^IRm >֌.J<_]SHM:p8Td}pĕhJUayrxG]-W'~]|Wl'?1[.&Qt!t<Ȏ``$N]9nY4?XlZM픂hidNņ)ϱsOtJO]\d=i`dB=Uqa0ZaZ#љ1{և96(Ag)|_kӎ:8Mxƹ1s"9FGޓ:J#ڔ~Y\j>:F[)@r~,ah\ݮ[Q:Y R&lɭǧ9.w{Mqf "QM(Ho`6Xկ *uCNWl#zrǴڿ橴ėW&rzByu @zl=rňc,셊71r>ra>Wᢒ-)2GԿP‰6Wn9J(-Ҭ?&NdB4y"Us?, x&lX-8%zUtT.ra)3PpLy vW'12$aU1ርJFiqZiѱ|M7wdzjHV3KϡRRr9D3=z֗YRuK &}5MbuDӧy0Sf''Tym˜'Kb}rkbM q[ 37oUvp;Eu>j|zk#)7q7!z!DpZ^,PAlҐKj೅;'MHqDlΔ~wO͕}c:sw%!׷ZƗ Tqtei= ԙ1O5ӵףF"WuA=Zܛbo\m}$u"lRPК2lHwADSx-{$/̬)hٗY~rK#iG}SDqֳXj*3\(Md8̻1^S;%sgTd Fڗlo~%1V԰*gKxz5Z%| <{mr}j gݠq!/yoAERc NRnTW׊$r5]1]z~#^QG֐Gz ŠgbĚ?4bp71k\zocʥViA~=>*a6im̔lXm{H) _IWnC>fz  _e4bSfZ k|~V3gs@@髀[ͅfJGL;a 6jMḲm%{$"o{5Fܻ--.4uv̽xn+ Jn.1zr1Kfxk*om_/W\6Չ<)EH/s/ .iVp%֣ՎGSG/(/>OwLY LJXVCл种X77} ւ<~f;dg]sCV8xDL\n"7( YC鄿EAPW=ssF sӟ85W}rS2yO$ļ>mU7K2z)pvNj'g<I>xɳ8g4C׮*v}ĥϔvEғAN͋W\r>}S dD[hZqA6v@J=3Z ɩpjQOK_X؍fs&9榬do$]Wzܹ|b dC٬3$繘?D6&HwGy}\ED1!)@PeJ-BAq ȓ1"0LԷ4NّitXm= -S'P y]'0;|14q$jݽ!X>-?.0rW:sfY$+|54NKn4_%x^[`&onWX|K6⴮{sa#}3#LgS/G;nxs|9q\r Wţ$z:?,Lv 7 號Q^mKEA:OL|`lWLެ֕'e;K?*UjI&&."8_f[374-s SElB.Vx"d.Xp#̠Jzu5Fi+ݽiݞ+1DV<{"ЛeL2`\,VZwCrM.%}̲qXKR6,%f۠1ƧqL= :b 0riSrkO)}jKc,.s+s:YP4]59[%hԿ#llA;#(6Ёx 䴾2N# {CRrWVli ) XTn-ʀ\ntBW>h?|x~OɢC_JU?jnk[B'<}nW]2s+0r\AW)[}dտ1 ؑш.,tR/>7ѽ-a{ ¤RP bn"amVf 9Y ~Yj&ԓ|d?r2)Mtf2ȷ[Z@(wgY3S$ di4ӯȝ0˛cⴁd}-޹seuSǮZIu\P#Xk mX0Ԏ>DмKmw \~LL(=vhZoM0s^VZ7k2XT}d;a2[-,-@RQ&L[ P ;]0F0 k.N)4fdaU֣ɸ:~w9f?C (O%,>}<ɝ&>qK-qi 2/2 B_ {$)]ev=3f!V 2Jbx^xlE:1Ms]@6<=0#˂՞00W\L4ٴ/;)^7dp4 |HoxGB60(o׉cԩ I[ڴм0u}MLzgjW=$I h'јN?B4˵<#qҋ\W%m-E~V5%-;omLµM%]ˏ{4场x4T+-`\?!Ml(|LD g#sez4`-ɂ16ЗIOg?4g`= fV=UKR'MeP[\hŰAxy'Ӷ;Q+^gv46kT9;=Ê\aaӨVx4ЍEZT,_CgOҷ!ܤu_ .X,h vIFHE9ȝ$z7_|'r}F\LZµrdKh6(oSӼ@oдGt$3CxC3BЗ_>vL6"2`ưcҧF M8^kh2:G7Ol1"V.oB+О6MyvةI}ꔃ/2Hrՠ=ƺmK&dP0oIΎDqnFqɻK-IWA+qzIzzvU뼯e+zg>%FӸBz22P]D ` CpzD,yG.4a t\iBTn`63#2o44#Rm㔹jLNh5W(zhVOzˑڛDvKxEˬ3m t_=G9he Si''-)^MK)njR)~&͝):w4U ԻhbRiP&vx'H1/-ڬ+TmJ6Zrպږ1qaXOuh۝?:zl}Aᖰ]pj,I,zM1F]J6W,}[ئu&Ф/=/gIROڴUdE9"y)O52ɶiA-.2*ISL#t|\0H+H 8qs[_Ajki[`X$Bu #ꆯ(ҟna&/c#$szl|FX/Td%LTУx$ &ɯHTV=hم(_zbuJ tim3jyKr[>5W^ 9(:\*hKtBi.JC>]!27Z6fZ&ԊSFUӖcH3I3v%Nqɂi]ڜjZڏ*AZ7q*:9- no[YĢ JMDQ"xX:0v+`8s׶~Ex;&╲?No5Y˳S.̥>9+IN\X=Z.`kIP9k9w_͉x'^Z;WgыibZ6Y OϦg\ۺo<҂K2eob25>:82VC~O}J? ʇd5V$b2uB2ÙO! C2_*LJ>&= R&F;<~`zqq`n Xhfd^ۍiK5awζPĖslmw߸(o0Q2jjXy9/lW:ݑu2-Yct6bvͰrv'TkŸ;2;犂#ja3raQV&Xffҽ2h1BtOĠQ+1^K.ܽ|e5z$^*0WKAl c13 z\:Qlb-zwhzk )/2;ʗR4COϤHLbN^P@[ec Xumm黧wocLxB#n<cH sΐj=[T܂m.,[Kէh.>:֑\ޭ58w`g{n0SԖ\#=e}o^(I1<Դ>|Yo|=3!OOj~s%]E/e٬'h얬-DњP f;6CIo%{>{l7$;}x-TwG>b\f15t:K%y#"T)t*{-NU%i!:CBKMaº"F<.}ZP}?H/ǧhrQR{޲9;KQĻ*$ 1!4֒.[ɩ{ɻ/Mlhze[3p%x Sec-Y؄W:,yN HI} Qon\s#'0}gadєL?/mZLb4YP \pJKe 8ͅEÓ@SYegg*L+o^z{xsJ!?^,ꬉ 6KLn<\*KqVzxVm!s-dc < 3Ҿm4鿘 0UrJ3j{O&I%vRs'4 I𕙎I v7";Q܊ܜ֭`ABU}" xvb|~NKJzU=0xF(.]hdz~HPġs0MW@W~>SݴwlsT5b 0n-ͺEڈpk7,*Mʚp|ZD/Ew/Mҋ`}wéP8|f=Ӆx#߰?*X$u]bdPcw=i#u> +ѯ)>p </UM:;p߃v"?EVnJqI7b{hؗo~u;-B>6{SWA>v{lb3_euϐV2EvO\8 ݗ&gqA/z&lq< L>DEZ.mVk;K0aQ5PQ:iG8Uƃ'X^;YUY& xu`[s7B}xrԙsJ >{ oD=I:&1cOL4xP*<+!yr#o|Jz5!Є(AW I<8%+Vf;9^ QL'?y b+d"Ek<ʭv cҜ ZY-/r0lVz| Z}+C| KfH ,tKVomVZC*rMkErMCfQC' C_3n}*C_։?!Uy4e|V뢖>-`v)Uʪ$*;Ơ?s3ӋOF:8w<(zt'!m{C<10.`>LT+NqruaAmm3BֆY)TPD.ڦfHRL\lx)~']{UL msue`oݼHfwfŕåD@Id@rnkVԺr~bW*2{1К/`ҵ6F(txr2kB1iNԟ2s?\w荞* a6X}2%=>)-,'+U9t( Bd 7QtM_X-ڋz:{;|ŋE %k~"ʥ狝5x+3ʨ`|K'g9LT1sQZh|Qddo$Tn+P薰ހQ@-ZD []PW!IQ 4E\g$[H!R3[ǪTRF5Q[. 8+>h-">HNo&H9Sc=قu/\4Zo&cC31^_J9K>[QavZ9ۭ`Z  גӷb4D'g2` x 6=d Uƥ=>1%^dOxȕ߻3uq8.ך%4\G*)zW;?‹6]n~"ɪ>J)Öeܓgl\klPۂ6b1.f>|ރ+BxC:8ekNB,@p?|}ǟgK9` @!6Ve5 b\XBLv v^(vGCFBZY39,vp5ۖDvsC=vKrVv ~7A4L-8 h l ن ;8vR9?F l{@`ij%?`Î6`~:l9~ya-w{CpH@kⰶAaN 6-liRfά;Դl 4D@msnv=FG!kpe d[Ba=jّgop=[aPωWu@;#kzx~ Ư breO?正lܿ`;@Igԁ,_g[I C Vd 3K[-2lAfۓ″./P:)niaۛ B)pĔq%$ŽBX8d`aN8~*dbqTԟcUHgCu蟿(dI?ǁlxب]'xFEa`wRuy@(=;%$*09qȍ{s;k-گ!ݹk-񗜇3! xz[ِPAp @awphwXG޶%_A.w}l2-9l 3mU;?=Xx $Hd )vK0)㷦9!ߞw^ooG81 O.~ !Q;26P9?Wg̼; K$?q}=,V|tjEU zz1^(3Hּ߫"!p~v)}n6].`0~L`&@]~Kc/~̐˴vN tݸs^cw ros}a[tC!`~<hm@00{w<&&ܢmwf;C;ޝC}{䁱]tޜ-!ր4p?IHp&@ htwU-wB=BBlz?[, {˿~UC% Ng^ף`o/ǀm=:vA@;SK7ExhXs#?~[B2{~- GZ׾9mAo`7m]vX]Hٳ㏡mq>p4 2=*e紷8ċ,ZW&ڻӝ݃ص4yC ޽!A!9ʀwvEQu ؖa|qOq6mg-*F/v.a/?W?ej ǡ3Ïl$kjcqҸCR>h!EGb5y|[dLO>*SBb}60E`jcSLl;7C]CMhPAP?@~gٍ+^w x$HpOeQ.~_Ue&8p[Kb{8;qeolW;IIJUMG^E=Vx#w45I;@[a0 `i ?RԁKN͝w-rXXL #d{7(?{V|zdf}l+X}+ lnט@}.[o%~Xah}Aal~ | j򭠦%+$~kko]}SMAjKkWtq`}e@}!`}.}YJK\[~5ego!о֎~w:~WdoݾS#o}%mhVڞf{3PRc_}m[}~}o#Ll}O9샍!g۹PNGYJbߏ.6Yq6Oʾ}Ǖ@%˄탷6e y MsXB[vF~wC+.liG 򴵝Hzخn 2Iηv3w+J ǟ+ϯ?G& -q*N" حNӂlq od~Y=BG0t\d!&⑿t*唴R楄dj h&|Ru"JZ4 bɈN<#YI{1^p2=}wٲMyCn)Jy4`qWL67$߻aՓ k(\>˻yCBngAᛉz5Aן5>zex5[7yvx׿`vKTLCSж1"I;1459<~Õ@mz~ª[-[_a=N]^Oڶ%7}km3Ow3#(?G?G?G?G1z p0x ?TFtֻyhnUpD x @^[ TFjHĥ}Q" .gg{aqE4wE㊸=5kDk4nňK\a/IE0iR&6A@z,bI+8%ɲbskDK0,Xa N3PfFc:09 \ұ2YQh1ד*&]YrEHa(3%2%A!sLADSŸLl",_z^mDsȶ Žsv"v8u+ J20TmCR'f Rʓ\y 铛,Jt9eyPs`hF$K~JEFl F2h:T y0쫥N&uZXpQR1dr mp RF>/zFС$"6zrʹYU >no[`VIM$TVqWPʙDZKcřzI`31)f'L% 5?DR #B(BH`̕;:8 a2`BҰ,rν0?ݤ5Db#mJPr Z tj@iBX R`isPelr<hUƁ}rPF(jlbW+^IRsB¨TMu]%)[~`Yk4h1ܒӔ1Mo ( (rcӠ&!g:pA~u:N4qk A#w V~1 fS%lg4\Σp/e0S9flؕhR(׏4ERljU^BpոQdl +& -SvD?,+Fj`w t5 b`*ߙʴ4Մ3.$E {$~Q1?3$Oԃ?Ĉg'> (hKƀ$F^LfIgi Nt ybЭ`-\°+hh2. h(3u]*PGQ$,,8I#a&3`YSn:qU Ge#CN0,ŵHeS45  O4 = _P9ʟa΄`aE7)JIJ&  1ɵ|MwohؐM*_yºoU6a`!& 'Y۽\^}e|d#hgЙ%,99T@v^V3\IfX+ kI$BЮxHQYD fqY%Xe)G*gR=uk U%G9^dWI#7ĨB\s ֯#2P@ݥ%-!€Rv<}_2 0};,pZKd\{-NCLc݆A#'eiM ,,Z% AkߘZcӶB E8בy'QTE12=1^U=C-o2Q ݶDXY#Qw,-_"mm\<~65JG$dVljAAf$,2yL'@)bdzxRٞLA7+A# IDS\zZE퍩lH*BBXnHJ-uA3ѕBj::w*Sľval NyLi< X0ł?=@"W\R5`1vv +B5gi*96Zr 3&2$G!g"/Vi &-UOX&kT8:^tKu[À  O`5Q ɉNa+#X$$lk+'0nDtߤi)Ye\5ry,O8/U ]WR},_Xj: 1WT%J)c$QhMתHU$=FY܀z,uj74!Xp )K DM&*K5cu,ءLτNKEr{+pK6 4ҖXFZ !JKHUhx:Ф&>z (0p@RظDx7҄DV3&U-&!jfE Y ,;}1`bG$E%jD pƀfػB(_ZToD3E)+1VCDRt,ʌ[62U@FҢ1QAǁ 08"w[dr'o 652A4[V-*m._f6(Ɗb#2!dj?. 1CYY!(RG6M'^QhN(5:M",pcƷGO 918P'lo!~Ev-HVuj_hoGR'mZ`&叓?8W>tQ݇q=A Bח 5rNylZ^6W W7~:vp#Vg-X|=qC>ukV}‰;йױ/ޟbHM1;Jz3)*< ex͹,=ExJ*W珴]yTvC.cӉFTIvMbe\(~C[".^j,=:t6q颰V#kl;{IDT;?v#?4x|^SddFUtY1翟F=7p?pmI$Q=%sxր72>}_lug)?w뵬կĝ)6 5c6 BM?vhnς Qݶg=v{){Z܇?[_q#KECOAgPgmiΆYvb)ǫ&\8p}G9}߽RRr70joMD"lCtɞ_N tѹ/FMYΘqQ\~|̂ uS^}!/?Q͸ְ :,i헓}W?WI}᷿:جӀ_ofG)G/L;n֤#coN_4AT8ߜmk= =H[ܞ7=w K/xKqy6[W/{Gjk]fasٸ;n섆o^WE4+H\ŪzD? 髷`_慔bg_yŗ.-L:4qjӑh]fu˜ ]WT\d~ "LsWn]:t/nqY$8}ϮiIXTހ_3تdA^ 0a3Ɣ,xC/ Xs]qmlɇ[ğE>eW՚pEoZe>T _oU;yƷ̣KGoɅSH/|îKTc<PCIО9 Jvl۶NvlNض۶m۶3_w5Uj\L?kUySjozxpo Abt(_@bG%%sm^N,}ʋCK딯;srb(ڂ+Y. d|ɞ/Ţg*w<9Zќ;iX'K=-N~{ {EׇVi$BfB9م[UmlB>ςZ7H/)BSy8Mkh@籆cdER;s1dBOmDڞA[.w;)PzD*Z}U-S⑂AG SȆ~e5Ǵ4Y L-n 篶oڻPU{]=.~۩Zvhbծ[9|63II9]B8TdF!d2q"i#>e5CóZ} Tޞ/+24>n'ʃ+2Es  #2~G\bhû[}4TS,ӴseBGu,򯐤rv[3cf'K !A$5x(%yNf؆ uc,ƱP2W2,N\fox@-8:b6&+-P`(w..Ps[P ńW[=G42kp4 tN$Gdx yi9T,v [v {\W3/?X!T-`vtU+K;0QK~ ҟ32C&ᓌuREB~(\ zCC w2H'^qָ;톀ɕt_/O? nV}E% NfֻVT1!2n[9d VK_*+*cd 3c޹g2L k>CO|q ,hj =a4? v6mn{Տ ]c'RTlv (R䲧5bl?ңwenB ^*a!)(*Z]XJap%.`p]KJt&S35B>~=go{Q#5.O WgbAncrEDꘝ!Bɭ3*tjumM9b\$l3 A7ZKZ.B;c2M# Z5'"nm"D!UCF ﹩@3My]!Ԯmݛ2`Ԫ L9\`:;L'Y DZ˺eqs<aRfHCf95nSFlwc@>RlzAo|)DJ+[NzJPR b+RW&!'PsV!ٴb?)Ru2aqhg+ vt$t[C}6$i~> ='[a@cS]0@YabY q/3Jfʴke`O)o&?@`YiZ= ,9 P~DK4_ >؀ /<â _hKU|+ V#ܖ/C (@OZb8`[*t*y_r3<)I,H9__Zs[qJמnuf'U0 x[%RR\:o b.9Ѯ 0A!88~2Xj }F%ݣ ڍE)3g,XɄK1?Ԧx=G%*Þ]hbW}r}ZxyۑuH4{wzuԲǙX rçU@]q̧R1o[~*yFFye^FFf^eLMi/j]y%Az^+T+yBvg*g_\\L]vxhDTmxCm|(I**c0AaT%k0' dd:hw*[DMI\ e\&ev*[*EZ]]9mwwImUFw΃~ tk )1{,M/qݾQ]Ų#1WtsK|Pl11rVUdf ,AS2?5LV1gIGLce4bWb j jا1co7 O$"uhG;j%beL fjo5-a6yĮ pO].Mo7--{!) J:w`1_4]x k[gf%:R/XQV_|%u4.7ɴͣ?ìց؁rlI 9HH ?q5o?EjYheFc79~%aCXgDLk#s%r [Rf Ե}%Bi]{FiuSo+F?ZT!PgKðg2Dv4Ir w ,Ҙ .-mFY5DPՑإ雰 )l.W:ԾB wQ+rֲLOB'O*iW\)0|N7Ze(jԺc_Ky>_aCR^C}zsF)زdwu$J36g)R oiQ(.YLN=ZH5U 5cGz\~u` /eWmmEU#!$="diO Рc @ tG(5'u^0cIT [=+)<ˤ>PFA"Z^qWޖD=b[4䄏*F@sv~C ZD̈I ib.*>nt4;@K6"K.{\UT%4?|k)c/z3JerbK{9ٯAЗJ#7tF2~uy8m%3^OmӸx G'*}}L ^J0Wq6KEl\1Xf jh_ϋt5W(\. A~܇^(3`#{GCJNvس## 5fEUE WlM ŶUr /.Vt}y.;l2z/&ů!4JX k?PBڀCy.wm~BJ3QW-S칙Je4AOA/sW9q&k Ю< tPM7cկ4# 갠h넉'E 0Juo~W`!{Hg=eoD½󍯙ݶbbĐӦD=n:1wnpK9Ke62w@8w) JM0rlmxK̥ D5$7)dt,iZ['-Q8 V"5uN"&>Ui ي8^9SUzdU9 ͬ9z>:zI0D1ii=O#YN<@`]mTA>@PsR).Φ`QƢ\*ˆ7!,m8y M fmŜ Ir b!'te"4v0# >z猆Us5b f,egT<M'no?$I;%ThKA(t H"ʨ+ͣxy/G-OoKHO&4|YӪQ?e=Gj>oq% f|D ?^n Z>@z9 @;R"i|Ȱs:`D_jc5BV^ n ϕ x3n,:|sUolN ـ+=#Duz ^:RM CbtElH_&^gOqޢ9*c=baUчMc,h_> ˄-&ɥ0y]FN.\K˧0;]L!pf{crCuq$|  >!eQW8ixJ*qSU|G y@eXN dt%NE PY)R~׼vòeĎ+,1xIuϷV:Z>y>$䂧P<+T92\Ҋs1}A|Rxjȑ3W~ ܠҠw'jtքY>ՆiC\vV_D|3Mx5FtKskֺ<(J!bo_%D'SJ}3? wXnR?N(cQfzɢgZ2HQ +Ϸ#78۟`,nt>ZeGIy#.ggZc/\Vgb<[OX2;49kmEt Svm7 cfhO8tnRE7tU.*NY;o65V!8"i&p]v6lI _JK%Z&B+聁4Eߪwג?{`Gf {xAvda{O#gɇh6y0=lp~k|p5<*D%dAKy2NdM5H"#.|HlBOK➎^wVV|:(#2<)r̆AWM9<+KWL/žYaO.[ )c~X2Hp۝='25_/,:2BWشngh-f#2"RZg3O%_hbBڍnW/>3z8e~PnwۧMLZy#4&WڿItG&`?huy!Q Tmj8g5{-ef&#Wck"©(ʾj^YkZ4ƠXJy¥YofEa͢kky'<V pcG\ȉ61>3'@?`aW󑂬|Nf?`X.U՞䡓Bߞ?2"&G5ĢN6.\{ /d2LtLX8 \L{ştn.}Uw̯zm@UBAaG$(Ch~t;b-Vǯ<;̯.045oMn/B۫ ӷ򔁊84'ƈqt#>k=Ur/DKe}P[F@yxOK"eTY$ةd]9 mYd g`i9Ӡ˷:r:19yNY@W1&^`S|$URZ}B%f3nP{"geSI¾Z@ dP*AYou]ș=f$F#W0]cDt##H>Yg7@:&dLJ jAǃk(:ԡθHy՞cDWdHWtȪe2^w6tw__{j =Aoc$].pN4t1av_a=pc׋*bU]reP=h1U;M'32a{g5kl__.|@Bml={19[A 3_:2'.ZW4GRlHUz1kd2/ڟ^쒐g`ٽ]f2_Z]a]2|DmZ֌(#?+Tg8F-{ꛨ{Bo`x,sb֘$ɠΗ }od^H5/r׶WT1Cb_1imr[pɕq>j`6,'7 x_OBM5ɨʝd5  ΅V.#Dq9&i?W+vx9 NĩV)e)rqÓKM{pwϫC"ˊ; XN,_qZxA>ʂ9Sh:~'sr̤b6ڻI7qXޙwh!bI|UL'ϋN?U0+ zاҭb4ڀӤ́P07E#-AK77 ?? ' 2zrYq7wM%?ߝP5p0`qI@B-wc< q3p4ǔίQ.jqӛwR9Z X HD8sd8}-tiK4u/[ٴ BM_E;_3བྷ`%ހ6C^A )&#ڏÖ\^8qxX>Eθ.5[ s  1y(%B$ŌpT ]{[<_/~]F9VdF)TD,'t׵Nh6V: F.\ #wY0RJv_ښzMT >Fim6w(qLz [6_YQl ˂I]\"*bI|o5cݯKNsn3z~#\/<7[yB߿!qǶwO$P3VӃG8y0+U4ks?נj]+3 `PV+ܶEը @'Ǘ2 S (,=jB7<`2Vkm7w>}㢯\SE j&iOx">VQCjxnO-΅:{'.WU2AUKu07 ]lWwLT{%EVp3Rⷱ_۳s3qOڶ@u |o>F::*E0|A M6EPy((5c;a]z!v_`>㲤Ԋ~ s-΋h- A3AB*ː*h\x{/F˰ks*Hȭuq%t>ŗ]6R.W*"PG\;}Ҳca|sƽuU~sp/˄ ^Ŕ[% *)9ҵ~5&!.p$ّ?E߁J44Ru}p[x!-Jr7=}Z N͉$xO3rZJw֡ϹR2ΙN3=\k7pLD`xUb~ V$v=_ g49%,DrCuo:GâPLА1VV WJwʝQu οwPx;i9ޅD+6tDZ|[:䕥˞HOp?pP on57՜%`~`A@Azm|G_h"rR WxoL]^ق`hu049>_ <=jnȀRٻGRܨQb>qF>XڣJ0+H٢6ppc!Hs)XC G'$m$3 $HXm5H֣7M9D84ӂ.u^Ac01 ;3=ݝE䎸rb~akqA={-xJG9Bd1YBzA7e:$5 tcpVC}$xFɨIӺahfGdh(Ɇ;5%^2揶bEw `sKAv[_!uN; s m\ fddkؒȾrƷ@FDn%qķkȷE)8ll %ӣ={VNX=~\$)*EYE>K[ >0)WMQ.61{ݬ"W& :aJ@#_贀!CS3֌2c^FWXvnOƇDnU`ᎍF`LTro.0cN\Y~aHNߐ8}_y# '#' 9)KƓX-){dv[UZe7hz_LPOzPQ+w1&ǯ.s%LZk'"=|t^ i2цp^mD5ڄa~v <֐ܗAۈڶ֏ ߵ&+_"IWnR?;4o>f95Q&aλ.uO;0;@4ڱ'aow$;0Բʹ2%+I_$Z?_?~Ǐ?~Ǐ?~Ǐ?~_ q,|׹xA iDB]}ͬ] \ %sF # bx @^}T7 -RJJ(% !(RR ,!H ) "]"". ~Q??y;޹Ν;`,qg78y8x<H8z=;dodo7Rϫ$4J0dʊ40Ag*'# wܞJ%wҁK!GA:/{ hL- WH Ži^ǁ'L4[7l|=鞧\,wz-$_ f=RN ޗ9me~BW'5 ɒ`L7wi&D,2Y-/,M3gJ`(aDz,?-t]rϼPL3Eԯs;).r#Z~+Ƌ+4JL!R׹Ɩ>z[7Q~Q!`JU^2Ɓ XUw^{ڎ`~.i TXCy15ѝf? ȜJrC ϕ {y}v~2RjKԢ=eQyEr 9ڗsߋ>)dɐT׷DG"̻ !i1?G~ iLh㙌x& ʖ:/۵Rx7IȀ|/݈2D =P/x!LwD'gC"D\Ri)Uِ=WFKϵ*):&rk ۟t& 5NB[^u-zW 1{s+@q4kFT$t+4md6:y |w3J!&kڤ\th yYOو!S;T φ[M6ѮܺVj+VC&Nb@A#d'3E1̇!])fq ]팩)m#q^lhL>^ z0M݉^$dgk3ϳ\gݷpU h" j#aޑ!b\R6U|=+]gN]0ĸvQ_^~驩K_Q&hci2"l%koLRF *h 2Ui-F#CGLe&.Gh6_SsW_]~ehM`\Ofԓ R1^jK YZ(ZZ9q)NK3J#B"BSS6ei>!4l6AfoyD:cK/nꂢ<4`Tx%"Su{"!xsUyǴK>ȅ%$@Yۢ.&>_Cĩɓ>&D)3$o2n~Btۻe]}Q)i"h򵾑Z'/MGQ{̝$ٔjn򠓟FLx|b.]v;⯶1-ؠycY[H-CJGk+dLXew/Kfmm_X|petO*Bdn ]Sw,YС㏭i!4L1bv͓} :Vu/s>7~fF)s&jmtI9;6㕐ݨ} %Đ+ `{*a {"^"|SO0Qvx6T_,ghN#INrtu=ZfKvi,e+3W^N2:x"V _^ 𥝇.gґAfsu%Z)ALtlOzޭY"CWM"+`Sgw{x { "16rB}L$3 cyfkH֯J4|mq)2YֆzsNx Aʕf;i&7:(Ԯ@H3vJnnщɹSg0M>kM㓗8bҳ ߀ή H.6Ebj՝@foS*0F6FЩL*qCjP'n?rkWvy"eƠVL w}͹5[N ȌE .tlվjfz,4aÊT6QŒTf&.[pke(, J%:O/]U?T̓o٬gE_1OMJ0y'EuM}uv݌sْ^ KDm)`_SrKD>5!r^ͯ7%NQUf5u |(z:/.'Z洂,!cX&Ԛ8YZ oGVК@Jy[Bex=4EF~Q}Rlme&(p"㟷ziIE}*W<݉x5qKTsmT }3+eCyv|rW.Z2;m^x-6Ve[6`U;{%'mwJir'l6%KZ<6.*.!EC.O-ӣge|7^M_Cqb[< gn~#ЅQ蛞z[4} HeGA9}1eN$;},uW*wT-oVi< M1RӉ'уuDQg^;NLae#Q=Y5> ig}dg?yx9 ,ƵWsL[̧Iah> (ŗ[C:"PqyƉRs!i˷x=#[8&Ѱm*+v§Mw"FLEȸ.r/W &Zv0/]oNN*ZfwyN0֬\BjuLk,s̅ Δu5E (ѫV)5ʞ|4zڿ1Qɭ1Y燝~gU $Q?q/g iVo xo֫?TJ/c ߽GUpK cH-zj7R-NUMNb 2,` (@(468c[K|.=$d4NUʩvt]B0>m!NL7hwQk$A]Mooj>yD= _rO9cɋԍR]bW9k }[1bZaN̕ɣT CK/`}Duk}.7w;4s1VubQNMC}>bV@K9*©Re=m#E˟>œ#6om}{)#.5늘+SU=QpZVڹ2W@W8Iږk!^&> Wh 0!\{U7?,қLLxKXIYʡ*#L5[U*3h5V`-⒰fJCe(:kۦf3N$+ ()uG.ovOHN<$B. ! ا[aU7OIa6nqMJtd.Kn#i=:ЋGx';>i$.!U g{VNw3nG ˒Bf^vh ʸB:cxoZ1 S)\ HꂈN p@ko I4ҖXєGeGqb{YlHgdRe\&c,>JY29eOq_% JaE_J'M|wv1NkQ0 Eo.XL][Ab~2Wh3#H_Y7K@iJQn!E=4l:ԚEҀTR4?ĠyYA. 普۹͗t+)vmS+j!;H?ks騴P7U JΤƝU=_xǓ_e9-x3˼!Q%QRZ<$Xb(_vZdQ݃n@'4 kC䁷 ^T}5W%[d;Gy28rX()ߚ5Z]W'v,"H`MɨxɶK$/n^8LPǚ}2)8R04 P ˻ڵ(@Y4uobN[h(|'*Yǫ\(x%=IȘKS27P\/ݳ @!-'\5\i=@V@pCb}$5m11$:68Ԛ{lbDEc; u2jWu=;@*XbPdÔe%H%Hozk f` //"ڦo9s8~1/E [k,檑9VbTV gpNH̫-ėXlF;"{C6RY,ˡa4ѮZqsVFʯޔ5;Q|#U&]w_6{B\J5 7CG : ~1\ɣk;U-zAgXg-3+rw\1ѿDDM4U2li6(Kc_Ծ*hͩ6x1x$WxT7V1*ey-Xn6\vQEyuVnwvI]ʊt$N$4uQrwʵ¦3ܩLj0{R;MeQJ }Okg"u;=]b[irs-.w> h\MJDPTu|r2-,>esщŧpgiΕͿU=i2 HCS;_hH[dx :!:(*gxPΧֲ1km"KNU)gҋiH܈.AڮJN^-IedIVT޷>Z'Ӥް̕Dq10eX65;! =`BtJ1^#RV‘ma)nt*M?Kش ń|UQj>N, `m'r63P5`פkKx Y`,;,fO{Xp"(=`Y($hW3a3Q$;y޴P}y輋bzqԗZw%Kx .7 _q"fb"%q9t|~3߉F:jM)&&tZ>Q(d?+kTrV;; $Cs:] ѪHo(i Ɉ)v9ё?@v6/`X4"MF1 >Mz|O=_#5O\q[4Q3-R<ÚCt N,ʑ+ac]@Jo[?ҷs-5m&y5=\{S+ c qblpRne diq3pɛt Q"ȶnQ6q ̓/W($znW eUlu9}+>.35,OM,KMEIyЯ}=ih~ 30Wr]5/H.܀PdIjҞQ_2*:ǝB T0PhPǣ'srB Ů"OKdžQ( ȵKa ms O7yٛ&]1Fm1vY:; i0](1.N Gz_4 5Y\.hY(-4-3䨝)`/_iS~Ow| W º?>~mD@QKҍtu~3zH*-u}{W"`pЄ&9M:RUjBi!,x~0VG0gL7Ѣx_,SNx˿5ҥPoF`u(P3U[ eHȁHK>秉V~1ar '퇀뚹_&uj<_/,7sSW\,˧W(B559CGR9m9#}Vi ՛%;N;vad}#=wf/dihDMNJ!,44A?H*v!|=Z@Hv>1v(܌DuF#c,9ɦ[!;"wV! E䡪8x" u|[hN ǘjԆC55f/1=ySٻN $ř4R$i6elQ!: Gۓ؈ `y+4@8%+{ σTZ #-6gݶn8IUyȴjUĮZKNwmF `p \ 7DeJ 4Xj`{ag݂{$ : (z0v6&'UZZ:'Ҕ.N+g݇_9j2(w7|ܠl0kh Wh;$0;KY>qO=!ɌrcY8M#G%=[ j'/E$t9? ERs]&] xA RkV9pe32blk9m:V6_ Rb3>(^?P@IQ+eL`~zg/+/@#V[Ts6 u(Y<}/{pFLdDsb/=@!A{~nP=w𦂵ŗ\;ucLzXo%C59?6a&"ƼF1ÐJnA&+:;[iKFuwE?F5T6HvoU?ώ$ܔ\ϓi>?$NKlarFiG&BI֢DtEeHB0EG)"0y 7IA -Ji^# 13~lA|l%4n=!mTIAkhel]=Ĕ+g>/{8`E7t5OnvؒU :RtTcj?F1jomZc춃<||tY5pDIrC(YNNzo&PrwxjVX+u;/_[LjzY2RX3:![|q<}?D=d%Yj*VK|rL uZd  %XzYOfi2j-Y'ĉF7NHeOx;T(AhpYe▷%VȄgv#b5,4WxJ6]$5TP]W EQeVҫ8۩,Z6H~`Q:?(4؍EXJSկ }z#m1R^X`cg9ܯ˼>ŝ]V!1[X`p_ 6(w:E[67Dzcg(ىLE545NҠ jݏQe8t25ܾļ,GE1E,R:'-h4Z #͆r5ܞ$L2g>3q4D$ʃ 3ۈ@UGECQ5;ɁWoZE{iq*R=o&=˴P݈e?i $${s?ܹBKO+g'BeȚ[uzD2CG<^/؉0B0=S,n;h";7)­취1#f($$VWH-83W/QH7p2[0yy~#:mܷ#lARQهx;.VcОx4Rt{SgT34,wpq9.f*QҚ,wH kY\׺xDnSǞn-,6 4 *2F SU b:lrN$R^t^uSX]6|uH@l&`]Bf45K.K2//%J9&O//JML$ \ T[]Q9Mj<9ŊO@)cL!fRj'<VA- *G˅yVE78\LKKJq&Q\dYƐ/zrnzX/ yfWjgqDl7j8egF.D$k$ n#M}L_>F3jZ&a%sc52~(QKu԰Xoٺ</mYݻC~+wIҏE tFΰשcVܛ /shUʑ'1LjC(Pf$+,+c*X Yk)ud`2]"O`W9Ey&"V,o$.`I<؆r[]ϡ]Z>#G>}(uѼ_;!/3&t4q̜Ec޶]z#ܔM̷a;/^1A7m&ޓڲc"iӌIӍtsmKZk_:h5 CLOSTLɻYCրwj9ǙQ^dCJ1\ иp*pY"c9Lnv'W#ϙ,aGNۭ.N%S@kbN]o}}S߇)[׭0kj{H>ܐc&5}ڹ;+rڐJsw`ސ kJ lO pve%qBb{/_E9*_ԵL;wrKy( Zc5xِV@2M S]lO/2ZU(0 wW|`h|]W8YsyFj#YfRdHY'm8-dgn|:B&sB!oqbi+2z:VCϛU>UdB}6"rn*~S+ԒH|EҤj#>;C; >Y*fc2/i8,-r钳3HLg5es1́rq0f|?dw9IKzή']!N~KčQCn.hHqqBo&Qp'ư˽BĽήtYp; xuΦړMܸnR;(%fɔ`3 R [fʾB+>ͨ1eWɈJ \w*K'YI/ n <·iu,w&º"nbH:Gb[1ˈhWB?=JQz$_X%a|T\M#+R_2@Wo귝%aiMncn9m7ܹ-yNX m'kC79~!u2'~91-cFMxX}-+髋,!(4K06ͻUkg]p)tV@5 {g[ "0P&>097ElK\Mmzh*#{GNoϏH>ާ,0Dp䎋wj]{tqNVް7Xڽ7. ަc1'+hI;uFLd%|{{KWWBC4&VnjRl*i'g!~10RЫ&VrŖ7zBSTP[mzz(trEK4 bq %(LkC$3~*z7ҽشc`=8z )SJhfb Ƥ^*ZPG=[l l}Gw&fE~yP<΀ŎT'hWp _iDZN2Uciw)6}1|O1y0q^KB~aKSc,)\#26_G yPAFE&'+V5t {JT`3mc(ٕq#?%-?ǯKqWbUfRϹ현qިJT}T'NBipo&a;$Pɦw;\MJ#e ݇OUgfX gwb{x׾{G$cȓ.k䩺m&yٕ˘&n:cݲ{kV8!)q>YB$fPLfkj>=rYFu&f-R3gi_n፯F7̃//+ S.V$#dJ\0PLүuܩ|Y?l;؀LP>\|ώao9B0 jZm؜Z@S `( 0[ٛ٬y6 3{[UJ`-@[cj_ـ(A 0ƈfPVԒj 0 eeCV_ ; 3?vRPhm ?5gu|s l7p ie vBe+>m`PV{[ fkk0ÎjW.ĚmjZ̎(ifk zwi3lAF {/f0:qT#.H Tˆ8#}j ;~Vhco}p/V?3oWyxg o# O/`{57P={mvVFPGv@|'!g ]Zؑ u&@(̆ `G:*Q@6&?]+!vX{}^:Y" fb[+3q{R;$'A?V!yx'\Kxyp7A~ CubQ{N1'yGU>=$}A{kC|X7f1vBGՇs-G3ƣ khH05<|`v~5{vvuFdm by%iX*DZ r J1T~u4"?ě#@Z;c)k8@VPߚ 19tczo.u~apqژ;'߯?(ˏx$܎`tf:?Vp{ȼ7 J$?p}=*T|pjpsP_^ 52wѕ@߯2X@`??U{b D8P17; kU\$"~""kn0o!࣍F{J9?_<}*졬?/kjX&v3޸{ _Mbw=C[cSm-~?Σ<qT87h?b& n?NSs@c{E?Am#t |˜lj𝧕*`da@\ |à?a)~n@ڊmW D l<&,"{aO({F8db;# x=]l,Y16)i"llVp֡a `{*sl/7:؃XM?~SlCc g\Q |tphD!>>ero-˰wqM|ڂA6>{%wOMG9qtYp?igQɇ΃|Ž_km Iwط 北B\"jhjd l@1?#8Ǫi=!5"qoW8_kq~e7 G&?@Grf~#j.fט!G{p/ `#+ ?،П])?/?wpd3Rm6ϟG0}lr~{8‹(Zg&G{ӝ 2!e\uKđn*sDΞ2@3]-VdzC j+ `m wߢ iDnXcWxTC渣_p?2s`mSm̏@(Co{O xv,戜=G>̴=vK[ L6X~Ƀz[xxg YK6`0:'`ft̟WY幸x5YEc*a:he;vK~?kwj ɺq?ݮj7)I*)k(^I]M v7Cځ:8fkc 2+Q![ {-b<>Va@cK3+ f@A.83Y@(>6 ߆xKg}_ MT?FVx"kpn &~g#[~1"w{7V@xwJkTۯ?O~wC<~~/ٿsBO4?>$Nو18we$w_E2eqsPlX `[| v u> Yj2wp+lo?,_`?WwKom~[Vp91|+ J6U11mfz5:@[AYI]ZF^J j 3 0=M8 u8vPleY m.\37T<`#58l.9o~!Nw G+rbs`Sv 9 .[r$@`y.g_;p@H}сpu/zmA s)́A;`h JS?かMF`k9P_> 2m%`rMA\FQ'}x_W}s6@F N[D~+v2VV@AMWq؈_W~`7_uq&yd222 s8x8\<<@n ׈`34540>_K/_K/_K/_K/}?zĶx @F^[ TFQcPp!`\p6!1hqQܰggM j`%/.D\h\(nKШUwO=3;'s9{uj0$ODx87$S/w O%~ ҁ^Vd.pn~(~YIDeq :3S*LP L}$ZV2h)R4h /BX 8ɨ#ee0Y~Z@Rf A@pQ0   a,s"t@QrL 3*ä5`t.0~,2F#C=FGJ+?bcҰ ,T:F9!ӟdjѡ,՚`dA|NeɔÄf 3`1{ܬ5a4h4|f]y)!(s K'2 `@%Z<#*W ELcbp6#f;wǪ|*YB`ۼLlm#BYYL餓VpJe _ֈ=2$ `(Y@z64f)`r%dByإke ua n UL#`PVRvz%2%Q!sLǃӉ  &qBjz^cDsȱ Ž{N"Ns+J20T`CR'f Qʓ\ 9铛,Jte}Ps`f$G~JZEFl ۃ91d4n- &a9WKLεᡤX_vշW0+`i ܢPZb*8'yD(V %N$psSl䚔 + TTY:ɋ홟BYhw˅ !!$0 LhB\B"\vBa0MId"&,)s(O7i ,8HاT\Ƃ(q݀QF!Aؚ-a_`+ $~qa\-3JZՊORphP)0*0kS=W sʑF|k :4%o4i EV8@r`Z¸ڧ2د^׉c?h^ʯc9\LrdðlkҸ< Rq.3k]G/+Ԙ1rHNS$uX# XXENPHa )ږ9U`I2{ҨFl!@!VAvULEZ6Pqf0JXp|؀/ };g=8iZx`z Ӏh i(IbŢl{PO;=0AIYinU+43=AF#P@K,H%z<"!`i`9FvG5N.X C:o&Wjpy:=J2E;݈!O`@3(h" {Rpr?H2 A= 9o(SwL*ȯRi-ƭcg ,,HѰ!DUTȯ\IQoW6a`! 'Yǽ\^se|d#dЙ%,99QC ; _Vmm$| P#+nF4VQB"K$Cr"]E3 ,wBG~n(nvTr}Ѝ=IM H3`.Tmqn rp%(_pKF`Q 6>TZqnNb܁l pEm8i̶ېyà 0Dg-۞¢UB7v~xp+#HqFW@z12(4T,VDee{)"qGI.v!] W =IqmCf h0($B `ඟCq.:4F !,5[Y mPB;5BD^ı;eơFNą,r*.Q O1*H@J36_EE} T. ey%LA7+AZ3^twIBS\Ž:EhH*B@>IPin:{"񡡝 q W!d7WSĹ9l=0Z`^(ll @J>@PY%G 8_hq2BZ\(iɉC X/ 0ӚR D*eVKe,@ѕ[JKM?0*,LpVC=@(;J"\ !nbȱbfň@_20-7%+훧IrP @r [UXW!機rRDI4eFIqsӵ*w/FY܈,2utj74/42BՁ1 ZIKZ,WlՌ׳` *2@>]ɿj/J:;\I \(K Yb0Bni`BZ\D[DAT&DF€I=z%n`([7DWuhI-dE3niY4;"D$)*ш`4K2ScD d7ƈ;B(5-7 a"F!):jIeƊJDܮVE#i(Ȼ-2^1{3H4[V#*c._f6(Ɗb#2.5djo\DE?Ab&gLE96ZQX'I'^Qh^,5:-",pcbENH?q}s8zpRN4(  gv*3;W C3vvzk#pI%qd]XZ9ct/RJ\t0E>oXNN)"sUS4n[5>(bwQ0qGo"Zֿ]իEڠ(z{΍jU5Taim= 4Se ZyԸSZ )xԅcssj=t5oOض◔V~/O|HZàl.,lf.o)念u\x/fw:yS F.>iK޺iTohޜ=ҏv_M? ]cA5|յf&ºZI2.^QQ?|jP]fK]0ۿ0|iEmc=nsQwwƚ&v@<ٔeuwoɌqհ/?*sޖ1wrg,]=B{@БU7mkQyÿUrxÄl6FM[uВ\t/~:ӭXي+mg]T~vd؏M{x)aV+(ݔxe~jq+{=-؊%ӻv9fʳD=79ava)G]G惓Mi < {ѵnʽnSIҧ8.gʥ]E5CvL?[ݨ[*{?zowg|[JZgx^65wM/f\tI{ /zq~{DMw:YJ%囯z]OF$f~] ?:i/~P鳽}1ة@Wc7u!~?y~ٹv+9\2wdtt+% R^L`i{ƇdF,|4ϙ[fN[||3^=ykoN9*ݛm^l۽V0ec.PiYMtw'S8͖ˣ>HOm_~G?]8E;_ϊZ0.yf3NvY;/z2.ӭ jůr=bɣwR,摓΍|sb37P6>1?h_RpIל~0lۜiG-/ǣ~X DGv?)keF1U-zt>O;[o\/קe+`J ~)mΊa\s;S>+nyuFJMz|1{?ۑ٭yYG$rf|պtCwwxW9oI1SE.nƻkI>s65^Xܬ`*eY O܉ik%L)4cVT´3u@ztO2&e#WNjB'9?&e %.f`j+g|ܮ;MmQtplt]8WRvŦ/_?o9[_kmN6=:{^!3_('WӺ/Zc`:Wkq&%[̙nl}}Y~NU!n컏dJ=n1Zl~YIɦKͿt2mU|tIK.+N9s/4aNL?OuFm~/5;~ۖ/fB`jd#T{l;[\ߋviz-$Q~۟OV>:\9/YyZG_m7!ytO>Rھ( s3#RJ싆.JLaR@ !haUCH4"ڿԾ!o.|~~.lA' 7δIpĚ./R_Z'qHH0` p~(Hf ') Hߎkz4Y`w-@*N'b5e5v,7o\CUNy=b크YA2yz=vM?:\lQX f9}Fѳ*,"2vr 5"nd%K%V\Q10+)}?((ao2_[Ԋ΄9 h'Ffd-3QޤOѹ|JطR3JI^Ġe/S , ĝ_Vw4ѺSr2t{U҇BEkGa|Ywo9ml,vE@FksRpNF3[X[QwIr73Z:jc6ؗ0$bwLK|% {ˢg**X8y}{^yuWEdhQ:kTQIa ~ Jk7[ŵ`w V3zWL Iv|^xKpq莑ӹV7-rkrޣ&= ?v7lߞ Ltjg%+*lD۾F=%rFDlq8JvI1GI)Y %cX[<+u.1/@Jh}ʄtx :D␚:* nd-b 4iMzs#k5iAfA>PnhG2{қ:FOl"j qKq,o߻_l!_A3+ >T1*<#BMkeeVE<ҞQ3|u63eLGPnY gljS:I brx2tɉ4/Z+Օ~%a>Cx@{?Hh5S38{tYئ”DmXGF#.LJw"=j(e|ւ۟$pg鱨?zaI/,w:(#\tt̛լ, SϯOA, j0 ^`icJ$2qFB-a0NH7.n!`r3ܠ(kN_|\W:7J\9#o}ӳ[xf2i_IuZ~uV ޡlh ,G?oٮz0O^awMG/\[Wt"wjADu݂BV n.6teh`/Muv%.?.L^c߼Q9DfPh;~++{)EQ;1j@Z2v( }j;jLiha e׀C[efXc}yGC]9 ݇{z^2H^|FvRvS썛oPoإ9cݫ1x*чI%wᴼb1isA+5Z5׍+q7Fe =?1ΌLA7I%SR&X6玶;\nr0L p(c`hоE r_.tlV1x>+G[u~y⧀Of{ޓ9 u7{Eyv>_]0]I0*eYkGZXo4 59^ôŦvزK/noOjfgK̷ ^k1+B S_=p]O'˥}'( jZ'9Dz~{,cDa?Oo@@sgaK 6WÐkj~EN4Vi K,wMʦ,BQaf : 1_̐ߢvTrٿw{4[S%ӤypD?gk.ؿQ[(VuCo1QjhqZت`ALOPN Ȼq7i֊z#WO5oPQ攉*?0Ѡ|Z,\rFFs;jVŻabvH~ * HX,3 eυj^rg4%#uôKs*f3f- ) դ(0bO/-iuFt]YL0sy*wPS#%pm+,B ) ɢ;? pjfG/J`d̪#yB)8fOx%#bnvݱgEbE?oga+d6Ԃi!stYzXԈBy?ak5! w!)~ے vlLm5G<|~ haq1Z#TוCkX"Q<˲"%Ěh dڏ%*ҋ <>۸4Wl-sśC2 ZP͏c~ oUhk+sy'9x ? KêLq"{%TK 1A9qJ( CiC{LkzD5l) bQ5 M סӈ,Tb)*f|40C :vW$!-Yۏez"MK7-!,,` `4u D]?:zcaф5kSVֿ-#Ef7dJG@F&!ѠN" o /ڮYW%V"_NH.݃0 EQ?hС~ٍu_!lNBf_k's:Oc,5BMSӦڏ>("N#L^O͒(J?:c|zl7LĴC7Tc{QaQzNCFZDqj"_n`3oU]梯I= ̐;D<㊪団+ \5J K:J 5O7Mopr4"=fhI: k) ׾of F-`q.R^oojΦBp;Wc&]Jf6>{<kd%cLq.W`1n4a-Ev ma롄n, &xW*ˆjoK65ٴ EGw:9,pG4}=惗i.)gR|3ʨZ4rQQ~ HN 'sQS-a&`dFVNbZ}/XvvLϼn*܇⍛E7E.r7Es}Afq&o+w𒜣mwL.ИuO{Iʾ_q7MĬO"bM Z*V,m &@gLyxB~h1cwQš<ھFuk~V'#$c #fpy~Ď ]y6hQ2G9BA0ƛ2Z Mޒ(p,G*~m{m3|FܘސEߴ;{p_&舗lZpU:48`t˔W7z%Do"XRݍJӿ&2CD"mpx:s,GdC S~ni<" lUBN .v=d~07[QP([0<(&L1e /./Z8eI" #G'eGb?aLc<n(LϺX $ή9k I7\@ kqz `eZ'RPWS~1s*b ~'$zrZ擺Rsl=r=ssWb/)'G͕dϲ S0q/FyѵfE5j -Ђ8% Ax䉾`u3S!qk֪ʧ[dj_tPHj6jpۇC>)`7;IɎ:v$ -u'Yj][M?FZ p2cum+$o[<%6k8P0WVu÷,ޚur'`UJ3ҙ%%A_ۀ{V {ЏDkkfLDnK!ӂ@3'"̫ >;3p^z\nc;5Y+&ӺĀ. 4P3w F$=Ah$J*y>O*h'CV]w5-rl&oKN Á{0qjay,7sN\NWzWjSM4/vveYΆ>5VZ(Q))iU7'd?!8Q0ڛ՗Z~ሀ0VϚImR'cՇP(y(~oG3Gpҏ< p08 AP9$m$#dRABeESF_=SZP|4W~UفDCsY7K/])' :Mn:2c/}8%1xDnL{k@ 9Wv%=M\N M厺$Gas㚯YM|6y?\?!}Z6%I{m.%Q11;6iaC!(n9W!4Šѝ_j?/ed^[Z-s n$sJ ˞ZDsujK;ͭ,:Wj33aRbq\w]W& :0g:@C5PSuw+>h'' @FS~n@3EO)0#M%@yӟ( CTh"Ed CFZ(?J2lQZyaAl:MoDF E`DgT)$WO'Y@}׮2΃ۥpVQZ,'X29KhHGO:tHGS2 ј)_[f?+>@4/Ki#Y3Ϧ4|Pwd@洶,1s@ݥԯ{ꭐ%Mj {U l;L p ^;nM'cQ-Ĵ:bA܂_^5{יuWBj&9l,%qsَXf!ʮ7N8i mah$Y1DRZ!&(sn R~D`(l2VB cqֽc7'm]|#UGK227w3-VYhy`vABHH ã~|K M3+_q}Gn76ZljPm? #^h33/Uxv3=S'w۴q,Xמ2%55%ѕaBl=1ǘ/pL& ̨޼A-;t)wG.Ӑ:~;:1EK5h{r٭<*+XZAz/.yoBpxX88HA{@sGHtؚFkҷ[,y]FNJdfލq#C5]S ްž$`fZf1tuHpZ1EVRCِ֫E{, _Z wc=I,ÍDT:yLKt]kNe]`@r]?b $\Qo0(\?S~@R=k¦|״(YLpd=&Rv![; rR{a,dgU<.$պ]'miZ7QpbTRݸlK"c(L-eȊM8YE9V\ظtW)((E 2-b#γ Jؘ#j! EƱ|~PLi!Gi}4-TȭD^g ȶ1*b:ȻW@wTQEvC_AUtaY"6|akG&Lf䎢g=-ڹ?Y=NԾH#WC )i@.\^h~`\Rښ: _Y+X>$-M3.6Yl3d 05g _1`ȸxe!9rԝ^4 ?RNyRNhYm#-&%{I@/$~R\fhG쵾$KY2'ox*]lt\+|?@n|Ҩj#WN[EmӠjf/ >9'm1_ВdbFg DճlzL# k"<{z`BhOy?x.H< Q)<ku+4CyՍ6?KIgӌJ6; 5Xg^/vls~ea-V ʶ7}O^o~)jY$z@QBո?_ctJlp˗υo|u:ZVqimJch-w8W R$kx=mB 8'|_0Jѫ9ݳܚط]o42XMmљQwW->TLFԳ@YF19s-1,nܥ˪SHu`a!WNaJ`5A60/4銇⪛Sݛj`-;uLGG[OKK{{}b)h R2k4c 'EtZuSt~X=)tөe'R*:K|OC[w#&-$7!"X C4Б㦌a9hwD謶{AJ W}|l09k+&J .hu&VKQRT$e)ƃ(n;:dyZMr\5W\J R P¥,=[K~J!UI|S`Q|U4KXQUr$)i lU0ƭ^"}ک:qݽ ,=FW+%H!А Rͪ*B5h-BQgrH<5\cE*J5 >^sK-\k1 jO3X.=WƠlQNrbGߋi0=RTbL+230"g[8wJGC m^͌BqpE-% NQ% H,ڒlPܐ2,杮i¦DbȘ 0xCT"~6B0EJ7RH0͈&gmvFL7F'%eDFReMG @3hHM ;O?sLekI?؅6T9s\`5##ΰ%XWHE(8{xJ0h@Uc^2?hn&-"->~v5RĨfP<F%vnBh |Zɮ(jhXξ -OH浗v"P #dObA $ "4 ?*iϞLYvྚlÅ݋Gke_#Dnf~Wtt%EskVȳwUo]~i6bͿJBT>>fLcJwƧ!&T@ ?w:CL?!^뎨 pz؂v6@ⶎ,3Zv8i#tϛ ݸ)vf1Ipt+g$ǔ\j(Es eѳOfݸ 9-НxR}YOhCv\:LouM40yh!Tqq:o2j\bńjyj#Gae#?<(DFn돰 - 2@MSgm&e|\-ypgM+Iסh7dКOݽo5&x  %p}5%\1"hB ?@`44v\Q1_jsfdXubP0xZء8I9BW, ʷete#b -F1`}+k ZcVDn~3wFCb*@ߨF =XJ(kԀi 3W8{]jWyMS*`!UQ+$U 0v>SNe]GTfndna΢ҽշ䝟+p?/=P3A{QAZ՞:dȐCBO s-֎YI [P^OG ."kK`O(~!1 W.i8PPqk[kJzb̠ [},#L'JCJ;.<-kn~ފ"#0$K, z07Տ+" Lti4\4|rݻHvМWk(悐 &(sϜ0ǯgv}Ys~)(p)B4,9}zSYPuj8+[@.)fD3̠w.Tzc j4LDf2'rwLnR뀄Ð & =- Yf,ϟ>\EJ|/uqMBI6x|s.)#w b CJ˫b E_q7R3/Z? n%i82'oATabR+OY0 [ #;q{t80HOg/ "ռR?<իoX/U;$菟v{SXW:S[ s@d0xO&_@\lo'kfRоnVO&:Aci|4)Jwa : k[ ŭ,+h6ғ7&:VG^#oZw6J"|ۅw<#`9kS;E#PT)8&Ef jnj\Kܒ.m*OHaS˘$tl0#^95$x.=hv~kg}  4+^z# s&T Je>Xg(&!{z t DߺG\<L5?&ֿW믿믿믿믿믿믿x31030HN6NJKKI30O4M5H5KKR)&IiF@A. x@k^Xͳ HwA RH/BHHBtDHS4)DlTE@%9sy[~3;3;;8!( 61)IBJ\RKLBZFFFZ\JJKTLLJZC?,V@,{(7?47ܘS<,m4^GF^^0%VГz4u{8'1vGe^Wn :BTMˣ}Qr%$5nmix89ۂe*pzz%T;rKީXK&Mi>vhlaȧ~7n` V? 3SzW)-{bԟI:(7㌵W\"Y89i͙ek)_W(W֎,VI̭/-pEܢ0HtڝuHŸ60S%R):z)/o] ibzm)Vy*W`H~8̭fpw`ݕײڇkڃ|Ԫ&Zùž ~dwKƚL؊Z-0 }mWX_2oHLhS\LB5oy[sBX1XKtZEDzG|^3#~4_n7ʇǝcJt KDD^KJPQUn^H`0Q󬉅T;TEk;Dkydw!SkuXzhܙ2=bW415 FjH5gR9(ʑ~lOKȂ2Dw"݊&ydiJޢRuSEe_y=ᛛކ+T aF;p3}%,uXi\iOE5efrXK\r{-+s i*45`l)q7N:?-\LcdnߛVטE8D޴4N ? %-iDuMh}Apžj|@=8y{'$ӗ;_ L)ΘP/PSP(7Xڹ+BT'D.5+V, \6]?|A71pqLwI UBpNYzf+J <]دk,(_HHʣsJ]O,W:>l-,Kk/^Q6x;~PsPi&v|u"@G 6wZ_Kz/X.\OO\eI9XqҽȎ^cBF6}3E)oN8?To #$ѥ!g1R$sm0IB5$Ak[k0ZߙLu צcX}JUۑϋq`+9;o:%BFH!|^10u<м_!HETUۤ,踄b eOjDx3Tr[O\a -p{ [p{'b4/I}v`.?c؉F\2,{zmW ' Q^=Duw&,3(SMWd m\^rj/nDq @qI_Νxmsu'Y}1iBs辯AuDa:YnP l"[l~.7Jbdh[ծ0eQE Rik6Y]3v<|LwQҋRPk=޵[@S÷wС[O:Q ((bޕ 2=VG(s\ LdgIN&wOI|贚,Y^~c-ّgϽ8;.NU3^]I{vX|\xu2?Qi!ml{ D4[N5t[4{Xg7suڧ;ݦf.\6 _~dD{&x)C`vh>ۺb}D׏yF뢄 [+˟{=N0] jRNy7b zx5kF_ᮟ8E&+dnԒ"Rcg c_]eaKz?>)~XKU3GcJ;VN}L+~Ag;f;f45Fn8tte8JlcE)dsO7(ZT8O` v|\OIrSiWy˞pwYliuz`*FU/W J_\}ǽR:JYTRm/ێ!w4*wÌThhㇿ=ۧ1u++å#&v-V4-]QmUX5& ;~3un x,Eu+C.\F*xlTX 5Ii,lqU5d9*bV~ۉ}6YjXx]bR}9s(m,Šsl l%FfCt+HT䌧#_ 0Y {N6]b.=~Wؘ>=TmNXhѣy*HR,t}{< eXPuw{Y ۻv]\UhIzQ}/ֹd)( (ɚ}2˞ήJdr O>{c#!piғ<%wkZ֊JlSt^&ϭy=\!1'݌d:˃ddF(}z>/\ЩWAU0Ls`܍W@kkM9~a^V# bD$1.lIeEXx0yl b fC͟ 5o%}Sx0{@H'Ddzc«l#OefpG֥T!#Z&sjf5<#XpNԉYt^rXT0[]j3-=>S9m*Y:݋97xqEgL6/AY|iMlE2̱Ĝ'&'⃢*s/:" zU&ìmO1N\$$tG )u)<"v+o^wIvy3DvP|3/%2}Yիe;x.[/L~03*j Qnz3I{Bk^ ru>mr!2hGaEv^`vHh\X~u@\bsdWqo,لsw?\t萛R0pA+l [ê*n^#fjx%#Qq!gE{rL w8¹\ˠ=^ukXE#Pie\`Wp\եEQ%&GW<&ZfLi۱s=_02>6S˅U9jοz܅e2{"S/oA^AR!7 DD}e&j8ÓYAlţ`v%e%g^HDQܷ_,06 z>#\lv*n2cC,Z%F*5,̑r w!_0ϑQx&Zc6 S'Y , I*Ŕ3qitܭ&Kزu3͹ P!?/;c=!5,ԯ#U*A'bav3 &,dɪlWE}u3O8>|Mfn=RYt%0X7L8@*8}b>π|-eeDzqiJn{ώ G)Iz?֨~Rp> y2R$6{w!'E{kTY4X'>d 瘓_wBۡS`86k|!+{ϾZ~b(ca DYGtL/Ze׏)uIԾxITD^L?w5C"j TY'{Xnhw{},UfԷ7}1G\$atd(-lA9unno3AԢޛ>-Hmeq@R80>}v)B]0LRCXPIfQ|v%V:c%V_mVy4EnrXTdZ]3u׆Z;zK.=xgҹI*-8V(")t5(_ޮ%vC[u, ʅܔyq6:Cjdhnʼx?%/~ɳL0X [ܖe_#RY>KN}v|r72+(M\x^ 70 GziBu"]?^Da8RTvEid: cD?r$yÑip S{nmc9Ww JNBHkyc<ה43RO%:UY -}QjrBM(DWKK'g9/J=bSn~R&`8VL}"/ۆJiϮn>/g`"רvlS}:|γH4êP̋PkIQw;c(O=Wk̗T%J?ܤڨTycԡ-y1DtPc0/s}kX!_f I&ǡ.&#_{M%Bq\rp~nr9 ;:{?ϜOdƥ($?"xs~SN_uaIB 9ԡ:V8 y f>S1 t}Q`aS~V4@ICO]5g=tVQ~|FeJRY}R o\3΀"iȐ:B9_/Þ@:ɺѺ,!DqZ' 䔴ɘ5C]_}%7 Ǚ?\F?jRi<2E(wFnbqקڂSJSl5/.98eZ_PPծp(&Ea3e~ (Jd^M<3ДpZ۫tcSkZ#gɮJ%Gk"?%mxpZӥ1NDbS̩Q$\d?Ѿ$aLȳD]Beil_K:?^Z70{SɃ* %ϱ?np#+W!"řH9f0:U_RaJ!, K>dCb́L RGe 3t[LޫWVBȋ~v1uͺ㾰Dނoys˭T(jt/煒WC@HMSrEXC2J&qp,Y3Dl*WT~AH[poJdBؾ!ٿ7nNEW6'cgW %X|Ϊ4$Sw|a2Sq|k)5ZBPJp N~{Y','Cãʸk^JLFGO~Cwa^zL=;7(~WOs;n+\7+V}6XoD2Կ+e"8ܒs_rx]q]ȱ|$O)MbK/m8U6Zl.42oE-[?tULb(l59@'ϴ6J2^:欎~[bpwFuʝQ \˵r~Y%&Yœt&49)B"74:7Rtݍk)WRŞ*V>ǧؘ_{_֌3|jW|gzc ~uf\w U@et冒إ 3ʁ="o Wg U^YcyE؎+8&oΞE el0zӮ.ܽht)n=ɝ|([ I{ˣDH䩃zyܪT|R9qU WF4Br-7Ϳȓ$ÐӇ{I)Kl#:9V_iX}QFDu bX>Fo=M\2Yoj4b~}r0+Cŧ^SUpIsH93-VUP.GnF|K@~<@{Uȇވg)S|\2ePTO4{-+-p-SROuR/Hyͽt;,4Dl,(Chz}=m &ʁo"Cj x87 *d<؝\aܻٝpJFlJ j@C^a5L^Ú5܉h/6Mu,Q} yN=[2g!YN+ {BLMEoD4Ek=z9ytd7Z9cXo0DѺ-ԤHVm#Y3}N1L)Z 4e  yBX"}N9:'VcoTY=\8GsNz\3+m[K¡ ,wO3s"x_^SA\8Uch͕!%`G!aSTpGHՃb+E6 Zq>2 \f үIiiAJ9w?(HQMS夛ͮ$P浥+3_XʏկaK^\J]ky-`p{yhFGSJҡtMKwTc$GSsoxӷ}4czb9eҤxydzyH+1΄HJek?(dNz+eIL_'m!oM5}úSӂ}p7fs9Z쉫ϠGFzֵ "w3Z´ynü!;ˀ1ICDv* P!yk骍CՙNs3x=%'"|!+}IBbס(:pwIJ%eՏBkh4NRi 5u& x2.RTgAÑl|ḻ_ ,.~tKtV*܉sbi7J uM2]p=~Z(ccA&FG u[]Au^4F>tV8/;dSQ$g!al$oe {66 TPIAvEzK0`ׇC8WwmPlخeg?ϼcFOV+>[IY-ą?A /-7.PaKqߣ4oGمrH'uY3IJ9T5ü[z}"$Zr8c9%Sz39`6[o=HO=upv1ַ6I؈Խvʥ6T6AC0?JR }_]@h_:br.< 2֗!5d4=3 blx7|y1Z.͝8$TE;X)-rXWfK@4-AiltzCYʦfA]olw6q2rEsi=dϵ%5Y)̊r\@|h.D@TfpD*8*gjț 㚳 \ÃxpiRIwS( jәΝh_MtgZFbe3>k3*5/RVrYu'Y_̐ԩuwxv-WkνQ# w<4 mQXE[1}fʯF ,-ڵ'WztY^&ͩ<%G92}Q>a)-J˼b:فF|R4J<+(m41{”ɪ$LO3ͼ}id20ۮb~w= _z^&˷jQ \!^FMȰ1(:U%#+-7þ:PjAfxޚ8ƃ }Kݫ:Ԯbg3t_=KfÒF%d:wޢ*0PԝDB)Da/Cݢ$Ew'/:ץf3G|13݋pc)(ʝ|~aW؆,zBqd+5[hP)x߄{;_FqyC+ L]*{@qq1$D2?6+vE- ETIMP_^Vl MM 5 RX=l*2| >$ә7igV?vn@UƏ FeXXΟzl,г GFG~b>Bϟ)7v="RlvKjT%L]o] tIԊPgOaX( 1nLWk32 ?vtk#k7E,u9ـXD'8fy"CeuZyvQJ_Z"O%7,Ϲ7=C%K4fҵ<=[˙3a(p*G_ѥ<_bl};zAGλƟcm~h#3 *T- >[s N(}i8h\#àBKy-U7nmzNuȹ}gi&1DOs}!]vt){8mD]ybRr֡wGJL8'"Ք y0&]"`SFÍǣ/ @ǻuN^@,ʿW=/J/xRI6r\. m*+} $wTގƊ^+&hF5S:pfYpZ芭 iJxEYŨٻoy=8*R[}BTH+^lwQ#n^\@O/E4gK3@Angۊ̞-t\t3KW41o_vd2m:0+JjquQY %pc xؗa"_eȰO [խաE%/2Y:{s^R/*aG*ǣkw!tKI#=}肨/GW$!*:HȂdeAr q 11 1qI,HFFBAQ $IJ%@`G9YIIikM8d1ɽ__I!|H0 uB`7T ժ t;@@7"=uD@ p I`PG'DdNx8@"30$ S M LB0'zft @w( B`e?lwmRG D:6WLAg0bpFR$ЎPwp= qqrF;h+0g G`(ZLGiNp7( U]}/a0.htH6^ݫf~Ew}&)0 qÀ]AG&諒pe +b qAm$r 1~kљ7u(5|kV RG[|ob;0?0poI 1|{mrv11+ҟm3t])D?t/=V[i -3әN:]ؽ|kފyLjA+7Ў ^e~#^-D@?Џ-; 1#vtJ}' /߳Ĥd{ `(!jA zm<@r~poA[>\=_}ut |ahG7n>W~ǽM&7z&QIaL=mE[Wߘ(f-xo#-a ?kϮ]ud?3=&mk C]H[>yB>@{{ W څIDc5DxS L]S1¬Z-AE}cxkfR=A]xW.PWVGǟпM 83 Cv/֮Q0plsx/Dئ+$o'2x.|%4K Boᅲ@zw `Or @s=nG{ z8OӮ1. hy? D\>05#F( =a^HnOD5 .hQ.]ܕJpkM \v,Fc˪"Vܾ[gބma.P{-צػ]@! 8_U[3k/]A;6P刎/Un>^=hj-B{ yBHȖ`&=ߩNRs[「YE^=w3#?g#?N-LN:/ "7AM fS!F[p̯mP@{ $ea˯ m=:?oݏ}ב; # `&W.O{ۈ=u%B8@ "}n8 bwqxrx_wwOoo{m=g{&BlFDRȯA jK=n?D0{l vr~@C]4bl;< tĬ(N{1މn݋\S/D~Zf~N7{V޺bpU/f-{uyfB~Rp%fz怱'ܩ#`o-=-E(hCa01:imΡ@n5舋KԽEP0} 8~g_>b~6?{5!A8 =w2b͛p\1G͠o`w Oq![bq08pq@jיiC66.yr\m (7E>w卑#6mm>j?<0Yg[H6}gG?(@\Ѝ[[T wf0>Tl@`o0hsc+[O=j^{i<@tog;Ay9Pm[{; ?໗%̈h@vMM/I:ZLj6ksCV*g sKmoKm ;p@ ޷j# G]ፎonb|ilA6ٰst|˸z|ˠ2gvj2`[ STD"(e A;0~D&N r 17Q?)tuo}k:H]UMH Q;b7Ovtqd ab١r12*;-b;R{0e. tGQ"wg##;oĎaw:uD;1U1wG@3{GZ槿{N@䎵Q;m2;fR^;`{֎]v;z#?#c;쌬836#Nr0z1qjU3F$=UL5u+[[GM@(zA;v e7tN 17'xwX`s? ϷoZH}ΈA%=5J Ƙ9A\G{ЌP( Fog&.Qqvj]BtV?"?e &/z FGHIbFb$r8u`CIA|9R8wK'>1w㺣p|,!\k)餾0OC59c=u>םi^Lp+`7_Q6V}}{H2Ke+OfOtպm:x.|ᕏ WRI=snGL{̺-zbaE$4sǜG &qfG1?ڿJ(8?ǟ濨/_LR\D87\>2X8i_.gegޟvvFzGjfaomhԱ D 1cw8$g*p:9Ү/pکsE?~"3|>8ǏkjVT^C֩džAٗ]CӾg} %CU@`c-P-Ls0d EbBO@vL$<G]k(0wy`_8OCuYc)#PS {J>o|:M&N5p8 Rk@n[%{^hnvܝ(+sh|YtѴG [dvkswⓜ\kWbՋn;ZD#Y;S#f}9wW}Hbypi^_@qu'|nk9׭1BD7DzKN{Ҫˌ8 y_ǒDJ.F?P!%%C!,(C`gd/*`yZJոɽ՘O;&-!47wqd' }bU@=K97=!CYt0W巼7&<#=5+<\ y)1>wHo=:xy1|/; d[3y}fsb) 6p:J 9dqĜۡ!]ޓ-UPfLAnz.Ľ/5OI's}c65 3rLSpl jR .QvպoQ ?vjr`$l.eSyKYFXga68*Ǥ;QF \' sT;)`1ޖQdnz#(Srf9=g XKw}MYDK">h}[NUގ*80uLD{d^/цI_&:p4սy)7iTHE"@t507޵Xщi +q]Tx9/_TϼM:[|GĒiE,n vJ3U&m7?} oڽ؋&ɣ-5O~Wc.dڶ`-͌u ٯc}7>(f(S,K{4عС ĉW.fkbrTq=ΧO9bLdY/`q.e˫pWF6dEJ;oR4{S͑ʑff+7\A>Զ %c\/FG#'bم'/+p+RYڝ*X7M]âx56jPLQ4p5eOK'Y %$WǪ kRƩ<hRs)CT (x^L%$x>K-'޺HU]c|ͼV32/T8 Dq?:TVp=b - VB ~ŋt^.6[K| o$I%&*AKT{RJX[A-Ҭr$'ĥ(bip;- 0Od!J^,v̛"?[ Kd&n_1S ^pO5IhI@۔< V7ȇ٤)S/oj,gMGWhSFYH\j`l¿|'9$1\cV#SKCIJyJt}K;㧒5؅U3J-lpOjF/οS!d}KU,,170hn${|.iy_2J|ǐJyVdR'&A.C:ocӗt G^QQ6T2Q@T%BG,A .eΨGJ@Aqc=R+~uZð¨uYY1Sk|ax _1.f-e=d!p]6oYq-O?vlqE;w*?nmC3ZoCRT 1&ܚCo2%KCİ|U u=mᐻtMkCԝm.Ozv֘IiȎfSٓvu],x{G[DH3O 'i(y(sZb5^Vw*Ep.I&tTPz ժ bgkh#&4 0l}2OJ5J4M]Aw< d8݀ܟQ8JoLoх'E"1DNA3+ck~nc\ Y*`f59T^KP]5@2;А֋UĒ]LۂCK=M*eӺm`2sJū4C;9 ufbi(/9]i|]pOnuR.DD^q/2G 1!p㯼7Jz[IFY&#Eؽs+,g6ͼۏ^n'F3 KD0˅'\u$¡2=g7 Y~kB jБYlVs{V7\!奈Y՛Rwc8aϳ& ߼qfDW}(9GyղAe! ʞaL:27ƢxyџX'SG]}u}l=Vx! Z-gƵ8Cߖt $nj|]jOEr3{ H S5γ\Xŵf7WϖfWĕwruN=b][# a6FqY'&!Mc[f_(R# ,^k Al)z*JTU `ŅyMdI6^sVԨAqn<ɲp[bb&/^Q%1]L*&}R:p+ۗ' :?kx- +bȱb8J㠐ڧ4>gQ&Zt u'PF@Yc=AoJخDzR]J} $F-k џ+d g}5u"5xZ>N=/{^̚7I|CbwY4Q2rBUDMXTNPnў^-q;;hK'J5 =!(tgeQvebnjMZ !_ĿRYgKQоA2#M dU`9cf7ܯ1s f>TDY-t=w S -? Vkz\/'}GA ܁:c V{C])RwhV0.2`tR3KLǍGƔM4J8NJ)}%2u3q05O Ƥnr$*Xhq\ӊ]s%ŠreԗGN{uctc}C卛LΜHl ҡ*TpXao 3WU("lJK rb3E;?&t}Z5B=vi˧˒!CqyN_+;X0oL\Aro?YEL)Wu??Ʃa\2qABdv.+ 9g0[Q-GW#Ʈ 78ٸ7[_\?WG@)d~87UXX} Nfv,j9~ӵst~OM4 DkB?19͓Tݨv%"YS~clط+Rw7Éj\03`H `~ " hh(3(fd+Kuθ./fF9᲎a\+Cw᭟kpoṇF7<[o#1xsaem }~Ew]\([=}j:C/}Q ~.~W~ǽZK`m)< xDYV jH/ɜKx9:QTS-2԰u65v>"݄S7`.l,wϬyܠu%^mA5܀qJZnɾQ_I3pN,O֧4Ȃ]ʽ'} XPJ`$KVV =DV)U%Jh[tϴ'NG\NTʽğ,4w’հ _COs/.X=6xkE12\u 1 Ǝ6<]8ʃDTk-!/'9v}U2Lr*A<x'm3aWHܠrqJItnj#b<}9; JoҒ7Z:AHvٹ]n'z&Aj"Kx)@Ι^\ .WXߜ&3*?/ck˶8<`]i/=B74d.̲W+!ˎD "]5kt{TC}L; Hzdtޫ4jW5rr+Ηs~R}}SӕR*pc"_ۻ%EݽAb%|)(x>8mV(LC#B,W ,uGؼnpq>W.Ф7 Ɖfc%3FovR=hM'7Ui05f%{=k8qզiWVv`@h.^BEjl҉v.{_vsmMwd,G`NpST-ZGW}ui㓋[8+b"bdb/hP ZhiY:31% f T{j N#V!M]Ҡ ĸ\)X' Wx\I#NoH%VxR 0m-.bݛ)ʝX7KNڑ Ms*_}p- kN| 4ӼC*hªC(\!zZ(n/O)Pǚu g'jd6.}IUG'Rs='eM%P\s0%rqpcQ$k^{'hWvn(T(Ӎ-E F|tUcD&[QOrn˺71]fv59ahM`nE.| ݋#HH5-w$pt%Z~VE87YIӔtjnw=a=:{Q??ϕ A+^G h4*|s^P>U GQi soBž";aϪJ5ja:0+SdQdFL\[j`_[(zAXGfiq<?I'Y/&p ÛxOMj|LnYdEbg| v4tLA>sI vj4U3yhc I$?T(ZhϡM|ո k=S8ƏBCY W!d,l0B g`'ZHjTD+_JR#soEPkVWd4(yH:Hwo/Ntuz ;6VjN6kxA34_ۻ6z=MúbJlBTCiEրE!e3;yz"N7BS|v]`2C%pw3=Ϋ=Sp']l+Zhm%Jg ]+Q;}ڰmF9oL|K&\˽_qA֜ UZ[C&K Q b6S e_򓱃L@;TX4HI!2Ֆ\PUuSͶ'';U,H;UʁRX4^>ͻ"+vOo/ d؅@0un̿3w=ݺ`:dYmTmDB5Ttrwohֲ ;u0G[W )Qt~ھ6,>{s׾[NcCN>ec=ʾt7vyKd <7>A)d#ia-ԌšHD;Z|Ma1WDC'gGq%Gko@oH"2~9_ѿkn,2[{[BA0%m[O%懆q/׷ye}\3Og*^W)Q抜IxXT_VR::bmrN2񧱰 TNWzɵ3I $ 3#BjcK0/FV$t|?+@\(ݻ[dcb&*_CnG~!( |/!> uPdP2P֖1ǡ./"X KU_|kMZ "zcyB%5,t񓦐_%7|RB`=E vTEH˫ٹQvLu2t2r|/0dե(jRρ颍WlqHv4+kDHyuK]ZY2dL Zs>8(v7Y$S^hu|MGⴙ'[ ok k;z]'k̕\J>sL§)TÖ~.RYa2aY~)ڏDIB^zKx V5F4Mй;.%9O~G7x|([>ͱtgZya:n]2?|`>QL,Osk<}T- =^@\-J],brIwr΅R1{H>/%gMi[Qɹyϵ-o>v4; 2 Cmѽxh 5դ.zQ ie]R,vjwФv? 1g^ט/SoGG/6ȋ^Ի8zS6=6%334(Xq&˞ss` ::nY>x ѣA_bfM L[)Ƞ@<((F9F`j9d&{,ޮf.K3mt xC+7|{Uj kC=>7 Iʔxkxҋ{A*ӵT޽AAOݗDu =S 0˻cΥހJ6JƮ'no# Ű K>MtO”ls;SМ o[}"*}wqS_F 4ygq/-Z&u}.g!Oy`*d,A8};3Zvuu/ U1=[CXH/~MPh1Q~W~iz^]-Lw &`å7+!m9e>I%墐O(э,"#ʗzm z|ۯudzy_Ï_s5*m["0SiE{ )qa n;t\2sH|*/kϕjgx >͢۱\1Ic[aQg1{P[\(+=X# o@ߵ-nb6?@>F5Qw9K)</%FfߺļRr5|`DBۇ YRX{{رe/sg,YBVrVhcZpD+kmKv-q}yAEO嗆"Y%nKطncȍ"ީC|Vņ)ȿ,F++>kՑk1YoNZnJJP- ,a#QF5~1 .Z5'[UTžVE=8_Ys,-g]q1C$fZļ԰;D.o$H>콾Y܎' ǥ!SEէ>*hE ڭUr>tEv,.Q F%b8/l|y.Gk96#]2/#"w~(LЫ>Zˉ)|]`,ImzRO*%`j01#n=:uyu'7#1i k'(>x}HH ZoS'Pfx@ 9ՐWF0^A>nA0D"K\I.a݊{OG5D~)^ncaz=ư*1q*A7J{h#=~Q(Lݛ<*4șk^)rҭ fn\Ic}Λ>ha 6 aa FVi_ceL$-u?zzr(C̼sRᗶ*]lZ=TN$*~XNQ)#j='N{Yxaޞ/(eHL͚fB8vWi֣oks R~Wd7mn`@ޯ]\`sg3ƫDlDZ-n*0þq^/>W4nn9C>UwRƞa+s~+2>=(4E yl[ ~BEq _¶>C%̹9emSpcL)%{kct'Kq,OnMw?.{] mK^6z$tmѨɱZ;p+2R6Rw' Pv~Ť3r[oCmmcp/- eZŖHc/,}`gCTg[jk8q%-`/r҇E.]۹.$Iry)ˊxL+sCAT χNj"(sxcTx ٽ@9aGӼZ.xoN#<ؽs#褕]^WX{le#k.7T79N?rM=y-ި0d݀~ ŅmO]Ɉ@ _ ̜R~qOϸ:CPs|ы\Iֺy5khBye^ZN ʛW} ]}cNO^:6w b6#:|V)_I-}?ODwslO~KZƝ"Ұۚd 2p"'B4=Z BW|ͬ60Ú=5Hv+!YZ3 g`'ҡjjZqj|%wƢKEi&:mk=D}fK4ghS{ȷ}Pܻz1Ehdk͢zST4΋ [{=t#V= *Բ,YooDHqi6f+{ lYRrQT"V',>lETv;3ݻ4Syjt~E,kjy2~5&v4Aq{!O(=礵=L~l e!ad05!>8N'FFKSC-=u@3Sa4g2LPdDP:: K] ~MiQs){ 4Q{ojf!)tRȾD֥5Ӄ:ߡ@`}(d[f'agNV߈41?l@`o%fb7Vn?27Z0R< :;7-u 9 Vc 27;0)  4S?%ɾ<&T>!:fIMntL)gfK)̾B- pPǖ8@SK#kzz~ Ư|H?ƭmܿ~x1Л鞜GJ߾,19QOF_kE<cN`mJhCJAWKPLsy޾K8$i'WG!c/;ZAt@fAGqe +bo 2MbC%3 Goù|?[?GY(Faaa07 Of~;A 94V𔻝mlKo ťgL|8N@ $?Q:}=Vlujh:*\ 5< uX?24[1X@t~UlK'BG h͟Nt4*@(^Կg M g}3M-N7kn @ zpp" :dm u8_==< M3}olX b8>ńdškEl ÙqB=ַҁ&6+`CSc0p? Pp:SS h.gu{pp6mhup<"Q;ߪOd4Zf$13oᅲ@z @~_q'=ݛ[@Ӵo m}hhs=Z*z[ f!z@`PGw^P~@3'"?, PdWIjuD;I4!n'zpKp=ȝIpwvbs3CS{Cђ{צœ8]ApHPgi'΃mJo?:T/ɓo[P s~P:Xk[B ^FB,`С@'=ߩ{R]Kz:b;5gGF851~Ztր}S3R\T`9A#_Zpj}2!~,puS_r]'ncouNP-4o=a_, A _G_q|N2>y{xxI|r9|&攌';9Oy7ѽFGMh&8߉ޥU_ˇ'߃;oCN Fqœs( P_`Io|(~>`#1h017߆jz'zpz/sOi;Pܟ ~\@4gP@[K ىۼoë,S(WgbN9T([/Qg&'䠨w1ӅڠkbOכ[~O!@ A hjfeFvI5ߦbaaW9CU(]t0g)vI~?JwLcahٟ&fڣpw\x1o YUq(P3$<ր9\,N 3757ęi!xC:~9c1iB6K &7@iYP a<[#֘6?:_ ~+Ovϣ=(h9,i?( u nA}8<76@>yzA б0tEۿw?h;ٻ~?M6ҿk0m˳c!pq)@K0{m@Õ`2Ӈ΋A `r/G_G/m뷺}dtq$`n~޷jd/Q~>z[OK/rz2:2Ɩ2o} tLea-gbz\E:hc1#^؟:S|Q%.%664?Tl w,w1Uobs[K9(xptɱ0@Hc&`1 4Ed9 ֿr2c8fopl!66ne.1鱢F?8ɱ`le,81Xj( )}lHu1cwj37]ֆAɀ1ǖ>kjp~;?"Bv<6Ӿz|;tW&`}ᘧ1x?11>lQW@99=~5L]ѱ#Yǎ?]2w&-ݷ{ ^ t|? Ϸ_ZHu3ΈuK{k~>sjC3ЛA GYg_.!qڃN@@O\!X['?{dMӿo7Mӿo7<OTԹxKL036366LLJ05OHI4O644I6O5 $Zp &x}[K@WWRLj_> "VS+tM&dWv7jwSgs͍T]M˥H .NXP* < Nz<\MNǣ~?bI0Nc̚8?%J93V˱v8FaUdYrNzR+nKHtcRU|c[Mɔ.iS/^B/5 8xMsSi(v,gl#dC\P3~z@^u=I{c1q6|-'QҜT5ĺlM|,Ѻ˄.޶xUۊ@}_}!0=@h%m/- À/v>uXGR ݞf%`_,-$@ѫy61{b_DB$k]fl8GT |w Ԩ?k4>c`uHVN<Y?FiPeҨPC&YZWaZ!p 4um/"?ۮ懼u8u#+ol]m?]hPj =ܷdIy Epkc+p߯ }Su$>XL 0Z?#@V&#M$X.Uk˜4$Bڗ0o1p<̥ CY7;ND}jܯs%-ʹﺑREɜY#F(_1b_2sm1Ȓ~&hi!@4vjƘNeջFy5U~n)z}ܗlQ,!Ӱ3_svTC,gYXwX3Gt"x=s6@Jh&78ڲFi;Z%6#)w.  %'nKb,Nڤ+ $o"Z ߾$p _ d޽CwB'㈴owH"_ CWܐlCB.z%ywdn{$pn.r[\ܻGɀD+DN G?\nȅ9&ڝKwxCl W--"Sy`;r}%q\= Ngu!~@vbHv6 ?Na-h azMn ݺ 2q8{w}3#Od~z :nk øۋ}p5Aޛp F锼&a7!z:8&d Z( % ‰lw &6 n6O׾Ä)!_=.K3XCw2sHCdC|s!o0ªW=rYӿuʹurt_7_i}]—߅Iukۍoڽ}ٯvB2m*|ڑ\zoNٷ'n ۭ-@ق|j,=tAD0 |" N\Q; iX8w<5=Ɠhfg÷~o6Mިw1XCo6h-Ҽf?p4F;iBHZb(D =ȇV+E3Zon֨w5 4`yLɊY3PNPfx+˓dJ'E`^PYl2 ~dM~]|/I͛i2#] %P_hП G@[T7zXhcn0eFXݠ}zJN$t!w)kr"pDK+]E+Y%gGx(`pwߓVv{DȎvaTthׁF!c͡zE0#(gl@̿esB;s,."H777 NxX_;Cw 'ݯǷR 4VK_G{DP 5'gt& @!N <\^^_U+"~APC@<2.)V. x3NJYnzn)5^&MЉbnyRri3 slh)Zд]/ RqVa |;_Ùiib<(`y9dJ9Yk$yƨE2CҲù"zr40{ ~ .F`ξ)l?0/^ o4?uc㐉553yExX)ĞŌJW_FK4{ek3+fc̃B:8+4\um#pB 4L[,{;pm8V+5Ѷ4A 򈳻LL ]RB3[vVfB>d7PF~wܻsbRʹR*g>ISyɗhDVSFra{ozʧeF'*`:,U!vt)|g*{cESj~$(@Œ2e{K;ǞTf CUnuH?hEC@,9Լ]* a굜0{,\Vʺz0>\:9~\;T216YE6|qrr[]mX1?p<_p>=ý{ ~l(fù=&&J#ϢkljkgH!X찑P_)Dk`aK\A(kD`}ݵ0f=*~>iPԈ`: };w TUmz0E݁Qndpm- wƫh[5ofĚdr}d7$:H'4Ct=`nrhŔHTm yk. Fha|Ȟ[ x fƭj?VDQt",K@^f(ƽ⩻]kTЬHsU~Y )OfYM7 Eq_e!9nOcckC*tA];z̨$PδX8 UXO%@ ˺`xv׾U)Nib3aM<;s.xq'wpJψfQDk ([VљHua+j^$|O0|͐\u'.<n ?Xl2|s3L# -Z' #™.M Ov - Nק jpxg=.poBݔGO?^O+,IP]0npynXu<Bq꽞C3pxPE\4 t74?8Cɼ.cE B]rѮgDiFa6Z̕`WKֺ\LY3B]l7wYgz2;ؤٷ~p8SYhW&-Q[jJ:qMbU@,43Ə -'dRڧ}(-ǥ\*QG&sN?gϦg/xjٻuT;x(3pc`Q|ڎ^ގizkmLr$y쵯p2Iwfni_L(mQV Ť+,݊\En!v4Y;W(0儩8ʝ𹊇0y뇡-N#'dsg62~>G_%9V4ͯdH,rZ&oThp4:XKV \rФsx^fSP`.tP䌅&4Φ igb"_v2if3PqJb *'(+%fD\gI(vw ̰^Ŭb٬AR1l;0*9UKPEڤFUQF&@5z}/:#^> pτwH\"t3-tM͆S}Rd(a+wxO.)q/.uC[ј#3U4UZ=zWe:1zrgk=SOR屠@ U-nJTIHՇ٤A#иEyM3 -3j|yNVpeE~Qt?0)oGD@#[Vf9k#;'۳kŘGF \!*NzNN% ,"CDnNu7LqtT- \i`:"yʇ=N09=;RlEhvͶt8X9Ŗ%r c&SeaN%dlEݯ5#4xOs}oY70MӺ7b7I=,~}(@V>PL`ërq}Exl:օWe鋊!0:_8[?TO)|zj|q3HGnz&/g1=E6% )$ՃxЊJUZOB8GRuŤ%PRU7w2G75|>'wbq wT/wHJ0gӐ:O- 8PEh~Y?Iz0?bMd ])^>pQ&-刮x^w0󧷍盥#=E~E89 TϛZQbq@T}8Fѡ iDhٻNjaT\rysm΃"keg0ê<}.r3g`PxY"\йY9 SU,nSTg˳Ez<%Wښ3ݞ0U-GAd4]y ܳuZӌ͒ {F>[QeΖ^'e}e)n'Ld_l'OK]G*ԗ_bF2ԺgM]U-`z|pī TmnX́׽F׳a35 þU, !$N#b0*#pG |Kj:Km3N[W,=핾i3y1y-\ij6&P+*.{ejn6[烷Y ԼFćCk#43剌(TE6:bm/hDML^aNIwA1_ 3OTjp+GyP p,֌!8fpAݘ1>}0>|}O^sc8 a6O <(Q8y6Ղx "qp/Rb@`%T2YykQZ~` :Kvyrf?pB'pP<ٯh 39f.D{y2r%HFMZPb =_, w,膪w\v{? 2ښʠyQjaZ*UxR>3pJkPIK$Jz6 M)sUIx(s¡nW'L*#z% JRiP2剃d&'U,X/zn=pS,"X )kmaT=b_q bjw!.rB'D@KetXAu ×hm*KV3T,oaK'SU+ˀȂOn[sK=DJ[D ~'_IYv@i%SQ; d!HڅxD9"᎕/k"9[~ner3bFػATmBNZ\INf O>ZN]MFavt&_%tWy{e9gޠTJ`vS,">ѡ\ >>^+a0;iEyRrzBQY>;E]2Ⴍ*8ҏ,h0=`X=){דM:/$HïNj"#4vĂk;֔rO9Z<gqM. @on~x}xzƽٻO~1/|5l?HE#Ax@4̍nvu^@}QZ&X}Wz?{>} vn"wcṰpeEQn'-Vf&Zοv:f͈G]>Pzjˇ 4XӟU)5Bx{jL%fe(*kZjngafXlS="c͌Q:ElPQ٤@LEr7 Vѽ#D[au.6jCIϡiVK"4m:*"L|0򷆋N\(3F4j}Tyqq\-̐.]v[e⼾Eȕn=NZBʮRGDJ_ωz ; #73Ɩm*Fjki L@zئjf.iܼ~s_q/XNF^<,7I,6ia@oZ%>HC-sYð|43"@L(_4F1gDEO쁙Tu)Ort;>fBs3z*Tvue_202JlmVL&̅/ik;/GB&o = F7yW(-cy<"hYh}#Aj.V`i$RK@z'7#\ǭTVd[^ڴ[|n>~ ilA6RKPX}-`Ƌ9?o]Fo9tZ)ln#@Vcf>N9De O=[܁j[c=~O@dk|EvF'r׫ؖP7 U3fr8u@I 8ҷƋ(7fmZ|VNrF̗0Co6#xUMHQrfc˽0O~Jօ8XrA2a["gDJ{J 60sń.Lzl]sPڒAH*-{z(zEӌnn+t/#2>pb`ex=[FWL/vC~6Is{l+%W!63i$^64mܻ y9HkEi=#G$ԯZ7Ο횖aZ*u &"{[l]!Y&yMs}^m2/9-4}z+b.-B߾ZCf Ş"xN$[$E@)q6$gkC+6ȹmXn`'zvE )a@N=@ˆ>~o:OxKht8zo<,f6?09`A؎C, i" L&/.'3xGvF`*sZCe/ a 0'Ϋyoqڛ 19vFygDŸOnY`NtY`L+m'+@k V԰kN բx* :%u@ ]G`db$YdEZdB ~{$ Ī9urjom}m2-0 BZ=w=wj^ > fQ'/(hiE@[_vaɫ˱6A%|.a>X7CpYg66(k 8 G`v1< #8md =q,_đ3zHԃ!vu{ p?V!CϬo%vXwN.ߧ_VZDLׁѼ*?fNΒ3VXk3JcX7 B @J~~xm9K[\w`!w/vO4@1mʀpo~o>{zÏxroϧ-MBOnwQ>d`k=O+0fV-lL>Z*ّlLmj;ӷ .,Cx ݷu=0Pb`bٳ6g<bA}I W+ڙi*O͵n405|ܺ9ӨZn frƅwy A6@m UZT1cƷMe7Ct3F]!d(h4 o\JVѨlG4 2S+f?F~vz7ީ3mGy`x$w` <|o9֐`5iMMe|MԌ혾 ԲH % ge Mr 9E-Jϴ9xfn8dgpmҝ遖2M:׊u#b9s 5<)nܶ4P ,?ŚCc8e/YʺV@tMbUB]yIݢb+׷#%X;<Ӽ+tN1"%:6%}THg9Z9at瑢 '+RX\%N+rGuhIUQI.) XKxP%1~-/ Eڏ'SBWf@ ьtm#iʜL H# FZS)+ئ`W5w[oO먱Ymx#uXnrR1Fc)-ʚ(kmXevyP{|u٨Ez6vv |PMV-ZSҎEY>EYƨ WjUD1KxH;LjiB٫ QS2,?*cR,Su*`6̓Z&P|P? (g|:`=)8ߩBKl&ћΨL(5B[Iqj\ \eGff %a eBRwhq/2zZWfk.Q4i@wYK-o*x~X ԖK3num.2gB`ikjZuWi$EH )*fÊptrt0 F80Q$v_%lBX@ Wk n-ca{p n06r޺k5>}y*C4Y>3+|cz A$enҢM`VS*ZL`dғ'k-ᓬ Af--!JPHi}>CUde7'_cQg\LjVPËKT(aHsVIynFrK7MFȖ[dO3Y{rSq [ǒ.Z@[9affsO+E<(_r1.ۙW_A(ϧ Tl ݖx ޻PNbD{I{AW<u_`7o(vTT`IU{D_;ۊqHfxF6a]Hj@v$ aHfa˚ Eo+ K Edjxʷ%>Ō֡{x{ u v4u?k OTۊ UxkV\xNfC+r0~x%7~UP`s^9GvBÑdz\vLs̓xga'3bu&٢娗W{Ԃva"Cz|D&ihdWAXG:*МBIǏZm˥osl_>lsD}ʒmKfW3-M̑SKRλl+2⁞4{*!xh N߭(zM@@2lxx @[q7Iג*Z~`k}/lz(oSD:;T2h4VC?)c k!\켻SR\ݽwB(}&1vÔ9Ͳ6@?aLOTDQlot]]6*SkR)¡~wdw7_<7y&i1Ѐ7N4OS-I+bb$޻RW8}n^t+btRN6#M-#4RCJ&^pQb~Az1*Uī$}jAx g9m(8<`2EK"rdTU"& mQKrĸrWfyf SNEsy[ 䕕UߖU6x:o*8Ľr_N+SI^P(uOs;Pj,>G`(|젅L2+?d 'z~c$q(wQR(Ʊ+Uf"Tcx?y%j4ӵt|RFbFI?X ꂢxSŧwK4v@_76z"۰u+T2˿}JOwAQ)̜!G~[Y+$׀JK2t>XTt}:dP/a%TIӳg9s?Li\( &QO(,j eW)X2"6pJ7Ak,|ʣ[iX>]KmcA5?SMJm:wh+B!a"9XiibAu&+TGQӁ%Z@ʵh,^"ht1B X~X% &J0乔Wj+dHT6IShl+|SOJn*o60,usa4 E' 'nD) jTDZQVprǾQG"zDM|'r}(-WTDQ}:i$? ^`&RuZJM@cK%Zw (w"ʚ ce/um F_e)N[~ʋ(.u05l!)crS (a,b Tx\4FQ0|ο.|']6 OltG|e#UķDIQP{)cCVu VT@UDEѩv2W/4)cErSnA28+.<6TY缾мȯ5RV7?#-JBMԢhAwĝ;Iڨ;<ӯwCskqq5.oy |TK^Hu/DJfȧ{R ᠿnԇtTCAL~c٠s*G(iۮk ɳyD.xR%LJsIJzuIǴҬK zįyӤz6?\t8};GOJY6>qP˼*^IwaŐݏ6XlEg jY&Ț iqglW. ȅǨoWU,ewꌝwȖc.O0ތv6G]Nu9< <j)ߩKEBqC IvƝikI5~X.SSSN#Sr(W:EͪR] +2"u8tve?zqyݟMq?W& :NCZX`ul]Z%iQPAnvD"Q\oBߕ횘/9Û\ƣ A3IoxM7Z n8Y4i;0Gq1!D[hUʤ lE郶ah- }AԭʺV^ y!2M.̍t P$d›ȴP\g O'0Ube yNS)ձEvR9'8~eRO'(ܷBӰ\wg>Yԇzqͱ&ƽAg=LҿA-I> L+q1.,r !}Q&,I*;>ubԛd=z݁xx$2N9 *[d+ c& )f ׌֤Ggrs9d٩g\D^oJO:IX M̷ a%M4+WZ|4uql\x)G*Srr3 jC5}hRKYͨ=,`0CExm @?t.sIFDhB{z a溏OLt4}I&" Β6Leh'A3P}ÐX2xxG_4V-db" eMAϕNFb G[ ʊ׃U[WiwGRXԺx̱ ᝧ 2wp0NRcM 7[[Щ~aj&1@lf}3hKݝa)2D9?U6owJҽYǫg[-ZM.b/xm10 ὧ( T18I-IEL-Oֳ(.HRwo!ҿa9dZLs1׶Q0Υߛ%>TҚ4llpǕKP܉M@y/ Q~xm9 ޏP OX 6#M,=PjצfV nc t.4]X`Iut1q ~ƥiuċOz .Px+-.LҼ̒JԒ̼bݔ<|=-. x+-.K)MI*s2 ӓ2"@\YR[ZR^WGx+-.K)MI*s2 ӓ2ӹ )\ v +Dxfunity-settings-daemon/.git/objects/pack/pack-5ce4060d767fee0af12bbf440f06f6c278661f98.rev0000444000000000000000000002774015172222611024536 0ustar RIDX' uJ&z: 9;:I  h^_G P  1 B{od ^ .n l j Jj  r  ?  <. _^ u'MQ {{y! 4 ; uD N ;H ]Lif } eT c E6 r8Yo9  +O1 =  j2  ,qda ? < ! G p\c <N D u g H  MF n 7vl  ]B 5 qm   'Dp < De {'eK>7I  * <&8I, I?ka& : 8YC B m S F  Tsuok RC  zu t*C3 + o  SS6x8e i g  ~i;J~y  o*=  d U8x/ @ sZ Z*96*cz` :    s L '   dG_uJMA}I | X' xG e @u{ ] gL = "It"F/ ^- O b q}  k ;# [[ l/R  6  %W Cqt4 U f l  Z b t z  t` HXz=n >   E) x L[Zb  ~zY v  I 0$ hPw P 1 @   @/} Y } h 9_ > AS */x   6 %:- qa  2?H } wi rL\  H ( G3S#; P :`A v( aE( [  WO `2Yd  O%3L $ y 7,z fW 6^ VmbQ_ F|X  +  @H6n uX & m ,`Th=  A   H dr (48c_" m;5BPxT ~v . = [  .J$J}1 g%6,k l O 9 4hLN7A w ^ \   {  i  \ I KYv s  g2s  [   3b ~{ W0l G- 5H ;j[]Cp#D0 #1  oV ?: 0 L ^ +~ %U W S x$F ] W EeG =e  n?hk; A tn5 -y J &Ia D  ; V BT m *# G}r5RK )MU 7(Z@ E nvb   Cx X t6$o lpe# ) , , ( b 7:  V  $UWi x  l>Y !w ze Z   44Uq K    Ot 2'ar _] 9uh @   + N2 d OC J *m7  Zym Xh  >E~P -8  X #7KU  D  { E '  P@ y $&) g   9 s  l k rX8Kf/ | N ]N v.<  ; gD , R  &C P [j [Q[ OQ >S fE { : BF<{ YO .  N E 5 ( |sAfRS5j(E  / g @ NKki  dG Hk d  q  ". s1 "J_ %gR-f5-`D |F p. Q 5  p."E  0 4E  @ W pr )C +    ] +X  $ag 9NF fxve yo6l P aZq}  "  JO/'  $ d  v  qw b ! pc3 5 R  <Tj) K q A   UH h3W+q Z wRa= 4nc #<a A 3 \  `9M W :@ ]  ^ M[S  _; LV *Vo1| ,&  ~o) ! &  K  )dt K  Xh 0#4  1 ? j  f| B SM M"WC" $ (  V n%%1 B uV  3 ,T  Xg1 \)  UI |! &`mBz l P + j mf <v=0* /w Z CD nf RG vj !# P6^ ? 0eY A Y  y3@ UL$~ O |  . ?p B  -c 808  r\*i sO M (DR 3r4V c LQ[  %Bb \  >  G7=S7AC %0 "FA'"! U 23c  >^ x|> >oY nm w &: + iy j w6! |  }K h  /pTz s I/  i  - k% F c H #yr {> aT  itR }b <  0Q>? ?2x\$ D !  4 'r  h   }b3p ~&ZI  (F % ^ 85 + S ` .]\q U wB T cT _ 2 dkf   Qw   bV| V<z k N  ~Q  u 9  2p G c"` 1 _ MZ !w] T`  \  ) ( g9)sM o.y  + -= F 2H2vk,  `n 8 Q{K L !) s :] j  yN7RN  t7 a\0 i V  eJ,- ~ m ? lX*5   -_Y MP/ t z941 =  ^ J'W# Q Q\ v +Dxf}t.}K׍?unity-settings-daemon/.git/objects/pack/pack-c68e31297965ded35043a14d0998835a7d177194.idx0000444000000000000000000001433415172222611024077 0ustar tOc  ""##$%%&&''')))*.//01223378:<==>>>>??@AACCFGHIIIIJJJKKLLMMMMNRRRRRRSSSTTUUUUVVVWWWXYYYZ\\\\\\\\\^_aaabbbdeeeghjjkllmmmmmoppqtttwxy{}}}}}~>5}AP)Vx3$F 3rw~#B2>/Dx2ȶ,DpW-{Y`+03:o6 k,&{ w;gYCXa[8bˆV]lH4c m-, Ί TТus\98}頻Q7;I,h㿝l1xV?> ۵ !7Q0I: Vc%R0%c V£2pEFoq_ 3g)O@/AeE:ӑ0ڵ:*O)6 = V%j:l!о+TXZrN=2긟I/=Ҍ>$pBW NOCg>Ua< 4g{:rw>ɻ5O=jn|>atiA˸w+^k?韹2k擇Agwĥh^.RB͠Hq~_m2zCW۟.v+E6Q!h|yŕEAKGh8mDJ*q|è53SGjףᕬզV9-LG!Jg)0f2AGk +*&oHW~ X!{II  E?8I{kQ/U'#okJ|Ic ÆV7x8JeJvє-yKE[XK;3|JN3?M9->0" ^etQxd4{)/.ۭ lS)BLwFeCTǟ,%joTilVʺHV-ߤD{lVgi(Vg)> Xf0{S(LT/'XqJ!`*XzU ?2a0aYyRC [׍Z5=B_["D{[pg%Z<ܝϏ_TƆ%ЦJZwb?K( 0Xdg ܗ*VoD kkQ:) 9`+k4&,'FQJkiǼ(U |^ B=AqT#I]7>g՞{KtU*t W ƊRofv?@U!b$\3кzy$SnAB]~}V, Y{Gy3%fi{;W#8)LFJ+j4G`|1ʅ62-jDžCDW-^ryqۅZu~z4R¯h?펁GDʌr&2> 󏎎1`Klij b;bXzˈ&ա$8$'fAJ|^IٓG+HE:'vTg?cԖqH#Mn-{ˣf@?/dJ(;V[Ѽd!ĂIr!k`xΒ<|@pv1;}ty[":I2~6p$ǚk֟ɜ9f—?4sPc> L8ima"u<3m4>{wW#bRLOt+"{rvj RS**B]'0D4wBIJ#Hw}P}y]f{w ^gXl6¶O#DVdߎŃ,BH1uPZD iMM{8"sdoK{FK:d!M 0'#v\ֱcrzu@ 5rQm!]dz~SZH墥KAյа_Xp?ECv[/qρr!*z=\ViѾ6]#y䟎lY{/Q=H.ڨZ .eM}\nC-Ypx -n*F @ IL(@hƹ ~hz)9ZN @R/$<}\UHzjrW읺il]s&@ 5v\K*Qڴ㗁At{(t(X&q-3r OgBwD?>4YrЁRY2>UXQ+~effњ&<\tpXQ)myyYi<`ZqgdQ aݟkWf07vb*){)'dJH4;=CXQnh%sSeHUf9xI6!\Ԫ[#;<{#.g6`W#rE ۝w""i-Zѐr;伾Sp;yM!yVWx {LYKȗ2A:Ng! ZgR/c?MI 5 a u%`?\=X 3[p6)nlC?}̀'ba^|Cb_zDbLJ [ug?~ ]iJD]+Rzk26ɿP430iS'}ecl|Fټi3Q07MV"7zRT ='oGr?GK!\V\Fتh]o ~k%Oc+868ȚE Wuƽ$]B_r}~?+4IMc:{re=<&۠Ce?^ȉ,ZgWĽYI 4DCDe='_ībIO]X*ݳ!m!îS>K; DHU%xzd`2鿅޼EUqܡ ˏ7aNܿizMVwnUb`0w.gVxa1KU/-{_s.q!7W0 1D7-e/ ,"-n+16878&D6pE{r1fG49#y2615Ox6DD&<#Cr$r F.T"8v.5*x'|&g`5".C4+&4RhTv, qF!6GB +h4X? !*e/{ /06-..4%.3D22&5k* p-3GG-2W5.7+'gc33# ̈m7+8,+E>4'D-8D*'0t8")h <1)`07*202*8 Fc.3/(%17,[D8e #J2nDVM#,aֵiY-KR-Ņ})L~KF׸Tߡfcm<& _F|QyM&˯_t wtI0۸MHʽuIt2¡Bet&O-U{T]VRG替%%Tҧ,ىǔdlZXNR-(zv7=qqEI=^ǫ97Gi^tk4+Y=Z{pq@~m՛_}I?;GBQr{7}:[ܳ)Tޥ՞-]\beӸZ"-Y{p4VZQdKs^n-O ,*u^z|[*㖮]>U `({m/!wՠ[E'z _or/jWD^5ԥm*MMVi묐'P^hxK =ʧ1xfҦR _-^oD' N[3{C4YsYH=f6ڻcԳ3#d]ф8R|₥PFwyq҆룎uZR0 Q@ӟC\.9Mx;n!{NH,)RNx{Sf`4m|rk\@AcBc!*qsB Kd6NjFʐLdCNǼ_O Q}ʏ?}*B^A9gƯ&⤵qOKE TyRoyޠw7A21"Yx10 @=ȎT$[ !ff8IRNO/ڤ8aKY=2N y{KJt3/YYm)A"KD)?(x'w^JkϺ2jHA>Y%-2Sױ `w̦yUi+I..Q260L#xMn!,-aiE^D%;Ptiŏ=C»J_WU3p5 !t?H8i}i$Bm)V GbTJ+|s((s%exJp-gk t"ЯJZZ)GY V/05Z{~͌ ?>.էx`h lI_l*l9xK;}Yy9Lś B=ok},w&)&ZmRwn o fU{'LnwPjC?_3Aig^c?zݝӅLd\ցOKx;n0{b&0T)Rv%EC$n~0hR))%9:6x#-"GR١A*_%sh,ֆk: >GOb_xA @ 41Ƶk=kR.zz{wYL20}4A} ;oK[Re9oӸz^sB@[}"9;myORswr1aCNWiwDH6M? \q2dz-LؔxAn Eb֭dHQu',dו|{܈@*N^z%[ڣV|0{cĎ `JU:vV)iE%HVߵ` s\"=Ly|LzVQ8hIGd!;cΰL dǰNsvFřAlb&x;N1ާ%)=㍵y')rzRpW<DJ& ޑVHA`TDmR6xLT?qЕN>\,Br ){>Ɨ>૷?}ƽ:}rKu;09g ZkxE(*3ZJwOjN]_PFovi+GOYS/x10{=R#!DM s.!"Qp(x=)hN]Et $zBvFՓVYFѹX)EZdCK̊z/LȺ}h~=&}%ˣ7iTICh<*:~wZFب/)Kx=n1@ާ>RE@R%a#c(8}ҾMxԃ2-Gv.1bYr4ZݨɵѠ S5 8xo%G??Gi- < f{ۺZܻpF?C}ͧF] Z`~Cth6zQ2xKn >hFcKQ,0 %sAUO jIϼL lA!^÷/t4a6$;9c6Av 3c1Jl_Ϝ|}*uD]5_CNoB97ŋTRaAqހnGIebXƯOR ,^%.ܹ< qVNфg(K7Gh}KR+pkR/364 # 1#~TxN^ bpØ[ޟ9KǠ]R* #!a"x=n0 @]^)Sԡs/bEt;t}t9^2I%+/[LzLٯ -Xh9Ҕs,p)9p rmɡn\6鮗1{t>KMGk_ ?=c^,Zk7U|y*ۓ]TSaCP/XRIxKj0>ۗJx޳ @N_ߡہ^@" Y9,'ooff9r2IAlVFp KJOg~rQE %a{㍱$==Zxu%}0&')Ni <9B`ͧ}i{kxT26r8PH 5h&xAjB1}N1{LL"Thd>4My"^_|1ɢ:.f!x5:d#2bALJw.]HNK68Bpt'XZtHA{?XXFTZCm;pk<3 q:'pmNxn D{/`(J2 ITӍFO7088B1i5k~^ٰb"!`۰pj [dgFdf5Ný]s>F|1'Hca OB m 6:%`zq93|rwGKLtcl!'%GXROq Hq%IASkx;n {NH+`R:x=|,W=}|3h z^\*V\:N-lP4 wCd/i8d#<Bڒvj n/}wrS\A97xM*)iK  (-/lX9Ã+ wH:8~Zjxj0U%CJD,+r(zaF-0DZyO*}JezruL]2eOѐPqo~Z WQs*$/nr^@9gY*頵!iLWY [i jٶ.?W1xA!;&fhѫ@K0&{C.ASX)lD.ٱάeHD b4LK)^$S(%MdG];\/o cmrD6CZ{d&ҨhcuZݶ\!NxN0E|Ŕ $䱝8V>Ñ3e Je0&ަV:OeCFYZfʫ.(݅u"CjwB"CզK]@!GYh;N>eHYxPDz:gxRTs%6|3my&e<)]z6w*mh]c d_xMN!=(c\p)Lt^ nߗFg e*#5ƬXkRvJtRzLy1ҁ$gGS4 U;۵h~V_Kl*JxJJ1ZtQpV4 : NH:))zBp$ӨTRI1ڀVOǓm:[=w\.7@k:‹D)Ź<'!>NsxT<f\h *e|%Wx=n {N1})RH ͰAk°CΐIk|r^94JOlS(^"KAs2EŨjG]l MO]*|D>'-k+ohޯ~Jz4fBcT"QJ1[0G|S%:N x1_r5C9ˆ0Cy\/]xAn =} !RUuE׽Cbqut0/!́%1fόnIST+wY؋>;9i ZG&YϚ8ƳG?x?W=Syx5 rO7@"5YxѨ:ZƐtr2(m8vѠ,O: k+sl-[ xM 0@}N1{A&?HqVO0I'-7p{ҙ82kk4%Pز^bQѐ>NNǛ.u8}A{b2z83um"VI667Agwĥh^.RxoXf0{S(LT/'R(t(X&q-3r O>,1I,h㿝l1xV?>40000 po\nC-Ypx듛Ba.vGh8mDJ*q|è53Sxah``fb'0[-Ik Z0jo>ֵ {WP~ĉYu08r|+\)肢́x.*$#™vBRRc&1[i4xAޥQ )TYRDe9.4̫$/ m]Ґ׍o*ӕN]{n* ">{WqqQD^k4I;}Yנ{Fzۃ`kcyuÎTV ɜ m ;<(KRޤhךBX1Q7c('qL Vӌ|AZVlenxsƸVQ92jSk̑\R 9I* (VT 5oDfam㗵Y[ MOxlkQj*BQRd*imCdݝv=i'.*6OaX\+/hJ%cv:Q]?jTHL:RLy `+pa۳W/NIuN  \֬/gU~Y` 8Mu|U۲ɲ[s'w:V Rx-Oj@ap V i2ݕB궣357a@VlB.FDGЛx pH,ғcXihݟ< %0jhMO'YSYAx Q+koPM͝MTӪlZrZKG+io|]N!R$` /X?OK=^ClNxk`4A|f"|oU)}MTTxxk>aXJjRFjNAjnr~nAbĭ国9& TdfBXƛ|xKIML/-/-.Ly%ũ%%yź)yzzZ\|x; @+DPuXs9\=D "b17YA,»q%f9^c &\QZ/time 0!%q p%XT@*00({H&x~.2I^(m xQK@ ǟOqCU8d(LJKkn]7^U[_Ӭ>+X[P)u_e5峞j KƲŚZ)$e\aU%}+ηС9:1&f˱GtR]E,Fvr ({O;ů,b˟.Z%hXp@1 RB#Cp'S5xA E9Ŭ#%U3r()F"rRQ+M:ӮqibH.ZM2F_$1$/C `+&;@t7ԭ:Mq|GOXS&?z5<=OMtd;sY&Нrw^PN;?"}>|6CN8L TSPg՞{KՓm[@ IL(@hxMJ@ Yh\.'6rm&fW6!XX(W[8b{njg}?G/81pdEFC[`A0#mC Բ(I]ڙtm5vL P)ʡwia%TƅHf ;9:ɾ_ 8?G1Az-KEEz4a5:i|&iP|0ٶLYF45%->k6lqu2eU 7a m~9Ex,pjk~㒣B]q0%2 |1-Gѓ9GDʌr&2> 40000 media-keysG+HE@GjףᕬզV9-L40000 screensaver-proxyњ&<\tpXQ)myyl]s&@ 5v\z$VsdI/dJ(;V[Ѽdx{iB㘜]SZ}I*Kj _Z;P'ysExذ%3DaZ86eNQiHSX'C{x`'100644 Makefile.am3g)O@/AeE:ӑ0ڵ) RJ\s=nPax;;owL, @Yu#M+UHzjrW읺ix]xpC>d$o`q6E3ETcꛮx{&Gqov~wל䒢bɂ|/ MTXS4Y_^93MA1%5-3/5E#>Ҡ">^SAM Y < (ť0B22JRKtJfqbRNjBZ~ļz3T_Olfe&dL/QH,K 6$#9 T!(9#EJ)-KW(HLNLOUWH*IaQ̦6ً_y ~;wj~3m4>{wW#bRx[ömBMlsŇo*Moz`c&N :*O)6 = V%jx;zI 2}Ύ>>Ne$57M{ kQ:) 9`+x4II  E?8˱ 0%c V£TSR SY0 jMdWx~$i\EZZ ӴOf|E E6Q!h|yŕEAKx[ƸqHصl3?jӴby%zD4+ ꣌`N:KZYx;zPuE /17UV(-;3'g&ݒ]P $ rv V)H&%eOCs2"! Ar^2s'fYyr" *>~n>ϰksSp``;YgfVɿYE'jCI:6'  _)#S@B#49t$F-VB]ѬR`M*%E)E)%X,&G(3)pNN`7F2f8,3y$B L#X_RHN`,j-dH]X ٠iMl[DBiJjYQiNj1@cU4 R2+4IeR*]Cj uK2K*uSKJ2ҋuSSs` x 6Ea5&a|e2TIr$W^xtID71;5-3'U/1a+:E7˅L ?=qz>W=2긟I/=Ҍxy{ljwJ[N ]: Vc%R|]ifqhuLox \98}頻Q7;˳b>xeCH˶Nl9McK  rxKqC?[AIjO(x!Β<|@pv1;)Kx1CD!9#1/=5'?aG| +J_Ms{ԴhFwlkxzuCH{B͇+j53ҽ#u|rS<0x 6]#y䟎lj:PxeCH]\uUr{~ .x@~3xIv|f^fZbQz*ӴdRJ@:k8x{ _~3d=O"UxzuF_ݫ0>sY7Y+ xH%100644 changelog1`Klij b;%20D4wBIJ#Hw}Pkx;4i!A\ ɡ)MPGx 0wHľXKF.}7Y4jSatfU}>kXWh(R>ɢ, 4^xeC<^_ΰx:SR*7Q x!'fAJ|^Iٳ=j xqCD!9#1/=5'?AvFAOKs7E4iy̶QUKqx!bXzˈGh8mDJ*q|è53SxqVgwHSȽ<EВYޑjkiǼ(U |^ B=A!')-(_O#S}3EdRK-{Bax42xN},6 ;[ˍ?,7xfǴQ֊3%#>3$1'GAW7-13G7783/ N uxviWiq~qFbQ~fr~^ċb }AF@i [4X HȿjUƓ NxzuCȁH_/Z6m:x 0[x!3m4>{wW#bR*xzuC 3yruծݓ Agwĥh^.Rx̦fh``fbY_ʠ\Ez9W]kpnvdƐ?RS3 &xl> PHI,Id8{B#+[{#;ЈV o@S2L &Z~xɫw |1HdsLD//76)jMlǤ#"^U.%o0_:xrK`Sxn yHE`S7)RMJ^ F@wSe T.*`2%ULE?ZWh0ѯr4Y X, cvl 9=r^ XhBVW[D Uۄl%"=de<߿?7Ǐf6~LP9L8BΔcnV%|]\d/4q(Yv+1N޽u"ՓnzO Kԯ_T΁=XG1qLc@H/V&vs)IVCvr>·(2`日1k+l.b 3jl=t5oz,rmHĞbbٴ 1Fgy ˆd*7QsP@K^&Ry{qyA+ NR/ |t@ZSA 1{tl&G] aoaQx=>$pBW NOCgx %T  =v &ա$8$x= p0[Zds48Kkʓ,-2pEFoq_ *Adg ܗ*8 UQH~RҽnR:}PulΓv1ÅJ !*GEs-ߓ왝' uN  ̜Zy*tHۏJsTWmS-Oi@cIlu qV.ƣXVjy$qa©5Rt b'L9JvX2$ꛩ1 i^Y69C3j?oE|#UQSیw=U1`F rL7nD^ |0V`9 $͞-au& jy@9<, [Buۼ X6* @LA2()n[+Xд[Wquk&k6+p)O{]ZgI %)8Oe>wB_!'uævtt7sf=ֹj^;[' I7]i-G5 Du"u{o}x }'#FG/yu>PXy~ˢ9{ahm^?vxv%'y5ˆ䖝p,;J*8R?oj[P( 1|6sڎ799(M(r'2$lDE3uhunV7 ͠{iyމY!VP"+mf͔O_Ѱ"o !U߳M:-#k%6{=jV^1 dG"j'繳`VHznÇճ4@p췖ZOJ>ԫdʌJ5mQrt WP0, '?9#'Er1[ܱ F)mJ‰שv@<=,O7peH+]T]RwbGh8mDJ*q|è53Sx|%100644 changelog6jThP&൑%1k,&{ w;gj.ي`od>dHڨZ .eM}a06{ humRuOmX+x+ e'oU)}MTTxxC('gnome-pkg-tool<`\,17.10.20170922I  LKs@x}۱#zZᚁPxkŚ:qrf̓Y qV}XqJ!`*xmtv1-$J|Ic ÆV7x8Jex!,#v\ֱcrz@>Ua< 4g{:rwxS" org.gnome"#"S&).( " b() (/ o$. &X7a m~9ExN_TƆ%ЦJZw!(Α)奷: V}߳9f—?4sPc>+'/dJ(;V[Ѽdx!Ԫ[#;<0MVPl 39ospiN` -0#N]Llެu֩/9Ty Ms^xWJ/EUa֊EqH#Mn-{ˣf@?x;y2 ϳ32oe;~N NNɲӸ&o{݅7,myf SD7`ٜvd9zqrQ~NnnjIF~(op4XQ(R(6gx[Ͼ}چO+_E<$꺧QdAF͉~L5>x}vFST8cR!)ɱX%ZaGېTbOwHIH n326O2w @$|=ukhEH$u{H'֜HZC7Gpha`ՋcquMq?Vh`OӚO*OV o ]?)u9taCϜӽ/O:fCDJuc;FFM'?u_ 8U:a$@/ljn$w.GϞXK"%?cC `o1TIz s+M P^Z# ;w(}B tmLd.'٬ *a|{ ڣo?YuTj˯=xzv $nF.XQBm>9x{,] eo=lO A:]i_$Z}%}G80pG1̝7pq.=&@'D߾~oD`Xs;,8c =bFU~/qҶ[ nCt%oJ|It=/HK.ozWIj^"%_FS|?w ,8-q|Ag1ӱƻW#LaK  @{lCY8衡XWc~ 0%p3 vkt-V ShH`$Z  -ĉ\`pBB*!-8 &;л(+ !:;k³(BrIw4U4  IHTЈB~\\"!# "H2y#U0@JB=B1 ƴ4>j;Rb`A|/)$wt L *sg*nb5G,A;zi:͖rF>JfrС>L ݁Y{*d 1zb\i4:.(ͰbmP"e*}N0܁iH@ƎψPzr1 W4yB7 y01 PQL,B?Ҁ^ɪ ˈCr>qbŌ)V#cNfn+j$h9%.`qP2V8x!G=J3`۸H|Dl瘈alMڝXqQq g(C! J tࣹ uhOП0W H#3>VD;< !x滏//_BWMEy$&q[īW/[^y)`;(xRaV$A/<5=kن1P8_1ʑPkNp*@ z,`fTX/yid<$C Hl ̌<0}\ڈDz) sH3!|e\PAftA>p#(ԓ>^#di%Hȕc\58D2x:Qn#J& `u8@`BF G@! Ml?EĚ*KU`,( Pģ' WV0.'؈/9y-@=ļH pdCtq=Fq94YbWsDC8Bq#aH=E݁I!2#jtT]VڷB 8*h0Іi9a&0eHt/1+Ú.?fHT85Ζ9]b}Dn|m^G0V XSH d"L]s%s$+tsxu+B1F0†҅FFsV)󈐀p1Kp+ F`<,(PD >*>(@tUR)5R}"@9䁐Iea;6L{q0TÁid9DwM ג^D 2|4rKܜ {T^渕epSPEM &. v]XHn x?!\YP`en0h; jЂcV&M%H i2ܢvIgSe MI v-pƼItR#JC zߢ|-g8 )@F#:=eI0EsP> "eHM@na d99;sڀszfХ Z,OD8]DޮR(b!CWxDԧE4JXȑ8MG54Yq&*}̥2KZT#cgsPdوݭZ;`Q aD')4y[op'gV/oG꫆!Sfx_ɺ&gwgԋιUOTȧ9,޿~{ ߭^2_Ln7 ">qF*n=#Om?[P9'QTCj́NEEF-6c3:K F 6s5 6LL)_@8|?dYPX-g:lI8bPpPr5|OұrZq;pi?_x>|>C,!Ѕ~V$#hb ?fq 2K[|l8$PBSJ}M*d.Ai"Te$<(-TlD0Z*=ϝ0rI,x.#n.O%kdlgt4rT ןO 5Ew/ cT>5Sv'[K{qQ*xQ[eDUpY Ęf+g (4c"^ϷTZ}8ԑ), |b>o-˛ ɰE~bǭsUO.Gc̫Bm܂sWP и|򣅓%8>v.>qGI]FA /.`ԚzPz^Nt.PUґvϸuz}&Ҟg3;Uk= oЁqI\c ]zT_tw"\&ٵZF,v%Sg>oc5_A*$&1+On^~(A)2tT*6_Ifn&JQI̤:T` ]Dz9ŬD[f@~%kp :bAYn;oFYԎFPWeؒkQC͑}/u.l2mU)a>WX52p8TʪjhT(Úh)<< UzTth~xZ\%-CKK*dBV?ARO+ml{xurn yP߈pެ7tP`mGXff=yi2W}ۙ>̌ +u9-NyX:nM.ZJ19 :L!q2sX՟"h NMnK<-'_G.z]tA>V|c89оX÷8,,+f N9>N4}TwL*'Ա«z2[xS-kDU\.(8BRXQD":lcGNş<=\>6SƃRퟘO{0Wt|YmKe~cWr<$kYE}&/5${9Jž g#[C1Y{xQ2Y| &em(oRAWcNm 0#H]5!V/rR.EUB\?[rN#xS>>LtR i2@>OU IuiL˓MSQlśqC5U ي2zz_MM"ޗ[b&27X Yd{?9ѬfztU^,Ú0OQH};w~]0rzJ7Z VWgUt6J+\.z|G_ Ϩ᣸ii“ҁb\IS-t-=bK"8Ÿ{w.1l& X\kBa {2T 4/u~XX"xppQԉ6ITp,n=rVbRQ>S mfZ8Be!&:p% /5&ii [<1ʤW6$= !#} MBGQ^wnl?%Z[_COtO p+^?vƮ?e& 2 hՂS{QSU~jyrkk&# dKZ;V R|X1%!)&ip7ʗ=GOIyz3nhnD(j5Am~[vU>ӧ: cEts_٥vB|rh팟A Վҋ a;ŝj 6zouf1kU*)zapH!Az^G$MUA?w/Ϛ&^c4e@zjQM~xh| ga,S0GK?و3fPey}-99&9^ foS/SHgYqR9;m^+lrgejΏ ِ*c{Dq+]Y/߂ԗ)ʄ5ը.VjT~m3 O718G޶,W<_RZYiY.s`7mo7ͧE}QicpG."GZ J҆m@x;ߔlxyx&^Fnæ=~bLw`8a2+p|2InVYJ74C*ڍy_c2 nnl5˘[r@xk&ܽBgW4dYuu Ó5Okmy§|NQ @1T?-=|>Blx?9=H5]r{-qej&k/YoXs]/Oz1R5VtvW7YwzRa1B}'[av/3=wZδQ@ 0/maRB*rzZ5Z @UO4͑c4|m}љIISJcf9Yb/=[XYVV[7/d^:K]]}'exjĤ7Oes'ّ>_䊡>-e@m#9+!>^,B]lncfOk!]fayԽb1=g$wxB,';--e|`/{VɃ;5>@ןeV`&Nhjz~pD{d*1ؑN|:&c2i2= +uRq};7-=}jzJȮ3pQN{61.COt`%^nQz=y74oX1r^I@׸fe[?3w.:w6*]RNwf6K.'k[d[axj*w[v_G?_2QV\\ɖ\x[>Y,9`ܒE )못Q6gԨxTSs/n/,41lsnLlUlr{HwuU@~ú&U>ngK6Rt NubPm(*-7ñЇ|o.κcp'UnE͎Hfb K~*+oE[-^0v]Z:gc¶` dF0/Z4U67V/&w7J<*p*?s3Ռ^ OR#*WXȨ̧WÝ,^ZKqQaGʃ·ލ{Z c{UchfpCsۖ8EuhmkZwmU\|z*nۈw'#yN+][geƕJm,/ݛѭ>^#N8RoWg#mAF^Nl*U;0}z/F"f2O Q@˼4+qh1'P^jUr[N\{·y khg.Subj'ˌI[Qo kf?7D^GsBl5i.r*{òMǯMJg$e`뼽{:~{uh1.@uo4I?PZy:F>@Ҫ~ֺa9W2=y_iyea/Rk힜Xi< 5]RykwȏYn϶WYx1:tN#ۣw[cqi"_lco`ޛJ΅S;m6":ҪcMtuӴ| ƨW1R%´ϲ ^&d6#穉+K,Nɕ|L}X_F69j桷'D2IZFkM![FpSٿ<݌gBf**~&~،QN.so &[,(xןCcRIB) ts27dMtbΜQ//6ҍ{ST|-/se-Qʟ|g>{W37|B01'^bcBu5#tcYʁbaU-C-ЊVDj5t˘ncc {vBӃoaHY|SmR ]5|EXb )DÁgN5lgG5ecM'Ә iC Ȭi y?Z[0;?[6IT ^m n0 #`oR ڙh$!O0Zr]o* 8¼jͩG&*kezB5N/bV}LEe /I7qpC{{K/)~Q؅g6~9720v[b[+)vj;PQcP኶(` ^LZGXv]*Zy"m(t.fioeb-&9&B[Ͳoܹ~B jk(D+}ζUiOO-Z V{' AU%h'>D4F}?? O]%C+jhiJswPvHT"YE Q?U&9gCYAgͶMxFdl/AQx} j7ؕPh5\ G5kQ-TនNJú[*8ťjn$%5 Cl2Tu%Qt,Vq):mE*nKL =$hkWK8f d k{ eHKh%;`|zQ^ݭ-x340031Qp  f)Y>R_|e3|*u bWR{L1Y.S|3[eOnS|//]U|Tkx0 3[O{uq[A. >5gnuQ7= USkpdKŲ@m_V>O:sSSҒ< 2mRD^W~AvF Դ"T6\q o;9Kr&@X0ABgT,.Y5qEwCS23,6xi^fD`=yũ%%yź)yz) UߵMu#zciF b%qsB2m[+,B`|8dyo8'1a䔦g30?3'/ _[._ Up۬] Wg3Z-1̂bWWW~h꼬#)DEIj1P^z;f0k~Y$@x340031QHHKOOgPQ:#wGRMM{B$0It1#hPg*JsO}Y˲RHp%E% yڪcdI{qﵕPEy)%99Eɉz ,7˳N3Yݏ]:s2J2K*uSKJ2ҋuSSs 2K&10S >fӿ.Kdi-Yܤbu|Do5N5*3|y_Q{{ri(01ҢTknfSC$PVj=DEu%wz I_cO\ޏY{W=~`#^T]Z\ X/%8$ʅ%?NaZL~WglirdKlt*?iTfY:]$r]:AӇ\ȹɢO+4ċH/fȹF={͋q;~:Hb\X!slzgs:LzӼ d1ʦSW0͓AHnφY_V~sԣFAO=ۿF{S?ߚ;.]=r!㖋FWoJY7mvuFmV9xN{YiԎNjs^8O\^W4"&B5jƑmn t/dnnVm=obƹ8col*xrlGmnWqJDjMy]ʦfWզ弜ѫ:+j9}wNE:|\>͆{=#jj8f#SL8'_9;U3,SwO392uzQW?Z'XfS<\n^_i'"6m\ڳ1W6M[2յZǽLڑlNմ9:QVVKHѦ~?*('xfcV Fx<+d1ʆs?Ij &=gWTpzn; qos%IW l,M{03>Bަ?tlp+CfDMthmS~MĩͱI?wQolF$ָ58>Y5fpGN4. $]X,@%@ܳlyG|;ݰ <=OnTiV=>JVQo2We+cr}z^$ϓxxa"@ Dd ?î.2#ؘ>D2O0N..>y.9ַ&W"u^qrڽh_WM;s7_ٲ$fI,nQ:cArfj|`yM f~ 6/KStRK__Zb٨7\[[_X0@% ?GX O0 ϑ)QKsQdnT.)^N3/ǯ޽-!i%vTrdjEuQM:XLB\93FMĉ9P=JnǙe]&sTh2F-ᇾ:L#Mӵ#R |@\E^r ɐlY iFz/esP{,hZM6,j^eᝢwAZ3jc"}I~z}eGH}ui:O~s )z;P%g0Y$9Bx r=%SpÂwc;,>,{dg9nB j£Ӄ81m. 'X8.AGWA]7 #oiY> #izCU ؝ 06΋ntkYäƞX"<'ó{N姼mX#G7-GR 򃕰Š(70E.t'D&.=]u$ÐEV<ȏC_'dA 3$d0 w:}pix-CcόtK݄ 5[cg@sE&S$X ԿjA$s(Q/hzVn1 hwx @L^ vjhG7{>ZB ?T>)||ʓkG@]U1Cl@l89 %lYՔ,6) q15^w] >ϯGjkX~ɂ7Ȁt$ إZW9Hth~:Uob/0&wa y:L>d=g|=+Fҁpaz J7<^- bS;>R4~SEkR~-"QaO1pxu.**WRٞ |9KFTZ"`*kJhq](7*>t\O}Q$v5|KP!۠0SvXEԴO}lGhW TQf€;fj V/C ]~"!(7{-Gl4Ǻ=ˊq}V`QwV,3OF1CLD2L%AdzUʰn^ f}t䣨yLh X_W 2 )qNfU,#*zV|Yabc8yDȯN: } P7#P 1%.4WSn|}t;]/myҝTs%kkoo[ ]>?py'V]$j,42Pf!q,cL{.ByQb@ɵEm6o~Dܽ)dނbQʀx9&A#\=9qZ?VV {/sZe^!TAB&T*" JE kc+O\)&juvSCp,wPsx%\1[$s& PX>d&Ƨ?Γ҆#*Eس3~ˠbW"rp6Rs[bv5wEuR(G /*s촰>K!鍙P Ţx[p:wTZpVG>+u"w;ҍ?\~{?<ڏ>Z8"b.ؽ f͆K}.2($|ьg&1mD=!n7Dꀫ#.Eu}ƒ'dZ`(<[e鬽5In4˚y2+B=E-)Yf6Xi)4HBb-mj穰>A@$sTf_<嵚ǺGhTS.&xeV̟0lHdϽԟC41i1)&z 5Yykj~%G@<=Z*>X.u7y *) !/;y_f/Nkq]7|)Amσ Ce+MzdQkv}J $(8OBߛ5\E;4wVv%!8Tq5ٸY I0grxLrzirtkWrJ{'V>M)5jj#,\\ 0L&3UoZ lħNB=/NڬBm| 4ܚ{d}@i\= zW}>$.}]66,<+Ka.\Ϗ0{h;\)9MFEG!΢AKP{{xV-}G|q:@ӄ"{#T%=Ǜ•~iaDr>8~ó'o}݋ʌtOr&RZ֒:?]b[Y_0ڗ1{Z+V[mҧm F kD24Y8ŗHܯ:I$fi.zJ ݞgX;bL܊~m{HIݤ\#=\3=^=4S::ȼvX쟗D۝eUJ VR@}I@#qKĞg2D,pZʇj5e!55+EyHMrׇ;Q ؃+NyKPЬQ IVJ_-ft^U;V'2l_)x"~DF5jHd?-=%LцEBLZ(”YSy%`" dt@g) _G 3zFJLoV_&:uŠEBH8ªlΥ;O<]A>қxtCS.|XrTJBvBK]|*V?vɅa*]dh SU9n ؉:.G5Dڶa-MFXW+>bQ'ތRAI|$3,xyŽ JtoKw"bP)~5;ּa?Hw0;2 ӡ*:E8ͺbW;,"SqZ&LϞLS JLW !Pʠ14E9E#{tO ʋ2P¦% m)m,{XY VAOV&'~d#q*H+l^N!6rl LIzew,3Ѹ JBDF#3c`75 r!~ôIJŔ5 L7e佄[ 3i"0h&dp9J˅d-}}4e®~> x?I)=Xk `E:I1A1->C$fVfX:ըWMCȵM$B;HAH@W\,hEеggq&CkxΒ͡tZ$J3zE7=͞43i(ՙU>v)0 o^(p)5Cהx%r:q~IPiNJYYW$Ha6%u/oxCLZKT^=7/!E00{h;ZaJ6 ^-b2Et lZ~iLéx(Nv֨hSY5Nm P2  q@*Vc-i%R͔q!d%\TׂNB-n@LOZbaW燳Ԫkx>KP^CM9˵d!S`2}Fi3,WAkз{^E#_ dͭu)\iq3!Q fBktnBG6)D O) Q*()[Q$zWU|Q)f 8c8Z"#-[IJXJ7jjs=wtNy:*Z xcmSD` koDABTFf$+:z:i^+Gwl#\O@bň6^S881 HO(*nJd^%DNox<+?%Sq/ɉxlR $ax+Y;?dCd!YЕl nFBL =xz,#e6]he vBJI|>4U#(1ŪySdzX/=XZHoz`<.+b6URa2A9RT;4d9z/03XrA>^lёKZCnx9[|8DC*d.[} ?3+R.&U AOAs4PQ}wbt}_y˝Nhe""i٩:tW[ǯ՝)Eo^!+SPǂBtd+Bݑw^2GE? 1:՗~蕝\n M $%Dڱe[`ܮ0+O !pX+`/,; X F;뉛RG` dv*^s/a iO?cA ge$ƚyx[ʺ%"ӕoPM^[}Et&xG 1}71&) /l7 E”[JЊH99!5I0FbUI,ϖA֝ !ା^:N!%:]c͗1:4YW.=~D n|I;:e0^M$a{ɀ{;w_҈HG0TC[E: `=U,`֧ [*'p@) "N'Jdߖ Rj jq1Gq',Ʒ%1^K$"$N_GNS|=]|Cû5.~LZsNyʳ4igvZE@ֵRUٷ6`mBT@B;RL,]d2RHjIU/TC2g: =c7: i2'V zTr@ B\S:dW@Khy([Ӽ>EjFq]i˨Cx"R.?7z$:2W(Iolڹ]1,eVݲ dԋTH;8YPM?/ vvp W)hV;A W268s8C^<AO2oћ@:zջF3K O$2T~ U>s )$'%h2J'<̏'.s/7ռTX翫`pB8ZsBr{ cX IS5uܥ ؘcx"Ke3CD_x KG K)Cq|gdDZ&UUbp)A3{]nye1W{1"@Z!wGi…wmn-9 x;oz2ӧ< 0<фð^J+T'~)+du§ĭsE_lN(H|z|E!+T5(VtKdH1b=S87gZ'sEl/3& hs0B)J_IiҸR@RB;PAu#-ĩfi1- v5Kv! X3!pu^YVbّaiɠ7eR>Z}ē{K!kf!P;TذxXQ۸~ׯC&ZvC)!@J%#]il٦  pf7CbM:%ݞZTVɭȝjMJj6[NqYY\G u%w7u>ҢZZgY1yɺoE+Ta$/2,!*Q?@n\ TN\Pg5^j*ݖ:Nr(6"j3hVb/Pj8YzyZfEYZMAyT- dlŹWfrŖruzybԦ!v.PJ;,I\y[h|dЋn_Pos6Oy>ũ+pK_H;;۷`2e-tq./x*PgᾉvW52Srxc˰y-zr2a (ĐJGKWBL9r s/Q# "#xJUȜʏ`Y Lw~ԣٛuM1qQT獝YY; ZN\ #c)TmhC $6;j^̜~^xSe։)}'1q8aH&#ɥQD;!^)ms~F!.b ]'˭র7alh+vVooFY9U jީjypW:ҫҕ3&h}{߸*[od/lm2y% 3o'f裭<˧ɱ}lc+ge9U`,Ez'&>q2|1o15j&;k`)N;DT 1.i%R%[:k $CzvJ~֗@Up_Nds# 4ꤼG? 9 &!xA5I'f2G84 (ɦ/8z,O1fɡϏ&VmWc0pd"e,p,'%;o F }MIT$ f%q OЌLB*i' K|1۰cPɼ"2¶eV &㞀o$H3p(FG}?:>pG@h .$+#?{ѻuqlqz<:! W?_>Ӡ5^w'dG/6.~6let>P.,a5TiXH?L4\uS]7@uXmCu7(Cw1WdBװֻSF j:{1uzmHfȇۿnךU})tt*8rІ-8AȢFKU3Ҫ>4I0wj˗F2(z{z/ckϣo΢(2<&u=N>][sT:px0P͈.['5='v[q=Du}AM(lyq~i>#{29vu9\=yֆiه):28 ,qO 5~xAj^߂0isL* n&으/G//`rͿɝ;EtPO#quS$wsx340031QMNMIKe(eŶE:{._'/,9#59;>='$(58*U/!~}߲׽S9jI,.IK!‘\]V"vB8TejJfnAbQ1H3MӗlC,$uz -:MX]H*0)=/?7U8$3/X7hJw.ՔO䷺{5,3¿/q>ȴ )C݁>71/1=h17˹yp`X՛d0ԅ^5dE;\%aʃ^6;0/v-9yyi@5-cϯ) u[IX__'7>\zrFA+fŧhUk fsLԙ>' ڻR睑c"H6Z qNBM;Ĵ>yI n_~DU 0=)IEi)`-YIUɎDI [q`p/{M;iMT;%Ũs2S9#J. )Ht,dpʬ}ojCq*`XDRdixE9H)6&kWO9${Ȫ|9 g%nMk*YZ5.Yt,w̔T̒"݂̲ĒT`^rԏ9Gb* =9.;T>鴶jե<<>R_dt@Y}W#*9S]KCTf2~O,$Οq , 3LKnZ~Z"),*MKL0۶}E⫡jcV"7dQMCzo EdG@&fm䬨5hkK'/JzEyedl{Բf n>_ lt L7Rai?A8p $^ 2#hIci}ȒXilMIl$n#Y wozcIc۷o~=v?(N[2*ΎI '#,pq9]_1=(#܅ރFoN,ƗyC`@"u-s,wQ!0^ցq[?<=8`F2& x>~Usv1_ͽh>L3nt93I`{ߑҏNP|۫dfJגoiGZYYˍei d/eZGcxr[ns}*;ՠ//ϏZG H8p h#x9Ov'd|Ξ$:f~T)8>vc8n V1{?]A4O;H! `?5,ޟϏZ-B Z`2g_-~ ϳoDY BҲK 'W?yD.>&MA]-kb_7LX; bkgV.wÎ71=Yp&A? 3g Gp,xK9z؇$ Ĕze^Cjgztδ#x(q+?vkk| ~S=Ѧ7]5'Sz6?Jy:.Ȕ7r_]UĠ$KDvluŇc>H-% v3&bSilKXZ `Q;{W ?ܪg4Iڤ.*zH4ƢBdx[PQ k d%[OBă֖9ĞoX9t9 #ly GBٓXsZ%P HS\"; ƷJ5=iit8^$Iq Z)ψOdĖ"" %-/ y h|ʼn(YحH vK2z%2$E"b8ȆvǮc8z*@Vdpnz1ꕥ;&Id4iZ^H3go{8v$P `\0逗rJ(\+Ε<7-(.BqUЗ;»m{2U$ ]vFȾtvN(|b :%^j da°t)Q.ӋSDCgÏ3TEY/%:}힚ɤݕe ImF".GU. Bc"uĦ.˹!Ssa?U!5byLu[.!b"+O{Ie ɪ4@Lޮ64hFUT[{/EY{% nOE5OҸWM.(A zRT4DIC; 6  /iv(\Fu)Uzi$&))Tk @-2jaYuhU*Rx+rEc%e(͹5}aS&n:!QLsX"۴Z.Nx UIt-[:S1;tD^ ljk\u 5*S~e $!CVEcuXruTrvRx[&y_}[aA7w#cc >!Jl2;67ʧUQzU4e$*TbJ@QJqB*ތ^ φV&Vc!bȏwGf+{A'U}O֘, ,(N/ԁۥt`ZO&MP2]I*KJHl:5@8,PڴDڨH} fzV9E#w芛*8B%m!$EKiSVH>"‹\J+aLS5 Hkj7_i\"d,R2+yIF /5@x^N,dݍt( n"ni54>_LrGb [F :E#XPkcr/zs* I=56xI7dA}Zԑs1\?`~\ YB;a=6>57BetuC eV]S ₭@\ "?Tx+v0]M TfdڂIѮi. W,@:ڠXu:&65B%R:ckS;puUSY6]t1mԟ1:JUD 2p1;ex(RJd{8Z"ڂ}O׭I8Pgsڤw\*D`ꜜ"s'!3T^7*!(t3Ќ+:~ aciWH6/ڜ*5vHFuKg= 2 V5?\uzs)jÑ{E=)ӳ qrit)=pStm"Sj0*O%3Pdy_Ugʹ c< sBZ-@%д&*IksUpmWnTKi=} qfTg W ў ͌UƼkTgF,]`!rj;Lm m rtpP/K:*I9H螈mx Gww7w?b*OGwBJr J*p[d;N][]Tvz;\V@C5 <r Ce ݣnp Qӹ,USK#۟lėp; 9x340031QMNMIKe~`Ԩ;lkb ٩IE) +;n:_0|3$uũ%%y u/ㄴCfYk9JKsKJ'~B[ˊWk"֠Q^T0]?KcV3/Iy(QYqh[2}yAYEP59E |}GpyS`y ?6\Vzsߠ J&<ўȣrosq(H)ͭdd'(yosX?gfmߛIV~l<? sM]|p夶%)(fڰEЉ@1)n9͗K'ݾ'[/L+I,׺o'?WrqoS3! S /:s0yūuWBRsKRuS2 r+v4јc_[YbXv_j4TaZvfNôoV ȗ^~t׮@''WT2/x6yM5j0Kg< }|Ex340031QMNMIKe8W>Z9Y?B%%&gd䔦ge1HM9o^3r% ҡ!zJ RKRusr  Rt3R=ffzbeq1WQ'0)usSzʦ*&~+9Oz2_qކ5yfϦJ>_܈]W s(F!6OJ6:$m@7ű}욟FSh5~f6軀x}U6O1 P6pw=鴿Tc9T괺"'v`GV;e 3o<A0Q0Л&DHSR04D+k)J\k-3s ]Q֐QImpDСTgG{L)vd{1)aU'%OaS&4.X[ap[p).q<: F{x}&`ATc~.-91I-9MaQ3B-m<GfS үj[GÁ8HQ ̸G>7Z+qsfb2RċMk8 In5܋luhOv D)[#0!6WYAbI.PrL12 $keޤ>dXFx2MzNS85E^0ӠmT%mZ /ċklh(*So<͒#x340031QMNMIKes ϩ^l1Ŷ[^} HaQ_[ZR^[SǠ6~̎(5%3hԩP}.>]SUfUe0/>ee;u"*(\$(hލs$Ko摐2x97N u] .]tQYR ?$ũ9i%%@Wa1{rZW׭)-Nnnb^bzjPBŮkA>,jmkmN FRE3~Oy+ m иJf$?N0f;c P9V7%$}U5(6PRlxUݫ0nR|iمaP^"Z4nPVs2?ڱKLb5[apɵEMꤢ2mʦ*#%"ߍ eq<6eH8 ¹ȌJYM̓]`IN[U/6M:Gc{dy4 okӬhۼn*}QZ5Ч)w۴F ƒKbc?bBBGjeY'CI+>w1KQs O0Q-5$yD'=(2Qi:dJ;ֲ 0!Qcgڼ//v,Vr%# K܊2{-#iexL"& Ea`3>.iԦ5hHiЋHQG7ӮÄvcX4읈yoyp3|^ 9Srކ²/_Vh=yR٩Gi,vSY*ղ|< ^ Gq.$k1,[DgOЯ{IasA.ȵ!8 +rl-On` :nx[{F9+:`pgp{&!P-$N $ߥ>Fڙ}gvvfvva՝*;;:d=޸x{u\ƨ:]CTGv:`2x~a? w;Ŭ*F l`M>}̎`~Kڨ:3;GM(?嚞X#>fKY<{NCcˑ:gna0 9I9I|cK>l7Cw9scqA=P-?%dq=8[F|*4T~ .~l!:dzo5ls υmhv$w`'a=^5E?.Ϛ}vqٿ { $0%DR٘ǶEZ1plb9ӸS!&v%4a~WM^@HV"Og:Wa|ۿA 3w؉a 8+jzVr$sĝͶ7SU܉fGi7s;e[}ЛnQ<WjKmOyKfL㧘ѸUw `Q vu"*kVJ=Y|ݑˇoun;i{h];?4RP5pѶ:mA*=:6\5K=,Y7[l)l O;%M"(<) /*o[nIv{?[ K4_8ví_vNI++E~%YX rb%ɀ\s\0&5nk ~yVL bv1)\^H|<-Bi;6P=xQH| %q.-`(a;]vK\ {}38k~_VyU`vb9uV]O@<mzgmݡE4`"K ~{Ѓˑ/zR{^m%!!│(B󟨈%;3-n=A/}#[O7SܒxPde% 2܉ў<^du0*≮,`Cj dj]#.k42;5YITX 4B/G D9CulX8-KMZ5ZԜ9Ό@6|%hIrЙWB{HWd+U& M)kʺW}֭<]#arPlky!)aV" 28j52Ă,oſ#"v"g&;oJ&`W@EiJj!G $4&vߑl*N3E6ڍfJal'#lĭ^*fPAE$ ylZc g&?>!y4ˌ5!/3eK8 I&fq =2Z)裃xZ#2XOĦ{nRD(UO%5)}@ݪٷTgoވevtDQNm.53hѣ9P(((ИP]ASI =XRb^.[0=~eALr<֏PawEqb2OJo% %%d P .'s ĈDOQfX$T|-%QuF}D-_u(.VjT j<$IXvd vW b;215KJ=h" b {O^u0öwcE@?QEo8/<Mi%L 9(&c\KjtOI8\<#o <@qHÙoP},T53NI0sϝӢ*l1ܮ5Z@+|Y0BBf=$)m⨿ҭ/|XYOjTp8H'AUTiXEg5^v?oT`njQ=Zv丮FpuR\ƺTgtSz_E6dsX}S{+#t z,vĞAS'TʥZ#㶟EV N}DppAxܟpm* !drMQ1ȸve Aޥ &Sy0Pٌt2+R WĒe/e:<-8/9iEd4;gckسp7hodo^jLh=AQQjia_D|ž wˠ+jO# YӗɎJ8`;5S.n#HW6`*'iګj#=_i{F~Vfj?ʔ֨B)rŒ4dMg-0oa/2'+JmK9PJ@ ODc'!*n$)%K6kZrH Z+AW@o&G4.)TSRV&G?GwF)Rh!tU@Ocy@b!zr. JPМL K*`m^ays+96`bj)9QG~4fILff{59TFB'y~?CHD3Harlh+GV+N6(F$9އ>\cqKTԂ0c` .CH2kTbDcM]ɷ'dl}[/*e 16yxB1j*MbfGa7Y,ˮIJ :3*HFAfVֻ&hPFaSFLãMZ3c]At BƖk+kip]c*Wkfo)w9qNN0v}&~EH=z}S.kBC2`GRa NZ6.U]ȋC_Iouw2OBD\ 8V ~ݾttfQq4:+LQ*3swLrZ3T^soܧϩ"CUSQ)㚺Xy gj}hK[SY<%4gLVDI*E BRpۏּ*#llt^&Όjk$Ajtge%vwHwߺ=2 ?Tgc{Β~ lΤ1sj' ҍrK5.zƕsy5Lo 222<\`S$̋9Tʥg㽈x K%CEb R'ePV4)`ӄ6GLlb"b` X[a͹$"D&:{Och yVl&6е1D|Q2@nb)U.eZm,ݲa>4q5Kq3(S)6ysϒF~g}jBfqgYibe 4'>ksd)Y2 q|P2x340031QKI++(g1GX{K*2(MNMIKec4IO̸|_+*K/NNLO,JMKLO-Kf?%Pa3fMħ#QAl*|o >¦ 4=3hEsg/mdkGf$ I%9@q3&H[T5M?_*t8}2 V /NI{VIyOCf榖d]Z^ZPܼXKm2ufnTWvRnrbAqN~rn~Z^A^:CSϯ7c^'VqaUVng.;6*p --DL*-GrλS_[{f>M0u}sjJߕTV:,x}v9rS('D9Modp99}(EqD }} (Ѝn'ٜ{  BP*l7f{dM2\5? z?I^652oq`&6:__ % ӤOvǓ3KJnm&Qw+,AE0/QrFɷw.|+R,%Wy6gɇd g>6<ϦV>OFٌjALi%z3$yFij>˒,zi Ai2ɒY6˓588LQ6 pMlgIMӛ& d `MtahIU";,vfln O*K@p@$O./vv/~|³1f!n23=}p:Uv޵?~u~쟜%;E{p,9<;=9om%oB+#5$ƀcYf0́ݰt3 p7N a!SxnG%h={ +U#kfN.2)KNn49Ax1fN^jL.wl>;d;][7kC={d[__ fppUz7#̌^FtUUq3̨z/JoW4 A{_θjW۷Cpgpe׃Q~:9j{'y+<>{ҝӶ]el<6Q\QUs0\\5c-A|GU;}n?B/.fhf F.5cm; C0yQ]C^h2yѸw]g N%M6ľfT@" (g$!̔A|TE{֏Nvң㝃YzкHOv.Zd CMuߓuLaS{oudu:ܣ{`{3 w[Xƣfaƣ-w0ZAdLEuq>>8<DְnoyQCҳik0i6:3&=lwEaEΡ-f`a {Ý^6{t!iR.Dd juxhPlIۀZ€/]U9.)Ma Ot*l@Q#ڝ'ݮMjiIF 10 )0`)T@RPd)ѡ ,Eݑ"UwXiK^ *һ7Lꂾ_eofo;.!FtG yn_1V8|\Z(us[%4G6MWmK2XV'5~:h0<.f0e1v.y#q?xy/]Ohv %1ZR8wsҸƛ@`1" ͇Fec##0'L]Raa:VL&ÇXH `݋F:A 1+6 C(~J0G4ƏY}a秧c)R:Kfec~3QDkaWw,ft^Ow4ĸ cR! hn5{>=%b}bu)Ve3\lu/ |wo:S$K? 9αڷ#kE|lJ uB^C?+6Caζ>jbvRaL Y{>n+ z'v${>=.5m :>l7˫h6oX\C,6kn+e^$ء=־6C',K+.9<$L ,YI+д5a9 9'늴tư4&$/^e`C-ZB|EZBo(%g-}sx 0fFwOjEYU^0KX]+oBwd 57DX \t ѝ*vg1-ő%0Hb{XY\:,| |IQ5Y/vQ1C0 뫕43tfBf Mo B);Lh* `hű PknbA[q5 77`}3 _9tri^6v]g瞏 BZ٪ID*J 75bjIGwvvb^u@+͘}me|p]*&(x̆IB "ha$aJeH8c&h!Si$<vX[[rw;8]/=}1y GbEq8i1>OYʱzAC,G.H6Oq[2j\:xv3o(l7TS۬aiXe:hbla 'R-جMoR:bOsn p!]Kz6NǪ tcoKaℎ.VI6:d(,iAkA[3hwRM1/->THM9w\b+$b/Sԩ~ڠ-#vZ +Y(dޤŠ, ȨxMҿ~h=T}y*P?j5+k٢jmhڴ2:[%߸Aj&9ŀA0aB,OHDnONɬbKOUqMʔ^,r8VA2*`$>7ء;S~Ջf"V0nD@MGִ|zOfn {x.z5ÓZ))\d&!7װwfœBlOm ?B"}Ўd`ŧ69h0oοwP`2u`R 5&܈xc- uM6dIErTؿ<;o=YEan{=_F5%x i4օi(8 !pF"QF~$E(XbϪuClGtUdHh`IDEF)/QB _ {FcFc%9KoX?J ,#Ͼ!L_Fl# 虩qbU+j7OT caFMֆQ/:(|Ÿt8t8n y/Np/t~p2Az7#vH}5G8'Aشy5 fvSe^l . Ǘ6ΧpmG4qna h^NT-҂90Qd-S[=84?F8:ƝT۞R1 5PSyyB ^$/K^5fQV-f2Azfx*Z ?]#Y4@U)]h2)CaOx:ND* |s Wve+V'QֹkLhRB̃t!pF#)Ek>-2#fyOmvEsr&SP7V^ײ4 oYh~\RB&zP1R?')dd"Gc{jdND b72SY _m֚=L;O؀#nu9{38XK}/ &x!Y'͸r5<>8nn~?3&k1>8_{Nzr(גʺ *\tk8e)zU\WV 7~9> qPﰪ]'?z7}.0 *LVƋ+L:Iga P,V-:g0 :tlaq2O#X^iXa2\&U6( '.Ȼ~䏝f2w]:3~R)r".| u ~|eԪW N~9,U7Ozsdw%=2Tϊ&)|`PXT1i% *N1LX?g X6h)AZC%R6:)pHfuvx{uv䌁1??E{)pS$8oFY h2vޒu8iŒe]GpަDA"C9"Y5L݊I0XJ ?]IOȾi}9~#'mc#3E+FauMZc@tI%,>A+xVX.&zF/t~FK&RihY^Ȧy6+,D|4SqbhgC{&Ẅ 3p ŏ(% ">K<11Im=3qKpo6M/^\Yc$BUJ}pgI*&$WlO|ßTSj@W/*^iO8!-,_``<aU\e?hG%sNfW?vœ`Y_1N|(XF|ëQ30J="CD '?~彵ڛj@'`V_> .MnCq9+.#&ǂۻr NtTy4fj"䞑R$A m]~n$+hgTƽR~H}R 6|KV`\/X D.ZnT`s/7<.,T #oR>a$ (f-_g-9N'Nф`VhFmOLI-< & CsϱIi:~Dԓ92N.Γ>ipP1vh@Ix$ܿ rnF>!B @ZeQB̡jaCK,Y&ۢip`w b>(r;Uh`TVEٷ`NѼ:9\( "G1>`K9 BmR#XiXK0izJ} T rǘH?(5ʮ;Wg&Z\G<}croͽLJpHdF? #Nu}g1jWO['d^a aq1E:>^T3{n/f sIסNaM7n6hy`&D&;E]XA.ixP2 |?)^: %D5AΐS I#(3h:!raOa%BNy~R&d0{Bp=C3BN=dh8TTNzSM#&iLB2BRZxͰ{ܲhabr5f3|z(!8R;J Dlyr`98\I]94Mnd|ٺ`WY\Q&݇piqLlv \c|HQ:ɺ/_5rL,БaX$+HU̙4ү:Mꑟw@q] Dx _ nxNSPՐ{pjij2I? a(``^/l|/P@{j@D~HA7Dki_pjȔ|TKei`6YxA1%ÂN25xɔQAiLM3kb1Q{{"]&P`,CGc Ƈv!4bQԳ pk->6O8Qm8UBrX_ʬRщ%v W E/9@Kj_'>1VN8 2k]7ryN}fcXI 9;:ha@!' uu3VO$1mv0ˡiKݙs51TJdv-\|ָܹL#2G@(~ ؅b./ 3AXqM;2H-τM6cF܍A77 g/HHX + hz rQL߶1Թ&AV,YzA:Dt=2JL= vz0Pe{)iG"q aAd+|SG4}/CHeȵ60XSmsuu;`SpK/N vny2!>]%p%DzNvɿ%I tIgPO$( Y4cFgjI*yyL:F̄1+iWySbT*,ZiDu)J |kP{g]՗~fPb/ ["Fe¾˲$,(H1Ѿ;r"81OBg|2x"&D EoB`3s$e d~]XlCܸs^Û[FD:Ti)e;{gEPVH7C3q̰\ӒI$[LFAAAٴ# feaQbAOT.}ъh+3cFIkY8m*Eݭ) \ 6t" hOb-,EaMȧ%쒍5K>*!{,QT-7wdcJdI `3,)׈V! O-|Օn+9ܙR1SkHI& )`%}/˦Ҟ0 coqAnWh2i,IBan.>XJ Ks܍A3T' ?nw0l9 ,J?i dLc5L0.X ScX ifOkt<6C!c$08X!`oA ,[^%I:p?PnH7+\ҵ>et!]&AږSVcY/)~?zJ+/ceጜ՜?{bxd|a/gW'j's k;[mZQYtJu[\bRUAl`[)hjBDNɜ.bY oPXrՑ<s4e_M+u c&`Ě-c & K\(:f}`saj JU%v!H~JpKx1A?R]Ed=+Un+RTjctđnNEB k43ܝ"=l> Aů9^)]AaF^uD2[uѣw\xU\_u=z|Y Ezgoes`Xu xSx2Z֦Ʊ?HW1JG,”0~D@Vu~ߠDA$N$ Pyx4"QӠdt Sn?3R|ܹHFuc(G%ʃ)WbD?20=G]fҨ</1$MR7WB\hsF{5#XIBB3[]%.ӣciFٿ2жE`1E LpJ2|WXeDsOpB>&#HxFhg," \( $O6^8ӏÌʖ^&ŚY_V#X DZϪI3q*kۜ40r?ɲU<ԐGOm&O u.==#Z cDKUTSXw|dCKZRՠiVS<^9i(C0*~wyځ'tV/T_t2x rm~(k 9Sga ꌶEw#,x+ֲ'TTSS=ʼnEEb[Xo6ibGH>V\29_)_Tiat,glj@^%mR<2/d6.˚-qR0Yɧׅ+PQGxȾ+^ (P8ʣ@-:)̄[q ${BL#QO3(JE#DrQrl PPK7a'OG&Dy0Bb 05WٴQG4S6>42ǹ AhE,5CT@Şt;NY'W %[,cx6"X_?M%Th__Dv,OyD8C&[*Y&VOl*nvj}Ty"c1L<&geOeW_nE<( uzgѿu7XփQ!@;޺f3ih!xq#~RM=\BTe6?X]yVib:vObyɸ`6Gfq|b?\ᒲfh{Gp/EğD[ZCp/^$34h{ev>y6DIyZ9" (I9 `UckvEQv&MMWթg?z,aK,apGΰ|kzzFCdpkNY$( i]ot69ŔV52BBv-jlTIJgJRSvQp,U0K_8ˠ,>lQ_TYZ VLI_B[׵]qE/>4|`5T Z]A%P7' =i͜{@+>#-E 5xN g nHmu]2atEPIU< \] e@jvn"e\T6l~%jG,@B[)\/oz QKg 1upksE67D,n_ͻ߅w5B\bP-d1.S ŠNHyyI#}rIgdj}9%"?egśw7B]h);Ȉ6F< N1TPByj據0Y7IXn(tC@aXm5ŝ~ٱ}5ȥ/\ ݔg:Huu_ZHd"0_H$Ɋɬ|>P'Q偫t{ԲU]Æ/i/z CՉ,ԯճ HIBUUա ~#ԌO:VD׈>|Թ M%BTP0JS}`~E DwrD]6!]*;Xv92F7ۯq SGтl1P68r$DAڈ+g4NWv9Cad ZeOԐRNX1,ˢ`vVQ2@-Fq (gL9M[Ƙ0̩DxlFnT-o4/,2= pRX_Y* zYE`;tFPg~tM gmb##jfknԥ<ڗI~e rEo,Of*ֿhN0'qQW?vBRgN0;k2t{qt.wt*'jՌPUcR/)u/ @QeE)~XКrML[^oUb[AL=ydf6 [[> G@ZBGuR;R|;O% <-vXI|ds9,!A$B~baى8dUE_0V..~(R*zJTT`X̔-RҰˋ',n'T}(>KU`~Y/? pZZ^d.C!I#C&4(O*PTʅƥ 'tNG51},VW0U6= CQ" uB1y.(e %[1Qs27VRCt3.;TU eA|9=Csݜ@H0k iݸچfd7dͣ2A}>Ƴu>N֣8o<->Cs(L602qvpM%H=d)").jv^dd4g~mŚ`ryW~6`io{u<&}'nZΜF 0s邫esvq 0t&X~BtFw>kK29B9 =P2[}kin WUMc5g UT@qQv#/'mz "4i %4CBEfhOL]A ?c#BLxTﯯmf-.?#"upɧnLzx2BFR#IH#e!HkV5lSCL3JJ,$IadqXTXrBfer0s8s^-&c""" YD#ٜkW&JVꂕa_#C02H]Ua+ yeb5&C٤Pb7Dt@㯙6[1`7RQ']$ ։{?kͰȽ9ycQ7We{w|Y5$ e|0f\QExY>N,#1~tӳjA.E=^їJWD@ۣ:"N9ܝՃ%!tE)ppv܁Z`(V%AdWYZw걅#r|+U0齹tɕD[w& GJuuWn25.#egc ILphGޗrl$CbkvGDvؓx"]m >H ;k;=1*I1y,H'& *t S^XUun #z(ɳLz),2 ψX_亽,C-TɬzKg_[jMzϵS@yyOw m9o7-+G.F%j6F(8_3u+_Ҧ(rs'/ G]/twq|_ SYL6j\2bWW{% ֒y_eI=yRrE c@7@Q *lՈO8X;CcK){G">|PY_̓Pē O) (ai&ÁTRn [S2'YOS >:\ﳇ 0K*i % 8QJNspbiF+uX&8tUIpR/tYv;'8h쏈$* N}ý6e36aś6o.bH'N=4ęD)`clNvz%\zU2}HISq^V:F)7컅VbrF)d |y"%2ir0)m&'G0r.ڠ^kOfG`ݍᅣp7*̄ic5=POs0|Q?@8cm4wۯ㶔Mh8Wj!=GIQS6pnj>:_GO\ A|$7)Ӳ# rDAR}pc^X д19@ uZ,>Tqw>(Qn(\@7ɋ8T;w=ЈH -%C":3;LK*5iPQ%N**>1J);8bv./R_O./jnb?Wjʋ.fm$ǢlY_^h@_ B#qsK]khCjӴ9' +ˊ jS-A{Y-VLfv~pbm, {GN| >{*OcӇψ7EpxHj|FW>e[{l6`0n- th^/GA ÒUɳPa7ϋ#&\'),V=cJ-4mߪՔlNzoO TbԉUT+!UbQCL8lGIR6!,oBT'Ms7-\#y{Y͑Lx0Y0iX@*2I{!M!CU3Ah/!Z+) ;&`ʔr􊷼K 14 7_ݶ IqU;ìmb)YB@QTԋtFl'NrAg5iTB65"C` xuU0,avvy|L.~wT?+ObM+&ԣI3a/ ?n-#R̩D~ -;gS[븛y>ʑ@'3wE;LIUfTR4]pVky {}B޳%&*vF6ebo hHYoPF'9V,|`e~YҬ$/Li*ά·VIb5xK V92eG 8 r?UƊ=46% AWD2.ƁcUMe$j |qWQ6.N6i`?aάm-_B M:^h`۵uaA=SmB QIM<٣43}l|#h!YWKbiU}6=eB`BWdZ'e WPV2JV|lf5%x]z@QB!sPi-k8wkJO?9=B|$g@J$6<*v >_6 S(|=F,^`INӝT`:9gi`ӈ7fLJr= ?樃lz퓴uvvrF. jݥs'v !q+x}1X^H"d lJF _3 x?ӕRN5˗CBDj!6/_ I1;eQ l(}1qse(+v'_r^y{.ӝtE_ 峯..*V)mGWy@QDIy=4=:S)¾y9hS!9cvϜ NN/NKE$`U˶ol怹zJg=GehV˺ujX(˰J{.^jMW\H l CVOX>b@{YuTuliě~SJ)A/Tyi`3@F≻cqQ*ⷸV68fkxm$AVA B3&!C$]!?` JxU-ceX$ e嗨FD(l[OjK4s3s5D٥@J_ ]@Nv#)5mCeN6n=%D0-fʅls>0=ܷHzO˥=sOØ`\8Ɗl 笾Qh=;m_-"Kz(gFk9 5k s"a* u؂dѐ Wx@v}1sJͮHSme ]'_R!~IjL'婍u=8OE;*:nEbsUF7lMؕ爗};Qra3xppέ^=$-TxRW.VrA/'[6a^îC3\9C;nsoY$7N X281By冩$l7v0c) xk,x-"ǓB ĞŸ ћ#)VGˬhhG3Zgq`W4{ , `ҞeOܥEDJ[$ynV] vig’XQ VvcA+bXP̪*(R,aаl4jO^TA|[i$䞼oP >MAA%AhmM{*ڒKN80}Xo)@BOLe ri]*`}ۖn2Kiy|jR#C *ϓƄTs7)sG=S:9T%:v)פqK`*8Ms+_XݽӬTSM2xf姰K;e4oŨK Z)Ta[Y) "uDrd1URݶhuT-x340031QMNMIKeX(oev׻}=<ð,U/75%3Q7;X1!Yv_^ke&ҋSts3sr2K~NbԜbS8AlƗ'j"j&&%%3| >i[)Oד}D{ZXRf𶏟]OANizfК3=͙T5훣VB+ i)N.JM+/--)8:ޚCݳfVt_ rMEͷMq7J+XV˒_H-#^uQPA[ZR^ uf_lV3](Uh{Ut>ԜJĤ$`V0l]N{+e f_X R̼})z ̡~~ f46[UzJKKuAQT{lz$wCEj U[Z\d0MϹ/"m[ *H,MLѭ/{[i? l^rѩxvfE /[.2G'eZy@I<~_,ͽ/_j?J<'ǓA6'?|cw-^Gkj[S>?&hnO ,˒j?˾O'ՒY6Y~\dIH,A'{wK~,ndn_$%Q>HA6gIMӛM6L.UK8, d}>K?JN22a>K&StQhI݊^1d$M.d9Ϯj $I~ꞿ;8O?'??‹ fwHX~;*h;@ uޡJM{3:wzYNNgݽYrzqvz&IDPPC+Y E?ͥ?c`n4Lnwxw Bjn4_s7#LdkcWO:YkJOf׻/ru:Wza+ɸnsI6J޻a1oJ,g:N8TWJS#0'tb/UQ{O@:sg` sKsDw߼霥gS&݇aVt<_$׃ &| ,I܎?a,&m7jzV{N$вISV3[ua N?XQ2V<8^NF$wB>)2O ͬp ϡ{TqXk[!M2av?~IHgܷQo*K_8g(ϳǴ<6T/w: Ч ~xa±t+7%)dcԢBiw݃wYwlr3s!93S;r[ɿ'y"q6RoyFprx;&VMN@W,Xwb2޽-`ca laoukCzp>G'((NP(%"d j`XwzON!O/@ד RAkAÈ{gg,Wᑧp#.|I?CC,\,ZJO:o-XYNaK3FӋ(g;'R!؀D[E˘> ҋZHnJ}@ix>n@tAygsl!{X&J찝è,P CI-œ#@K+@Ew7Hmf/}br% ނFMKtH%"90MR*!!1y͔}cQqE-/kHʨƸKXW|y*d'HdZR!m򗄌v#,7<.+WsZS!w=&d_-f<6>}4='T6\2tIoz #^wp3&c) .PrWyRT.$Y RZa^{a,FJ Ct1kco&\rߩg| OX Tئ3TB+ng R S*2S21z˫Zh s@%¶)%4*JWLڬ0{IO^d+GW3<,PK 9!)%$=,9Rf?!F2 ,,mMYzɞ|ʱ{;& JT\ane] &,] ukG" ɶ5R"TO铞cvW i,Vm |ʋB[Ǩ܅[06ȕ ZAmXW,> DxtO[,C^|<3/r +M]f ̜QGrXD~e] mxNE, 1u]N`PMw0I)]!=x6]DZkZcD 6X=6Dx}9!3ؚLibщm*? ӕI3fX} ~4(a  ҿc Dݑ/[{[ߋpTjX1A:_u͛#?̓˿AJ;ˮ! حakٿ07\kYl +b| Ym }tm"h846n))y9.Z bc䣓zB`n'ow&N؞NdIʹªF<`'ݷp#Oū~>{wvr|Ɨԩݸ~Xχom[,V3.tSҜvadC+̺ugfi2/oJkhU;xx7=VO>PmlW .Gm>&"00`.FEVrEt^ٖL}CFhpͯJ w)7XqsnB%h;w;Ij66s|={m|u8dF`[J $%mI y _\S@#/#~Pҍ83Ek,) sH.رl2oiJ GɦpW/_*R3Q6^Haɿ7is~r M[BԡiOM^ Tb1G;k/b=($|ކtp mPXΗ)ðh٤u{746nz*t i9#oTu"3_1SzsNx'ԕn i6أ WHoIt6g!0 f"BS$! {l5C0-$z:ĵd!zYJ^Rqf.3[ㄶVM0cq[Yς!՗VkxQSScP!I@ )BF":BF[h1hz|' &DW}-hW/O=!C̎|yWD5թlS͠ …+`-q$aN@Tف\Weqso3B1i:|m7wJGM.1e&QX4Sca2+ [-uaC6t<E 2aZS2:DC~D@<@K7ΟP/OHG#()8 5F2߱ƎJsv&ٶ>oGȶ$O->طNyCckAmjd7ݶֆ'D~ش`R+}!y=́eCJcpg_ʛ@RoaNp˷/c;pV;S m6DL[|B'VEj6Y4Q4F yNQZNŊ7Uʶz Ih&cgDq@uxNV:3P1k> L{߸+1!_&S@1ب.*GiRGhU;Y-.V,L. te@77E2,f%M\ʱ1Z-9DMZ:-B3iB?z = O1/IkQQUf̆HQQvADGck+pyl,ExnϺ2 :\8ՇpY^1`^a?u=ϡMr,=xh8 3M,L_ <_:϶v,¶%7Eg|c_IzcOasa'ǝb-, =-正qϞ]8 >f[ІKǥ84;.sV;Ln.96B1V;$Y3B3shA$cKo`iH6fh_ GI дUѝmc4wOoXӏFD(*_Q_Š?MBY$?W*Ǡ1'Xe0QL1NgdY40qgjj"j0B+WK Qoo 7Ev߶3J݊'!߼4!߼4:N{6ryI敍,V$0DH1!"D=U$`*\;bSB=JS2TR%KPPg\1W~9E ~r UdDҬf%[Fn""i,h~ |#NF;#z@L܉b98-Lf!Yr?J|Ajb_֦ R(D*oڡr46u#ohS±rvoIFzLemf(ۥy6hղiPt sak?ϺHjf/Nii$(<+~0˾2p0- jĚCoS"D&yMafʰ>p̣%δlXWn~0e0j<dTI+֮6Oz QF7aW̝I18EL5 J$V浄D`y+WI%$7Y;ɐmZrEWy3Z۱} *(@' HCM-\g@HԠ$eb ^9^NEJ]:*s \Fv7J3F aJ% ȡ*YC9t 8 -OioK[Z0_tT6L::C`PAkZߎ P\7XAJv#o['Agٜ6d)g} G9Hy%~w>~я1bs,Z>_!村0yL(SHl$i&JK6yzז;G$Nʎ LB.SۢXct .sAr}P5EA\@V  p2')"S$$TZ^;PI60$z~S#]p9F"  { (  JaN"0"Py5+,;A.O|ܹNܥȻx}qIx8@&8?vM[ג&2ޫ'u+:T?[mA]uOen( y1"v)h+)߄+ m$ bjgp<li|a[/nK k|nUc@*.\)0sqBfQNef:J`gMMln~SPHYUh,4" vUW?#hm p%D0PJrW qsc z(KNl!C{:AH`rkElÁYZc]fYz K;S FU_/QST2눢'ltk|h@n ȳss8oMs RYtSpH8$jX+Ŀ }OdcP- 'J-"HŘVj.2*`f V,^ NG"+o j cĞvFn3Vj KaZ #}XCI&J~e[7v̞H?ğhZ f9*یBcGhPWbh/Si8:d\%ٱ_N89k`JZ$(wQ"IYz%2ǹ0? EO:eĎ). C#X?|-n|y>1R=zjBzJ,@zi2*  #B.KiCz&b)+%f,bHgeo xy*AO{J0/y9]9u1w&剳 BHن_Vu1U @,TU UH;DSW<+&N0' 46h\4e-}$%=C EҲHzW6QZɻ;H rz2=S mJ_p8;甔W+ffcUqdžzMp]QK~456xDђY? 4=h'!ϞhA~0ECKJ;PP Ho, ;<|{u(p GO9P sX!9^-Q0veGcc:g RuۅFUhP4DHlNI`8%EjZSϳ{($d-'ڍol*Y0e5jV)aGJY h/\1InI&2T+(>_T-ObKr wtiv΂**ӌ o mY7R7j[Bxɠ6I3lfԍT[ej KrLi/a{n`8$~/8AM1“S=4FNH? H3lQ3}K ~<ZJ𩷥gBrfSJ{yЭ2TgZ,- D"jJ&FD%Tp*cGjJ- @{:eڮ&6:P[tk)ݨ;~Cn`;tmĂ$ɔ"Gb {^I硄NK #H%͐!RB=;31SJ4E\ ak*!Ħe4\i/0]qxEFKd򢪔jx6iTD@NJGUs٩@_j3iV |&W_cq939E(l{%#k x%/]k%  |}!+)o.P8gP 7V&-z0v VtmءӴwrI^WѧH5ӻvGmKnYՀTŸm`I}տ30UQ"fVbdIW&.XowᯗX\$1E3h 4e=ڌ0Eb_w!-+FK,`*Ȯ ʻjJ~Z?LFה7zqQ:å'Ҳ \e qo?ᐒzG l!ܓ5a$Ug=QOs)"Oz_HUJvW鶃^tvP) kDE1z7~;m%#CR1O-AAqJS[]kWÅ,!oe1yy`fIC *r,ȘU laJ BxcE } =A:n`@WʅzԌT/"8RI!N穾S~ dɻ86Ϸ'g{3/lcY|Cd(B<_p$bPv+d=TEX ʶ g|cBUjk[>M@ omϨ(>4HES?/O:ؤ5}o__Dk[wߞxNpA_dUO(5L%:o%{*/8F9*-f5ɍdOEr&W*nFZئ f$ܒarB :MعE-ƍRU@8<ênʣF7v0@r6]9XAj}ڂ5?NdP?c ?HuϻǸbi{?icvIgid8CtzON"4R[[Htt#\WXӳIגcc ERYwnҬ#0oz}:l͇^Ũ"f5'4uIkjc^rLNos)"vlZRDm\ju ^HzG?2N;ж@ _9_TyclV ͨwPWQ.X~_s~ <.*#Vgzr\Vr;d g49~WUhC:M+WweBZ@t & ~-v`h@nCɣK1#4Q?wv-SʿAvq =`}ԁZCHYXg 䶘WcIy * /h Ms|m3{@Ä;TyR]UF1b%n'U]s$/+O𠧌 ^{1C~O0ʳɨ~5l gw7I=°3)Ȅ}YHAޥt_O }51b`p +S@SK {sĿwK6-0n :t~ʚ}52WbS/"p.jo4MlQ$l.>,?,2Δ"N K A2(AYq:I+AĐ"^Ŧic,uynXzD$+J 0G@"zj{P&U *`+qK!waX7'"Qcd%U L)nf3әtKV&h:8hUOp3mR9(O@rтi/3{uÀȽ1ݰ^d,Hbt) 5ӈ`WpԉFш&ӏ2bȧtv$P *{`ωz8gsP鹂H >`;}ƨ_bl ءEFSD-ɬf Yq'BRUMKa,Dp Uˈ&ֈ[wYL/ra_&:@fF1g+CNsc\;]q͏bGݿWwni<%sMaܺ%y.gnAhܦć؊;`C/r]ڢ&V>H.Pe*(|`Ld~~ӨM.g>mMҋ2'@Eds$ R78KF-e#2%5uK|ʻn˞.2n9(+$;Z(Nb4_qDZVB|21%N>Tū1Fy/ҭDmL uAF;D>a)*R9zC=𭦧'|t3 Xm< &(Q`&[[ (޸X\t$ T>6RW!A؃9F13caW)c6^@!ϒ1? =a6 HIxgEwC"Zu4K3 ]"RL,`+)R𒲹t0 d :KH~梷bc9#*1pLai|{BxvE2#ĿP7YeQPRj2X./^3=whjT!A=CpML346&&,F,GN@¨(JQ}L3MUECT+SMKʉp ! _/d;X`8`̰4Ne*PMזö25EuB(9\H'%/  `TT`%$ 46ꖭN]5 dY;`C t-T5ibO^;JDU蕝-ZE L6~y/8_ ?bKYvxd]G¦0#k JQG"eWY%8 qV!ϼ UuaQ4Le QAE+(T=qO)}=/ra\<(.lࣵ)ߪ;mpW-REIׄBUWeDNYh-)ll%V4A3X,D\e@SlBz"Ki#|VboRFv2GDYoAs Gҏ['eFy ~89E7=jR.]5s96;&|㭪L\xKYcɬ?(al'`3} n[֥^3߽!p 3G2;v tC:(`5z_9їrjIOF ~K %4҈<=Q5R҉*|;ed#58EnQP'X'r{=5I&W=e8ƶDe>fC WivDʅOOo8 JrGNEJϸA)0srWlTr?c@uK+#9CQ281hBRwz#FɳRts>H0ig@& ߆N xk@fu$9LЈ3&2 x-)eI7Pzv#؅˚ ZMgRLMT)alʴD@SzzxC+W|Le Vj;H['03pܸZؙ~EY\;>fe3 {ț̱6?*e(=69m^jAE5o[?? _kA197rlʙ2xaRjQYB:-RYiә(T A"VʠXRJ LuLnHVjp'FжV uQqtEd$jDb`?$K>Achz$cjo7h $Ia+D9MŨM#R[KDh2IbfAE"ZY.+O}JAZ1hNvj<}l]c-KFv榣8(V|D.\D*X+a6Y,ޕM v'7/^lSۙ\{6x^k_@`}wqvycs.缩+4φG x&;',I^CBYi]j( h 8)ludSXr[V|E!ǎrOH wQȅ8!5Br%&[ЀT7y+g0PdM\EFqt,68"$T2bʔ6J*QSk3h~Oa9!dW?ɘmqp>EK "4HKdE$zq敔4mx >ɷ.e] Zd)H_AL!"U=أ 32ȓ!԰THfjqE -6,V`x:v*vR@[he)/e K>q \W |bS}Lq2[F_RYâoch2iHw `-4,jfxBt,Y0*%L 5d8Sf@N]`seVbE[bjDnݏflt#>XRq N~k>P;~!XgD`M*l#&4V uX,g4‘|IzĺET&Hd]kj\Be-~Q,T鈡%mRh;upxP]4uP.ؐTFFeyq]"q']p1Ԣ .LX:ǟQzg sZΏv2ۜωc<$ +ŧLR2Lk0l>i\FJ/Z'Mk$*Y9LcfӠ/p{9މ01M;>W4iл!/,wsN͇5@=`)b0A.ns:p%bkI4AQkզ 96q}O 38fyn)~ dG=,$؜gMۿkRyVms^wf3 ?M^%іYr32L?ˁΪHϢՐ!nO%`=A7P;p?cGZU- ,Kg,asPfS;aswK \l#SZu>[8{la))噔ֵ4tS}||e-hءZP4i3(\%X# y1s5udck_KueԺqjj ^]~1F[Juoä\aazn1{nXIKw=ByoS}Iʪ|pĩ?kW&}ɻx]UÒ<'ݼɏjZ~ }O\J `\B;&o#6kj접,T}& wĽD=ËJtf\͎v&b-]AJ& B̐7fX/,d%%V A+UY(lO:)H; m&/}-g%,CHB!w2ܣW`iYneB]Km_ըljp2)^cM9EڔT.䖂s{Jq1P!ܐ&qjI')R)^k#:Vg!)m&g٨ Gߣ"ֺȪ[ 1L0c! 3i_FSf}Aρ<]OK A)1 s$@Jql;^V1?d]J =6* |>?#9 7bd9NGdžeF&GmQ~}[U| )#ArL!exÉ ,2e]34u-̖) Ġ]sG-j^WȜŶBО~vtEkGiLkKW-Bi+L0 ^һ|M(!K]$t)@l| T( 槑\DN&n~=Y5{c ךH1/x l*UזkuB+yPr:lOjbzu?kሄa`&&1'bq' vG5* .,~L.rܵ>9^ԁ쁶ҋ H$yY8\wFX傓NpEev ?$ӻ2&7& z;6 YKO/cG¦c-tW|#maAPr 苖¥)Gh{gv2AmG~hxmlBǸ݈GAWٟ1&EܜIc)-=Dbt(,$~XV!]/ZhYŇv+H TVcƂxH%ܱyBNzqB5OmWjYLpv]I(SN~5AZct89fruSݷ]Ē?''Gi=IM-bmz@ ?+40>O6Pe8DU18)Pș:bsAS v|5lK(So o)ŬRMF3g5`igN>6(G jC}ΠhJC=5|w<\LON]|C9 ӹ"lD$LfvPܽ0]\@lm@LHeocdPizPA$(at#cSx֐=GνO@YlAhF*7D^}~LRms\%@s:.5݌[y֩pIN2@\m0jd8Uˊ#x_gOg VpaEUcX"UUXwĶaԦmYK".֬w;[I 0qIˉ"]NO~Nת.z18 uhXU@5`dc'ń0Z‘0(\1̬}\ޛCijA7vzz~iSdz 3oϘZHj/p8¬pYk_lcA-<(.svo@3U)UAMUӺ3=l-E>=ϛHegc(8.V|UBu|;YژfS&!tO/8 o{NWl%rXJ,.. Y` +4K-=Wΰ'<),.Ջ̀7`+i@1/` O}gT$e؋0 44uXGqb|)C[h3MlQCH!*D"aczd[J vY=JyXBmWt479%W"'44&C Qȥ T3 1UO[A&)DZ`WvA8H}!Mw!t6[avhZ[I\Fmׅ8kkLbFٖ)D;g'i)pR 3ER0 Ҧ'6_${@%e|&ڳw.a>(v wfB/j-[停-~ڈOaf>ns9/P8!1bj㓐ںT.b?,s:y!4xb3FG*Cz"nD4r!pJjOS ʘ􀟏n!H #”VAaxrd")4T;6;3l#=Hjr`%RM^CzyE1-vm뢰z>`/wE&CVlX9 p%-x`Ij] J\hD e&"+zM Z{1`-d3ep\1leADOUSgA8u)F['Wh&S.0(/Cp xpp0\.ʄ/=(8aEӍ'of0>acW#~uh^i< +:L~!¯,?F[ FR6u)g iЧ?IWCǭė|#햅ߣ4~|adv wCtրٯx1a<_xs>%k;6A=HE1v*YHPo>Dۏs> {AM봏M3Z,h?Q^iW1E5+WbrpYk,3 W#v9?-l N4|[d%,x@V&Xs0c˘8L|Yc1Ne &g7O>r璞]\_Uѽn2Eo|MI JH BPF)sŃi&)4A﯒ m~xr1A;8(co-`!wc{ut0`}|WLZ-kk'_Ix!ƳYWqs: K¬>?Md3DR7Q" قX ͗󓋽wTbḺҀ <GU8 a3E+/6_zɪN]\W^7ksVMm>ZL4mZ{8TձdɺY}xxatx:3xo)- 5Cٜe@2B *,QDD$ ]Xu9H`wp#}{#te O!CRL{jhԺ夕Hűwq>7y8-YTRr8%; ud?,GtTiז*<oN!0ncbĞevb$B[ $(0|P}靟T[L&pX< !@J-Ub;AUCn}k\k S,ۈE5Zz>ǒbA-OGo#I`@YǏyIa"RM{} KmٝViFd_<\7F)kȴ  \p'.O5+':`dsuةq5C643O^ПNlT, v8|"H\$k3n= 0JV6$W8c2jDZc.6o[TzBPDPitʟ)ڏ>[j8IBa5t!N}'EJiG@XH [KS1ϯ{R-7?vb_kaKJ$59Y3 I*i'l'cE:Rcv%py6b>t!z@̳d{OOnanGs=<D>H2'`\1!s5 !bg?dǖm v*kkE2[1C1傢֬ 5Y.ѝ V kf~n8ŨC\^ ’C?{9qK@\ iLUǥeC,lPE5rոԱTII.J%0E6lֿfiIJ]rBKG&zmC'`b 1s:_JSdef7.V~Pl6B\l9J;d ,F-*nSچ8/֌n|ƹ`HY?;V ay; Owe$cX3"T FX9!TeI jEDXbX^?Q ȴfo@ۃ)jbDNɳL@~P2ˊ4%tO"z5ӄNV:MH@ҦZ,mV , hĠJEV=kH.UHIo I9KD| 17/.=ˠP$%Vh=R=Q;DwA=IeMd]_XԢ6ƣKъ)3ZmZOC8Ԏi <ґZ#P.iC$XY 9xLKVY U+Z"/?h"sST++\Y9>(+= -Ouj({%g솽$j^(Q]8=^rY70?/FF{> cUU. QE5R}_QĐ<)|1ӿKO\WC+/``8 WL+R}o 0i`\{>粒356 q\"1A68*fnXѤT|<@$N(t K)_plN/wAzXɈ' ZD,5鳶x1ϧ]/Fz!WA/MCekQN)(W2Ƽ\g;lɟ;A.2!ny@Li AHۺfLU@d1[U8c CG|XW<,XޕKizD=CGݽ c z]\rcY-Tr&Qr3!{W_P)NjuF&V)FPboZ,4r2S-v( J1._MR?a? H1jNkIu6)"pM\'Q2Æ_HP`4;3ə^pB[Ldӝ>_嵠piI!.s (MIOw2=rSUG(g 5pa%-iZF$Agĝz_Nv,]gFj.ELvSFX+fd$TvHDp3sraB !!h#PȦj0 52`3qTem* 1-)nƠc $2 (V,HA+e䧠xC :C`Xњi2ݞG?`Vdb8gs /,"1)Niޘ Zg-;j |Mm}gn]pSt?=H:Nu$bHcX-҃7Yc$X!LF6NجUvT?4] HyX13rQZ\^Lhs*VѦ2-GEc2& E#0_!e.vK)M6.7ɦ$&Yb]NPI"c@CG3CSrI]*^7lXW׿6WvTNѸU'iL u9/B&q=ĎT!k]m+Խf-#S}xV!2t-wH!/F9݇ہ RBQt Dw"CnoUؽ;Ulrjæ^ZGl!N}dbq@79?I{a\X O?x("%&ۈ(PngS2Cc$œѺ5˵Mqg^~h'$Pr$JO螶߭l HX4 XS*ӵJ=/wX+6z~uUQ N(]sX`QE)r'"*E"2,bw:\s87J-I_t0NMҸ5(F5 KZfy :G] \eC?:x*z؛Kq96fM(e_3hK}0b 1K7\%3˰YA j[W 3}ecFJNjBo?M{ŢKF?buD!* AAB0gs'Dʏi ef5 &Z܅HheC*sǘ2X(]iv$_j=8ZfR6UnbQ\fbFS^Md h$9t4Fkud. [cAS7&+S3+2s!=8vңQLW9ɋ5d B`3Maa"3Ͻt#1Ҫ5}XY=7CMb^c5ZXo_Jz8yȌ“.ȤLVU=IY1džS*Et5Pq,;e>"=Y6V"^JKW=1fNpIp>f{X-/?pz'ҶKr3^2OK KLpyply =yCŜq%6ຖʲo1]p} wߙun h, Q8bwa!\06Tk<*9!= QupA†59PoI4[ 1hr:veB YLnrJJ\u6py\Gk"44,khBK=Q[t ,~\qk1$̥n"5xJBǾ{:_A;]M>ϳNn^mbbh 9|ӗu՟T_#Ի8 wj!r Ywman3u̲㏆>V@BDQr\,32eE.J 8:AsFzjQu04**Yno Фu3Wt = ʫI먂|4y3eWkj.夑)M@ SdxTd1.zSx ]]w6"oF5v2Ί&48TkJi~3ҝ;vK韐t>^< f"{Sf4-䷛)\#IwsvL%ôE]=͕[{$i,6L2ّ2^zyӮ7`7bê,ds~Y2X?R6%hX۬:ȊtȦƏ'7-{ngæbNnβk3MQE{D'Ya<0U9i&3#Ngg4.ܿz&(uڛfzMq[N)?:׺/⊩y8KO4q;7ȶH]9D4kwh!rTBhjd=;-|4O颀ZΌv9ZF;߭k̆mH9dܺ {y+Lk{Jy&>-ATjPaQ<鄗@e1ӱ 9F9QHRZZ/HxR$77:ا[hƮ |fT^]2p(yjW@.:3V7%Da,psGZu%9c6 kI膣do1Y-z0v'P8fK)Y/g# bl#>vy 1H+TL' RB㊩Cy)i̜Mp0(El2+ϲ+  'iU((j<6\P~_XsCCv xCr$=F^z>nthD{^>8Y85F. µ9Q 9 xď n/Z[_.jf &g:_3 y "= B<"КƆf6ŁMgG̫"P\sL:ӓs58 <$1򜚢4:1.!htNYx07<#pIYs48ȸ 57#a+}?a8v/ ؾnIJ]#5rB#i})#O ͗sǹN}CP|"RU` ʨW1gkFP1i*(1 cuNhq_&vL7oN15X2X.]V20\7 IUlF!N18š;, r(g'@c^߂(t7`VqJK  .^u@ZȒ:ZRƚcyUi ZF8) d6{J縷1դg C55n9vB?aMIp=cs?;GVRQ-5LƹưCNG=WrfHƠCƒvk^JSL 2^fJ\Cc=} UGW (\ty#mZs u+"1hѵf~$*F xJ\16Cq>`gވ#Z6`@B"^pEb4!FX"Ollʻn"`6K|g_vd^>]N9Ip>&i#O!-UDt㒮iXFj(&֒(TCK5&v8d=Xv)Z04:Kkfe\#ub9UzKGH88х+3N1P ڽ|,r/l H!|SdQ"Hblgb(8A &XQ/`Vu>f.;%g5oMlB2Qe3 :g&9|bQzOO)F&^`kB"u9-km8@z=YT( ;1g5Пi}}6p|;&}VGdi[uߗyDd e zP_ ~`{ZݨiOdti('qR+[3gY07wR({EγWco[#6T/s&Sg>9c,e,w_*QF\n? Wz4l6M7QҮ^#/WTk7껗CHJ|a'$N=5&+9e `t(+~ƎRBP&I?-Sv׏ t<Yo6?l]vOדyb뢫ݓbٓbGNz\C<x:Zʔ^OC /Iˀ]NW37boE3Oޢ,Gk@; G(EJ7Wଢ଼V)PvE ]Jyڶ|_8*GZ*3j0#U~l0lt~E!P_³Wr0*`J,Q؆12- +[^VB%\f8os"PH6w"NɆ Z F {}qLYx\v IM!>ÖinUgtt=+*G^yr,X*+l{&ͿFv4>PȔ KRF<ȫR:t&niYľb tL޲PsmPdVI1 R䁦 5Fp5Z8:yXKN! 2sk5wR1$AaО\ȝv=)/Ram ,9[F,f+@PzTz8| +;W`0j؟u0W"Ȥ 5SD*1dV[fEQ|tevU2Xff:9 }=3,pDξAT?(DZp Evcx-_' yuvFҹcꪄYmgF; TRD$R4:+#38.% K ^z2A͆W.sp'y>c+4ON`HMe)O*l@Q9fՌ'@O؍PQV]dwΌŊyVb'4R5_…wGo&fjm; =Җaۍ;T4}k*6 P)Ƨ[.kMB f4i2#}աA2[}Cި{C:-#hU*6:x340031Q03MM-N-)K/MIL-J+*I-fh /򯸸w!B!Դ̜T\W_ڻQ<[fk| U^5R771/1=H/t=>({fKn '0xTى~~뚎 4=3h|r3'˿z"p !ML*|ʱ WV]UJ8 &,^)9n'gP&-y ZZ7NyﵵWwPf0t,0g\#Kz3>)I-.I2lS\/33\ļżlxMo0WDr WT/vH .E#jzl`7$rd^fN9+VR,6iZ[4?> hL_! =I"r]0. L`gQp}8YWv+f|~E]'83E.hc{'6I7MVե[uyvEYW+v`GXD݈A`/KJyUNx!%0-cCՌAӃQ/WJi'ֱ_´>OzF?x!jA^yoF G-Mfȹʻi$HYJ"a0pC\N5u!m l"{nB n'|4dy2ࣩlSlc' j7I]jUr<8H$`8 ,GOzLD/ꁢp;2Sb]]^7J.c. ۡ[ lOcDv4S㰲@x  :Eod^HF6!mD^1EU$HFux1+dr'Mp^z^~nnqjIIf^z.Ԑ<Ӝ}_{|IAd`zh՛j}wSK -rx340031QMNMIKeثDz;S[V^1(K/Nѭ(JK)MKLO-Kf K~`Jch{3r7oHyjKUnY_T_S4oLv龚:2]^$i!R׏7&Yv@"mhWsݯ߱Вޓ6b##3h>@ڒm]eM(6+Pg_ſ{ o;!&Og*0W݂㘏5l/PW\Vmg>Û+.뛆HlĈ^z^~nnqjIIf^z.437Mq:{gUv~~fH"Ɋ.x}S\G.է8bB2`${flEahڂn_XgϓYYuNn9vEwd{eee=\VתW^jI5] zӳoTa?څ4ΟTkGxmtr2OђcܩVz<8=V˛+W}S28?t/ WǛz7{ZA3< &xt:Ƹɸ߯&UwR]fƯ`2f~5Vah\a)kΉfX㸚i|1F'j?쏻z98' 80# ܝF'Uxl0j4&0)!WK[y`YU@3ltaH l??d@I{o__67v}ӳ~P ܎57Dg;/w";[Ջjz~뽃: 0'Bq+;t[:bGT HO|v5_#AdFVvO\PoaHWϻj:q~z6LGիW?^{oTo6¢޹|WKǣtl}zpz}ٟ=Mm`v2ֿG`5B^zw!@Stu}s_6f7OCFiC~Mkv9dZwv ~ OzǍ:llrk`WC BTW]j5餷.@4 /gӵe\u8ANteԚG'`NYx;6ZbĪ\]/=Ο_m<%~yy:ypkyR-ow}=8Wh@6Ha{+kxKx=\Y={/:?nA !d0^GLp]>YW~~@c?B{ JO0C+˽my~P}Hv/& ]?}P+~l2;jZJݨ!ٛm鯥ueD74{qXkuv:M.4֝;K(U\_8}xJ1}x$WKw{ th?t[nyW#‹6`6;OMGϟA_Bo\_οwgQtc FQ7./ϯ78ֈ ݵj .^FWMy O>CR=pTkk 9> 3}Q4Ň/ u%qlpp%/.9q}I-c8 ۝̦q%,M\Db?oj0A?~C k$HR'ɟ }2g2l h WFAH'Wc"ƿ?O܁ώmֱ^1ưZ_u&'ӣl8;M @[uB%Q| &h6MӅWaICmSbu;Ónj|:ï%?.R *m:Zrv]=wUxP[Lp7b(g25P٘*s2|hlnHE:VW0C˗ !U(0~hhluVt~I/*lp|V]6Ւ2m,B$8#Îc!bmyBW$, /tcF _G=6O 3͎tG]_m!<hc_^B::˔/;8a¦?_翛Y@:*^"l"*h2;&X˴;T"?zKs~GqP/⏆_,oxyyhkp 0"~"5Āu`o{$>W"p~4ɲ 1' (3l`X-SIYttzJԚПosX|hG-[ Vymr0ih68ExBЩj.G5AzqXd0u\,|dRz\:|-`|'J!Pc%ӖQ[ݿ_L};lW?'>NY0z_Ehtya~1#}C .1O)&¯?W5c`yg&ps[ 8W-f?QbrZ-Wi-xP{IZ.vw[艣͍Pcw6x@_ Į.\\.虼vr#lL`U楨ʯ:; Z"ۑB&D {*LwJZli /"a6ewl!ܼXktAu!qRe> ٧}hHllRh# {ב%lHLȼp/K7ptHP`P43qhpn満?-%ПjڵKڑ}ӚA{{%DŽ Liu ZJrq_LB( yvWA!߁$& PLư7CѤA{tݟ,UP)Q(bѣ'4Ф Xje kc#;yI@Z t['-؝H@cr6dnڗe _SH0F>OyZ:hXr(^~`&q*B;4EP<O)2';|q G%_εWk Q8.o\HY$)}.V(c]͡"ᚨ$'6d {l{Ꞝ1m|(ԋD,ZXKs4q∕҄cbJ1iIzHVg6I('XDH}u%B1p [띓vzV]pWaZE$"A.~35zZAiu(7T2 ڃ3y+~8.ٰXpT({X{ʿڞeЃVmԙ!kv2_e *)4suG0i;Ў2lA j}S,{]9<=lD-.t:[(uH_EP.rJ/D[nP8zH{]Q0'۝"o{jYYa l .ba峍͟m3$\| ަC =V%t_O'Ǟ3XW_D)`CZWGiy+ݛ$UgNp1`nnnإǀa6)϶21RZZyϟbF Vbߪn_FC6.iPwu .-"'}AIn75pq9O4I+˪EC8W-̹;w^A0 ޷]~l3$ 37R<˘TY[&9n"m{&m"+tjpyG(*rV:(uHoG w )_]C:k<::Fw;u̧euKˋPdp@irtN'I=P$8 s}\"h):i#Mv2zS$N|B+ 'M #b܏6C393#:х[ l 7$*> }d d|xZ}׻߁hoD} Uyxzv#6(/:/iqs{jԡ!}KQj`w j@P!՚?m,)Ըx +GxČ-L+U=h\3-YX 2B=\8zQAQI+q*B&1xp=u&|6*9Y :DbDԙ .!S9 7ڱah;T^[u7@OT: IÎft4no?du'FWul +[Bŵ.9옌~)d5E}qovC9_ #N3XR!^H}O_n[+f`:܎ۨ4mmP}EYUQJ P~2&UdmW?k˃D8u\G]+=d0RR1ԸJIel(e6L@E1D?|)-z'rm=ņUU*Q:?S~W[9 AYk`Lj5&)OU.g,ʊvYA7~+Rhwp;"A ָ4&ѹU 1I\0 PHK ղJxv!ܟlh U투\_:n(eL9"jz`HA[%뤦<&mB۹N> -y#>ShˎRY*4h;2A(O/}uKqp9Ed:FV;8tvH-lL_|Iv-5 Nl\dӤf#ske| s(àF@%+6UYe Cd9 g D`}ւ/.ap:n-XUZl:ܔ tðѨxwC*3[32~䠵A GAXtgyBnrwN͑')zn&\IA%H ;งs3GcYY ]h!ew0gj=悁zeGncJrބڈ[\]WטR=6оX#gvsX&8HF "_ ]Xfysd}vQS(ϖM,-D)STE0MMi6OUkmbMKrh_D&869HvvW6,yjH%5x =Q@XZ~43<jXfQב~ zUfd&4J]ĺY pA {Op0X ViW88Vv5[*̄Ј^omLDz; bg~Šl{F̿ vL.E%PZcPR o9EVN[vЙyLkxhz3 1ȉGXn_0ШRo1WԣNc 5'9rWy!p0% |9aY-g=UJ,FA :LTE\pE\{i'gsʜ(r:ĂGzP 8@ĆfP`]C}xn域dD:30ލ-A=<>]td("+AiAkkNgR[7z<I^:xL-0`Q*͋2k*ZbRJ5\52tDlcb@%?S@4YqF1[[ᅔ\7(F D"CpJj'Ynl>(Z(WR4)ulʭұY4ﹺΤ{=`ir>Ъ!T*f%E%OMŅб D\kh\ppzW\:' HG> E^=Xllc:`ЈEwvo.jye9{?}nOQr*S.\z@K?)*R`B_z\7Z-ANStRJ[do^;uOQRR w`ξf]7.WӷNrY3Ov+G'z}Xx ]l166c]>U/ "4SmMXurF5<%i,>.}gX7,aFw l`s֝mmxAp",iٗ-2 'b\V8AQNfS K~b,>8m3 H#n€R:H` zMdk1_1f3?76VnQ1vqf+ґ.dVOc| _红=lS[3-#2PtFVHP_R9Tb>A\>5]^ȷ~9%0ƒ#qѹA#b6 4vru@oSxeM1iv7P2"Kɟ\pJPn:P#v%*1Z;J5 ".s:ަӕ6-a ~77(z TYؑ2TzPe?B.Kh~e os@XbA:}iQndqX;0iH`JܱAR4<6N?Ღ˧oL@XD@i,6c"g3eyAQHz(NE`N7Et u)>7Gz~i~ò49-kH]UGsmxrZE,#}b-9o(Zn?a5@nfpdv(jLJkEZ7C i;sUH|k[èaotfx@pD4N"ū/Ck u R3>k4 Gao&arK] eY쪖l& {|REik5v#.T Tr8Gؓ|Z Ѣu~z L>Һٌ@ 8tq<"[BvҘtk 6UUsMY(aPiehۜag]˦gf( ,oiꟁem2[e 撊겤с 2;q]RC--HnbhX90Il+"+>+>嗿'0uc rvJ= wk7rQm0ܫHAjŬbX 0- Օm҅P/dVL5 ,R͸E"kDGW/$TcI[4gX 2VpD!~vw~V)  ,[_L;s̚3֦宸Xbn3NF.#oC^#G3ԟef+G(ZufZ`Lkm:Z;+*:SЗȰfVT /ϥ"j?^ՔcXD8`sOb8Icr$>mV⽂SzT(jSu|r{Z::-N!ܑ!,R9%U!(X87JrkDϽǛ$Y4ebM:5s"8A7hvw2S;rE~U[: qeXJdI(H Q.?0`vx @.Vլ 噋cShʫ,Z{fC'.!XΧ[{h#z*GRz3tЄ#-[`kOiJw~ÆN}ۉ|Ɉ?Z7SP>Z*K5s}~БUMP5$~AV$ ,NO"oP;oit ⠥gs$C>aA-_hIHt2_}=g]֯WЏI `/pvޘ k@Jt~ooyyys9:|IXL* 8y+WQ:;϶~yg~˗{t^j3.`1cFxG0Wok6 zֹ2Ξ }ZHNs(t.0*t5(يh( y ^*:QrT&6}>e'-O>Iΰǜ5Sb'lL7N{٦3X5,?l@k̒ Sj$i >- i/~Èڬ E]h2kf& `toFq~2ў` $'؆E[|t1rZJt3jLۺdFL6 53A"F16?U_'30sBYPqTA*+Dғl R'lY4]9ǝv$c:H(ӫ :ZybX6ݕ9("6Ϡ׊dB6?Z|HvT󼤢GI،3c+t澖Rehas>8F~:c1">a_<\q@.\3HEP0dt+?m(8LP[!Y֛ ;/S©GnAW & u\6}&PFD+bu߁0˚g @lGX'9m9Z1e:7I: +A_ͥ\b+>`0\J4ddE)l\Ol(-Ø?X7(K;ab&uCɲl,u52VQ݃фKhYN֓8~^FAW ]"|Lk,T%$a诡JaٮxV+\Im<+ xЪaJE㷠Jj&^I!mb a#7gr3óE'õߠ|9M>Q,RSZoVK! +L+O hx_`׶ՅXq?M*9CZf Ed[-HY>{cpu &GJzkK8h(!EuYXvt b1?m@u1Gj8g"%w;2Pۭ{<ݻF^ O9-I~uLNP~8:%N,*Ɨeo<;M˔GoD34<Zz&d0=I:<ٓAJFNႊNBl6=X bK!OlUSI6 SrfÛ0*hKQJcynOn⃔kV3uB&U`Q"EZsQ]URXvrbZs6+&erqvG2⤀ilBFV(t\fY@Fa$C #~ b_REԷ9ՏZZ%op?Ihs r;b/[m^X8.JDyYPr[szgvOT~wd/֧,1I`n!YUkQZ[;`O |]$ Fw Wfvm?ҋ M><뮟꾎ja|~|:_?_5W9`LH' M KTwviw SI#J!>">n^{8 5V2i0;'XV.}wL0Y@Z0Xl:.a( :4"4![LNiՓ 8'DnF\ Lk]KcΉ%8ځ"FpKc|eqHj_uqx*'BQx4;=FfE";+?O "] ˺Br:Wl)!s:xꤙ+t 5Xg.M|^Pnx=?laIu#,Yʃ1Q^'޾ \lxiEi1)Pm֖euݛH59;L@@SAB;,  (&tA';ZurG;2fmتeOk{V}L :?+X"ܾ/wdP3*GQO/X[Q4•kBqiKrӈ"RH,9ӏLu1Ofr(Rx- 6h4>zZ7t\#WHl 6 3Xe#1gwBˉpf|i,"뿟aDۮ:]BvaGq7*z4' XV⢏7H1>,"DKsl $!/oEF#8Ńp2JlW'#x5 U@^}Z? YAcMjv_C?Ix~߲7S7s_}Y(ZÂ!DymBQ}x+G2W5 ̯^kujyNOw{EAg'_K6w{ΔWy~p m'0~Ϸϥg չm!I~jU&hP@lwAitK~B/DY)OU??ygviv i.h=~AGؼNֹN׆6Br.;ԝs`-ꚺ_ w>wi.c#Y|m OL\u zӆ1lp[΢ϯȈr` >'Lb@?1pl^ΣEulKiܘ71뤏0C x^}c:un'd=, Qk*QE!$H NI}'Y*4Wy:;Hq/~kmǼwpr?"&%dۭ & ^i/ bޜ |roA#D2֍h\E *7 ?<_E{n%?o9}<.x0s9QPGiD3'[1H<o5B}$έhqBhmWXa9'˻f=d3xŽ5PR@?3s9؟?`s[_lMn2 +Ӯ$ ddt(M.ZsCJd^&R51o a79poNexMHjל}!Th,݆RnZޜCNDrŇB."j&BSϓ&o|;{;{>,Z|DxS% D6XS^@VƳ;uXl7q1x2ο[n p;VrƹeGCeIνs$`-ZNG7MpR fn}ThR 5o`ŸȤ \T@ -R@ҽb+ 7pz5S+ld*˨ۏi=pHs ]ߞ#"-gv-Z*_v)N\1w,BYjzfH^FV5bbWA窫d~=ܘO pskiP, G̢e& mgso6ZE%@4.Ր W lD%3dDclfG W-;g&pɭAUFZ5O9)6P@)H皑ɎRQ8mhInp?AIAG{yMusmV?cokQUa|-B^v )!{=BҖT}G&2[tKNgbؔ" mwznx#+A8kJVKj(O7C:;Jh U_y[cڽL:g'luϔ'^U0tk=)_S$gO,,Lmx Ȣ3B 5 Yh?ͻAYu:Tڒ3vdZJ!Q"arv W50@R]G[ZPs4XT & μP>!MifdWziD& m566zKHi":ͫpoV;6YI(U]\ + tmj$7rYl>nӑp  t6qBTҽM\ڵz$f >OlIM1׏De`|gޢ/OydCU @4nAƱkLrs"zo[uiW"x!<Ҳ29!5|6fR%F~y 8$8nhAB mi<7H H?H*>+ǩJW{.b?Q3SlhZ9lxoS~i]"T6*lIǼ6n7_@$ɿ dƆCj~-tX4HC$')Ƒ>f5f7ථ(/ V .o/oJqƖ f^S r{]y&]yO%PtEp6 EA?1 hb]N$Jtc_nܰRCS&HLl-ɨ;-xc\y8j.Y¨2.jHFs;raUTݻFƮư!9x53ZJxfn;"qQX-UT/¾ߨFmR7`̦1t1Q'/Fb͔ݜ{4anE5궴ŵ%  NGI2{Z׺l)twu7ث2eiXa뉫. 1 M6y4XGW!]rcsا(󷳂eB""Vb$| wN*/rjPiɬaQCZL9x6iۑRq3 zZC$9Y3&@`ɾpXJ0Z ʪqvm^F2(XK%TLN7)E٘φx[u4\)4hF#oHe+ZlzxF6AdQ[}Wy,C " >&(ӿX +R-iN>t Y(ao U#[@y,60 vj'Z1ܰa?`}=agu9F #d &ڏ~c>ysp$6IhGV-u_vo7ˣoףuǏ?}f~ 2C*'[BT߽_ j8BUv |=F8Ax-=VKr̷Κ!P)*zHrwr͏nrIgy`տlgAACSke%J"j!sS\`b'~%CB̪>ԾFx;+l ԶOa,' C/'D uP't# `?cҢY;VX8qM&wX|1im,&V}ÓR{ hp氟׬I(CW[Up^Wmy۸st6:ACoya2B Tg+;cȩSxv:xHm5D2WLr]KԆs˜?6 &SźC}G븩WzRcdLJ׿Bj+wĔ6P`(G9@MXrl 鬸@H` ;3AAIYץ&x a WG7q=I.S |=_.1T_%L8Dr NEe!C@ma>MZ!=8uޱr%^r7H$|擘U{T-%_TQmjIBy)4SpΣFu,`=s/#gPO8˟gm5}܀D]a7HHc P1Et}ʣb;~V##,Yc!#}'<'y8``oe7%"W2Lt,Ra8~`T(Xޛͭ֫WB6lL5^.PVzג)~l/_CUֈ0O ivݿ ˌ$n'J *aHz\`* ( PO:qSʆvP(UىTg 'amFfw"$9mQ;0ch$(χk5:; r;B`Y8>thT%H/+kjT=%n(m9m M^!_<,bnj1 JF%Zج;hn-?{<ǯ = OIx&D4j2Hv|[0obuVU6r.?ksI?Ony_xS69=!,YMR;4( @ zi?/6A9B'S;NbpR;,ΗW*F.yĴ$~z(^ko+MGl2~x4>w5`n \"p?>R}\re'xj=cQf4HiΪ;4͙ y u ҼO,a²q^ԘS\6,SbDk"@#fʑjfy&%c6~I#8-.ZU%E@tvYnonb]a40Q6X*et'jZ|iۘ4>o9|v6<ݍ{@r[6@Qb' "%DRh7%/u̙SU9e.r2n% ܿzWTeЁl-:겴l/܇Gx1iRvV3M:ה4}# .ׂZM=sy@k . gӣb>py8Deu8\܄p#/pfbۄ_-e sP'q q -WJ9ѦXicmM||bAmP6@زn|V7"Qa.k]+Y6 OshEJ\~O/qCf?g"VW h&}T(pXO۠$hmJ秃rBy XZ:i;;eI{Ԣ~~ '&S΅oLkžCxpUf7?쌖~ *idapLuɞ\KmDYohؾhuWڤq**]-^d&acu%~r yLSA%|ko\h7m)bZ6Q}Ԏn?7gVCH]2I8tf=P )@i ሊ攁]PpcV[]M%=!j&ZjJFAQjb mJt^2|tu {{=1ktZ<}]BCP_ÔE8i"\=qՆg?E2+.:#U;,. W_Å9|8^b~I#%v-Oj=F%PQpxgcM#&JDMjmRT"}}j]t0)<|kꤐU<4O2GD$U\(9lxDo.Wv#ipӳLx1}ֈ~@IHny,,lk\< s Cgsld^wj/`~1Mi_daQ]l87(%QS',Rg.qPƦ3A ފ;fI\:GzTUW9;1Y["Ǧs1>%aȨqK/Ÿesن Bu +KdsK4,; m ? N`7~j)(4CYp`?8j68"^Os>be$4p!I1lo0-{_nHo6'Zwko.6mUOd۽ȯdۼČ;%!&bR!Y89:x F,>nՍkA88('&Q_ޞ G[i.t{׌Tj~P_Ji$؝Oا'3BrQ'aSRѭ5€M 9?i{<}UQy<0|6J3f~rYZ qSC:Өx]y8]4&5P7IdI 5[3QWbdWBA$Tʮ)RQJ"s9u]>hki(z<ݭ(\K5T]y&p{ZWe%lRT^UbvpGl96C6чDK{9Mo[%{@)#j1 ۂDM5sIӊt&V' /D>՟b@mdB@GbsqJQԼUWsUE ` ]q_0M:o)aoV m"_PegԧNpIO!GL^[ )]%a\;t}ńn])3֫eD ٟ?BpAh`QIe|zQ=QM$Nbʓ< b׉=ɠIz^`5*IĒ!oFi)@&eoixqS/Jm*)n%,< 98AzS}n<}dQ6'eaN48 J4 X >Y0͚;,5N掅Y[ IIɫUÙ1%GKtP\kѸҶ:!m;]Mc3늋a+-sZJ5X)&&.e MBɯ7)۞g˥4 $IuJR7H4o k B쑔N00+~,>:IWy ewwpY9]3\'Ύ1̚|AOPyIfAۂv 9#h#c0J$F*!1\U]Ra)X!!Ѳ^`ўQK奂Vz1۫>U[VO@-z&u!eW=@w@he캯a`"6Ct*o1[r&vHuiooN3&- . T9xqվrcBq; B_T@tk$ ; 'gky.9&g%F`Վ3?PpZ|/Yw ^/N%ªc:P#0xfMFG<?U`lԳ= #x83%E ۯ&_XR^E21YSJwa!'s~^}̖?@8JHɨ s~akgX_Fˏg2& "E~L>G;`5ɯJ~<#ZomQ]2f%t8oEFeLL׼ |z)|b_"fk,uA 0GIs ss^K|}XLݚR\ey^w"*!ۆgҮ 9/)c||6g)Hz_cqXI F~>i/5NIT_- V)5)c-țJ۩*xVn0+ȍ"r hV@DŶCR$5#fыܡ=j'{ɑV5G*9u9CAB#*-XmcO~Ď{m`F2aQ Qmw8/ C'#yG> l5olfc12մ4nGP7'T=m8=_C5G? .i \c|6*J1i,iY/'1qIHuEz}lX`A_bMp<LE wn-JIfJm7ea;zݛ݂S:6^qܢrĢY^gӖt xKNyA=6 :S\Q:(Ijnd$= x֩H_ }0m. .;*ܝ8=X x\{sF[ Be ڲsu ,|X1.DV$@~=/(?BGLOOOOOO5C^?/ kӭFFD-Ccn;k{_)0gzQUUef{X.=GHm^:AuI1Dѭ7}cYrrd֯2}";0!n?? ;s>ku͡7컕C?[b,S79z_IQz-{Z t}Z s=F,< 8y&NcYNb)Ti^;_0l]El"6׶i`L \Z%^lZ5LZڏQMjt_ptU]5--|fs37VnpbٯӰN3ܘ3cˌ|25SFW 1q2i3~zhĩb|lox3 >Eo-=4TBݷ2}1 uu*\d;V59Y eռI.W/ ^ܾ-%.L\k/o@̠Jྩ7l/PѻV[8K>E}9e^TyFE[[AzEC&~xY} apKZ)CFrxPa]wƺ{D}w ٸY7^|.W+ o``ƀk]9Ecy26Jv(pǴJi=Bxߟ z [wG, .ږTyթF6~YG^3f`w熴wk LT= rUX*Tg'\ yGaujG74jMݟpmSgB r9y8jv,#5QV..DEDxMLm䯡!<ݟ{dkð#]F d |R#Ξ=,d.n M#-NTT}3qn'#yNxͶAc=pbA w^>N*߃*VXE"t2w<)ٖDX瘡rnL0>F.WU9S;)mȤD , G$NxcAZ!깑&-vtBr;"XEC^ϝ8DKS.Kbn&tE(繝ޫF{|+"6bl:^tp8.]%M JKl``m`Qa|IJBCW--,|״qؽDcF˙#jBA=B!Dj'{|:$P)|(J!RY_6+̞Ȝ C'{[+)ڟRBY)Iחe}dJ'i \$M61aL%cq639rp6o(KwjG~藠k/k6u %Z nsE~QE4A+)@J9A`_'¯*l١w ׿3YrшYQđ)b `\db!=Ӛ'Y  Y?N0]e"|Z֩JEps1rocNB򊿻>qQ Dڇ$$Gƚ='샔R?MQ<Wtڭc1{]OT>pv0WwG#&ӭ #~M߭Smd:2ai߼|A1D&ʎ 3UK~Y~#e~RE2lS""“L<ėZCjZQ0_eYo[~qBzqXVaPyÐ4$>2HI;h|JXS =TrX]б02 SVR=~[owG?4~>;0rִlnG6ɺjь#(vSr[Ξ}h"K?`e 1.mJؒFQ/>E< :ʟ`Gp+5$OteOLs?U D2ciPPJK 㑎k@lG>ځG`+;*,nޏ DqgHXH8 Du뷮s۵zz9CɟE,aber7ҍ5F^?¹gC12OzCEiz"j4&aÓ *p= & Ѥ3J2nl\g07 gBfܬ0sgd3NYG$_xb9GO~aȰWXZol&FX txDt(pQAT6Q,g-4ŕ+T^3JbnV}5㢿ڍlPaJ ?bnLȓ9#cv^mol3/J6#Ш {QYN?͙mN-e;|f+r*,Oq < g3T(SXҠlv(#k<皅m9Yg u*Yp/rzJV+g!D&` k%O4~x<gv"EC?Qf>J]C͑ņ&JOF윙;i/ |/s=x/ d_X2"hxY3h xD!Ůbp:IibJO/F`J?wMO+_!aeI>sH-V2 H+<8_xL(Tz{>8B } P]-=}3%ѷ1XțVz)[MxH~Ʃ |U;|g,qz{7BO-#:#2{G/c}T䘸 4RW!eWv_<8b+;!)S /ci$7I\ d藿ƾHdxioNP)4P-%. Xӛmx340031QMNMIKex*ѱo^S3GO!DYr~^rb^~^frb^i^fI^qjIIf^znJbjn~^AjQfAFjQbN^zqrFjn^En^f1?~I < woÆLA`xSnsYHR)M+K/b'c91{? э SKRK2sS>ygͫ)ݼ7wafw`mz4t8ŰapF~iqjvjj0ڱ8 8̥6ϛKSJL>{Y<Ԁ [S+Rذgu~W䜸!+f%/6䦦d&Pg,(_\g|mDRBԼĒL`KlNJ|/{r,)/OŖTe3;`Br 2fsNEy%y%i| ݘ)`{grڣl>D ,H$òDu輄 >q82 *RV˖?תSJlbZCK|o{b39]>Ef&}\ǠV Ԣ'I~[|83,tXW[ T_*+Eb;;DoAd&k + ArVtu͗٩>6]h^qIbNNjĈܺz6ܴxVq7w#>#RRK 5C>.YGSګ^Nzvv|E%+иզxZnF}Wev4A`Oⵝ`Ƴ-h-alZV $?/S}(D}0 Su}Y;ajhb„Ju&d7^~v\(y!k3[֊{d˿~uq}}Oޜzdv2Iu9MJ6JմRQ'VJY𢞰d2úYnu&t6V8TFj&̮*+R&)dzҭ&f}XͬfM-\fsYhRL)ܰL*F"~vϰMW#Zx<QuH&RU DTM3n#:u( h`yNjjK*jJU]PÈ$>TgbkR;JX@S'_h~9.tzp)P7Ixʮs-, B m+5\(#XF́7E6'L3͙h'eBqoq;]4ehhnDQ$`iT .ivjՓ^׵)C5fJ0bܽ*MmuI97&ùUI1=C11/;c;e^b̞PF&HFw\7G-zѷ\',C&DP|.7B0 ̓{הoG@#e=gƒS<$2];8v +Pۣj)Elub&DvحĠOȁ(D(F"JKeH9dl\l*m2g%Ϻ%ie.5 pwF . tM6Z^@QWs6jasa-:z  kjEbsD!ǹ9lsj-!J @V@bn?JRP: ¡C8j|`]sl\zeM-nx=Ϯ)qS* ڃN)ou)jJwǗ02YsR b}i?Xb ၈ٱѓ3 d;s=eS!)[TȞcf4uG`d*`U'=P7D>ז] Fq%DȑIz1OAY9\]g~MGt mxHE٩b^Z_m1P\Qj1"?"7P`hhPD=>Uu{%Iع@f5% W0&:1ZwƟۄ0%sI#+vXKu%ՒW sj/DO`DA`iv9H THٶIWP%g$}:lJ eUHd ͅoTHu%G(n (ԍv%{א.b*`W!R>߭L  r L ?\t vg8'.ܮ5β5AQ7Ւ҆+zXL5|~ܨ{BAy?'}0&jɼ|pgbߒ :() [ţ/ qo؃ϟBNqS%MdȃIhmē@Vbc%dU;`v8tݙ.n\0[@WȌX&˥{: F2 ~)NyMhyR+pF*x^@MJh:H4S?(W՛ۍp1IDŽ[\lئ06rcAa~T8U/) 1;٠׎*;3~RvH-8f9迨9f (5*PAR6}s]-Oy;:vA?![tEiW>51< r0AM(#z81GOTO&|~ڗNA;#ה A1#ݜį_e5XxT]O0}'&1 h2h`J d2L&zm-旫dbrkT2~x/uP΢m4Yk:QM:r_z9JvP)&-b}۞DΜ21`ϝL(s&FP4pN[j_.5"X1r~ui-%$X壺WT {{ySQzGf#K ʦVԱs4MR=x nx{q01 -p26^4և,*_$Wѩ syjCsU]@ھ쮜IHc m`A%,@UM+=U&CsFO*TUUuG~AW`|_BQT˻ K{~@v9n~k1Ni.)c Hq?"$x}r[Go)hH6M4!)[KC-%vDk奪$h;6qΩKVVfVfVVvLŋle6|c=m\ˬqޝ {Y1e%`<*_:lf)BZ1;JڹLI ȫ^`߀|T{1 hCt2]t|/."n?s{S'Gow3{ԟv?$uOlɿGFo2Lk5N;;G:fEo|.vuQ`I'?~y9%ܕ\C\+h$+K̨P2Zн>A?t:yqN}'OQ)N?l_w~ΏۓӃCcZ఩s fq1f Hd8D!Ycuu^={߾p~zWV( 2.;b Pʏ/CK*+`gt 儷?FL`ry־iJyנ<gW\i.Ӭj.{w~Vh]= ŖȜH`1mo.H`O&;n@shFpWxG~a`Aχhea9ِ}%Gy8&WZ2; 6z*-!dPQ^b1,<#92w\HO)pۭ ||xUscэ ")(΂i 0X\ p/W,ю1sf$Ubԋ;+3hԧgx?~}j}Q=hA  H;ͱtm+fBwPJIx'I5p0fZoVA绝Îܫl0l_^G A@f7 8@h_ut2@UZP r>$k_H V#Ka F#6!,Ed$;)2ɪfm-uI~ìl_17$5~ 㿿+ Ku9/ߪ]K5%%2V|Ngͯ'|^2u A$Qh NE _Ɲ B\CcK60=mEPiA>x |kLvvysu>aϰr)E!%Ks/c idlhs"}B? K.ɿ7y.A1sfN8?gM j9(ƝP6BծΨQ$  '?ېM`!r͠aⓂ&)Ԕ."pĢl(`O+Hĭ( X]:98555]bF\U,]Ρ" jdٝA1#g-qɬ~U d/ M(j(tJٖ]t*"fSRzXQV`Y_ГIlv=AkO%>*᷹^IGgpaQe+ 4H t|^`^Kos.9y?RZ5X+ a=eⒸ94-|1_Ors!$e^$ f~p>xm$[ٷ@Q vGNLV^BaPlhǏ,7F(/7V:G@m3?}=B- %ۃI'^)n`bX Wh&iq5;R; v9<p_$up5<8dBpY2nX!w+Tv'曙DS2RocQU&X_iˆ^Ai.38& X#PpGd}g2iu/_#BĶ yoWǡ3%Yq +z"`H0 0[@vB]cQv*Bs=~)8lG?,{> _< ?|5hiQ%\m`miSw6Dތ[ AJ!%%jh0F]KUG쬚Jigf}ҹO{(YsuGAldm1luBՏ=1&X_&^30%s?|=՟&P@4htMLSX엒3յS$`[Wv2gpdUJQy8Q2Ṡ95X t7?8{:1ai ГPhDm} $ "ü3\_vkB8Ԝ=jPwCBQe%`$\jRn Kї@CA.-M|i'5E_WJhq={{(P^;z8|\l&!_kܱܿoHkng*lmK& o1C-t|'k) X &)Oi]B[JE ~n:Lme-q^tuj@pT10Jщ}'r fg_L>s zkb>O\IE%0+TPYb!*UօS,VϺEz5RlUDrRJpQYHN`Jbip>*n݂BPʽ2Je ٱ|5MBETkb#rP\^GnMaB2U“)Mg"Y3Q9ĊJ9l0D7^O Zj;3+h 5].w/ȃ(UesJ}ԅD'yxUlc* )xV&Z‹~ G[!17Q#1ab+AI*4\yJN``TbE0֚W/F轘-u\8gR7%!]ֿ[I(5B #5,qj&F] "f_4ERM`K & 9 Emh<J(52*}YajkZX[f[ ѡ dV ى=crƒC 0#s| t; 4C6#Rf_6hwm JTîD/C-6N~$SXEZYftLɘ JH˂"'g-U'k8!u VQJ0/5'U!Nql[E ] 8+29[ÎAO3^JF1-Z")UF3g ,0-B XG.VFh{9 jz5jXk%o5ANO :ƈb~LVL$s%.kOq4~o[?;~,HrIҐ 8  m[n&a^[2b) q_&H,'.а5(G$3Ψ!{ѝqi{@0OK))Lo=ao`NQ B)JU;`' {h_(+( ,5N9&r,JImId W&PݓB򷩚~|J"]zK,߳U<-6F!WZT.&8WBç%o%.\1˪P$KgrB/.ᥓp蹈Bʔ9L"qDWa&WL,"l,`dgkPD{p6Hf4%]8+=ЃԵQ͏&V6$ňGz`Ғ)Jk(GyPbѤRbB= :=,̰\T(fysq#?v`p  zȈ QRB6єb~⁲ 9g7o_)=j-`gzJqҟJ}m}PFĵ-4;BƐρw*s{2&>]!x6U;`'Rx=\`BփÄHC!ƇwP0n';> 6yl'o%~؁yqcM}X#蒌ت%= I>AJL&"g,\)3Ԉ(3O`/_8)\}MBZ"Ե;{<ܺ5py8>i44U`d^^y>MiD䊱oo4w;MJ&_|7Q&xZF)~WO=-E\T@rCS6~:g7vT/i(\բ &(PobrH' [P_Ls) 0@6y6+ï?hSdu8&)<(䌹eX(9:jl#=ίCհ9r%>TRbtԹHJHkj#'(ꐍmDmL4πJLIFiu-We|tYvl E X}s<"C(չTqPJlOM~ΣvS~fRCdZy6<0dt{&whz m,ݚsQ 5ȌI0pM)+Op<  ^"h3)8KĘ-ӆ'R! =gNK䗂k-A֑t$'٠-*K"I%$loiSЃ?Aw6C 8(B3w ~+̽ Ƙhp%*-y[>8eVZm}B$ɺY-[1,[⎒""p7vmA̶ ZjW+ΩneL$ԪmCI7Q T m~S+6D(m].Vxjxkg Ni-BXY`nf*¦@ cǶp&ÄjJn=Ib׾Kwļ45{"2׌=3G4Pr `٦ֺo_!zBTf"L =ky~r w6T>EH@/N︉f-yJ#Y mllB3CV* LY* G/T*+;rQ C:d!_V {HQiID>TT,J;wy[g>48Ycpx}iw;/J&b A]ҳ/r3-iٍ,ū%|"S VhEfrmjf/~؁7t3k;;|C {uBrПMf\!Ku(fic3.fz"wC_Sdf8)d{3^ {uhȚFHrJbESD 0 aO,6)sMI3-l)* Xl63Ѓ w d8'Nt,r9nnr]` "O\w^y?%bsƺ2cNJnSp%_aP?u R:v7,6 ׊P \O&:#$ 3C6Ec'4Vji.jE7l(7:h+$'K ^(4nQ$M_҂7Ùv=]HCO"q$b@ȫtZ.业\zY >!} 3.n+"a_W6Pp,)[sJ+"鵕 !Z8nLZ 8VOd5\ hZ0bȖӉ︬JO\+jG]|؃ MD탟~ϡNu&sDaS6y9Q%-ěZUe] G1䊸(isR0dΥN[ը&KnN q Iq+7$%vb҈rC NDiLbR|iFT%l]g|>IRxZ,:{vƹ;Rh? 5N1b -g4r yH@c#~\밮[ahV$GK!IoJ1SeLI(OS21uв1܅sw1!()w{2.#]aseѢOg,~IUfvv#c3 ͋w6DHա1jũMD h tC$Wru_IL6md VDV^TG@'QYL« vocSbGQb*#4g~n;?>xRU<ԱcyG2IUFF2λ)쐪в/㩲`էJLD(R,0~CTN2A`7XZл ʏE%Y9;@n+ ~ PY\A i#KCicZRۣx6KR@JntZ7Wwpl[ e|,UސX곡?6T v8fWwo'Mޗ@hX %4X]h=ƕ[}ib8^<$Zfո3{Jvi U7c8F^rE=X;rT xF!0y14]0|pOg2 d;lD>(&Umd-+\JEVHrpӏOHxvcSOH-mbZ@ݼk #xރ쓳 R$Q_7 U. 瓠-˾ejg[!Ɏ(jzHBv92 [S7ꡜ?[cV,_PJwmզCs&C| 蛞˳'i׃{jabҤn\SNoq2}y~]]QrC,h*i]vU9D @P#)y.cC\֢eiua{ӏL#Huu,gt%*PBH5CEUv䰂gE(W®},EOJT^{80!yYB@C|R5y6n}aŐ1 NHs $cx| ȔH쀙6`A`R'@g78`L:e+p~fL&B,PJ,#( xo4.ܻG?5`Kƍ1(<48lo~+E:}aE~ $jbWς:}< ;W_K-G b/%-ί9.z +L76~. >ʭA]JApjn&|}fzDυd@`afkŒnugؐ?qS^%4ƈ)` =!tǰtFח p1]]laŒwFNp"~ỷ{)?~~}wW3C48fh˸VT/fL]%4=j89 A1rSCmF9Ũa'A1AJj欍$nsc=I'M#$"q7:4zHŀ;ꪘT3a^pT=4M@ Je(7)2!,M(FTMhS 9M9nVՅ,ʸd_4ZY{e]ަZ+ hD+- p)E z1X~@ SNѐfӨ* $:Lڪ[ 'LNB=?sTR<ƸDEc~`;Īrl+aU߰сN."-eb1]%U$F2-4Y1$k*ev$0Ejx՞кP'ߪ7 'ijDs&|%\$h E#1Aģ Oyؒ~>_ ݖYqx%ܗ+9eZ1ek>ejb =[S m$8 I6Y^N#tDD3F |rG["A3ʅ #1UW ,H@EM~\~àdO($+BF+&k祐iFteKCf-| k^m(SJ W+7ET=ǒHES"B,YMZ/c 6Ra]%R[bkoJ8 OvvEC%.e@>~K/ng W)E RR%FuS~ eZ6hlbhQuTy M ڰ_TV4eBl.0`b$E45f%g;`&>=_14KLHJmBⰥ &C%NH&NmLqjhenq _*Si]7]:ʛۓZ­^%iȭҬ43 = `!9ouP=-u0OgD0{eD\CsW?&hJSfS@S@H MPnzZ)QQ lU 55NG'^|ZY dlZ U?ri.8(LKYT{qNƲ)KQ1P%;)x)Ş/\[cwIlkr]jX\TqCPama.boGqKA{ӽEk#l!Y5 ~2aCO ? 0adxcÄ:VVo1Dૢk1y^a\0C1xG#ƨ‚ '%;llvUDXuGB` ?1ts0}#!Z&4$kmxB1$rvϞfv:@\!4YV3@,pjr^>+C4bfp) ʀ|w\tNdbùd 8 p- M\# 6gVB4 h:%!Uڤ, 2XX0:Z.l{#!YHH +*ǣh.uiHUU` *k;o=žR5w5U$vD s W ~ozSMI֦7ڜj #a~]`Bv+$MVPu?>lIA;ׁ۽c}ޞ!$M's{wUaM緝w3 "+A4nñٯX{9Bqwbvp. Xgtm.l×ZC8|~Ĥ7)Nl5jl-wajMp`Ti'@2zr5k5ʔd% f`CW/"U]jŘbҜ.&^aIdۼ)1% ǭV2lhav̴#D$yuj+il,LH-n!`(ap:F"I7iT:NK\)\mbOgad 4dW s(jm0#>l|aG2 6 iqvڍx*a"qfaܖxC,B" ZS҆ ̣PWD) |j8%aRg׈6̎$S!a˥ΣhM k@_P7yXrpetEّ1*4AZ,$ DpĶ{DR x AjoRM`aͰVJ/bbWbJ? Zi,L&Y7J/!kPl{Ñ!$w%)3jJ[]am.(N)E@^47y-cԯj(SQVǔ0LeE-ZInbU%~Vy~ JQI({PdM6T4S[iXc])G\mO߲>}o1C^T^J@*IZ@i6OES>~Z=hǟ> ڕS/7^tT͍Y۵:rk:pT/FxaU&%Yr 9tuQKTfo\%o_caNݯ ps| 'څm/`d I]PȬ<^{ Od)LDaicYCC &G xb fm)[(K-q +S|mAz~dӝhFSV)lܧ4THTĬDI+Ll a7tkj|IPYeItI#ˑ#6BjrHEwnb>ЅcD''p`K̔,7s(DJ91 VcTJFIslԧL1QuĴ pm 'y Bg&Sr>4Und*(7y(2vB <޸F5^6)84y ;W,%dSLl`"=ߛMJ.SR5mI:S&&GoP'S'!X|Y_Z}E*Xp6 ^UL#Ty.)\}[[= ,* ā%LB= 4.4Qp)? ke%Rakhfp"mqS09+a!6Wu)ss$ N <h?t:yqTY)Ll f@B#A5:MSWң!5< `ΪA5TyWCŮc #bZ|őh?+:gOa% C#JB-"TV)ײZﭕ,95f(" wH^ GLMiqB !pNvQ( Pq(ej{`.WXB,'AHMHQk>v'kФX<-&ȶ'N I;4eQHcMpm8gF2}D >8{owLe"[䕃JK35*Nѥ7 %8^5t+n6*OC+qot8mk `u{n[7ڮ]ھ~f\iyn-T$כ6~c/8Ɣ>L`yR)*TŦA?wg!%4RF"A3ڴ {>3!E ^TcQy‚]}e.x!Ūe%y&˝ਇ'-]M("w.{bO.|3`7VX4Cq-XY"Q)cˇ޳ =bp_*o_8C^F[srE ,.> f\3m]k;jKpDSa WYSZ.\ PNnl5`ku5b/4{WpDb,S⤤d´8gLq*ےQ̠lM+Y.9Xg ]G;?v^G{Pfvg,#AO8q)CčQCfF"yWB*{$'SR=iE*'0QD&`81Æ9t`MeG0VY,?bJ0uf,dŅѨ:FL_f2@e@+ !sp됿e] U4?D8毚쒲24!^|k9P޴U>vN:ߟ?ɚ, kY[^i[cΡ=/ڧN+?6l5sǮ*8oǸ~憎 :Y),Q7ugy8̥м2XVp{_ ɋ{_ NjWM$av\jsUTx=αz ,)RROr},ُSg4ST7eAysVU{P*ET&̜NR>Y]@*cW˶;'jF:`.0o<'u(g>&_mys["c] AR)1GF mj<Pw2B^S9ρ7ru 1ͰV- ziLw!',?$aFe(i4LZC8R|t}QVBe.T|` 9S9J{G$.U dgGHqv65A{I'){⭌f$(/*uÒR,ӓ'WvlE4J ڜFumx4 (J'y[z⎢'`mф7!o]x<ц-]&:5]vdvX&waVpb&C@Fc^l⥅(.'A8*BGN&B}XsEt?+ʻBwtM{ uG#YwM OBx@ Z fQ]AN6{sp.KC𲀵Y@ 3z/Qi8j8^!8~DLyngT_t+kȝ}0{$hK6f;FB?eWT0+ъ.bC~mCA@:@*FAZ; x`! d6>0y![x,B*B^d4sYt)h@35~U a֏6( Z-d iU{F/}`Lz Hwxӈ0pӿ> h $I'IyaL)a_:Aޏ"E.$Z>wH#YD{0)%eH{׶p 6"LW\*6=>j'*m<6+P ;LrzEHu)B/U\\@J` [~k߃D`adw+%" 7∵ ۪ۓzV޾xzI |*wfQoИxuXA}-J{6c~JQH؇0SI:x}-KbR8%Qd_Jñ%*agĽj%*)" '(I9Hܷޒߊ-*C%L)Ȅ)2^f71ř GI٨;QLnPUd|drY. +:H$J8Jd 68BRyzITJc]U!H>~g:&.SN @y'[-9iQ#?VQJ~RP/r.* sNb, 円LÇ/ytIBIh4e)(:$h]J,}֝Y^O:kDYvwKФpЏ,( 8$.WZ 4⸩U~]fz?\|1Zѷ9#fOvB`l0HƔMB^ ,LTЕPm3a&D/JªҚ5iz&8(s2W~[:>>nҜ'Py}+@vZ%Wdɯ2*Zh w )l"8qI_ ݌hi-zi5Wgp1|ws* 6߆;eBHci (?CL?ae\Z;GrkoAR]T4r ۷)LN6DnU:pvt>;:yر @oKΝa[524ąs=2ťа> #|PC||TGy$=d" waf6^Yw r8vU>1fڈӄPDqS"&ibp7Lc&s .7\ɒ._iնHaO&\hѦ %&JAq;+5X`y7Bŋ+?q~]ߋXFtE L.ɠ^'ȢxA1V'n3l騗좘OIsv={xs3vaɽFX0PZ&bLNPS}0ݦA1:[Ω+^kcN @1d[N\T_\;_#4-Z S5h|A7@@ ax (J9$#jc^U@9|%Y\JHa5./9!w$#OR(鼋HI$Ͼ/83L~V~n ߿ 5D jd4e& fRFtJnJ~=)t)#6=cB\Xл} ºPg#.Δ r'Z\wUKADj%@2QkKfǠVruK] Q PWNOpf׸7tf rC8!c(nZat11l|MlIF[7js BnƇ WdqC:"} ې:vg^1J *_wKch}ٸWrw=wB)+k'GSTš}:&f;:r+D乕L .Wt*BґY2L q( jO{!R_'99zf x\}SIzT{ь%ZB$"I@y co_\o.83@ܞlŖϪ0pvj;vpuOh, Sgφ q7 ␽%ݎ漏54Zgÿ!gX^ϛ#t7i@bN GQԇE40{FX=Cw2ZǺgR2ɝh! PU$oT7ڄp2(JN8"Pn2]1"r+9b%]& ] S_ec"xvf^.N!_wچrXIbGIz/3MEL;쯪&5!}^@㐔5GwWΣBrՂt7˔;Զnfy39} [lo<2E4a<۝ǁ MZ{1L$v,)Sjy'Qڷ2j[<%Ƶ0lFr7aE-)=b/i*ݶaRSH>};i쮝&Y@e2֜Z2R۰^Q_s#M7Z8qʥkA"uN Hcdة;ʺ5;y/*j o D ڈҾ ķEԡb9Z&W ЖXA1@HձQWBT<ݼ* Λt[ƴXH3þ,r/ Td^bEϞ |G(&= [(FW5*m XԻJdw Bw"NC-dx12rD*fA<5=iYڨo!kOTk `% ,re|'K@K<bĢ\~I0!ٻcCKݎȾe F"fiĹd MTPGQ/A9&cIP|P E> LT C -`H?-bK^ M|J(? l>?9$8Y;.lǤy5&㨵fo}7Ynw /-9ȶ8n)O]T3Ϥ؁[!obR/=5;ĺT>10pWW,VU@* ʦT46eV KGȻ`0^Ic0!"8El4]H,V5uXֶ-.[K^\ -@2̔SAڅK8 KގhWVu7&LϮ{·5揔eΜy5(/©5W͆FRXd(r>?ΦAҌ'XAB1tՌl̎]ąro+ߪicذbbZkL ւe<_pDrc>Uϋt@\#!N0w.M6vCՂS#!s.蜫 `gXXY9) UOE4;blvmD|_K ̇Ey]9m(&샽?1DwJfUmQr!vg*XI`FMriwGr Xk$~/ɰxG6ySeϲ)Q+#U:T^[ b +N<N'xwLl}%>|qA%{m(QsB_|ZceU0jI$֓Yeb˥L)*8Z])U 3Tfj-evi"+3h}N-tr,Â|+nbJ큜֙o©KUf]95YɚdrJ6DX$r獖/q|f #ӶRjm8 gkIO g)+HUrJSY<%Nq޶f 귂(.YBɔ5 NMĀO(U Ekz ƃ3QUI]#gt@})xAf6E#,8,tn// 58:ْ=8zg_pYۼ\IE(~*c%wB2ԝ`F|~(^!`D4J?JŖ|ɁnjI93B_ PPtN Ȏ1e@?vA_]#CTh@9((Kg>@N7Zvw$j'̙σaPބU]|?)YBzk7RQv?^jvP~/U(oIYeCCpd6͘J5IXm[vYDMfHana'&i#y 7$uL]t kl&BL0DPa [1j1 :s6q`BKGs!rdD5lGT,KS ;lwHP++Fکw2Q|D:}Ɵ jSS yjV:_Ū1ٺ8ŷQ1Z:<ֿKWbBrXqPkvDERJ.Ǥv,T%4 [Iߟ8Pi@$5=|+BI9gn3d8ȝn+HU5 (*f^jy|n%U&nB8Xab&eM&VJ 3eaɐ.3U,nR av{zW~*Kd{ nAiC(D/$zB0X5Izg1hbՇ $담F!hBFW0Q,Q\K@(.Cy}!WuV68#k~QƯnUv`ީ{j(x,~8=Y娩m`JMfj i}m ϜU)yf k*M+n+ѭiscm)4!ff<NIulsќE\5WkꌸXM.th+ !$6k5B]z16&@1x P !r|͚ P@JJgSX{'}P^X$$ luEw"H111P<>"fRR$FaP k57XYNЙTļtӾ}*q\7oTisq*`?1[wE\\bw 9y@P'rAqg18$375'3/[8<~B'ěqoNDKκ燭3qz~vzi7HCKɥi$Qƣ; Mݨ/ E [ Gx LA/864d$dTrvS{MD(E!:3xY2G-lgg|ҝZ[S9j{λ)޴d:hJ55}dv{pmc?-@PR>@ݓݷa-%p-sP vJD-lДjǭY!m^a6l5r~b'R HfQcHc ~y4ֿ@0o(bD1{r:cj"5:^V1~^. fYY8͂?~GkB0fi?X "rF/01r}gu"1r}B>.qPl\`)X3n* 6  No^8A: oƑ˜Ӹ/8Ә@KfB! `I)zAoiCE @yd+zXLȵP̞(wD'0*|I '[h9ta-?/?zP4j>VR.%VlhZbF<>7miDs,0u.-=v˼R).µ'JB]PbRX"*-T;0 ج0N8JrӐ>PΌQ t^nĂh%C1õ̭7a)mxe0$j.CntccjIع4Y3 +zz(V9cF5UeMg^)ܴu",F\ ]k r|^^oym_u|uA@@v5nn3 \pEZ+"8R?PV)OnW/z?sdaubh=4QWT__OTZ$ bҡ4`cO}hl֧C8×lցLw%'_u ԓE!l )qs." 2M5a3;,t 6q0JȤg++5̿XZXu]H.~.Qv6]E{1|#pܣGhvtiuȆ+4k zp*6WcÆ&ѣ\G)5L5M跐|W3x{I<}FҸpe~əI9j;M2 DoD>fv+x )BUS*OlC@ۿ>\Ĥ>̳4忱34k;3 TP;VW8->Ŏ6DI|z&ϧHS1%ߥf+z871"HC(fE#"B4J2ɵe~]BEUh7ΏwPr=Us\( zDngk"a"$AaJP7dc*)ل $N4S•tz#o`P"N) "w~QHwa>}й+h1F&?TWdy1kAb $Wd]RŶAw R`<"AzFj[a`,o%TR0>Y2s _|&O2 `c𼅤\X[[?_&pOieSo>e~ HTjP zpEaEU#l?MaXw+ye0 *:%B!}2:C|/HI8[ZTJ >/E"҈*P4X!8dz-]CO/e F&?4#Kcu505Q|=(WS"u0H)GjЈI#\-o+v~e/nHZq%κs CzږFx gA@\~0{\&L*? b8aXBΏ|2l'v b#Aʾ!G.du,J'M~do/v0u i%Xd#7E:ː^*vIxbm/2ե5,9q\G%{IOu`?[NUNSңy9z;PB|lɤ"5۫D85ǸO@;Kdz"07)zeۧez7S/^Glmj!opL LborsrBuE6'x-":0"߮eZ5AA^3Ti#1.NyW c|,(8G PxJA/8|%`חy>c Q?#cO+G`+(jɞClH` \ȆRV8 V~?jjFvV*OʵT[,]|Aḻˆ&%)ÂRu0lSzS3@??M[!\Y?2] 3{!!xV.М:D(z@zڀb(S"0wl 3ݞV>D A@7‘-Pql̇䖀AbW4~J+.>hS e٘_mnG* Ӫ ?Oϵ?Hzr[{MueE1pCdnIBr%M(hC^ eZT(ii++A0aۀKEYD#+T4F U׼[r=83 ,o cƍ$Na cr ȅ';- J]`_>64T<(u( g)g]dIT `7IO09H̰!m)[8*8Ŝ~W"2]~\]RFRe=}PFd]#?ԬTFI?)d ;l30SHn:| B3=iCW%_8:3MM8(er8bOW"1)u]1'M5YRUbQvgG9vm=X8/-㢲O6|>/Ћ=B.<:;reXJQGgqCsN=>i1oKȻb a@ƞEoʰTiLY%-*KfQ,퐂)˔֮&Z'U=0ӌ6 VwJ'Tptʆf78RƌA j͌{w3i87y:fȊkظɐםȯM˯c듯n=V V6JjTt?"Jqbw,ep|r:i>~8 p/]|toxVnf O2%%~~0s$|L\*(llUZۻt^m kj7V^Lʺ2̣2Ks]R8YBߥ ~ƭix%lm@^w E [2/q4rST$1zA>aHGj)* H̷9my+L.?0m Qyhh),欁愊,)"?5NmyaEU(̹Y;ivE7֨> ΰkϊc)ch΅DW+6NPr>:b7y/ꈛk^Y j;gEviҷݰLa%ao?v筲#y98wsfk,-~w9U@y{xprqK1.\Y h A&G8[Ƣ)&N`4M߮-uNJEc}ػu-Not/,o 2Z2Ӝʫ!ͳ$j:nIt4Jʂ5r,vpvT^o/0;\̝/D~~j2A@Ձ3%xb~d/6Gr Ebk8.z=<}]Ҧû Y~rL>Yb٤ #BwpkyOP(c9ǭ4 tМ5)9`070'i3ҋ-&]ި\FY1jyo۝eʑ #(BY OML{Catr?Np4 nFUFORyG’5Vj Ut".]'kV1*FO/ =w0{)= A:6/JuYBkMFKbB!")O"TVfhzٛB{o0!Gu=G"y\@ՖFx_Id\S|1ZFv i>N{GKf%T>S8J[ۘALPO}NB(Ն>}~15O$Pf <#+Y0 ggq5zVy&?ʥ/s딊ɷU5|"0{3!tbIx E)m0R ĂA((riƶJU,4I T@rf9!>s^ybGvA+P [Tc3h< 3׽5;TQֽ5\P&%O*D",Qdt^~~Ӕ8ǎ%?H-rŧ7CX( GsC'Q)gE F|D|N'I^ak%i%BУB'XPy=G=oAlP1,@z.Z&x}'9 ډ\ =ME'LjR ?4iEWCeè`#vDϢs&'Ƿ*S1Ik'o?Ne8"Q.ƔG}ρ)3ձ\TnԳ;SB҆X+DUל:dߢry.tp݇ 9eҥ̑;9]oSm )z ur:'gH@s"hx%ruicAu2 D8: ,6؛*e]r--Ǡ] $*ϼH0(s2ʹ'GG-:svjy rI^?zIs%Mw-z'JF43=a-"ǣExi*׳:DIo dB1HLE㸶.8s7 YY(={LJmI/PlrMؓ YzlM`9YGmEoVn>bA\{$ BLhPS\E'Xy ,.#)Bi ӋjI{Lb )c' eg{*_> QՑgEy#)^%rhMt>:y]4G2IBu1c,eKսH1R%Coa=|g8Vf (*_j@ O ! :0[eI/u~:<|}. # ~.,wq]!Dm'@m!;<^@&[4K\zHf4\Y >`58i]gmr̥CM V>t;$G0Ny {q 6f-!teW QhXUmLMIӤ*MY t!7{ѣ}Zoį-͘3^{"xΕC Dԛ湻gz:i%s%A# ]Rg+{Y-U'.x.U)ws(` w"oKeVX.*kpǛuh Q{[ZrS"+,N%cl>^7 o!,O:wy ñ! Ooz\ib8V#jWOUebeJ(go*ǟ/\Me#0 HSQ@0׽s6WYs%AՊjPЧp6ݻ{ǩ:8 ~ǓT{6(k)9g$O"8,M[>h&;ZjxK7EZQ[A7XPYn^n\i1 0g|]f W ZsŒ8ж/I$)vlK\(΂;Q9rvy.TX5,zFq; vVzqe.۶ x, J pbڍ,OQc:WAKMІʥ:%)ÿ0|P "l7ߔp"bCy]uYymњ59Ԩf4,8elr\ԚZ2< g4S*+WeT#.Jfi4;0*As vp:xJ~IsQ24xepRn]cy:4 @].\'3 &/ 2y~n pЪ߯qȶ_QUrvQuzY6p4>"(z>6'4W銮9Qyp>$F@uu.iw%ʤ-#U=ΦQ4D~5#uѨ]Fpɸq1˲d4kbRvj.Č2/*x~لE :s옄Ty`!цɈ" 6+AU<S 8 AvB(cs!SZdxL1RYҐ'M2%QVz?CJH|ivhZG($ T!kQ;J[AT#|5 `^uM[d+$P!! 89CɅ9dq7JF!!dtmA(GrSBc[-V--hmqYx[r}#DtIuSSGBK\2R_b@[ /Yi_a* q[6@cpbWN,VX8ԓ Ecq[(٫& 3WDXUZѕ:͝0ڔ"[-p٩A$K0e 2.ϛKVTz; w8R7tV_T}zq.!%@_z6>fjT?z$Y`UocB."9yo W+#.M*-)I/--)J+I,ਥ n}ow5~x ;mҊ_%.'/q~4Z|u/t3Aj y{ љЮȝ9bŗΛW%u$߃;M79?ʀeVP H(A@v79y-5tCSQ?6R w$&\a8"B4qT1{M}| Gf YjZ<]nUWl`^us=N[;m0 JXzo,#%!~Iig/3:dxrk'O2b.) p*_KD+cƎ1)yePCM Z}qՒTYkV%ι>unity-settings-daemon/.git/refs/0000775000000000000000000000000015172222611014014 5ustar unity-settings-daemon/.git/refs/heads/0000775000000000000000000000000015172222611015100 5ustar unity-settings-daemon/.git/refs/heads/ubuntu/0000775000000000000000000000000015172222611016422 5ustar unity-settings-daemon/.git/refs/heads/ubuntu/devel0000664000000000000000000000005115172222611017440 0ustar 662fe0ab86b979fb022f4ebe98496c0305b082bc unity-settings-daemon/.git/refs/notes/0000775000000000000000000000000015172222611015144 5ustar unity-settings-daemon/.git/refs/notes/changelog0000664000000000000000000000005115172222611017012 0ustar 28797e59376461fdbd00e32a2d96e165d25cc1e0 unity-settings-daemon/.git/refs/remotes/0000775000000000000000000000000015172222611015472 5ustar unity-settings-daemon/.git/refs/remotes/aleasto/0000775000000000000000000000000015172222611017122 5ustar unity-settings-daemon/.git/refs/remotes/aleasto/ubuntu/0000775000000000000000000000000015172222611020444 5ustar unity-settings-daemon/.git/refs/remotes/aleasto/ubuntu/devel0000664000000000000000000000005115172222611021462 0ustar 662fe0ab86b979fb022f4ebe98496c0305b082bc unity-settings-daemon/.git/refs/remotes/pkg/0000775000000000000000000000000015172222611016253 5ustar unity-settings-daemon/.git/refs/remotes/pkg/HEAD0000664000000000000000000000004315172222611016674 0ustar ref: refs/remotes/pkg/ubuntu/devel unity-settings-daemon/.git/refs/remotes/pkg/applied/0000775000000000000000000000000015172222611017671 5ustar unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/0000775000000000000000000000000015172222611021213 5ustar unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/artful0000664000000000000000000000005115172222611022427 0ustar f670167cc6b3365c22d99d86e2224bc0d0cef81f unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/artful-devel0000664000000000000000000000005115172222611023524 0ustar f670167cc6b3365c22d99d86e2224bc0d0cef81f unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/artful-proposed0000664000000000000000000000005115172222611024260 0ustar f670167cc6b3365c22d99d86e2224bc0d0cef81f unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/bionic0000664000000000000000000000005115172222611022375 0ustar 7a59e1b61af6de957765e77fbbf58787dd595e88 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/bionic-devel0000664000000000000000000000005115172222611023472 0ustar 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/bionic-proposed0000664000000000000000000000005115172222611024226 0ustar 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/bionic-updates0000664000000000000000000000005115172222611024040 0ustar 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/cosmic0000664000000000000000000000005115172222611022407 0ustar 24265629edb6e424b175d1b4601d6dfc63b64bb8 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/cosmic-devel0000664000000000000000000000005115172222611023504 0ustar 2df71f1809b49864b7e9ba8e5957d323886a69ed unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/cosmic-proposed0000664000000000000000000000005115172222611024240 0ustar 2df71f1809b49864b7e9ba8e5957d323886a69ed unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/cosmic-updates0000664000000000000000000000005115172222611024052 0ustar 2df71f1809b49864b7e9ba8e5957d323886a69ed unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/devel0000664000000000000000000000005115172222611022231 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/disco0000664000000000000000000000005115172222611022233 0ustar cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/disco-devel0000664000000000000000000000005115172222611023330 0ustar cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/disco-proposed0000664000000000000000000000005115172222611024064 0ustar cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/eoan0000664000000000000000000000005115172222611022054 0ustar 52efe8d0337105bb49293d6840be99da080e1d80 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/eoan-devel0000664000000000000000000000005115172222611023151 0ustar 52efe8d0337105bb49293d6840be99da080e1d80 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/eoan-proposed0000664000000000000000000000005115172222611023705 0ustar 52efe8d0337105bb49293d6840be99da080e1d80 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/focal0000664000000000000000000000005115172222611022216 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/focal-devel0000664000000000000000000000005115172222611023313 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/focal-proposed0000664000000000000000000000005115172222611024047 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/groovy0000664000000000000000000000005115172222611022457 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/groovy-devel0000664000000000000000000000005115172222611023554 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/hirsute0000664000000000000000000000005115172222611022615 0ustar d53bb9dbc145dc529b36c9712dd389b5b159c06e unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/hirsute-devel0000664000000000000000000000005115172222611023712 0ustar d53bb9dbc145dc529b36c9712dd389b5b159c06e unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/hirsute-proposed0000664000000000000000000000005115172222611024446 0ustar d53bb9dbc145dc529b36c9712dd389b5b159c06e unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/impish0000664000000000000000000000005115172222611022423 0ustar 5bc9dc4af4da1b756db0011523a5920e87c6deae unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/impish-devel0000664000000000000000000000005115172222611023520 0ustar 5bc9dc4af4da1b756db0011523a5920e87c6deae unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/impish-proposed0000664000000000000000000000005115172222611024254 0ustar 5bc9dc4af4da1b756db0011523a5920e87c6deae unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/jammy0000664000000000000000000000005115172222611022247 0ustar 6f0e8ea50b75b073c4db7efda371eec5e501c97d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/jammy-devel0000664000000000000000000000005115172222611023344 0ustar 6f0e8ea50b75b073c4db7efda371eec5e501c97d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/jammy-proposed0000664000000000000000000000005115172222611024100 0ustar 6f0e8ea50b75b073c4db7efda371eec5e501c97d unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/kinetic0000664000000000000000000000005115172222611022560 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/kinetic-devel0000664000000000000000000000005115172222611023655 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/kinetic-proposed0000664000000000000000000000005115172222611024411 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/lunar0000664000000000000000000000005115172222611022253 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/lunar-devel0000664000000000000000000000005115172222611023350 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/mantic0000664000000000000000000000005115172222611022405 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/mantic-devel0000664000000000000000000000005115172222611023502 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/noble0000664000000000000000000000005115172222611022231 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/noble-devel0000664000000000000000000000005115172222611023326 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/noble-proposed0000664000000000000000000000005115172222611024062 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/noble-updates0000664000000000000000000000005115172222611023674 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/oracular0000664000000000000000000000005115172222611022742 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/oracular-devel0000664000000000000000000000005115172222611024037 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/plucky0000664000000000000000000000005115172222611022441 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/plucky-devel0000664000000000000000000000005115172222611023536 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/questing0000664000000000000000000000005115172222611022771 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/questing-devel0000664000000000000000000000005115172222611024066 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/questing-proposed0000664000000000000000000000005115172222611024622 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/resolute0000664000000000000000000000005115172222611022774 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/resolute-devel0000664000000000000000000000005115172222611024071 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/trusty0000664000000000000000000000005115172222611022504 0ustar bcf1d099c28d98f7ac6ad0c00cd2271c18135fa8 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/trusty-devel0000664000000000000000000000005115172222611023601 0ustar ff8f712dadc9d9332fb203a1013acf8c697b12d1 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/trusty-proposed0000664000000000000000000000005115172222611024335 0ustar ff8f712dadc9d9332fb203a1013acf8c697b12d1 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/trusty-security0000664000000000000000000000005115172222611024351 0ustar 7927f5e5b4f0384f2d8dfa16f619bfa318258119 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/trusty-updates0000664000000000000000000000005115172222611024147 0ustar ff8f712dadc9d9332fb203a1013acf8c697b12d1 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/utopic0000664000000000000000000000005115172222611022435 0ustar db4a3a51a94edf8ffcaf994b9048b3902eda9bab unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/utopic-devel0000664000000000000000000000005115172222611023532 0ustar a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/utopic-proposed0000664000000000000000000000005115172222611024266 0ustar a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/utopic-updates0000664000000000000000000000005115172222611024100 0ustar a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/vivid0000664000000000000000000000005115172222611022253 0ustar 5c326b3491c83269cd4a5626b95866a69dcbe935 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/vivid-devel0000664000000000000000000000005115172222611023350 0ustar 8601902a5268c84ba441f2a194faec96d75dbaf3 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/vivid-proposed0000664000000000000000000000005115172222611024104 0ustar 46b51b71a8d3b7c8fca4726a8430825f6addc35e unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/vivid-security0000664000000000000000000000005115172222611024120 0ustar 8601902a5268c84ba441f2a194faec96d75dbaf3 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/vivid-updates0000664000000000000000000000005115172222611023716 0ustar 8601902a5268c84ba441f2a194faec96d75dbaf3 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/wily0000664000000000000000000000005115172222611022116 0ustar 39819d0a06eb08de7f48e6e5884e5831c3f48f20 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/wily-devel0000664000000000000000000000005115172222611023213 0ustar 90c237f94fffdba051fe83bebcfcb0368cdb8a73 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/wily-proposed0000664000000000000000000000005115172222611023747 0ustar 90c237f94fffdba051fe83bebcfcb0368cdb8a73 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/wily-updates0000664000000000000000000000005115172222611023561 0ustar 90c237f94fffdba051fe83bebcfcb0368cdb8a73 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/xenial0000664000000000000000000000005115172222611022412 0ustar ff04fe463c18fe9988c4142b60aa810d3519b446 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/xenial-devel0000664000000000000000000000005115172222611023507 0ustar 0c06606b427b1890311277821d91051ef3a4dacd unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/xenial-proposed0000664000000000000000000000005115172222611024243 0ustar 0c06606b427b1890311277821d91051ef3a4dacd unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/xenial-updates0000664000000000000000000000005115172222611024055 0ustar 0c06606b427b1890311277821d91051ef3a4dacd unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/yakkety0000664000000000000000000000005115172222611022613 0ustar 4c3c6169349777fb0e36403f065dc3e011542917 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/yakkety-devel0000664000000000000000000000005115172222611023710 0ustar 4c3c6169349777fb0e36403f065dc3e011542917 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/yakkety-proposed0000664000000000000000000000005115172222611024444 0ustar 4c3c6169349777fb0e36403f065dc3e011542917 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/zesty0000664000000000000000000000005115172222611022310 0ustar 5aab4fdc93c00a16104443b9a2947122f14b7a8e unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/zesty-devel0000664000000000000000000000005115172222611023405 0ustar 75b72c143b6774598759627e0cf964ffd45df2a8 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/zesty-proposed0000664000000000000000000000005115172222611024141 0ustar 75b72c143b6774598759627e0cf964ffd45df2a8 unity-settings-daemon/.git/refs/remotes/pkg/applied/ubuntu/zesty-updates0000664000000000000000000000005115172222611023753 0ustar 75b72c143b6774598759627e0cf964ffd45df2a8 unity-settings-daemon/.git/refs/remotes/pkg/importer/0000775000000000000000000000000015172222611020114 5ustar unity-settings-daemon/.git/refs/remotes/pkg/importer/ubuntu/0000775000000000000000000000000015172222611021436 5ustar unity-settings-daemon/.git/refs/remotes/pkg/importer/ubuntu/dsc0000664000000000000000000000005115172222611022126 0ustar 438e8aaea637702af2c9adba7ac4cad3b78da62f unity-settings-daemon/.git/refs/remotes/pkg/importer/ubuntu/pristine-tar0000664000000000000000000000005115172222611023776 0ustar 4110edb5cb1c8a4bb4752fffcd1977b12b53d9a7 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/0000775000000000000000000000000015172222611017575 5ustar unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/artful0000664000000000000000000000005115172222611021011 0ustar 87434be575ac61fd9adc14d77468ae7f8a4437ed unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/artful-devel0000664000000000000000000000005115172222611022106 0ustar 87434be575ac61fd9adc14d77468ae7f8a4437ed unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/artful-proposed0000664000000000000000000000005115172222611022642 0ustar 87434be575ac61fd9adc14d77468ae7f8a4437ed unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/bionic0000664000000000000000000000005115172222611020757 0ustar 701dee94195a6a6b8c8dc4736c3a5fb12708f532 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/bionic-devel0000664000000000000000000000005115172222611022054 0ustar fdac6c1ba597c17bce992b5377e49e89c0b42e05 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/bionic-proposed0000664000000000000000000000005115172222611022610 0ustar fdac6c1ba597c17bce992b5377e49e89c0b42e05 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/bionic-updates0000664000000000000000000000005115172222611022422 0ustar fdac6c1ba597c17bce992b5377e49e89c0b42e05 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/cosmic0000664000000000000000000000005115172222611020771 0ustar a256b4651d4b7fb339efc899508b496fe8aa20b5 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/cosmic-devel0000664000000000000000000000005115172222611022066 0ustar 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/cosmic-proposed0000664000000000000000000000005115172222611022622 0ustar 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/cosmic-updates0000664000000000000000000000005115172222611022434 0ustar 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/devel0000664000000000000000000000005115172222611020613 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/disco0000664000000000000000000000005115172222611020615 0ustar 059329a966e982c7fc0e29c5af6687203d6a5bf2 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/disco-devel0000664000000000000000000000005115172222611021712 0ustar 059329a966e982c7fc0e29c5af6687203d6a5bf2 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/disco-proposed0000664000000000000000000000005115172222611022446 0ustar 059329a966e982c7fc0e29c5af6687203d6a5bf2 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/eoan0000664000000000000000000000005115172222611020436 0ustar aa274a2ed2c2cc7476f50d58900689353523eb60 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/eoan-devel0000664000000000000000000000005115172222611021533 0ustar aa274a2ed2c2cc7476f50d58900689353523eb60 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/eoan-proposed0000664000000000000000000000005115172222611022267 0ustar aa274a2ed2c2cc7476f50d58900689353523eb60 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/focal0000664000000000000000000000005115172222611020600 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/focal-devel0000664000000000000000000000005115172222611021675 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/focal-proposed0000664000000000000000000000005115172222611022431 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/groovy0000664000000000000000000000005115172222611021041 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/groovy-devel0000664000000000000000000000005115172222611022136 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/hirsute0000664000000000000000000000005115172222611021177 0ustar 7c905087ef3826d312b5c9681b52693d08bf1546 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/hirsute-devel0000664000000000000000000000005115172222611022274 0ustar 7c905087ef3826d312b5c9681b52693d08bf1546 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/hirsute-proposed0000664000000000000000000000005115172222611023030 0ustar 7c905087ef3826d312b5c9681b52693d08bf1546 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/impish0000664000000000000000000000005115172222611021005 0ustar c30fdce9ca1bb8aae46ea53e7555123ea221c753 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/impish-devel0000664000000000000000000000005115172222611022102 0ustar c30fdce9ca1bb8aae46ea53e7555123ea221c753 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/impish-proposed0000664000000000000000000000005115172222611022636 0ustar c30fdce9ca1bb8aae46ea53e7555123ea221c753 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/jammy0000664000000000000000000000005115172222611020631 0ustar 1d911e0b2c85298cdad43b5610282144c03b266f unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/jammy-devel0000664000000000000000000000005115172222611021726 0ustar 1d911e0b2c85298cdad43b5610282144c03b266f unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/jammy-proposed0000664000000000000000000000005115172222611022462 0ustar 1d911e0b2c85298cdad43b5610282144c03b266f unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/kinetic0000664000000000000000000000005115172222611021142 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/kinetic-devel0000664000000000000000000000005115172222611022237 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/kinetic-proposed0000664000000000000000000000005115172222611022773 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/lunar0000664000000000000000000000005115172222611020635 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/lunar-devel0000664000000000000000000000005115172222611021732 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/mantic0000664000000000000000000000005115172222611020767 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/mantic-devel0000664000000000000000000000005115172222611022064 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/noble0000664000000000000000000000005115172222611020613 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/noble-devel0000664000000000000000000000005115172222611021710 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/noble-proposed0000664000000000000000000000005115172222611022444 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/noble-updates0000664000000000000000000000005115172222611022256 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/oracular0000664000000000000000000000005115172222611021324 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/oracular-devel0000664000000000000000000000005115172222611022421 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/plucky0000664000000000000000000000005115172222611021023 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/plucky-devel0000664000000000000000000000005115172222611022120 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/questing0000664000000000000000000000005115172222611021353 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/questing-devel0000664000000000000000000000005115172222611022450 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/questing-proposed0000664000000000000000000000005115172222611023204 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/resolute0000664000000000000000000000005115172222611021356 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/resolute-devel0000664000000000000000000000005115172222611022453 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/trusty0000664000000000000000000000005115172222611021066 0ustar a65ef112964724e5b169d2c5dd29dbffa000b0cf unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/trusty-devel0000664000000000000000000000005115172222611022163 0ustar 0534e8cf748ff159459f7d722eafabde575dea67 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/trusty-proposed0000664000000000000000000000005115172222611022717 0ustar 0534e8cf748ff159459f7d722eafabde575dea67 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/trusty-security0000664000000000000000000000005115172222611022733 0ustar ff5c937499aa60b84af16c3fb74007eb1b31ac69 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/trusty-updates0000664000000000000000000000005115172222611022531 0ustar 0534e8cf748ff159459f7d722eafabde575dea67 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/utopic0000664000000000000000000000005115172222611021017 0ustar 6fca73822e5900b051be84fc6e231f73459bb0b7 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/utopic-devel0000664000000000000000000000005115172222611022114 0ustar 33b24fedf01adbc16ff519aed5ede636f43c44e7 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/utopic-proposed0000664000000000000000000000005115172222611022650 0ustar 33b24fedf01adbc16ff519aed5ede636f43c44e7 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/utopic-updates0000664000000000000000000000005115172222611022462 0ustar 33b24fedf01adbc16ff519aed5ede636f43c44e7 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/vivid0000664000000000000000000000005115172222611020635 0ustar 2ec8c6572be035c690a34bec0dc124fa6f122ec7 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/vivid-devel0000664000000000000000000000005115172222611021732 0ustar 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/vivid-proposed0000664000000000000000000000005115172222611022466 0ustar 3c4733f85bc83c90703f95faefef46ba3c451410 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/vivid-security0000664000000000000000000000005115172222611022502 0ustar 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/vivid-updates0000664000000000000000000000005115172222611022300 0ustar 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/wily0000664000000000000000000000005115172222611020500 0ustar 6b036413a54a0265a561ec36065529786dca4b61 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/wily-devel0000664000000000000000000000005115172222611021575 0ustar d639ba4ec35d3fecaa1af51cc059d55832e70c1e unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/wily-proposed0000664000000000000000000000005115172222611022331 0ustar d639ba4ec35d3fecaa1af51cc059d55832e70c1e unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/wily-updates0000664000000000000000000000005115172222611022143 0ustar d639ba4ec35d3fecaa1af51cc059d55832e70c1e unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/xenial0000664000000000000000000000005115172222611020774 0ustar 7a88377c31cdc83a3fdfa9378b305123ffd8d142 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/xenial-devel0000664000000000000000000000005115172222611022071 0ustar 75edc6735ce0b8beef515a0a936560ca716d5133 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/xenial-proposed0000664000000000000000000000005115172222611022625 0ustar 75edc6735ce0b8beef515a0a936560ca716d5133 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/xenial-updates0000664000000000000000000000005115172222611022437 0ustar 75edc6735ce0b8beef515a0a936560ca716d5133 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/yakkety0000664000000000000000000000005115172222611021175 0ustar 4592ae2d51c94d313ba225149e0700d627412b5c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/yakkety-devel0000664000000000000000000000005115172222611022272 0ustar 4592ae2d51c94d313ba225149e0700d627412b5c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/yakkety-proposed0000664000000000000000000000005115172222611023026 0ustar 4592ae2d51c94d313ba225149e0700d627412b5c unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/zesty0000664000000000000000000000005115172222611020672 0ustar aac80b647a63df9defb4cd2ca190bba29edeb7da unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/zesty-devel0000664000000000000000000000005115172222611021767 0ustar cabf6621a0835b22ba17b4627e761c1c01cadbf0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/zesty-proposed0000664000000000000000000000005115172222611022523 0ustar cabf6621a0835b22ba17b4627e761c1c01cadbf0 unity-settings-daemon/.git/refs/remotes/pkg/ubuntu/zesty-updates0000664000000000000000000000005115172222611022335 0ustar cabf6621a0835b22ba17b4627e761c1c01cadbf0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/0000775000000000000000000000000015172222611021164 5ustar unity-settings-daemon/.git/refs/remotes/unity7maintainers/HEAD0000664000000000000000000000005315172222611021606 0ustar ref: refs/remotes/unity7maintainers/master unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/0000775000000000000000000000000015172222611022602 5ustar unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/0000775000000000000000000000000015172222611024124 5ustar unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/artful0000664000000000000000000000005115172222611025340 0ustar f670167cc6b3365c22d99d86e2224bc0d0cef81f unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/artful-devel0000664000000000000000000000005115172222611026435 0ustar f670167cc6b3365c22d99d86e2224bc0d0cef81f unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/artful-proposed0000664000000000000000000000005115172222611027171 0ustar f670167cc6b3365c22d99d86e2224bc0d0cef81f unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/bionic0000664000000000000000000000005115172222611025306 0ustar 7a59e1b61af6de957765e77fbbf58787dd595e88 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/bionic-devel0000664000000000000000000000005115172222611026403 0ustar 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/bionic-proposed0000664000000000000000000000005115172222611027137 0ustar 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/bionic-updates0000664000000000000000000000005115172222611026751 0ustar 6b01f3986b3ea5cfb9e67dc4c14f3c071f8f6e02 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/cosmic0000664000000000000000000000005115172222611025320 0ustar 24265629edb6e424b175d1b4601d6dfc63b64bb8 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/cosmic-devel0000664000000000000000000000005115172222611026415 0ustar 2df71f1809b49864b7e9ba8e5957d323886a69ed unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/cosmic-proposed0000664000000000000000000000005115172222611027151 0ustar 2df71f1809b49864b7e9ba8e5957d323886a69ed unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/cosmic-updates0000664000000000000000000000005115172222611026763 0ustar 2df71f1809b49864b7e9ba8e5957d323886a69ed unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/devel0000664000000000000000000000005115172222611025142 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/disco0000664000000000000000000000005115172222611025144 0ustar cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/disco-devel0000664000000000000000000000005115172222611026241 0ustar cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/disco-proposed0000664000000000000000000000005115172222611026775 0ustar cb21cf49dedda9247f4c6f5aa5a6b58578eaea3b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/eoan0000664000000000000000000000005115172222611024765 0ustar 52efe8d0337105bb49293d6840be99da080e1d80 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/eoan-devel0000664000000000000000000000005115172222611026062 0ustar 52efe8d0337105bb49293d6840be99da080e1d80 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/eoan-proposed0000664000000000000000000000005115172222611026616 0ustar 52efe8d0337105bb49293d6840be99da080e1d80 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/focal0000664000000000000000000000005115172222611025127 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/focal-devel0000664000000000000000000000005115172222611026224 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/focal-proposed0000664000000000000000000000005115172222611026760 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/groovy0000664000000000000000000000005115172222611025370 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/groovy-devel0000664000000000000000000000005115172222611026465 0ustar 7885e3b9a606920c6a55b53190c515c40131989d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/hirsute0000664000000000000000000000005115172222611025526 0ustar d53bb9dbc145dc529b36c9712dd389b5b159c06e unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/hirsute-devel0000664000000000000000000000005115172222611026623 0ustar d53bb9dbc145dc529b36c9712dd389b5b159c06e unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/hirsute-proposed0000664000000000000000000000005115172222611027357 0ustar d53bb9dbc145dc529b36c9712dd389b5b159c06e unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/impish0000664000000000000000000000005115172222611025334 0ustar 5bc9dc4af4da1b756db0011523a5920e87c6deae unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/impish-devel0000664000000000000000000000005115172222611026431 0ustar 5bc9dc4af4da1b756db0011523a5920e87c6deae unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/impish-proposed0000664000000000000000000000005115172222611027165 0ustar 5bc9dc4af4da1b756db0011523a5920e87c6deae unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/jammy0000664000000000000000000000005115172222611025160 0ustar 6f0e8ea50b75b073c4db7efda371eec5e501c97d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/jammy-devel0000664000000000000000000000005115172222611026255 0ustar 6f0e8ea50b75b073c4db7efda371eec5e501c97d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/jammy-proposed0000664000000000000000000000005115172222611027011 0ustar 6f0e8ea50b75b073c4db7efda371eec5e501c97d unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/kinetic0000664000000000000000000000005115172222611025471 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/kinetic-devel0000664000000000000000000000005115172222611026566 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/kinetic-proposed0000664000000000000000000000005115172222611027322 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/lunar0000664000000000000000000000005115172222611025164 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/lunar-devel0000664000000000000000000000005115172222611026261 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/mantic0000664000000000000000000000005115172222611025316 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/mantic-devel0000664000000000000000000000005115172222611026413 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/noble0000664000000000000000000000005115172222611025142 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/noble-devel0000664000000000000000000000005115172222611026237 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/noble-proposed0000664000000000000000000000005115172222611026773 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/noble-updates0000664000000000000000000000005115172222611026605 0ustar f223f8a37c17169dc539fabf8a4e104e0d4bc000 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/oracular0000664000000000000000000000005115172222611025653 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/oracular-devel0000664000000000000000000000005115172222611026750 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/plucky0000664000000000000000000000005115172222611025352 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/plucky-devel0000664000000000000000000000005115172222611026447 0ustar 624c730ed1f0f7c058d3abd2830a7c46bb07a474 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/questing0000664000000000000000000000005115172222611025702 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/questing-devel0000664000000000000000000000005115172222611026777 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/questing-proposed0000664000000000000000000000005115172222611027533 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/resolute0000664000000000000000000000005115172222611025705 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/resolute-devel0000664000000000000000000000005115172222611027002 0ustar abdb145b64dec7e468f4f2b4eb6403aed2b0710b unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/trusty0000664000000000000000000000005115172222611025415 0ustar bcf1d099c28d98f7ac6ad0c00cd2271c18135fa8 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/trusty-devel0000664000000000000000000000005115172222611026512 0ustar ff8f712dadc9d9332fb203a1013acf8c697b12d1 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/trusty-proposed0000664000000000000000000000005115172222611027246 0ustar ff8f712dadc9d9332fb203a1013acf8c697b12d1 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/trusty-security0000664000000000000000000000005115172222611027262 0ustar 7927f5e5b4f0384f2d8dfa16f619bfa318258119 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/trusty-updates0000664000000000000000000000005115172222611027060 0ustar ff8f712dadc9d9332fb203a1013acf8c697b12d1 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/utopic0000664000000000000000000000005115172222611025346 0ustar db4a3a51a94edf8ffcaf994b9048b3902eda9bab unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/utopic-devel0000664000000000000000000000005115172222611026443 0ustar a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/utopic-proposed0000664000000000000000000000005115172222611027177 0ustar a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/utopic-updates0000664000000000000000000000005115172222611027011 0ustar a334f4632c2ad31baa8a2e4d72dda94ef5afcca3 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/vivid0000664000000000000000000000005115172222611025164 0ustar 5c326b3491c83269cd4a5626b95866a69dcbe935 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/vivid-devel0000664000000000000000000000005115172222611026261 0ustar 8601902a5268c84ba441f2a194faec96d75dbaf3 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/vivid-proposed0000664000000000000000000000005115172222611027015 0ustar 46b51b71a8d3b7c8fca4726a8430825f6addc35e unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/vivid-security0000664000000000000000000000005115172222611027031 0ustar 8601902a5268c84ba441f2a194faec96d75dbaf3 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/vivid-updates0000664000000000000000000000005115172222611026627 0ustar 8601902a5268c84ba441f2a194faec96d75dbaf3 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/wily0000664000000000000000000000005115172222611025027 0ustar 39819d0a06eb08de7f48e6e5884e5831c3f48f20 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/wily-devel0000664000000000000000000000005115172222611026124 0ustar 90c237f94fffdba051fe83bebcfcb0368cdb8a73 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/wily-proposed0000664000000000000000000000005115172222611026660 0ustar 90c237f94fffdba051fe83bebcfcb0368cdb8a73 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/wily-updates0000664000000000000000000000005115172222611026472 0ustar 90c237f94fffdba051fe83bebcfcb0368cdb8a73 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/xenial0000664000000000000000000000005115172222611025323 0ustar ff04fe463c18fe9988c4142b60aa810d3519b446 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/xenial-devel0000664000000000000000000000005115172222611026420 0ustar 0c06606b427b1890311277821d91051ef3a4dacd unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/xenial-proposed0000664000000000000000000000005115172222611027154 0ustar 0c06606b427b1890311277821d91051ef3a4dacd unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/xenial-updates0000664000000000000000000000005115172222611026766 0ustar 0c06606b427b1890311277821d91051ef3a4dacd unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/yakkety0000664000000000000000000000005115172222611025524 0ustar 4c3c6169349777fb0e36403f065dc3e011542917 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/yakkety-devel0000664000000000000000000000005115172222611026621 0ustar 4c3c6169349777fb0e36403f065dc3e011542917 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/yakkety-proposed0000664000000000000000000000005115172222611027355 0ustar 4c3c6169349777fb0e36403f065dc3e011542917 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/zesty0000664000000000000000000000005115172222611025221 0ustar 5aab4fdc93c00a16104443b9a2947122f14b7a8e unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/zesty-devel0000664000000000000000000000005115172222611026316 0ustar 75b72c143b6774598759627e0cf964ffd45df2a8 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/zesty-proposed0000664000000000000000000000005115172222611027052 0ustar 75b72c143b6774598759627e0cf964ffd45df2a8 unity-settings-daemon/.git/refs/remotes/unity7maintainers/applied/ubuntu/zesty-updates0000664000000000000000000000005115172222611026664 0ustar 75b72c143b6774598759627e0cf964ffd45df2a8 unity-settings-daemon/.git/refs/remotes/unity7maintainers/importer/0000775000000000000000000000000015172222611023025 5ustar unity-settings-daemon/.git/refs/remotes/unity7maintainers/importer/ubuntu/0000775000000000000000000000000015172222611024347 5ustar unity-settings-daemon/.git/refs/remotes/unity7maintainers/importer/ubuntu/dsc0000664000000000000000000000005115172222611025037 0ustar 438e8aaea637702af2c9adba7ac4cad3b78da62f unity-settings-daemon/.git/refs/remotes/unity7maintainers/importer/ubuntu/pristine-tar0000664000000000000000000000005115172222611026707 0ustar 4110edb5cb1c8a4bb4752fffcd1977b12b53d9a7 unity-settings-daemon/.git/refs/remotes/unity7maintainers/master0000664000000000000000000000005115172222611022376 0ustar b02e4e32de28c646ff70088515d84a5c5bb539c8 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/0000775000000000000000000000000015172222611022506 5ustar unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/artful0000664000000000000000000000005115172222611023722 0ustar 87434be575ac61fd9adc14d77468ae7f8a4437ed unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/artful-devel0000664000000000000000000000005115172222611025017 0ustar 87434be575ac61fd9adc14d77468ae7f8a4437ed unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/artful-proposed0000664000000000000000000000005115172222611025553 0ustar 87434be575ac61fd9adc14d77468ae7f8a4437ed unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/bionic0000664000000000000000000000005115172222611023670 0ustar 701dee94195a6a6b8c8dc4736c3a5fb12708f532 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/bionic-devel0000664000000000000000000000005115172222611024765 0ustar fdac6c1ba597c17bce992b5377e49e89c0b42e05 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/bionic-proposed0000664000000000000000000000005115172222611025521 0ustar fdac6c1ba597c17bce992b5377e49e89c0b42e05 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/bionic-updates0000664000000000000000000000005115172222611025333 0ustar fdac6c1ba597c17bce992b5377e49e89c0b42e05 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/cosmic0000664000000000000000000000005115172222611023702 0ustar a256b4651d4b7fb339efc899508b496fe8aa20b5 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/cosmic-devel0000664000000000000000000000005115172222611024777 0ustar 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/cosmic-proposed0000664000000000000000000000005115172222611025533 0ustar 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/cosmic-updates0000664000000000000000000000005115172222611025345 0ustar 060966829c8bcc207eb4bc5d2d09e38f37fe1b1d unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/devel0000664000000000000000000000005115172222611023524 0ustar 662fe0ab86b979fb022f4ebe98496c0305b082bc unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/disco0000664000000000000000000000005115172222611023526 0ustar 059329a966e982c7fc0e29c5af6687203d6a5bf2 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/disco-devel0000664000000000000000000000005115172222611024623 0ustar 059329a966e982c7fc0e29c5af6687203d6a5bf2 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/disco-proposed0000664000000000000000000000005115172222611025357 0ustar 059329a966e982c7fc0e29c5af6687203d6a5bf2 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/eoan0000664000000000000000000000005115172222611023347 0ustar aa274a2ed2c2cc7476f50d58900689353523eb60 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/eoan-devel0000664000000000000000000000005115172222611024444 0ustar aa274a2ed2c2cc7476f50d58900689353523eb60 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/eoan-proposed0000664000000000000000000000005115172222611025200 0ustar aa274a2ed2c2cc7476f50d58900689353523eb60 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/focal0000664000000000000000000000005115172222611023511 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/focal-devel0000664000000000000000000000005115172222611024606 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/focal-proposed0000664000000000000000000000005115172222611025342 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/groovy0000664000000000000000000000005115172222611023752 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/groovy-devel0000664000000000000000000000005115172222611025047 0ustar 708e3d30f27d850495e004fc0fbfa3c6752bbcdb unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/hirsute0000664000000000000000000000005115172222611024110 0ustar 7c905087ef3826d312b5c9681b52693d08bf1546 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/hirsute-devel0000664000000000000000000000005115172222611025205 0ustar 7c905087ef3826d312b5c9681b52693d08bf1546 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/hirsute-proposed0000664000000000000000000000005115172222611025741 0ustar 7c905087ef3826d312b5c9681b52693d08bf1546 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/impish0000664000000000000000000000005115172222611023716 0ustar c30fdce9ca1bb8aae46ea53e7555123ea221c753 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/impish-devel0000664000000000000000000000005115172222611025013 0ustar c30fdce9ca1bb8aae46ea53e7555123ea221c753 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/impish-proposed0000664000000000000000000000005115172222611025547 0ustar c30fdce9ca1bb8aae46ea53e7555123ea221c753 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/jammy0000664000000000000000000000005115172222611023542 0ustar 1d911e0b2c85298cdad43b5610282144c03b266f unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/jammy-devel0000664000000000000000000000005115172222611024637 0ustar 1d911e0b2c85298cdad43b5610282144c03b266f unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/jammy-proposed0000664000000000000000000000005115172222611025373 0ustar 1d911e0b2c85298cdad43b5610282144c03b266f unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/kinetic0000664000000000000000000000005115172222611024053 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/kinetic-devel0000664000000000000000000000005115172222611025150 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/kinetic-proposed0000664000000000000000000000005115172222611025704 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/lunar0000664000000000000000000000005115172222611023546 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/lunar-devel0000664000000000000000000000005115172222611024643 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/mantic0000664000000000000000000000005115172222611023700 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/mantic-devel0000664000000000000000000000005115172222611024775 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/noble0000664000000000000000000000005115172222611023524 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/noble-devel0000664000000000000000000000005115172222611024621 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/noble-proposed0000664000000000000000000000005115172222611025355 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/noble-updates0000664000000000000000000000005115172222611025167 0ustar 6f51a661c0e92afcd2ee77444d2d20ca0fa52722 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/oracular0000664000000000000000000000005115172222611024235 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/oracular-devel0000664000000000000000000000005115172222611025332 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/plucky0000664000000000000000000000005115172222611023734 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/plucky-devel0000664000000000000000000000005115172222611025031 0ustar bac95b8567cc9ac9d345fd46203ccadfe607f2f0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/questing0000664000000000000000000000005115172222611024264 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/questing-devel0000664000000000000000000000005115172222611025361 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/questing-proposed0000664000000000000000000000005115172222611026115 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/resolute0000664000000000000000000000005115172222611024267 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/resolute-devel0000664000000000000000000000005115172222611025364 0ustar 4902530ad071fce5e14573d4ae8a07acc281863c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/trusty0000664000000000000000000000005115172222611023777 0ustar a65ef112964724e5b169d2c5dd29dbffa000b0cf unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/trusty-devel0000664000000000000000000000005115172222611025074 0ustar 0534e8cf748ff159459f7d722eafabde575dea67 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/trusty-proposed0000664000000000000000000000005115172222611025630 0ustar 0534e8cf748ff159459f7d722eafabde575dea67 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/trusty-security0000664000000000000000000000005115172222611025644 0ustar ff5c937499aa60b84af16c3fb74007eb1b31ac69 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/trusty-updates0000664000000000000000000000005115172222611025442 0ustar 0534e8cf748ff159459f7d722eafabde575dea67 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/utopic0000664000000000000000000000005115172222611023730 0ustar 6fca73822e5900b051be84fc6e231f73459bb0b7 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/utopic-devel0000664000000000000000000000005115172222611025025 0ustar 33b24fedf01adbc16ff519aed5ede636f43c44e7 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/utopic-proposed0000664000000000000000000000005115172222611025561 0ustar 33b24fedf01adbc16ff519aed5ede636f43c44e7 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/utopic-updates0000664000000000000000000000005115172222611025373 0ustar 33b24fedf01adbc16ff519aed5ede636f43c44e7 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/vivid0000664000000000000000000000005115172222611023546 0ustar 2ec8c6572be035c690a34bec0dc124fa6f122ec7 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/vivid-devel0000664000000000000000000000005115172222611024643 0ustar 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/vivid-proposed0000664000000000000000000000005115172222611025377 0ustar 3c4733f85bc83c90703f95faefef46ba3c451410 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/vivid-security0000664000000000000000000000005115172222611025413 0ustar 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/vivid-updates0000664000000000000000000000005115172222611025211 0ustar 82b7b88738d757dbf02b9c16b8991a7a01bd5c0d unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/wily0000664000000000000000000000005115172222611023411 0ustar 6b036413a54a0265a561ec36065529786dca4b61 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/wily-devel0000664000000000000000000000005115172222611024506 0ustar d639ba4ec35d3fecaa1af51cc059d55832e70c1e unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/wily-proposed0000664000000000000000000000005115172222611025242 0ustar d639ba4ec35d3fecaa1af51cc059d55832e70c1e unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/wily-updates0000664000000000000000000000005115172222611025054 0ustar d639ba4ec35d3fecaa1af51cc059d55832e70c1e unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/xenial0000664000000000000000000000005115172222611023705 0ustar 7a88377c31cdc83a3fdfa9378b305123ffd8d142 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/xenial-devel0000664000000000000000000000005115172222611025002 0ustar 75edc6735ce0b8beef515a0a936560ca716d5133 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/xenial-proposed0000664000000000000000000000005115172222611025536 0ustar 75edc6735ce0b8beef515a0a936560ca716d5133 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/xenial-updates0000664000000000000000000000005115172222611025350 0ustar 75edc6735ce0b8beef515a0a936560ca716d5133 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/yakkety0000664000000000000000000000005115172222611024106 0ustar 4592ae2d51c94d313ba225149e0700d627412b5c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/yakkety-devel0000664000000000000000000000005115172222611025203 0ustar 4592ae2d51c94d313ba225149e0700d627412b5c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/yakkety-proposed0000664000000000000000000000005115172222611025737 0ustar 4592ae2d51c94d313ba225149e0700d627412b5c unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/zesty0000664000000000000000000000005115172222611023603 0ustar aac80b647a63df9defb4cd2ca190bba29edeb7da unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/zesty-devel0000664000000000000000000000005115172222611024700 0ustar cabf6621a0835b22ba17b4627e761c1c01cadbf0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/zesty-proposed0000664000000000000000000000005115172222611025434 0ustar cabf6621a0835b22ba17b4627e761c1c01cadbf0 unity-settings-daemon/.git/refs/remotes/unity7maintainers/ubuntu/zesty-updates0000664000000000000000000000005115172222611025246 0ustar cabf6621a0835b22ba17b4627e761c1c01cadbf0 unity-settings-daemon/.git/refs/tags/0000775000000000000000000000000015172222611014752 5ustar unity-settings-daemon/.git/refs/tags/applied/0000775000000000000000000000000015172222611016370 5ustar unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140219-0ubuntu10000664000000000000000000000005115172222611022137 0ustar 7007f2846e81b8c2cbb95e5f07b28f04e9242df3 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140221-0ubuntu10000664000000000000000000000005115172222611022130 0ustar 4df3f944ade06e9cb79121f6b6b533e26dbd11ed unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140221.1-0ubuntu10000664000000000000000000000005115172222611022267 0ustar 0f9fa7dfd892d8611bec2ae8ae97eac8bb6a3c41 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140225-0ubuntu10000664000000000000000000000005115172222611022134 0ustar d17479dfc6be7b28f39086e76161a827704f7664 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140228-0ubuntu10000664000000000000000000000005115172222611022137 0ustar c7499af074b2689080c41e1635e4f7a20bec4372 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140310-0ubuntu10000664000000000000000000000005115172222611022127 0ustar 5aed97639e83c5e7113b92974104671c6a5a1c0b unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140310-0ubuntu20000664000000000000000000000005115172222611022130 0ustar 95dcd7761d8abe8e21ef0fb72a607cf55cfaaac2 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140402-0ubuntu10000664000000000000000000000005115172222611022131 0ustar 47f77e4f674e73b5ab13d0a6d254c5d14b1f6f19 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140404-0ubuntu10000664000000000000000000000005115172222611022133 0ustar 1adbb9a90d39ac88a3cc03f4a44930ac565bd5e9 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140407-0ubuntu10000664000000000000000000000005115172222611022136 0ustar 69ec0245d984c634718dd8f05a635d15912611ad unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140414-0ubuntu10000664000000000000000000000005115172222611022134 0ustar 83d8fbf44c8f8bdfb63b31fc60782d39c64d19cf unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140606-0ubuntu10000664000000000000000000000005115172222611022137 0ustar c57012053473af92dd9d7f896ef47398cd151715 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140606-0ubuntu20000664000000000000000000000005115172222611022140 0ustar a82cbe519251878be88931b9a10aa41bed4e7568 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20140606-0ubuntu30000664000000000000000000000005115172222611022141 0ustar dc58b2e641e229453808caae2e27ee6704dc9aa3 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20150825-0ubuntu10000664000000000000000000000005115172222611022143 0ustar 7db13af9aa8ca6bfb2d99442a5caf603bcf5bb3a unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20150825-0ubuntu20000664000000000000000000000005115172222611022144 0ustar 5d630bbc009b53674949dceaeee855c954367cce unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.04.20151012-0ubuntu10000664000000000000000000000005115172222611022130 0ustar 4436f53dc4e3b7cdb02a35e1e4b3165d7c64a95a unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20140604-0ubuntu10000664000000000000000000000005115172222611022132 0ustar 567cab64ef0500aac04501c19d7496d3c97a2c6e unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20140605-0ubuntu10000664000000000000000000000005115172222611022133 0ustar 2e79b391d8e4612ca78a95b0bb4a4cc9c08cd125 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20140605-0ubuntu20000664000000000000000000000005115172222611022134 0ustar 20e5c2a7baf70f8049c266e0ae6f3595dc3aff06 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20140922-0ubuntu10000664000000000000000000000005115172222611022135 0ustar 85d4e2307a1676ff81e7fc1c006498bff42084dc unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20140922-0ubuntu20000664000000000000000000000005115172222611022136 0ustar eb4eda3ea80e77f5b2b14f98c30c6e5cd0a3e32f unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20140922-0ubuntu30000664000000000000000000000005115172222611022137 0ustar 9fc6f7ecd66d07649fb9ef4e8073e67568c0ff74 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20141010-0ubuntu10000664000000000000000000000005115172222611022122 0ustar c8a566d9ea2c36898aaefcc3120cdb5ac6f4757c unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20141014-0ubuntu10000664000000000000000000000005115172222611022126 0ustar 684e45cab0eb791d8805664d60aec57a433405c0 unity-settings-daemon/.git/refs/tags/applied/14.04.0+14.10.20141014-0ubuntu1.10000664000000000000000000000005115172222611022265 0ustar e8ca4c5be09b3e5ccbe3a7498d500957fe8b6079 unity-settings-daemon/.git/refs/tags/applied/14.04.0-0ubuntu10000664000000000000000000000005115172222611020574 0ustar 122c77a058b084394203249096bac267982c50fb unity-settings-daemon/.git/refs/tags/applied/14.04.0-0ubuntu20000664000000000000000000000005115172222611020575 0ustar c6ad65ffe296e13292497f808796b49412bbb820 unity-settings-daemon/.git/refs/tags/applied/15.04.0+15.10.20141030-0ubuntu10000664000000000000000000000005115172222611022126 0ustar d89628a424d35261364d5cc7ff3ed5f3bcd5916e unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20141127-0ubuntu10000664000000000000000000000005115172222611022141 0ustar e64dd67069c72e1b42ff31c366d1cf8a0620460f unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20141128-0ubuntu10000664000000000000000000000005115172222611022142 0ustar 0a5fa857ff59dfd00fa0aea16cdc823d620141bf unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150107-0ubuntu10000664000000000000000000000005115172222611022137 0ustar de5c13d6da724a1c81859230d524b72437aac4d6 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150205-0ubuntu10000664000000000000000000000005115172222611022136 0ustar 48b0a7265af36d783ef6c2001006e93f95d26589 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150310-0ubuntu10000664000000000000000000000005115172222611022133 0ustar 5f6d16694a2df0263c6edc0da171b33f4ce65fc8 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150313-0ubuntu10000664000000000000000000000005115172222611022136 0ustar b5d1741bef218205b6258de6a038636888524388 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150318-0ubuntu10000664000000000000000000000005115172222611022143 0ustar 7938158ff642249978d36a38540d9f366e3e7c8f unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150324.1-0ubuntu10000664000000000000000000000005115172222611022277 0ustar 1ba4ddf9f9011edca3ff803e658409b8fe529d31 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150401-0ubuntu10000664000000000000000000000005115172222611022134 0ustar f4b407fc8a2e3229f96f689fa654391d60408704 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150408-0ubuntu10000664000000000000000000000005115172222611022143 0ustar 6fbfdf950c57da778d1d8b14b528fd9580ce3545 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150408-0ubuntu1.10000664000000000000000000000005115172222611022302 0ustar 4be51335656731fcc4a77edfaebc6b8579754a74 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.04.20150408-0ubuntu1.20000664000000000000000000000005115172222611022303 0ustar 8ef391ffb4a5aea4f5442fbb82779da6a3f415c4 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20150630.1-0ubuntu10000664000000000000000000000005115172222611022274 0ustar 56118444f3f06cdc2cda34ed9956b0e2a5840c6c unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20150720-0ubuntu10000664000000000000000000000005115172222611022135 0ustar 0ec58d725506270b7de0a663f2e02d8ee4c6cace unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20150818-0ubuntu10000664000000000000000000000005115172222611022145 0ustar 0c2efa9d88c0666d28bfa0e8d241865711f6b43a unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20150825-0ubuntu10000664000000000000000000000005115172222611022143 0ustar cf943dbc5884ce65e33a1063b32f85de9bde87bc unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20150917-0ubuntu10000664000000000000000000000005115172222611022145 0ustar 506e66f11995bee789b5c7aaa55e83cc64d81c4c unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20150930-0ubuntu10000664000000000000000000000005115172222611022140 0ustar 5fefadfc1bdcf8a2dfa43480bfeec689fe99f9c7 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20151001-0ubuntu10000664000000000000000000000005115172222611022126 0ustar b651f8a94668c759b40bc8a4945310b885e0c717 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20151008-0ubuntu10000664000000000000000000000005115172222611022135 0ustar 2a2b72d29ff1e164d741bd5cb49810388df7b89e unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20151012-0ubuntu10000664000000000000000000000005115172222611022130 0ustar 96c14972fb3ce3c7f2ccdf0beb6aa2770d2a3f4c unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20151021-0ubuntu10000664000000000000000000000005115172222611022130 0ustar c3ca1366ab9b48febd092149c7a034b05a80fb19 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20151021-0ubuntu20000664000000000000000000000005115172222611022131 0ustar b63789da2eaab6be16ee38a7ae78ce6977ac9af9 unity-settings-daemon/.git/refs/tags/applied/15.04.1+15.10.20151029-0ubuntu10000664000000000000000000000005115172222611022140 0ustar 98c9ad15cdc26ed52624b339902ced746b8be37e unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20151106-0ubuntu10000664000000000000000000000005115172222611022140 0ustar 7fd5eb16d897bddaf6f292a94c28a8060ae52c8e unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20151118.1-0ubuntu10000664000000000000000000000005115172222611022302 0ustar 8da1cec74adedd0a226168fa8a351fa03af87b77 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20151118.1-0ubuntu20000664000000000000000000000005115172222611022303 0ustar 59f6645d7bddd510a306af1eec11ee49a60d2fea unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20151214-0ubuntu10000664000000000000000000000005115172222611022140 0ustar 6bd5c37fdf906e6de69698524b4f679f9db0b603 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160119-0ubuntu10000664000000000000000000000005115172222611022144 0ustar d4dd88bca2577931a73cbb0f061e126b0acf0249 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160121-0ubuntu10000664000000000000000000000005115172222611022135 0ustar 9bb93d22b0aa47e0c46c5a2a7b51b8f5b34704b2 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160121-0ubuntu20000664000000000000000000000005115172222611022136 0ustar 8002fc863fc152938a2a10715b185058ebeb1646 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160201-0ubuntu10000664000000000000000000000005115172222611022134 0ustar af9d2f52c3469dfc3886d63e1b11d183534a48bc unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160209-0ubuntu10000664000000000000000000000005115172222611022144 0ustar ca7c7351191de8272d9310b9ae63b225a4a11d4f unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160209-0ubuntu20000664000000000000000000000005115172222611022145 0ustar 4ab4728685611757fdc11672bb3fdac390cceabe unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160701-0ubuntu10000664000000000000000000000005115172222611022141 0ustar fa124e6bfce9af1f67b9338e260eba122fc8d7a1 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160701-0ubuntu20000664000000000000000000000005115172222611022142 0ustar bee6fba0ed330313ea9b7e6d6c272b4aa3e9f5b8 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.04.20160701-0ubuntu30000664000000000000000000000005115172222611022143 0ustar 962d5f7795c1465dd8cbf3305868a4489e33487b unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.10.20160613-0ubuntu10000664000000000000000000000005115172222611022140 0ustar f4b82ce685b30d7c44426877addcd52fca214a07 unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.10.20160615-0ubuntu10000664000000000000000000000005115172222611022142 0ustar 5cbba82abcddcd41608dafe4adbb579183dda2ef unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.10.20160819-0ubuntu10000664000000000000000000000005115172222611022150 0ustar 44bb210a829a025c30163339157c2ab00fda9adf unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.10.20160819-0ubuntu20000664000000000000000000000005115172222611022151 0ustar b691ceeeeaadd517ea40c02cc6a5e1516527377e unity-settings-daemon/.git/refs/tags/applied/15.04.1+16.10.20161003-0ubuntu10000664000000000000000000000005115172222611022132 0ustar 7694ce9dc1742a681ed3c8ff43dfc579d1b50abb unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170322-0ubuntu10000664000000000000000000000005115172222611022142 0ustar b0ae9f2f75904ec600433b512a8672e0fbe3508b unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170322-0ubuntu1.10000664000000000000000000000005115172222611022301 0ustar b5271460001a32dbde695e2f645612e66fd9c4e2 unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170328-0ubuntu10000664000000000000000000000005115172222611022150 0ustar 4becd1449ea41d1c9fee01867d7a7035ea4da805 unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170418-0ubuntu10000664000000000000000000000005115172222611022150 0ustar ca129bc6513e6c33c20fedc8369424a25c191404 unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170619-0ubuntu10000664000000000000000000000005115172222611022153 0ustar f698d820b30b82061dafda51584441808aa3209a unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170619-0ubuntu20000664000000000000000000000005115172222611022154 0ustar fd2f65a45c155b76c71bdce1ebc8579b867e78e5 unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.04.20170619-0ubuntu30000664000000000000000000000005115172222611022155 0ustar b7c3fee4729b829cf055d5dc7f3d9ca2b0abe81b unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.10.20171003-0ubuntu10000664000000000000000000000005115172222611022134 0ustar d9c39fd2d3f42428e532d68e29f4429f802abb8d unity-settings-daemon/.git/refs/tags/applied/15.04.1+17.10.20171003-0ubuntu20000664000000000000000000000005115172222611022135 0ustar 00e26f3b570ced86e5309b8a4cb4662b14a4aa7c unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180214.1-0ubuntu10000664000000000000000000000005115172222611022303 0ustar b721ccbd6093fdf86681e9401e132949277437c3 unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180216-0ubuntu10000664000000000000000000000005115172222611022146 0ustar 2079e503f8ebf7e0034120ca0451487cb8c078d9 unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180413-0ubuntu10000664000000000000000000000005115172222611022145 0ustar b553a701a38c23f3f0b4ca31ff462fc6ee19345e unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180413-0ubuntu1.10000664000000000000000000000005115172222611022304 0ustar 45b349fa343daccccfdd7f1aa369d3820f70d25d unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180413-0ubuntu1.20000664000000000000000000000005115172222611022305 0ustar 6b639cb568d9dd42a8afbb412e5f417f69c76ff8 unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180413-0ubuntu20000664000000000000000000000005115172222611022146 0ustar b26a24c96ba9625de94664499503354ef19c7cea unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180413-0ubuntu30000664000000000000000000000005115172222611022147 0ustar 0a4fd8ee1ae33132ace2309c45cc6a1816c304a3 unity-settings-daemon/.git/refs/tags/applied/15.04.1+18.04.20180413-0ubuntu40000664000000000000000000000005115172222611022150 0ustar 13a693ea5e76592444305772a4ea838959466066 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20181122-0ubuntu10000664000000000000000000000005115172222611022144 0ustar 49435d2abdc629aa45fc54a088a3b87b0d3425df unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20190209-0ubuntu10000664000000000000000000000005115172222611022152 0ustar 6c353519728a4b5e1c4d5d9bba01c344560d1304 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20190209-0ubuntu20000664000000000000000000000005115172222611022153 0ustar da5171b8febc4f23c9d581a31ac86cf08c3fd0d6 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20190209-0ubuntu30000664000000000000000000000005115172222611022154 0ustar 5848f0180cfdda1d94cee292be6b9c52360a82b3 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20190209-0ubuntu3.10000664000000000000000000000005115172222611022313 0ustar 551ef658af24ac3fa5da4cbaa0ce72d844b00c91 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20190209-0ubuntu3.20000664000000000000000000000005115172222611022314 0ustar 3e98ae13d99ae0a9e0cbc4e40406e0590dd56d68 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.04.20190209-0ubuntu3.30000664000000000000000000000005115172222611022315 0ustar a70d8e1ac768403b9b388e50653fa0370c330f52 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.10.20190921-0ubuntu10000664000000000000000000000005115172222611022150 0ustar 0f0e316ae13fb70391c1b75428a18dab5cd53432 unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.10.20190921-0ubuntu20000664000000000000000000000005115172222611022151 0ustar d1ec855783c726e136de8e18bf70b678e84720cc unity-settings-daemon/.git/refs/tags/applied/15.04.1+19.10.20190921-0ubuntu30000664000000000000000000000005115172222611022152 0ustar 4b62f9ec652516e615630aed7f4c801a6dc041d0 unity-settings-daemon/.git/refs/tags/applied/15.04.1+20.04.20200311-0ubuntu10000664000000000000000000000005115172222611022124 0ustar 1bbab91668b3257943fc8894b43e5ae9c14093ec unity-settings-daemon/.git/refs/tags/applied/15.04.1+20.04.20200325-0ubuntu10000664000000000000000000000005115172222611022131 0ustar 7876b362caf7147986e88e49a8aba2417bceeb8c unity-settings-daemon/.git/refs/tags/applied/15.04.1+20.04.20200325-0ubuntu20000664000000000000000000000005115172222611022132 0ustar 843f4df1216a911bcbb12c7211e775ab14eebc59 unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20210715-0ubuntu10000664000000000000000000000005115172222611022133 0ustar 0afa45ec67d9055577b187dea5fc0838e3f71ea5 unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220207-0ubuntu10000664000000000000000000000005115172222611022130 0ustar 4ecad81e50e41182503dce81ad51360d9616e6a0 unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220802-0ubuntu10000664000000000000000000000005115172222611022131 0ustar 9b18a96c9c546e16507683297bfa4f9d5856063e unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220802-0ubuntu20000664000000000000000000000005115172222611022132 0ustar d14c59b17aa05f14d9e26c84dae9e0ee8b8bd0c3 unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220802-0ubuntu30000664000000000000000000000005115172222611022133 0ustar 7e477f68e0d78f8531fa1d993521239abd22d945 unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220802-0ubuntu40000664000000000000000000000005115172222611022134 0ustar 0c86c36de8e2fc6d6b99dfe29b6ae78da3d9f486 unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220802-0ubuntu50000664000000000000000000000005115172222611022135 0ustar 8199bf2cddb3123da641553d280840bd61b0f5ff unity-settings-daemon/.git/refs/tags/applied/15.04.1+21.10.20220802-0ubuntu60000664000000000000000000000005115172222611022136 0ustar e6a9c59a720521e4eff7334bb5ed9e16a5737b87 unity-settings-daemon/.git/refs/tags/import/0000775000000000000000000000000015172222611016264 5ustar unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140219-0ubuntu10000664000000000000000000000005115172222611022033 0ustar 97dfa3db0f85d1b48d5e1f2fe378d27951667b64 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140221-0ubuntu10000664000000000000000000000005115172222611022024 0ustar fcad43d94bf0a59f345f8d09e15f8f90c9653f74 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140221.1-0ubuntu10000664000000000000000000000005115172222611022163 0ustar f886d550e1d47bd7431cc1ca0bf0d4b372a0de97 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140225-0ubuntu10000664000000000000000000000005115172222611022030 0ustar 080012b1a9dbc858f9fd11ffe41453bf32e3c44e unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140228-0ubuntu10000664000000000000000000000005115172222611022033 0ustar 0b1254f6d9d02f864697764561b78c3f3a6032a5 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140310-0ubuntu10000664000000000000000000000005115172222611022023 0ustar c0b7aa00f1fbd4a5baa7fb9c5d9543bcf9e7eb35 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140310-0ubuntu20000664000000000000000000000005115172222611022024 0ustar bb84a333a27ae49e9884e452b66e19edb01662f1 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140402-0ubuntu10000664000000000000000000000005115172222611022025 0ustar e922e4c133457f9cd2608c861e58e59b8af21e2c unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140404-0ubuntu10000664000000000000000000000005115172222611022027 0ustar 7115703229913bab58fa0e3d67b1a1db9bdf041a unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140407-0ubuntu10000664000000000000000000000005115172222611022032 0ustar 6ef1a19096a29215db26d7e0389d1f87ebcfd1e6 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140414-0ubuntu10000664000000000000000000000005115172222611022030 0ustar 74f041ddbd8246d723ded24de49caa4287f4609d unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140606-0ubuntu10000664000000000000000000000005115172222611022033 0ustar 543ce44fe875c7a96820b4fbf0c49115ffc9844f unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140606-0ubuntu20000664000000000000000000000005115172222611022034 0ustar 805cccdc6cf6e2dd7401a3665d2e97b5332ec03b unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20140606-0ubuntu30000664000000000000000000000005115172222611022035 0ustar 7b3e09985c6a89f89eb63049f97099d1d80d5e0c unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20150825-0ubuntu10000664000000000000000000000005115172222611022037 0ustar 28ae3fd59a4db1d739087ca0592404a95d8471ab unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20150825-0ubuntu20000664000000000000000000000005115172222611022040 0ustar 849e6a90c7850b98a7d984d37c237c6622834686 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.04.20151012-0ubuntu10000664000000000000000000000005115172222611022024 0ustar ab4f6ae16cdf9e412f646c321a4e1ca15cd23393 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20140604-0ubuntu10000664000000000000000000000005115172222611022026 0ustar 206cd0218205d59703879ec2a5773e155a5a162b unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20140605-0ubuntu10000664000000000000000000000005115172222611022027 0ustar b852f594fbef069dcedce537f00bac26686217f3 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20140605-0ubuntu20000664000000000000000000000005115172222611022030 0ustar 12e032720192c217628aca16c7012038eda38e48 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20140922-0ubuntu10000664000000000000000000000005115172222611022031 0ustar cffa4d40a66b57c45b55f926f0af57d96c88cfde unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20140922-0ubuntu20000664000000000000000000000005115172222611022032 0ustar dce798bfcc76e702a4d4dbe9e904252fd97a91b0 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20140922-0ubuntu30000664000000000000000000000005115172222611022033 0ustar 61e4b71b46ad1eec75d4d15f600f54eff640635a unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20141010-0ubuntu10000664000000000000000000000005115172222611022016 0ustar ba9a582f9f71867c0e98d0dc907d7e0957c58f59 unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20141014-0ubuntu10000664000000000000000000000005115172222611022022 0ustar 1dbd7c2209c102a6573f58532c1f4467b81109ed unity-settings-daemon/.git/refs/tags/import/14.04.0+14.10.20141014-0ubuntu1.10000664000000000000000000000005115172222611022161 0ustar 65db1b9227615f9f85b41b82f7761a5a7813c931 unity-settings-daemon/.git/refs/tags/import/14.04.0-0ubuntu10000664000000000000000000000005115172222611020470 0ustar cac9602fe48ada208e9750906b989dd2199c2693 unity-settings-daemon/.git/refs/tags/import/14.04.0-0ubuntu20000664000000000000000000000005115172222611020471 0ustar a9cb5e1ec2041a93a098575930bc6ef495163cd8 unity-settings-daemon/.git/refs/tags/import/15.04.0+15.10.20141030-0ubuntu10000664000000000000000000000005115172222611022022 0ustar 0ed658f782c632598e1a8dd09c9b8b243465bfba unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20141127-0ubuntu10000664000000000000000000000005115172222611022035 0ustar 9dd387b9c551c55fa4a2ed5e3dc3ea382a35fd8a unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20141128-0ubuntu10000664000000000000000000000005115172222611022036 0ustar 0d9e7afa6be2d5f8e1982eab4f32eda7d50cf26b unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150107-0ubuntu10000664000000000000000000000005115172222611022033 0ustar e9c72aef5fba4c7125d5b3d2d8c88346be23f96e unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150205-0ubuntu10000664000000000000000000000005115172222611022032 0ustar 71fd1cea0fd51dc1f3ee3fa9ba7dd9a5ecd399a7 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150310-0ubuntu10000664000000000000000000000005115172222611022027 0ustar 2250ff34b171d5c283b13bea6531e26f2e1c499a unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150313-0ubuntu10000664000000000000000000000005115172222611022032 0ustar 3b88190143be4a756a5cc71b031650fd2f5dfd9f unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150318-0ubuntu10000664000000000000000000000005115172222611022037 0ustar 0192f3b5e929b9aca62cfac17dfbdccb3c8f0d7f unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150324.1-0ubuntu10000664000000000000000000000005115172222611022173 0ustar 2c24e8c7bc379dbad8f5d9c8177325068daa94a8 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150401-0ubuntu10000664000000000000000000000005115172222611022030 0ustar 051605b9e26c283c150cb200608945e5eddcaf64 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150408-0ubuntu10000664000000000000000000000005115172222611022037 0ustar 9a465904a18b7b45c515a7573b8b204804f0ffe1 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150408-0ubuntu1.10000664000000000000000000000005115172222611022176 0ustar 67ecf41b7b97f17fbb7ba8d6dd7b40f0ed5136b7 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.04.20150408-0ubuntu1.20000664000000000000000000000005115172222611022177 0ustar 2493e054c2828a3a0bf7f5d5c0095b60619c6b26 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20150630.1-0ubuntu10000664000000000000000000000005115172222611022170 0ustar 58ffde230b9c2bf19010e6c4e21ff4cbd12057e6 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20150720-0ubuntu10000664000000000000000000000005115172222611022031 0ustar 5e3699d290d596f12c7c1397bd2a792fa9bb219c unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20150818-0ubuntu10000664000000000000000000000005115172222611022041 0ustar b6cb5780d28e89182d263d520514c110a9300a46 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20150825-0ubuntu10000664000000000000000000000005115172222611022037 0ustar bf14e433cbc135d6945385b8e91637bff5e1ee39 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20150917-0ubuntu10000664000000000000000000000005115172222611022041 0ustar 5e0e8c0c82137113ef642acbe0d53b7210bf2b07 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20150930-0ubuntu10000664000000000000000000000005115172222611022034 0ustar 91f91c7930bdd8c31def1ddfa3d5dbbb24eb82cb unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20151001-0ubuntu10000664000000000000000000000005115172222611022022 0ustar 4c4aac6e60c8efee9e22099ab37f8dde075ed19f unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20151008-0ubuntu10000664000000000000000000000005115172222611022031 0ustar 787fd97cf79768efd5bb96be2900961d17f0529b unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20151012-0ubuntu10000664000000000000000000000005115172222611022024 0ustar dc6a0e68da3c8e1a05fa5345cde0fb50d838554f unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20151021-0ubuntu10000664000000000000000000000005115172222611022024 0ustar d4d48e3e9f5e149393d4acff387a0f3c1ed7f95a unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20151021-0ubuntu20000664000000000000000000000005115172222611022025 0ustar 67d0fa1c797961468641f71b62c1474f7643e7a2 unity-settings-daemon/.git/refs/tags/import/15.04.1+15.10.20151029-0ubuntu10000664000000000000000000000005115172222611022034 0ustar d7bf6f36f17bd48455c789adb45be8fba4f50295 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20151106-0ubuntu10000664000000000000000000000005115172222611022034 0ustar f968c4e967ecfa294fa3dc35d1c2596d84904a0c unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20151118.1-0ubuntu10000664000000000000000000000005115172222611022176 0ustar b9e14a089c0e06dbf7e7c35fd46dc8e111b9b697 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20151118.1-0ubuntu20000664000000000000000000000005115172222611022177 0ustar fb1ff18317a9d6a336e4e35dfb537b0d0434f6ab unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20151214-0ubuntu10000664000000000000000000000005115172222611022034 0ustar 3cc018547de5e5e1cc5373eae7c59a6aac5249d7 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160119-0ubuntu10000664000000000000000000000005115172222611022040 0ustar 0eccb91c047bb7e1934c45c98c46a2152e003dd2 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160121-0ubuntu10000664000000000000000000000005115172222611022031 0ustar 77c055d8781e16a61bf8d6db301af56eaaba450a unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160121-0ubuntu20000664000000000000000000000005115172222611022032 0ustar f95f8463df08b42540730e85c88f074d1d288af2 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160201-0ubuntu10000664000000000000000000000005115172222611022030 0ustar 3f94a00ce641f77f37dc3f1a960b1abb2812c54e unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160209-0ubuntu10000664000000000000000000000005115172222611022040 0ustar a053030e368bd1a52aa20d487512ac97eca4d355 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160209-0ubuntu20000664000000000000000000000005115172222611022041 0ustar e57e76f707cd7236607f60fbf648b3c8d0861977 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160701-0ubuntu10000664000000000000000000000005115172222611022035 0ustar 46c1172690f92716b79f799570ae1f9857d38508 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160701-0ubuntu20000664000000000000000000000005115172222611022036 0ustar 3755397b09bb39f0550eaf081d59312611daa615 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.04.20160701-0ubuntu30000664000000000000000000000005115172222611022037 0ustar c444058846f84515ad11f9e88e4a03d26e7c065b unity-settings-daemon/.git/refs/tags/import/15.04.1+16.10.20160613-0ubuntu10000664000000000000000000000005115172222611022034 0ustar d3d7f2546b99769bd39af7168800cbd93bb534f4 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.10.20160615-0ubuntu10000664000000000000000000000005115172222611022036 0ustar 10e77aeaaa3aab8d3cc473670ebcb4f4fe3118f3 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.10.20160819-0ubuntu10000664000000000000000000000005115172222611022044 0ustar 7818ad8751d110b6b5491f51808a2d61fb58ad32 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.10.20160819-0ubuntu20000664000000000000000000000005115172222611022045 0ustar 5609ce437cf025f7aa860d59860fc951a35a60b3 unity-settings-daemon/.git/refs/tags/import/15.04.1+16.10.20161003-0ubuntu10000664000000000000000000000005115172222611022026 0ustar 7c0cd1c5dfcc1102759ff342480a80552030574c unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170322-0ubuntu10000664000000000000000000000005115172222611022036 0ustar ac5d1472f4608e2da2ee17e5c5691e02a1146bad unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170322-0ubuntu1.10000664000000000000000000000005115172222611022175 0ustar bfd7eb9f29139fa6d8cfcdff19a40c2cc14d6357 unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170328-0ubuntu10000664000000000000000000000005115172222611022044 0ustar 52f67185f07a923534365574af5e98bf6b83816d unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170418-0ubuntu10000664000000000000000000000005115172222611022044 0ustar 11cfd3d9217d7df3f325a2a706626d393512cdc5 unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170619-0ubuntu10000664000000000000000000000005115172222611022047 0ustar 5010731d30cdf500c454a9be484e30080be79b59 unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170619-0ubuntu20000664000000000000000000000005115172222611022050 0ustar f66a4c86e122ad0c75579bc0e1950c7b158420ba unity-settings-daemon/.git/refs/tags/import/15.04.1+17.04.20170619-0ubuntu30000664000000000000000000000005115172222611022051 0ustar 54999bffb78b2f10095dfffd6566c329959847f0 unity-settings-daemon/.git/refs/tags/import/15.04.1+17.10.20171003-0ubuntu10000664000000000000000000000005115172222611022030 0ustar 97659f8cf68f687d52151db61c9edc3cc6ccb797 unity-settings-daemon/.git/refs/tags/import/15.04.1+17.10.20171003-0ubuntu20000664000000000000000000000005115172222611022031 0ustar 0602c7b74c57252f33fc2d8b5b337ba7e4800350 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180214.1-0ubuntu10000664000000000000000000000005115172222611022177 0ustar 4b24b3b811453902392930cf96ab8bf520ad0ad8 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180216-0ubuntu10000664000000000000000000000005115172222611022042 0ustar 1188bc99a33b022ddcbb59a44fdd2f5a644656a6 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180413-0ubuntu10000664000000000000000000000005115172222611022041 0ustar 077bdaecbc92a7790cf177169e826ddf9afa32c8 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180413-0ubuntu1.10000664000000000000000000000005115172222611022200 0ustar 1c658c0f2f3227e2dc3e2486ebb7a738236ba001 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180413-0ubuntu1.20000664000000000000000000000005115172222611022201 0ustar a3ee231261f8752c1bc782a66967bf6cfc5e5f73 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180413-0ubuntu20000664000000000000000000000005115172222611022042 0ustar 279af09f7ce5fc67bb269c75a52cc01ca6447d69 unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180413-0ubuntu30000664000000000000000000000005115172222611022043 0ustar 9c2f6ea4c8e6985be19fa9085f99ff981753ecff unity-settings-daemon/.git/refs/tags/import/15.04.1+18.04.20180413-0ubuntu40000664000000000000000000000005115172222611022044 0ustar 24d4245bfdd500ff7a3a4185b7823752dfea3b4b unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20181122-0ubuntu10000664000000000000000000000005115172222611022040 0ustar 12b510fe8f2ac5d04ddf0b2bdbf33cf8e3702b99 unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20190209-0ubuntu10000664000000000000000000000005115172222611022046 0ustar 565673c2fc60258d2489b6efe9aff7b425822fa5 unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20190209-0ubuntu20000664000000000000000000000005115172222611022047 0ustar 86fc44cdccff2507b06a54ab173b346f5d40759f unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20190209-0ubuntu30000664000000000000000000000005115172222611022050 0ustar 3bb7572d16aca726f700fb4aae86c406af7d23d3 unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20190209-0ubuntu3.10000664000000000000000000000005115172222611022207 0ustar 96e5d4d4db15de44b623d7b0cdf072e3bfd6b30f unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20190209-0ubuntu3.20000664000000000000000000000005115172222611022210 0ustar 532f3299bd8d27da755731378fa197b3b4149bdd unity-settings-daemon/.git/refs/tags/import/15.04.1+19.04.20190209-0ubuntu3.30000664000000000000000000000005115172222611022211 0ustar 85d4c3dd37131ad7bcbd820421e1c085317b5d6c unity-settings-daemon/.git/refs/tags/import/15.04.1+19.10.20190921-0ubuntu10000664000000000000000000000005115172222611022044 0ustar 0a4fa897825b6c5614657490ceaf82346ee1cdbc unity-settings-daemon/.git/refs/tags/import/15.04.1+19.10.20190921-0ubuntu20000664000000000000000000000005115172222611022045 0ustar 9c10e632dd2eab39ac263313bf62463a1a978b6f unity-settings-daemon/.git/refs/tags/import/15.04.1+19.10.20190921-0ubuntu30000664000000000000000000000005115172222611022046 0ustar efb612b96111a3637ba24fd77a48fecc9ef72dc0 unity-settings-daemon/.git/refs/tags/import/15.04.1+20.04.20200311-0ubuntu10000664000000000000000000000005115172222611022020 0ustar 1f1580ea183c279a86423865af2b5c2501bdd6d2 unity-settings-daemon/.git/refs/tags/import/15.04.1+20.04.20200325-0ubuntu10000664000000000000000000000005115172222611022025 0ustar 4d3510c8abf83d4a65c7384efcf61d74a4a75cd2 unity-settings-daemon/.git/refs/tags/import/15.04.1+20.04.20200325-0ubuntu20000664000000000000000000000005115172222611022026 0ustar 1d1b3e68bed94a061836032802e379011470fe00 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20210715-0ubuntu10000664000000000000000000000005115172222611022027 0ustar 902be1bbc317e12bb1077d993815bf4cafa36e44 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220207-0ubuntu10000664000000000000000000000005115172222611022024 0ustar 0da7636ae6c1cbe83061401f5927ccf7c8c60c58 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220802-0ubuntu10000664000000000000000000000005115172222611022025 0ustar e8ddcc4c454ee7c877a12e0e75cd2c684885baa4 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220802-0ubuntu20000664000000000000000000000005115172222611022026 0ustar 771691b7f8766a0adcf21d21121dc60dc006c115 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220802-0ubuntu30000664000000000000000000000005115172222611022027 0ustar af5b1d8df99c225bab7f5516b579fb40681baf91 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220802-0ubuntu40000664000000000000000000000005115172222611022030 0ustar e1540d40ecbf3780c15c5febe5a5c73faa976fcf unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220802-0ubuntu50000664000000000000000000000005115172222611022031 0ustar 0704b86558364321744a217e1ecb417c503a6906 unity-settings-daemon/.git/refs/tags/import/15.04.1+21.10.20220802-0ubuntu60000664000000000000000000000005115172222611022032 0ustar be239386ea5040bc480831ef0da43515ac7f63bd unity-settings-daemon/.git/refs/tags/pkg/0000775000000000000000000000000015172222611015533 5ustar unity-settings-daemon/.git/refs/tags/pkg/applied/0000775000000000000000000000000015172222611017151 5ustar unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140219-0ubuntu10000664000000000000000000000005115172222611022720 0ustar 7007f2846e81b8c2cbb95e5f07b28f04e9242df3 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140221-0ubuntu10000664000000000000000000000005115172222611022711 0ustar 4df3f944ade06e9cb79121f6b6b533e26dbd11ed unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140221.1-0ubuntu10000664000000000000000000000005115172222611023050 0ustar 0f9fa7dfd892d8611bec2ae8ae97eac8bb6a3c41 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140225-0ubuntu10000664000000000000000000000005115172222611022715 0ustar d17479dfc6be7b28f39086e76161a827704f7664 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140228-0ubuntu10000664000000000000000000000005115172222611022720 0ustar c7499af074b2689080c41e1635e4f7a20bec4372 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140310-0ubuntu10000664000000000000000000000005115172222611022710 0ustar 5aed97639e83c5e7113b92974104671c6a5a1c0b unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140310-0ubuntu20000664000000000000000000000005115172222611022711 0ustar 95dcd7761d8abe8e21ef0fb72a607cf55cfaaac2 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140402-0ubuntu10000664000000000000000000000005115172222611022712 0ustar 47f77e4f674e73b5ab13d0a6d254c5d14b1f6f19 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140404-0ubuntu10000664000000000000000000000005115172222611022714 0ustar 1adbb9a90d39ac88a3cc03f4a44930ac565bd5e9 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140407-0ubuntu10000664000000000000000000000005115172222611022717 0ustar 69ec0245d984c634718dd8f05a635d15912611ad unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140414-0ubuntu10000664000000000000000000000005115172222611022715 0ustar 83d8fbf44c8f8bdfb63b31fc60782d39c64d19cf unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140606-0ubuntu10000664000000000000000000000005115172222611022720 0ustar c57012053473af92dd9d7f896ef47398cd151715 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140606-0ubuntu20000664000000000000000000000005115172222611022721 0ustar a82cbe519251878be88931b9a10aa41bed4e7568 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20140606-0ubuntu30000664000000000000000000000005115172222611022722 0ustar dc58b2e641e229453808caae2e27ee6704dc9aa3 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20150825-0ubuntu10000664000000000000000000000005115172222611022724 0ustar 7db13af9aa8ca6bfb2d99442a5caf603bcf5bb3a unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20150825-0ubuntu20000664000000000000000000000005115172222611022725 0ustar 5d630bbc009b53674949dceaeee855c954367cce unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.04.20151012-0ubuntu10000664000000000000000000000005115172222611022711 0ustar 4436f53dc4e3b7cdb02a35e1e4b3165d7c64a95a unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20140604-0ubuntu10000664000000000000000000000005115172222611022713 0ustar 567cab64ef0500aac04501c19d7496d3c97a2c6e unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20140605-0ubuntu10000664000000000000000000000005115172222611022714 0ustar 2e79b391d8e4612ca78a95b0bb4a4cc9c08cd125 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20140605-0ubuntu20000664000000000000000000000005115172222611022715 0ustar 20e5c2a7baf70f8049c266e0ae6f3595dc3aff06 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20140922-0ubuntu10000664000000000000000000000005115172222611022716 0ustar 85d4e2307a1676ff81e7fc1c006498bff42084dc unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20140922-0ubuntu20000664000000000000000000000005115172222611022717 0ustar eb4eda3ea80e77f5b2b14f98c30c6e5cd0a3e32f unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20140922-0ubuntu30000664000000000000000000000005115172222611022720 0ustar 9fc6f7ecd66d07649fb9ef4e8073e67568c0ff74 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20141010-0ubuntu10000664000000000000000000000005115172222611022703 0ustar c8a566d9ea2c36898aaefcc3120cdb5ac6f4757c unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20141014-0ubuntu10000664000000000000000000000005115172222611022707 0ustar 684e45cab0eb791d8805664d60aec57a433405c0 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0+14.10.20141014-0ubuntu1.10000664000000000000000000000005115172222611023046 0ustar e8ca4c5be09b3e5ccbe3a7498d500957fe8b6079 unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0-0ubuntu10000664000000000000000000000005115172222611021355 0ustar 122c77a058b084394203249096bac267982c50fb unity-settings-daemon/.git/refs/tags/pkg/applied/14.04.0-0ubuntu20000664000000000000000000000005115172222611021356 0ustar c6ad65ffe296e13292497f808796b49412bbb820 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.0+15.10.20141030-0ubuntu10000664000000000000000000000005115172222611022707 0ustar d89628a424d35261364d5cc7ff3ed5f3bcd5916e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20141127-0ubuntu10000664000000000000000000000005115172222611022722 0ustar e64dd67069c72e1b42ff31c366d1cf8a0620460f unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20141128-0ubuntu10000664000000000000000000000005115172222611022723 0ustar 0a5fa857ff59dfd00fa0aea16cdc823d620141bf unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150107-0ubuntu10000664000000000000000000000005115172222611022720 0ustar de5c13d6da724a1c81859230d524b72437aac4d6 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150205-0ubuntu10000664000000000000000000000005115172222611022717 0ustar 48b0a7265af36d783ef6c2001006e93f95d26589 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150310-0ubuntu10000664000000000000000000000005115172222611022714 0ustar 5f6d16694a2df0263c6edc0da171b33f4ce65fc8 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150313-0ubuntu10000664000000000000000000000005115172222611022717 0ustar b5d1741bef218205b6258de6a038636888524388 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150318-0ubuntu10000664000000000000000000000005115172222611022724 0ustar 7938158ff642249978d36a38540d9f366e3e7c8f unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150324.1-0ubuntu10000664000000000000000000000005115172222611023060 0ustar 1ba4ddf9f9011edca3ff803e658409b8fe529d31 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150401-0ubuntu10000664000000000000000000000005115172222611022715 0ustar f4b407fc8a2e3229f96f689fa654391d60408704 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150408-0ubuntu10000664000000000000000000000005115172222611022724 0ustar 6fbfdf950c57da778d1d8b14b528fd9580ce3545 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150408-0ubuntu1.10000664000000000000000000000005115172222611023063 0ustar 4be51335656731fcc4a77edfaebc6b8579754a74 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.04.20150408-0ubuntu1.20000664000000000000000000000005115172222611023064 0ustar 8ef391ffb4a5aea4f5442fbb82779da6a3f415c4 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20150630.1-0ubuntu10000664000000000000000000000005115172222611023055 0ustar 56118444f3f06cdc2cda34ed9956b0e2a5840c6c unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20150720-0ubuntu10000664000000000000000000000005115172222611022716 0ustar 0ec58d725506270b7de0a663f2e02d8ee4c6cace unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20150818-0ubuntu10000664000000000000000000000005115172222611022726 0ustar 0c2efa9d88c0666d28bfa0e8d241865711f6b43a unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20150825-0ubuntu10000664000000000000000000000005115172222611022724 0ustar cf943dbc5884ce65e33a1063b32f85de9bde87bc unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20150917-0ubuntu10000664000000000000000000000005115172222611022726 0ustar 506e66f11995bee789b5c7aaa55e83cc64d81c4c unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20150930-0ubuntu10000664000000000000000000000005115172222611022721 0ustar 5fefadfc1bdcf8a2dfa43480bfeec689fe99f9c7 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20151001-0ubuntu10000664000000000000000000000005115172222611022707 0ustar b651f8a94668c759b40bc8a4945310b885e0c717 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20151008-0ubuntu10000664000000000000000000000005115172222611022716 0ustar 2a2b72d29ff1e164d741bd5cb49810388df7b89e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20151012-0ubuntu10000664000000000000000000000005115172222611022711 0ustar 96c14972fb3ce3c7f2ccdf0beb6aa2770d2a3f4c unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20151021-0ubuntu10000664000000000000000000000005115172222611022711 0ustar c3ca1366ab9b48febd092149c7a034b05a80fb19 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20151021-0ubuntu20000664000000000000000000000005115172222611022712 0ustar b63789da2eaab6be16ee38a7ae78ce6977ac9af9 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+15.10.20151029-0ubuntu10000664000000000000000000000005115172222611022721 0ustar 98c9ad15cdc26ed52624b339902ced746b8be37e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20151106-0ubuntu10000664000000000000000000000005115172222611022721 0ustar 7fd5eb16d897bddaf6f292a94c28a8060ae52c8e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20151118.1-0ubuntu10000664000000000000000000000005115172222611023063 0ustar 8da1cec74adedd0a226168fa8a351fa03af87b77 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20151118.1-0ubuntu20000664000000000000000000000005115172222611023064 0ustar 59f6645d7bddd510a306af1eec11ee49a60d2fea unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20151214-0ubuntu10000664000000000000000000000005115172222611022721 0ustar 6bd5c37fdf906e6de69698524b4f679f9db0b603 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160119-0ubuntu10000664000000000000000000000005115172222611022725 0ustar d4dd88bca2577931a73cbb0f061e126b0acf0249 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160121-0ubuntu10000664000000000000000000000005115172222611022716 0ustar 9bb93d22b0aa47e0c46c5a2a7b51b8f5b34704b2 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160121-0ubuntu20000664000000000000000000000005115172222611022717 0ustar 8002fc863fc152938a2a10715b185058ebeb1646 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160201-0ubuntu10000664000000000000000000000005115172222611022715 0ustar af9d2f52c3469dfc3886d63e1b11d183534a48bc unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160209-0ubuntu10000664000000000000000000000005115172222611022725 0ustar ca7c7351191de8272d9310b9ae63b225a4a11d4f unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160209-0ubuntu20000664000000000000000000000005115172222611022726 0ustar 4ab4728685611757fdc11672bb3fdac390cceabe unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160701-0ubuntu10000664000000000000000000000005115172222611022722 0ustar fa124e6bfce9af1f67b9338e260eba122fc8d7a1 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160701-0ubuntu20000664000000000000000000000005115172222611022723 0ustar bee6fba0ed330313ea9b7e6d6c272b4aa3e9f5b8 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.04.20160701-0ubuntu30000664000000000000000000000005115172222611022724 0ustar 962d5f7795c1465dd8cbf3305868a4489e33487b unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.10.20160613-0ubuntu10000664000000000000000000000005115172222611022721 0ustar f4b82ce685b30d7c44426877addcd52fca214a07 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.10.20160615-0ubuntu10000664000000000000000000000005115172222611022723 0ustar 5cbba82abcddcd41608dafe4adbb579183dda2ef unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.10.20160819-0ubuntu10000664000000000000000000000005115172222611022731 0ustar 44bb210a829a025c30163339157c2ab00fda9adf unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.10.20160819-0ubuntu20000664000000000000000000000005115172222611022732 0ustar b691ceeeeaadd517ea40c02cc6a5e1516527377e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+16.10.20161003-0ubuntu10000664000000000000000000000005115172222611022713 0ustar 7694ce9dc1742a681ed3c8ff43dfc579d1b50abb unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170322-0ubuntu10000664000000000000000000000005115172222611022723 0ustar b0ae9f2f75904ec600433b512a8672e0fbe3508b unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170322-0ubuntu1.10000664000000000000000000000005115172222611023062 0ustar b5271460001a32dbde695e2f645612e66fd9c4e2 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170328-0ubuntu10000664000000000000000000000005115172222611022731 0ustar 4becd1449ea41d1c9fee01867d7a7035ea4da805 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170418-0ubuntu10000664000000000000000000000005115172222611022731 0ustar ca129bc6513e6c33c20fedc8369424a25c191404 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170619-0ubuntu10000664000000000000000000000005115172222611022734 0ustar f698d820b30b82061dafda51584441808aa3209a unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170619-0ubuntu20000664000000000000000000000005115172222611022735 0ustar fd2f65a45c155b76c71bdce1ebc8579b867e78e5 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.04.20170619-0ubuntu30000664000000000000000000000005115172222611022736 0ustar b7c3fee4729b829cf055d5dc7f3d9ca2b0abe81b unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.10.20171003-0ubuntu10000664000000000000000000000005115172222611022715 0ustar d9c39fd2d3f42428e532d68e29f4429f802abb8d unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+17.10.20171003-0ubuntu20000664000000000000000000000005115172222611022716 0ustar 00e26f3b570ced86e5309b8a4cb4662b14a4aa7c unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180214.1-0ubuntu10000664000000000000000000000005115172222611023064 0ustar b721ccbd6093fdf86681e9401e132949277437c3 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180216-0ubuntu10000664000000000000000000000005115172222611022727 0ustar 2079e503f8ebf7e0034120ca0451487cb8c078d9 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180413-0ubuntu10000664000000000000000000000005115172222611022726 0ustar b553a701a38c23f3f0b4ca31ff462fc6ee19345e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180413-0ubuntu1.10000664000000000000000000000005115172222611023065 0ustar 45b349fa343daccccfdd7f1aa369d3820f70d25d unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180413-0ubuntu1.20000664000000000000000000000005115172222611023066 0ustar 6b639cb568d9dd42a8afbb412e5f417f69c76ff8 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180413-0ubuntu20000664000000000000000000000005115172222611022727 0ustar b26a24c96ba9625de94664499503354ef19c7cea unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180413-0ubuntu30000664000000000000000000000005115172222611022730 0ustar 0a4fd8ee1ae33132ace2309c45cc6a1816c304a3 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+18.04.20180413-0ubuntu40000664000000000000000000000005115172222611022731 0ustar 13a693ea5e76592444305772a4ea838959466066 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20181122-0ubuntu10000664000000000000000000000005115172222611022725 0ustar 49435d2abdc629aa45fc54a088a3b87b0d3425df unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20190209-0ubuntu10000664000000000000000000000005115172222611022733 0ustar 6c353519728a4b5e1c4d5d9bba01c344560d1304 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20190209-0ubuntu20000664000000000000000000000005115172222611022734 0ustar da5171b8febc4f23c9d581a31ac86cf08c3fd0d6 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20190209-0ubuntu30000664000000000000000000000005115172222611022735 0ustar 5848f0180cfdda1d94cee292be6b9c52360a82b3 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20190209-0ubuntu3.10000664000000000000000000000005115172222611023074 0ustar 551ef658af24ac3fa5da4cbaa0ce72d844b00c91 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20190209-0ubuntu3.20000664000000000000000000000005115172222611023075 0ustar 3e98ae13d99ae0a9e0cbc4e40406e0590dd56d68 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.04.20190209-0ubuntu3.30000664000000000000000000000005115172222611023076 0ustar a70d8e1ac768403b9b388e50653fa0370c330f52 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.10.20190921-0ubuntu10000664000000000000000000000005115172222611022731 0ustar 0f0e316ae13fb70391c1b75428a18dab5cd53432 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.10.20190921-0ubuntu20000664000000000000000000000005115172222611022732 0ustar d1ec855783c726e136de8e18bf70b678e84720cc unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+19.10.20190921-0ubuntu30000664000000000000000000000005115172222611022733 0ustar 4b62f9ec652516e615630aed7f4c801a6dc041d0 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+20.04.20200311-0ubuntu10000664000000000000000000000005115172222611022705 0ustar 1bbab91668b3257943fc8894b43e5ae9c14093ec unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+20.04.20200325-0ubuntu10000664000000000000000000000005115172222611022712 0ustar 7876b362caf7147986e88e49a8aba2417bceeb8c unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+20.04.20200325-0ubuntu20000664000000000000000000000005115172222611022713 0ustar 843f4df1216a911bcbb12c7211e775ab14eebc59 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20210715-0ubuntu10000664000000000000000000000005115172222611022714 0ustar 0afa45ec67d9055577b187dea5fc0838e3f71ea5 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220207-0ubuntu10000664000000000000000000000005115172222611022711 0ustar 4ecad81e50e41182503dce81ad51360d9616e6a0 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220802-0ubuntu10000664000000000000000000000005115172222611022712 0ustar 9b18a96c9c546e16507683297bfa4f9d5856063e unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220802-0ubuntu20000664000000000000000000000005115172222611022713 0ustar d14c59b17aa05f14d9e26c84dae9e0ee8b8bd0c3 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220802-0ubuntu30000664000000000000000000000005115172222611022714 0ustar 7e477f68e0d78f8531fa1d993521239abd22d945 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220802-0ubuntu40000664000000000000000000000005115172222611022715 0ustar 0c86c36de8e2fc6d6b99dfe29b6ae78da3d9f486 unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220802-0ubuntu50000664000000000000000000000005115172222611022716 0ustar 8199bf2cddb3123da641553d280840bd61b0f5ff unity-settings-daemon/.git/refs/tags/pkg/applied/15.04.1+21.10.20220802-0ubuntu60000664000000000000000000000005115172222611022717 0ustar e6a9c59a720521e4eff7334bb5ed9e16a5737b87 unity-settings-daemon/.git/refs/tags/pkg/import/0000775000000000000000000000000015172222611017045 5ustar unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140219-0ubuntu10000664000000000000000000000005115172222611022614 0ustar 97dfa3db0f85d1b48d5e1f2fe378d27951667b64 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140221-0ubuntu10000664000000000000000000000005115172222611022605 0ustar fcad43d94bf0a59f345f8d09e15f8f90c9653f74 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140221.1-0ubuntu10000664000000000000000000000005115172222611022744 0ustar f886d550e1d47bd7431cc1ca0bf0d4b372a0de97 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140225-0ubuntu10000664000000000000000000000005115172222611022611 0ustar 080012b1a9dbc858f9fd11ffe41453bf32e3c44e unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140228-0ubuntu10000664000000000000000000000005115172222611022614 0ustar 0b1254f6d9d02f864697764561b78c3f3a6032a5 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140310-0ubuntu10000664000000000000000000000005115172222611022604 0ustar c0b7aa00f1fbd4a5baa7fb9c5d9543bcf9e7eb35 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140310-0ubuntu20000664000000000000000000000005115172222611022605 0ustar bb84a333a27ae49e9884e452b66e19edb01662f1 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140402-0ubuntu10000664000000000000000000000005115172222611022606 0ustar e922e4c133457f9cd2608c861e58e59b8af21e2c unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140404-0ubuntu10000664000000000000000000000005115172222611022610 0ustar 7115703229913bab58fa0e3d67b1a1db9bdf041a unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140407-0ubuntu10000664000000000000000000000005115172222611022613 0ustar 6ef1a19096a29215db26d7e0389d1f87ebcfd1e6 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140414-0ubuntu10000664000000000000000000000005115172222611022611 0ustar 74f041ddbd8246d723ded24de49caa4287f4609d unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140606-0ubuntu10000664000000000000000000000005115172222611022614 0ustar 543ce44fe875c7a96820b4fbf0c49115ffc9844f unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140606-0ubuntu20000664000000000000000000000005115172222611022615 0ustar 805cccdc6cf6e2dd7401a3665d2e97b5332ec03b unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20140606-0ubuntu30000664000000000000000000000005115172222611022616 0ustar 7b3e09985c6a89f89eb63049f97099d1d80d5e0c unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20150825-0ubuntu10000664000000000000000000000005115172222611022620 0ustar 28ae3fd59a4db1d739087ca0592404a95d8471ab unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20150825-0ubuntu20000664000000000000000000000005115172222611022621 0ustar 849e6a90c7850b98a7d984d37c237c6622834686 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.04.20151012-0ubuntu10000664000000000000000000000005115172222611022605 0ustar ab4f6ae16cdf9e412f646c321a4e1ca15cd23393 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20140604-0ubuntu10000664000000000000000000000005115172222611022607 0ustar 206cd0218205d59703879ec2a5773e155a5a162b unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20140605-0ubuntu10000664000000000000000000000005115172222611022610 0ustar b852f594fbef069dcedce537f00bac26686217f3 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20140605-0ubuntu20000664000000000000000000000005115172222611022611 0ustar 12e032720192c217628aca16c7012038eda38e48 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20140922-0ubuntu10000664000000000000000000000005115172222611022612 0ustar cffa4d40a66b57c45b55f926f0af57d96c88cfde unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20140922-0ubuntu20000664000000000000000000000005115172222611022613 0ustar dce798bfcc76e702a4d4dbe9e904252fd97a91b0 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20140922-0ubuntu30000664000000000000000000000005115172222611022614 0ustar 61e4b71b46ad1eec75d4d15f600f54eff640635a unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20141010-0ubuntu10000664000000000000000000000005115172222611022577 0ustar ba9a582f9f71867c0e98d0dc907d7e0957c58f59 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20141014-0ubuntu10000664000000000000000000000005115172222611022603 0ustar 1dbd7c2209c102a6573f58532c1f4467b81109ed unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0+14.10.20141014-0ubuntu1.10000664000000000000000000000005115172222611022742 0ustar 65db1b9227615f9f85b41b82f7761a5a7813c931 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0-0ubuntu10000664000000000000000000000005115172222611021251 0ustar cac9602fe48ada208e9750906b989dd2199c2693 unity-settings-daemon/.git/refs/tags/pkg/import/14.04.0-0ubuntu20000664000000000000000000000005115172222611021252 0ustar a9cb5e1ec2041a93a098575930bc6ef495163cd8 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.0+15.10.20141030-0ubuntu10000664000000000000000000000005115172222611022603 0ustar 0ed658f782c632598e1a8dd09c9b8b243465bfba unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20141127-0ubuntu10000664000000000000000000000005115172222611022616 0ustar 9dd387b9c551c55fa4a2ed5e3dc3ea382a35fd8a unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20141128-0ubuntu10000664000000000000000000000005115172222611022617 0ustar 0d9e7afa6be2d5f8e1982eab4f32eda7d50cf26b unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150107-0ubuntu10000664000000000000000000000005115172222611022614 0ustar e9c72aef5fba4c7125d5b3d2d8c88346be23f96e unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150205-0ubuntu10000664000000000000000000000005115172222611022613 0ustar 71fd1cea0fd51dc1f3ee3fa9ba7dd9a5ecd399a7 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150310-0ubuntu10000664000000000000000000000005115172222611022610 0ustar 2250ff34b171d5c283b13bea6531e26f2e1c499a unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150313-0ubuntu10000664000000000000000000000005115172222611022613 0ustar 3b88190143be4a756a5cc71b031650fd2f5dfd9f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150318-0ubuntu10000664000000000000000000000005115172222611022620 0ustar 0192f3b5e929b9aca62cfac17dfbdccb3c8f0d7f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150324.1-0ubuntu10000664000000000000000000000005115172222611022754 0ustar 2c24e8c7bc379dbad8f5d9c8177325068daa94a8 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150401-0ubuntu10000664000000000000000000000005115172222611022611 0ustar 051605b9e26c283c150cb200608945e5eddcaf64 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150408-0ubuntu10000664000000000000000000000005115172222611022620 0ustar 9a465904a18b7b45c515a7573b8b204804f0ffe1 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150408-0ubuntu1.10000664000000000000000000000005115172222611022757 0ustar 67ecf41b7b97f17fbb7ba8d6dd7b40f0ed5136b7 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.04.20150408-0ubuntu1.20000664000000000000000000000005115172222611022760 0ustar 2493e054c2828a3a0bf7f5d5c0095b60619c6b26 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20150630.1-0ubuntu10000664000000000000000000000005115172222611022751 0ustar 58ffde230b9c2bf19010e6c4e21ff4cbd12057e6 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20150720-0ubuntu10000664000000000000000000000005115172222611022612 0ustar 5e3699d290d596f12c7c1397bd2a792fa9bb219c unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20150818-0ubuntu10000664000000000000000000000005115172222611022622 0ustar b6cb5780d28e89182d263d520514c110a9300a46 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20150825-0ubuntu10000664000000000000000000000005115172222611022620 0ustar bf14e433cbc135d6945385b8e91637bff5e1ee39 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20150917-0ubuntu10000664000000000000000000000005115172222611022622 0ustar 5e0e8c0c82137113ef642acbe0d53b7210bf2b07 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20150930-0ubuntu10000664000000000000000000000005115172222611022615 0ustar 91f91c7930bdd8c31def1ddfa3d5dbbb24eb82cb unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20151001-0ubuntu10000664000000000000000000000005115172222611022603 0ustar 4c4aac6e60c8efee9e22099ab37f8dde075ed19f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20151008-0ubuntu10000664000000000000000000000005115172222611022612 0ustar 787fd97cf79768efd5bb96be2900961d17f0529b unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20151012-0ubuntu10000664000000000000000000000005115172222611022605 0ustar dc6a0e68da3c8e1a05fa5345cde0fb50d838554f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20151021-0ubuntu10000664000000000000000000000005115172222611022605 0ustar d4d48e3e9f5e149393d4acff387a0f3c1ed7f95a unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20151021-0ubuntu20000664000000000000000000000005115172222611022606 0ustar 67d0fa1c797961468641f71b62c1474f7643e7a2 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+15.10.20151029-0ubuntu10000664000000000000000000000005115172222611022615 0ustar d7bf6f36f17bd48455c789adb45be8fba4f50295 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20151106-0ubuntu10000664000000000000000000000005115172222611022615 0ustar f968c4e967ecfa294fa3dc35d1c2596d84904a0c unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20151118.1-0ubuntu10000664000000000000000000000005115172222611022757 0ustar b9e14a089c0e06dbf7e7c35fd46dc8e111b9b697 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20151118.1-0ubuntu20000664000000000000000000000005115172222611022760 0ustar fb1ff18317a9d6a336e4e35dfb537b0d0434f6ab unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20151214-0ubuntu10000664000000000000000000000005115172222611022615 0ustar 3cc018547de5e5e1cc5373eae7c59a6aac5249d7 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160119-0ubuntu10000664000000000000000000000005115172222611022621 0ustar 0eccb91c047bb7e1934c45c98c46a2152e003dd2 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160121-0ubuntu10000664000000000000000000000005115172222611022612 0ustar 77c055d8781e16a61bf8d6db301af56eaaba450a unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160121-0ubuntu20000664000000000000000000000005115172222611022613 0ustar f95f8463df08b42540730e85c88f074d1d288af2 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160201-0ubuntu10000664000000000000000000000005115172222611022611 0ustar 3f94a00ce641f77f37dc3f1a960b1abb2812c54e unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160209-0ubuntu10000664000000000000000000000005115172222611022621 0ustar a053030e368bd1a52aa20d487512ac97eca4d355 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160209-0ubuntu20000664000000000000000000000005115172222611022622 0ustar e57e76f707cd7236607f60fbf648b3c8d0861977 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160701-0ubuntu10000664000000000000000000000005115172222611022616 0ustar 46c1172690f92716b79f799570ae1f9857d38508 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160701-0ubuntu20000664000000000000000000000005115172222611022617 0ustar 3755397b09bb39f0550eaf081d59312611daa615 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.04.20160701-0ubuntu30000664000000000000000000000005115172222611022620 0ustar c444058846f84515ad11f9e88e4a03d26e7c065b unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.10.20160613-0ubuntu10000664000000000000000000000005115172222611022615 0ustar d3d7f2546b99769bd39af7168800cbd93bb534f4 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.10.20160615-0ubuntu10000664000000000000000000000005115172222611022617 0ustar 10e77aeaaa3aab8d3cc473670ebcb4f4fe3118f3 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.10.20160819-0ubuntu10000664000000000000000000000005115172222611022625 0ustar 7818ad8751d110b6b5491f51808a2d61fb58ad32 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.10.20160819-0ubuntu20000664000000000000000000000005115172222611022626 0ustar 5609ce437cf025f7aa860d59860fc951a35a60b3 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+16.10.20161003-0ubuntu10000664000000000000000000000005115172222611022607 0ustar 7c0cd1c5dfcc1102759ff342480a80552030574c unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170322-0ubuntu10000664000000000000000000000005115172222611022617 0ustar ac5d1472f4608e2da2ee17e5c5691e02a1146bad unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170322-0ubuntu1.10000664000000000000000000000005115172222611022756 0ustar bfd7eb9f29139fa6d8cfcdff19a40c2cc14d6357 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170328-0ubuntu10000664000000000000000000000005115172222611022625 0ustar 52f67185f07a923534365574af5e98bf6b83816d unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170418-0ubuntu10000664000000000000000000000005115172222611022625 0ustar 11cfd3d9217d7df3f325a2a706626d393512cdc5 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170619-0ubuntu10000664000000000000000000000005115172222611022630 0ustar 5010731d30cdf500c454a9be484e30080be79b59 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170619-0ubuntu20000664000000000000000000000005115172222611022631 0ustar f66a4c86e122ad0c75579bc0e1950c7b158420ba unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.04.20170619-0ubuntu30000664000000000000000000000005115172222611022632 0ustar 54999bffb78b2f10095dfffd6566c329959847f0 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.10.20171003-0ubuntu10000664000000000000000000000005115172222611022611 0ustar 97659f8cf68f687d52151db61c9edc3cc6ccb797 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+17.10.20171003-0ubuntu20000664000000000000000000000005115172222611022612 0ustar 0602c7b74c57252f33fc2d8b5b337ba7e4800350 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180214.1-0ubuntu10000664000000000000000000000005115172222611022760 0ustar 4b24b3b811453902392930cf96ab8bf520ad0ad8 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180216-0ubuntu10000664000000000000000000000005115172222611022623 0ustar 1188bc99a33b022ddcbb59a44fdd2f5a644656a6 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180413-0ubuntu10000664000000000000000000000005115172222611022622 0ustar 077bdaecbc92a7790cf177169e826ddf9afa32c8 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180413-0ubuntu1.10000664000000000000000000000005115172222611022761 0ustar 1c658c0f2f3227e2dc3e2486ebb7a738236ba001 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180413-0ubuntu1.20000664000000000000000000000005115172222611022762 0ustar a3ee231261f8752c1bc782a66967bf6cfc5e5f73 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180413-0ubuntu20000664000000000000000000000005115172222611022623 0ustar 279af09f7ce5fc67bb269c75a52cc01ca6447d69 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180413-0ubuntu30000664000000000000000000000005115172222611022624 0ustar 9c2f6ea4c8e6985be19fa9085f99ff981753ecff unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+18.04.20180413-0ubuntu40000664000000000000000000000005115172222611022625 0ustar 24d4245bfdd500ff7a3a4185b7823752dfea3b4b unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20181122-0ubuntu10000664000000000000000000000005115172222611022621 0ustar 12b510fe8f2ac5d04ddf0b2bdbf33cf8e3702b99 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20190209-0ubuntu10000664000000000000000000000005115172222611022627 0ustar 565673c2fc60258d2489b6efe9aff7b425822fa5 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20190209-0ubuntu20000664000000000000000000000005115172222611022630 0ustar 86fc44cdccff2507b06a54ab173b346f5d40759f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20190209-0ubuntu30000664000000000000000000000005115172222611022631 0ustar 3bb7572d16aca726f700fb4aae86c406af7d23d3 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20190209-0ubuntu3.10000664000000000000000000000005115172222611022770 0ustar 96e5d4d4db15de44b623d7b0cdf072e3bfd6b30f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20190209-0ubuntu3.20000664000000000000000000000005115172222611022771 0ustar 532f3299bd8d27da755731378fa197b3b4149bdd unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.04.20190209-0ubuntu3.30000664000000000000000000000005115172222611022772 0ustar 85d4c3dd37131ad7bcbd820421e1c085317b5d6c unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.10.20190921-0ubuntu10000664000000000000000000000005115172222611022625 0ustar 0a4fa897825b6c5614657490ceaf82346ee1cdbc unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.10.20190921-0ubuntu20000664000000000000000000000005115172222611022626 0ustar 9c10e632dd2eab39ac263313bf62463a1a978b6f unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+19.10.20190921-0ubuntu30000664000000000000000000000005115172222611022627 0ustar efb612b96111a3637ba24fd77a48fecc9ef72dc0 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+20.04.20200311-0ubuntu10000664000000000000000000000005115172222611022601 0ustar 1f1580ea183c279a86423865af2b5c2501bdd6d2 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+20.04.20200325-0ubuntu10000664000000000000000000000005115172222611022606 0ustar 4d3510c8abf83d4a65c7384efcf61d74a4a75cd2 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+20.04.20200325-0ubuntu20000664000000000000000000000005115172222611022607 0ustar 1d1b3e68bed94a061836032802e379011470fe00 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20210715-0ubuntu10000664000000000000000000000005115172222611022610 0ustar 902be1bbc317e12bb1077d993815bf4cafa36e44 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220207-0ubuntu10000664000000000000000000000005115172222611022605 0ustar 0da7636ae6c1cbe83061401f5927ccf7c8c60c58 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220802-0ubuntu10000664000000000000000000000005115172222611022606 0ustar e8ddcc4c454ee7c877a12e0e75cd2c684885baa4 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220802-0ubuntu20000664000000000000000000000005115172222611022607 0ustar 771691b7f8766a0adcf21d21121dc60dc006c115 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220802-0ubuntu30000664000000000000000000000005115172222611022610 0ustar af5b1d8df99c225bab7f5516b579fb40681baf91 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220802-0ubuntu40000664000000000000000000000005115172222611022611 0ustar e1540d40ecbf3780c15c5febe5a5c73faa976fcf unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220802-0ubuntu50000664000000000000000000000005115172222611022612 0ustar 0704b86558364321744a217e1ecb417c503a6906 unity-settings-daemon/.git/refs/tags/pkg/import/15.04.1+21.10.20220802-0ubuntu60000664000000000000000000000005115172222611022613 0ustar be239386ea5040bc480831ef0da43515ac7f63bd unity-settings-daemon/.git/refs/tags/pkg/upstream/0000775000000000000000000000000015172222611017373 5ustar unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/0000775000000000000000000000000015172222611020715 5ustar unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140219.gz0000664000000000000000000000005115172222611023422 0ustar 0d508075baa33233e5c59b44ae3c99732ccf960b unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140221.1.gz0000664000000000000000000000005115172222611023552 0ustar 0b6677bb46a9afbb0884197f3406a8b6ccec19f0 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140221.gz0000664000000000000000000000005115172222611023413 0ustar c9b8da8edc821a07a4d2300c942a5f943ff56ee7 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140225.gz0000664000000000000000000000005115172222611023417 0ustar 20b722c7d607fa0545ace676aee63bd0654e58e2 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140228.gz0000664000000000000000000000005115172222611023422 0ustar ecde0193ef2e46e31ccef05c82e989e200a4a3c4 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140310.gz0000664000000000000000000000005115172222611023412 0ustar 28483af390daeca492fc3ddaa11e3c2cf4d5d544 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140402.gz0000664000000000000000000000005115172222611023414 0ustar a1dead0162479f94ca93de9abd793e9de9c4a7a3 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140404.gz0000664000000000000000000000005115172222611023416 0ustar b17a76dab28b296e7c79625c414f09c0444356ed unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140407.gz0000664000000000000000000000005115172222611023421 0ustar a08c0f76f1bacf7507c48071440d6b3d5c798ab8 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140414.gz0000664000000000000000000000005115172222611023417 0ustar 4961e2b7955573344b459bc557d40463234fb1ea unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20140606.gz0000664000000000000000000000005115172222611023422 0ustar 40fd03d0d7bce669bb9e8d94fee04419c528e733 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20150825.gz0000664000000000000000000000005115172222611023426 0ustar ce749d0414fc9aedb6775c655e8ca65d1127f05d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.04.20151012.gz0000664000000000000000000000005115172222611023413 0ustar 54f6c9f9191cf5c48e3c6a816eae442699b908cf unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.10.20140604.gz0000664000000000000000000000005115172222611023415 0ustar 723b2ef9610fa6e304080a5b7e9456fabace2c80 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.10.20140605.gz0000664000000000000000000000005115172222611023416 0ustar 185aa83861a0122c59a80624bf91758f4dad7b7a unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.10.20140922.gz0000664000000000000000000000005115172222611023420 0ustar 21aa76eaee0675e76d29b602c9bdf9a503709b5d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.10.20141010.gz0000664000000000000000000000005115172222611023405 0ustar ee9c975b4aa1bfd721e935a5d033d7ab6f88affe unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0+14.10.20141014.gz0000664000000000000000000000005115172222611023411 0ustar 47d0f17f4ae0e7209e77955be9d861fead28d71b unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/14.04.0.gz0000664000000000000000000000005115172222611022057 0ustar 18e9c73ca12dc7edd9c0a0f099e54a76dd7b37be unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.0+15.10.20141030.gz0000664000000000000000000000005115172222611023411 0ustar cd2e502e61733ba9abc50076c1c5e28aa47125ad unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20141127.gz0000664000000000000000000000005115172222611023424 0ustar dad4f91fe5b615ec403cdd3477585d472037a7f8 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20141128.gz0000664000000000000000000000005115172222611023425 0ustar 3c349614b7dd0c177d8b060faf3e44cd46c3532d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150107.gz0000664000000000000000000000005115172222611023422 0ustar aa05ec9834f8fa8e3b6c2973703735038e6ec31b unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150205.gz0000664000000000000000000000005115172222611023421 0ustar b22ef89ab70222f54d7de10df8fae935d398b065 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150310.gz0000664000000000000000000000005115172222611023416 0ustar 6300492cbfe0bc61d1f3287eea8c4c837e93f8ad unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150313.gz0000664000000000000000000000005115172222611023421 0ustar 033e80df1fba35fb440b302c09c3e8fb63d4ffab unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150318.gz0000664000000000000000000000005115172222611023426 0ustar 1853e4ceff03e82a95ab48a2299b404b19c6b0a7 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150324.1.gz0000664000000000000000000000005115172222611023562 0ustar 90871bf0481f6ef2b639b78d9b849c3314aacfbc unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150401.gz0000664000000000000000000000005115172222611023417 0ustar 09c0cde7808eff353ee4596dc6a716536969e974 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.04.20150408.gz0000664000000000000000000000005115172222611023426 0ustar 2cc1765b545186838ec803c04bb873cb76e55135 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20150630.1.gz0000664000000000000000000000005115172222611023557 0ustar df18d1f9398544bfdeadd38ab0eac72dd796abfb unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20150720.gz0000664000000000000000000000005115172222611023420 0ustar 9903722feb192671ef54c5d60f0b08a4f02ac28f unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20150818.gz0000664000000000000000000000005115172222611023430 0ustar 6ca0d0658e6864a2e5825327d74ef8ec8b27133c unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20150825.gz0000664000000000000000000000005115172222611023426 0ustar ddf6a9fa1991641eabdfac43a24f424f87a02135 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20150917.gz0000664000000000000000000000005115172222611023430 0ustar 2947c02264314221b041b210502d1a724e2031e0 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20150930.gz0000664000000000000000000000005115172222611023423 0ustar df639929f7b20598eee5ab5448abcb3536c27eea unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20151001.gz0000664000000000000000000000005115172222611023411 0ustar 95d2d5a4312e114432264742509d90251ce8ffdd unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20151008.gz0000664000000000000000000000005115172222611023420 0ustar cab4d18371153a06ea87dcadb03c87f9faa85dd6 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20151012.gz0000664000000000000000000000005115172222611023413 0ustar 1d2ebe755993e3ac175f7acd6b2bac5bec54c74a unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20151021.gz0000664000000000000000000000005115172222611023413 0ustar bb95dd063dcaae878c2f66588acd4edf3014a4c0 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+15.10.20151029.gz0000664000000000000000000000005115172222611023423 0ustar 49fb23a23914fc13c44266b644fd93b681589d44 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20151106.gz0000664000000000000000000000005115172222611023423 0ustar e1e50fd6b0bdc7670a73e6fcd10440adb22740de unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20151118.1.gz0000664000000000000000000000005115172222611023565 0ustar d317ade5588a80875de72931461dcde96693d000 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20151214.gz0000664000000000000000000000005115172222611023423 0ustar 401e625351a84caf5168d5b98d72dd36b063d0d9 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20160119.gz0000664000000000000000000000005115172222611023427 0ustar a7eda08f0f25bf3523143d2a6ff22f5ef8cdd391 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20160121.gz0000664000000000000000000000005115172222611023420 0ustar a184f482600b1e5204ad0eeae4bf86992eecfebe unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20160201.gz0000664000000000000000000000005115172222611023417 0ustar 08dd7c77e94d86152a770b0abeebb6e7cbd6f7e4 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20160209.gz0000664000000000000000000000005115172222611023427 0ustar ae541d61db554e86001055cddb370e5561576d49 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.04.20160701.gz0000664000000000000000000000005115172222611023424 0ustar c592f7157251c0bb0a69c00eef540e8d806375f9 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.10.20160613.gz0000664000000000000000000000005115172222611023423 0ustar 6cff8bcee8dea78ee0e717145461fcf8bd68791d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.10.20160615.gz0000664000000000000000000000005115172222611023425 0ustar ead50163b7068458ca02fe208511d8465ae71f1d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.10.20160819.gz0000664000000000000000000000005115172222611023433 0ustar f25fda139a0c049a9fcba94f9d776fe5ea902b1d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+16.10.20161003.gz0000664000000000000000000000005115172222611023415 0ustar 87d9dfaf350bfde3f203c3db6021d277db397b33 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+17.04.20170322.gz0000664000000000000000000000005115172222611023425 0ustar 82546b9f0d494725b2befedc7579c9f2d20da5b5 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+17.04.20170328.gz0000664000000000000000000000005115172222611023433 0ustar 9009157908e9432ae2034d150a77828d22eb8dca unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+17.04.20170418.gz0000664000000000000000000000005115172222611023433 0ustar e348bbcaf996d57569616bfed7ca9954b0b7694b unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+17.04.20170619.gz0000664000000000000000000000005115172222611023436 0ustar 4f52416b49f543622c5eae12386558f98eee23ba unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+17.10.20171003.gz0000664000000000000000000000005115172222611023417 0ustar 47701edf11a076f2bfa691be51bb3d3912426f4e unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+18.04.20180214.1.gz0000664000000000000000000000005115172222611023566 0ustar 27b9aba72bd516b6dd5a6731fdcf589442612fca unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+18.04.20180216.gz0000664000000000000000000000005115172222611023431 0ustar 7e5f31da044e34f99b0433f5a5d9e92488ed31a2 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+18.04.20180413.gz0000664000000000000000000000005115172222611023430 0ustar 978f8276b9dae6c51ba4620fd316c09ae071d3ae unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+19.04.20181122.gz0000664000000000000000000000005115172222611023427 0ustar 9fbe3f5fb55b7c8054a698d8680ffff262bf0c5d unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+19.04.20190209.gz0000664000000000000000000000005115172222611023435 0ustar 164d1e7e4092123fbb7369fa21bf4c0b30b99b1c unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+19.10.20190921.gz0000664000000000000000000000005115172222611023433 0ustar 4ef8f8c6d41ae607f203973d243ae750cd77e370 unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+20.04.20200311.gz0000664000000000000000000000005115172222611023407 0ustar 70cc6854a5e94957f6f27c9a3ca5cdc73939956e unity-settings-daemon/.git/refs/tags/pkg/upstream/ubuntu/15.04.1+20.04.20200325.gz0000664000000000000000000000005115172222611023414 0ustar f9a699360aa1ce5b55a9e8cd252959a1ddd21642 unity-settings-daemon/.git/refs/tags/upstream/0000775000000000000000000000000015172222611016612 5ustar unity-settings-daemon/.git/refs/tags/upstream/ubuntu/0000775000000000000000000000000015172222611020134 5ustar unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140219.gz0000664000000000000000000000005115172222611022641 0ustar 0d508075baa33233e5c59b44ae3c99732ccf960b unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140221.1.gz0000664000000000000000000000005115172222611022771 0ustar 0b6677bb46a9afbb0884197f3406a8b6ccec19f0 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140221.gz0000664000000000000000000000005115172222611022632 0ustar c9b8da8edc821a07a4d2300c942a5f943ff56ee7 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140225.gz0000664000000000000000000000005115172222611022636 0ustar 20b722c7d607fa0545ace676aee63bd0654e58e2 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140228.gz0000664000000000000000000000005115172222611022641 0ustar ecde0193ef2e46e31ccef05c82e989e200a4a3c4 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140310.gz0000664000000000000000000000005115172222611022631 0ustar 28483af390daeca492fc3ddaa11e3c2cf4d5d544 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140402.gz0000664000000000000000000000005115172222611022633 0ustar a1dead0162479f94ca93de9abd793e9de9c4a7a3 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140404.gz0000664000000000000000000000005115172222611022635 0ustar b17a76dab28b296e7c79625c414f09c0444356ed unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140407.gz0000664000000000000000000000005115172222611022640 0ustar a08c0f76f1bacf7507c48071440d6b3d5c798ab8 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140414.gz0000664000000000000000000000005115172222611022636 0ustar 4961e2b7955573344b459bc557d40463234fb1ea unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20140606.gz0000664000000000000000000000005115172222611022641 0ustar 40fd03d0d7bce669bb9e8d94fee04419c528e733 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20150825.gz0000664000000000000000000000005115172222611022645 0ustar ce749d0414fc9aedb6775c655e8ca65d1127f05d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.04.20151012.gz0000664000000000000000000000005115172222611022632 0ustar 54f6c9f9191cf5c48e3c6a816eae442699b908cf unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.10.20140604.gz0000664000000000000000000000005115172222611022634 0ustar 723b2ef9610fa6e304080a5b7e9456fabace2c80 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.10.20140605.gz0000664000000000000000000000005115172222611022635 0ustar 185aa83861a0122c59a80624bf91758f4dad7b7a unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.10.20140922.gz0000664000000000000000000000005115172222611022637 0ustar 21aa76eaee0675e76d29b602c9bdf9a503709b5d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.10.20141010.gz0000664000000000000000000000005115172222611022624 0ustar ee9c975b4aa1bfd721e935a5d033d7ab6f88affe unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0+14.10.20141014.gz0000664000000000000000000000005115172222611022630 0ustar 47d0f17f4ae0e7209e77955be9d861fead28d71b unity-settings-daemon/.git/refs/tags/upstream/ubuntu/14.04.0.gz0000664000000000000000000000005115172222611021276 0ustar 18e9c73ca12dc7edd9c0a0f099e54a76dd7b37be unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.0+15.10.20141030.gz0000664000000000000000000000005115172222611022630 0ustar cd2e502e61733ba9abc50076c1c5e28aa47125ad unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20141127.gz0000664000000000000000000000005115172222611022643 0ustar dad4f91fe5b615ec403cdd3477585d472037a7f8 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20141128.gz0000664000000000000000000000005115172222611022644 0ustar 3c349614b7dd0c177d8b060faf3e44cd46c3532d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150107.gz0000664000000000000000000000005115172222611022641 0ustar aa05ec9834f8fa8e3b6c2973703735038e6ec31b unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150205.gz0000664000000000000000000000005115172222611022640 0ustar b22ef89ab70222f54d7de10df8fae935d398b065 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150310.gz0000664000000000000000000000005115172222611022635 0ustar 6300492cbfe0bc61d1f3287eea8c4c837e93f8ad unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150313.gz0000664000000000000000000000005115172222611022640 0ustar 033e80df1fba35fb440b302c09c3e8fb63d4ffab unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150318.gz0000664000000000000000000000005115172222611022645 0ustar 1853e4ceff03e82a95ab48a2299b404b19c6b0a7 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150324.1.gz0000664000000000000000000000005115172222611023001 0ustar 90871bf0481f6ef2b639b78d9b849c3314aacfbc unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150401.gz0000664000000000000000000000005115172222611022636 0ustar 09c0cde7808eff353ee4596dc6a716536969e974 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.04.20150408.gz0000664000000000000000000000005115172222611022645 0ustar 2cc1765b545186838ec803c04bb873cb76e55135 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20150630.1.gz0000664000000000000000000000005115172222611022776 0ustar df18d1f9398544bfdeadd38ab0eac72dd796abfb unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20150720.gz0000664000000000000000000000005115172222611022637 0ustar 9903722feb192671ef54c5d60f0b08a4f02ac28f unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20150818.gz0000664000000000000000000000005115172222611022647 0ustar 6ca0d0658e6864a2e5825327d74ef8ec8b27133c unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20150825.gz0000664000000000000000000000005115172222611022645 0ustar ddf6a9fa1991641eabdfac43a24f424f87a02135 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20150917.gz0000664000000000000000000000005115172222611022647 0ustar 2947c02264314221b041b210502d1a724e2031e0 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20150930.gz0000664000000000000000000000005115172222611022642 0ustar df639929f7b20598eee5ab5448abcb3536c27eea unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20151001.gz0000664000000000000000000000005115172222611022630 0ustar 95d2d5a4312e114432264742509d90251ce8ffdd unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20151008.gz0000664000000000000000000000005115172222611022637 0ustar cab4d18371153a06ea87dcadb03c87f9faa85dd6 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20151012.gz0000664000000000000000000000005115172222611022632 0ustar 1d2ebe755993e3ac175f7acd6b2bac5bec54c74a unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20151021.gz0000664000000000000000000000005115172222611022632 0ustar bb95dd063dcaae878c2f66588acd4edf3014a4c0 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+15.10.20151029.gz0000664000000000000000000000005115172222611022642 0ustar 49fb23a23914fc13c44266b644fd93b681589d44 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20151106.gz0000664000000000000000000000005115172222611022642 0ustar e1e50fd6b0bdc7670a73e6fcd10440adb22740de unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20151118.1.gz0000664000000000000000000000005115172222611023004 0ustar d317ade5588a80875de72931461dcde96693d000 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20151214.gz0000664000000000000000000000005115172222611022642 0ustar 401e625351a84caf5168d5b98d72dd36b063d0d9 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20160119.gz0000664000000000000000000000005115172222611022646 0ustar a7eda08f0f25bf3523143d2a6ff22f5ef8cdd391 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20160121.gz0000664000000000000000000000005115172222611022637 0ustar a184f482600b1e5204ad0eeae4bf86992eecfebe unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20160201.gz0000664000000000000000000000005115172222611022636 0ustar 08dd7c77e94d86152a770b0abeebb6e7cbd6f7e4 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20160209.gz0000664000000000000000000000005115172222611022646 0ustar ae541d61db554e86001055cddb370e5561576d49 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.04.20160701.gz0000664000000000000000000000005115172222611022643 0ustar c592f7157251c0bb0a69c00eef540e8d806375f9 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.10.20160613.gz0000664000000000000000000000005115172222611022642 0ustar 6cff8bcee8dea78ee0e717145461fcf8bd68791d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.10.20160615.gz0000664000000000000000000000005115172222611022644 0ustar ead50163b7068458ca02fe208511d8465ae71f1d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.10.20160819.gz0000664000000000000000000000005115172222611022652 0ustar f25fda139a0c049a9fcba94f9d776fe5ea902b1d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+16.10.20161003.gz0000664000000000000000000000005115172222611022634 0ustar 87d9dfaf350bfde3f203c3db6021d277db397b33 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+17.04.20170322.gz0000664000000000000000000000005115172222611022644 0ustar 82546b9f0d494725b2befedc7579c9f2d20da5b5 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+17.04.20170328.gz0000664000000000000000000000005115172222611022652 0ustar 9009157908e9432ae2034d150a77828d22eb8dca unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+17.04.20170418.gz0000664000000000000000000000005115172222611022652 0ustar e348bbcaf996d57569616bfed7ca9954b0b7694b unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+17.04.20170619.gz0000664000000000000000000000005115172222611022655 0ustar 4f52416b49f543622c5eae12386558f98eee23ba unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+17.10.20171003.gz0000664000000000000000000000005115172222611022636 0ustar 47701edf11a076f2bfa691be51bb3d3912426f4e unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+18.04.20180214.1.gz0000664000000000000000000000005115172222611023005 0ustar 27b9aba72bd516b6dd5a6731fdcf589442612fca unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+18.04.20180216.gz0000664000000000000000000000005115172222611022650 0ustar 7e5f31da044e34f99b0433f5a5d9e92488ed31a2 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+18.04.20180413.gz0000664000000000000000000000005115172222611022647 0ustar 978f8276b9dae6c51ba4620fd316c09ae071d3ae unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+19.04.20181122.gz0000664000000000000000000000005115172222611022646 0ustar 9fbe3f5fb55b7c8054a698d8680ffff262bf0c5d unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+19.04.20190209.gz0000664000000000000000000000005115172222611022654 0ustar 164d1e7e4092123fbb7369fa21bf4c0b30b99b1c unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+19.10.20190921.gz0000664000000000000000000000005115172222611022652 0ustar 4ef8f8c6d41ae607f203973d243ae750cd77e370 unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+20.04.20200311.gz0000664000000000000000000000005115172222611022626 0ustar 70cc6854a5e94957f6f27c9a3ca5cdc73939956e unity-settings-daemon/.git/refs/tags/upstream/ubuntu/15.04.1+20.04.20200325.gz0000664000000000000000000000005115172222611022633 0ustar f9a699360aa1ce5b55a9e8cd252959a1ddd21642 unity-settings-daemon/AUTHORS0000664000000000000000000000011015172222611013254 0ustar Jonathan Blandford William Jon McCann unity-settings-daemon/COPYING0000664000000000000000000004312215172222611013251 0ustar GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. unity-settings-daemon/COPYING.LIB0000664000000000000000000006350415172222611013664 0ustar GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! unity-settings-daemon/ChangeLog0000664000000000000000000042501315172222611013773 0ustar 2008-08-03 C de-Avillez * plugins/mouse/gsd-mouse-manager.c: add '-k' to syndaemon call, in order to ignore modifier keys when monitoring keyboard. Thanks to Dag Asheim for spotting this, and proposing a patch. 2008-07-01 Sergey Udaltsov * configure.ac, plugins/keyboard/gsd-keyboard-xkb.c: depend on libxklavier 4.0, updated API 2009-06-01 Jens Granseuer * plugins/housekeeping/gsd-disk-space.c: include config.h so the notifications stuff can actually be built (bug #584217) 2009-05-06 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (make_menu_item_for_output_title): Make the menu item label explicitly black. We don't want to follow the theme's colors, as the label is always shown against a light pastel background --- using the theme's colors makes the label hard to read on "inverse" themes. Fixes the gnome-settings-daemon part of bug #556050. 2009-04-15 Thomas H.P. Andersen * plugins/xrandr/gsd-xrandr-manager.c: (status_icon_start): * configure.ac: Replace deprecated gtk symbol gtk_status_icon_set_tooltip. Bump required gtk to 2.16. (bug #578480) 2009-04-14 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (print_countdown_text): use ngettext for the reset dialog (bug #575409) ==================== 2.26.1 ==================== 2009-04-14 Jens Granseuer * NEWS: * configure.ac: release 2.26.1 2009-04-11 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (gsd_keybindings_manager_start): move the lookup of allowed keys after the directory has been cached in callback registration to avoid GConf roundtrip (bug #578539) 2009-04-11 Jens Granseuer * plugins/keyboard/gsd-keyboard-manager.c: (start_keyboard_idle_cb): preload GConf keyboard directory recursively to avoid roundtrips (bug #578542) 2009-04-08 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (user_says_things_are_ok): Use 30 seconds for the confirmation timeout, so that monitors can settle down and the user will have a chance to read the message. 2009-04-03 Jens Granseuer Patch by: * plugins/media-keys/Makefile.am: don't install the plugin descriptor if the plugin isn't installed (bug #577815) 2009-04-02 Jens Granseuer * plugins/keyboard/gsd-keyboard-manager.c: (numlock_gconf_state_key): use info level instead of warning for the "NumLock remembering disabled" message (bug #577578) 2009-03-28 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (sanitize), (generate_fn_f7_configs): if the sanitized array ends up having no members at all return a NULL configuration since the following code assumes it has at least one valid setup if it's not NULL. Fixes a crash when closing the lid on some laptops (bug #576875) 2009-03-27 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (on_notification_closed), (on_slow_keys_action), (on_sticky_keys_action), (ax_slowkeys_warning_post_bubble), (ax_stickykeys_warning_post_bubble), (gsd_a11y_keyboard_manager_stop): fix crash when closing the a11y notification bubble caused by incompatible changes in libnotify API (bug #576535). Also remove workarounds for bugs in libnotify < 0.4.5 2009-03-27 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (restore_backup_configuration), (try_to_apply_intended_configuration): remove unused variables 2009-03-26 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (ensure_current_configuration_is_saved): New helper function. Ensures that a monitors.xml exists with the current/unchanged configuration, so that a latter gnome_rr_config_save() will create a backup file out of *that* original configuration. This lets the "revert" function from gnome-display-properties work properly on an initial login, even when there is no monitors.xml already present. 2009-03-25 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (restore_backup_configuration): Handle the case where no backup file was created for monitors.xml, because *that* file didn't exist (such as on a first-time login). 2009-03-25 Federico Mena Quintero Centralize the handling of GNOME_RR_ERROR_NO_MATCHING_CONFIG, as that is not really an error. * plugins/xrandr/gsd-xrandr-manager.c (apply_configuration_from_filename): New helper function; centralizes the handling of gnome_rr_config_apply_from_filename() and ignores GNOME_RR_ERROR_NO_MATCHING_CONFIG. That is not actually an error; it just means that the user probably changed his monitors and the stored set of configurations doesn't have a config that is usable for the new monitors. (restore_backup_configuration): Use apply_configuration_from_filename(). (try_to_apply_intended_configuration): Likewise. (apply_intended_configuration): Likewise. (apply_stored_configuration_at_startup): Likewise. 2009-03-19 Federico Mena Quintero http://bugzilla.gnome.org/show_bug.cgi?id=576006 - The confirmation dialog from the RANDR plugin can appear behind the window from gnome-display-properties. This also depends on a change to gnome-control-center. * plugins/xrandr/gsd-xrandr-manager.xml: Add an org.gnome.SettingsDaemon.XRANDR_2 interface in addition to the old XRANDR one, with an ApplyConfiguration method that also takes a parent window ID and a timestamp. * plugins/xrandr/gsd-xrandr-manager.c (gsd_xrandr_manager_2_apply_configuration): Implement the new DBus method with the parent window and timestamp. (user_says_things_are_ok): Use the parent window. 2009-03-19 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (user_says_things_are_ok): Revert the use of g_timeout_add_seconds(), since we actually care that the user sees real second ticks in the dialog. This isn't a neverending timeout anyway. 2009-03-18 Jens Granseuer * gnome-settings-daemon/Makefile.am: * plugins/a11y-keyboard/Makefile.am: * plugins/background/Makefile.am: * plugins/clipboard/Makefile.am: * plugins/dummy/Makefile.am: * plugins/font/Makefile.am: * plugins/housekeeping/Makefile.am: * plugins/keybindings/Makefile.am: * plugins/keyboard/Makefile.am: * plugins/media-keys/Makefile.am: * plugins/mouse/Makefile.am: * plugins/screensaver/Makefile.am: * plugins/sound/Makefile.am: * plugins/typing-break/Makefile.am: * plugins/xrandr/Makefile.am: * plugins/xrdb/Makefile.am: * plugins/xsettings/Makefile.am: revert build patch from r763 ==================== 2.26.0 ==================== 2009-03-16 Rodrigo Moya * NEWS: * configure.ac: release 2.26.0 2009-03-07 Jens Granseuer Based on patch by: Christopher Taylor * gnome-settings-daemon/Makefile.am: * plugins/a11y-keyboard/Makefile.am: * plugins/background/Makefile.am: * plugins/clipboard/Makefile.am: * plugins/dummy/Makefile.am: * plugins/font/Makefile.am: * plugins/housekeeping/Makefile.am: * plugins/keybindings/Makefile.am: * plugins/keyboard/Makefile.am: * plugins/media-keys/Makefile.am: * plugins/mouse/Makefile.am: * plugins/screensaver/Makefile.am: * plugins/sound/Makefile.am: * plugins/typing-break/Makefile.am: * plugins/xrandr/Makefile.am: * plugins/xrdb/Makefile.am: * plugins/xsettings/Makefile.am: make build work with -Wl,-z,defs linker options (bug #574452) ==================== 2.25.92 ==================== 2009-03-02 Jens Granseuer * NEWS: * configure.ac: release 2.25.92 2009-03-02 Jens Granseuer * gnome-settings-daemon/Makefile.am: also install the plugin header file because it is needed for custom plugins (bug #573610) 2009-02-23 Jens Granseuer * data/gnome-settings-daemon.schemas.in: add missing keys for a11y shortcut names (bug #572807) 2009-02-22 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (user_says_things_are_ok): use g_timeout_add_seconds instead of g_timeout_add 2009-02-21 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (timeout_response_cb): revert the screen resolution change if the user closes the window or hits escape (bug #571492) 2009-02-21 Jens Granseuer Fix compiler warnings. * plugins/housekeeping/gsd-disk-space.c: add missing include * plugins/housekeeping/gsd-housekeeping-manager.c: ditto * plugins/housekeeping/gsd-disk-space.h: don't declare public functions static 2009-02-20 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (parse_binding), (bindings_get_entry): don't output a warning for disabled shortcuts 2009-02-15 Jens Granseuer Patch by: Leo Iannacone * plugins/media-keys/gsd-media-keys-window.c: (on_expose_event): fix alignment of the composited media window (bug #567249) 2009-02-15 Luca Ferretti reviewed by: Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (ax_slowkeys_warning_post_dialog), (ax_stickykeys_warning_post_dialog): * plugins/mouse/gsd-mouse-manager.c: (set_mousetweaks_daemon): Don't use legacy icons for keyboard and mouse (bug #571823) 2009-02-15 Luca Ferretti reviewed by: Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (user_says_things_are_ok): HIG fix for button labels (bug #571819) 2009-02-15 Luca Ferretti reviewed by: Jens Granseuer * plugins/keyboard/modmap-dialog.glade: Fix label for "Don't show this message again" checkbox, isn't a `string change` due to reusing a yet available label (bug #571821) 2009-02-11 Jens Granseuer * plugins/common/eggaccelerators.c: (egg_accelerator_parse_virtual): don't return TRUE if we can't parse the accelerator at all; fixes crash with invalid keyboard shortuts (bug #571329) 2009-02-11 Matthias Clasen Bug 570590 – a11y plugin warning * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: Avoid warnings due to notifications on nonexisting statusicons. 2009-02-08 Jens Granseuer Patch by: Nirbheek Chauhan * configure.ac: add --without-libnotify to disable notifications (bug #570885) 2009-02-06 Matthias Clasen Bug 570743 – restart on crash * data/gnome-settings-daemon.desktop.in.in: Have gnome-session restart g-s-d if it crashes (heaven forbid!). 2009-02-04 Vincent Untz * configure.in: post-release bump to 2.25.91 ==================== 2.25.90 ==================== 2009-02-04 Vincent Untz * NEWS: * configure.in: version 2.25.90 2009-02-04 Vincent Untz * data/Makefile.am: fix distcheck 2009-02-03 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (restore_backup_configuration): Use gnome_rr_config_apply_from_filename(), as that's the new, non-deprecated API. (try_to_apply_intended_configuration): Likewise. (apply_intended_configuration): Likewise. (apply_stored_configuration_at_startup): Likewise. 2009-02-01 Frederic Peters * plugins/housekeeping/Makefile.am: * plugins/housekeeping/gsd-disk-space.c: add low diskspace checker files to housekeeping plug-in Makefile.am; and make its clean and setup methods available are made available. (bug #570132) 2009-01-31 Theppitak Karoonboonyanan * plugins/media-keys/Makefile.am: Fix include paths for non-source-dir builds. (bug #569955) 2009-01-28 Jens Granseuer * configure.ac: require gnome-desktop 2.25.6 due to recent changes 2009-01-27 Federico Mena Quintero http://bugzilla.gnome.org/show_bug.cgi?id=545115 - Ask for confirmation, with a timeout, after changing the RANDR configuration for if we leave the user with an unusable display. This also handles the case where the machine may crash after changing the configuration; the old/known-good configuration will be restored when the user restarts his session. Refactor: * plugins/xrandr/gsd-xrandr-manager.c (apply_stored_configuration_at_startup): Factor out the logic to apply the stored configuration at startup. (gsd_xrandr_manager_start): Use the function above. During startup, restore the backup configuration if it existed, to recover from the case when the machine crashes while applying an intended configuration. * plugins/xrandr/gsd-xrandr-manager.c (apply_stored_configuration_at_startup): First see if we have a backup configuration; if so, it means the machine or g-s-d crashed while changing the RANDR parameters. If there is no backup configuration, then we have a known-good configuration which we can use. (apply_intended_configuration): New function, used to load the intended configuration (i.e. the non-backup one). (restore_backup_configuration): Utility function to overwrite the known-bad configuration with the known-good backup one. Use a timeout-confirmation dialog after changing the display configuration: * plugins/xrandr/gsd-xrandr-manager.c (try_to_apply_intended_configuration): New function; applies the intended configuration, restores the backup configuration if that fails, or asks the user to confirm if the intended configuration is usable. (gsd_xrandr_manager_apply_configuration): Use try_to_apply_intended_configuration() in the implementation of the D-Bus method to apply RANDR configurations. This way all apps which use this D-Bus method will get confirmation for free. (output_rotation_item_activate_cb): Use try_to_apply_intended_configuration() so that the RANDR tray-icon also uses the confirmation/backup logic. (restore_backup_configuration): Restore the screen configuration itself in addition to restoring the file on disk from the backup. (user_says_things_are_ok): New utility function to handle a timeout-confirmation dialog. Fix error reporting at startup: * plugins/xrandr/gsd-xrandr-manager.c (error_message): Handle the case where the status_icon is not created yet; this happens during startup or when the status_icon is disabled by the user. Handle the case where there is no matching configuration at startup; this is not an error: * plugins/xrandr/gsd-xrandr-manager.c (apply_intended_configuration): "no matching configuration" is not an error when looking for a suitable configuration in monitors.xml; it simply means that the user has a different set of monitors than the ones that are available in that file. 2009-01-24 Jens Granseuer Patch by: Andres Freund Fix possible crash when pressing Fn-F7 (bug #568713) * plugins/xrandr/gsd-xrandr-manager.c: (handle_fn_f7): only try to dereference the error when it was actually set 2009-01-27 Federico Mena Quintero http://bugzilla.gnome.org/show_bug.cgi?id=545115 - Ask for confirmation, with a timeout, after changing the RANDR configuration for if we leave the user with an unusable display. This also handles the case where the machine may crash after changing the configuration; the old/known-good configuration will be restored when the user restarts his session. Refactor: * plugins/xrandr/gsd-xrandr-manager.c (apply_stored_configuration_at_startup): Factor out the logic to apply the stored configuration at startup. (gsd_xrandr_manager_start): Use the function above. 2009-01-26 Ray Strode Delay drawing the background until SessionRunning. * plugins/background/gsd-background-manager.c: (queue_draw_background): Cancel queued draw if nautilus is now running. (on_bus_message), (draw_background_after_session_loads), (gsd_background_manager_start): wait for SessionRunning and then queue background draw (gsd_background_manager_stop): remove message filter 2009-01-24 Jens Granseuer Patch by: Andres Freund Fix possible crash when pressing Fn-F7 (bug #568713) * plugins/xrandr/gsd-xrandr-manager.c: (handle_fn_f7): only try to dereference the error when it was actually set 2009-01-22 Bastien Nocera * data/apps_gnome_settings_daemon_keybindings.schemas.in: KEY_FILE maps to XF86Explorer, so use that to launch the file manager in the user's home directory 2009-01-19 Ray Strode Add crossfade transition when switching bgs (bug 552857) * plugins/background/gsd-background-manager.c (draw_background): Add use_crossfade argument that initiates the fade if TRUE. (on_bg_changed): call draw_background with crossfade. (on_bg_transitioned): new function that calls draw_background without crossfade during slide show transitioning. (setup_bg): set up transitioned signal handler. (queue_draw_background): draw_background without crossfade after 8 second timeout waiting for nautilus. 2009-01-19 Ray Strode * plugins/background/gsd-background-manager.c (gsd_background_manager_start): Don't draw_background immediately when nautilus is disabled. gnome_bg_load_from_preferences forces a "changed" signal to get emitted which will queue a draw anyway 2009-01-18 Jens Granseuer * plugins/media-keys/Makefile.am: fix automake warning 2009-01-18 Jens Granseuer * configure.ac: fix build with PulseAudio, too (bug #568179) 2009-01-17 Jens Granseuer * plugins/media-keys/Makefile.am: fix build without PulseAudio (bug #568015) 2009-01-15 Bastien Nocera * plugins/media-keys/cut-n-paste/*: Cut'n'paste code from the PulseAudio enabled code in gnome-media's gnome-volume-control * plugins/media-keys/actions/acme-volume-*.[ch]: Remove the old AcmeVolume code * plugins/media-keys/actions/acme.glade: * plugins/media-keys/actions/acme.h: Move to plugins/media-keys/ * configure.ac: Tell config.h when PulseAudio support is disabled * plugins/media-keys/gsd-media-keys-manager.c (update_dialog), (on_stream_event_notify), (do_sound_action), (update_default_sink), (on_control_ready), (on_control_default_sink_changed), (do_action), (gsd_media_keys_manager_start), (gsd_media_keys_manager_stop): Use PulseAudio directly to change the volume. It will automatically change the volume of the default audio output for the machine (Closes: #567177) * plugins/media-keys/Makefile.am: * plugins/media-keys/actions/Makefile.am: Changes for the above 2009-01-15 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (binding_unregister_keys), (gsd_keybindings_manager_stop): also ungrab keys when this module is disabled 2009-01-15 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (gsd_media_keys_manager_stop): ungrab shortcut keys when the plugin is disabled (bug #567867) 2009-01-14 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (gsd_xrandr_manager_start): If there was no file with a stored configuration, don't pop up an error message --- this is not an error when the daemon starts up. Fixes https://bugzilla.novell.com/show_bug.cgi?id=465968 2009-01-10 William Jon McCann * plugins/sound/gsd-sound-manager.c (register_config_callback): Fix typo. 2009-01-08 Jens Granseuer Based on a patch by: Lennart Poettering * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/sound/Makefile.am: * plugins/sound/gsd-sound-manager.c: * plugins/sound/gsd-sound-plugin.h: * plugins/sound/sound.gnome-settings-plugin.in: Add a new sound plugin that tells PulseAudio to drop its sample cache when the sound theme changes (bug #545386). 2009-01-08 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (gsd_media_keys_manager_grab_media_player_keys), (gsd_media_keys_manager_release_media_player_keys): add a little debugging output when de/registering media players (bug #564433) 2009-01-05 Bastien Nocera * plugins/xrdb/gsd-xrdb-manager.c (apply_settings): Quiet xrdb when there are duplicate rules in the .ad files (Closes: #566610) 2008-12-30 Matthias Clasen Bug 565310 – support hotkeys for a11y tools * configure.ac: Set GNOME_KEYBINDINGS_KEYSDIR. * data/gnome-settings-daemon.schemas.in: Add missing schemas for the keys in /destkop/gnome/applications/at, and also add new schemas for keys in /desktop/gnome/keybindings that define global keybindings for turning ATs on and off. Todo: There are no default key combinations in the schema yet. * data/50-accessibility.xml.in: Keybinding file to group the new keybindings in an "Accessibility" section in the keybinding capplet. * data/Makefile.am: Install the keybinding file in the proper location. * po/POTFILES.in: Add 50-accessibility.xml.in. 2008-12-31 Rodrigo Moya Patch by Vincent Untz from openSUSE package (bug #557647) * configure.ac: require giounix for diskspace checker * Makefile.am: * plugins/housekeeping/gsd-disk-space.[ch]: add low diskspace checker to housekeeping plugin. * plugins/housekeeping/gsd-housekeeping-manager.c (gsd_housekeeping_manager_start, gsd_housekeeping_manager_stop): start/stop the low diskspace checker. * plugins/housekeeping/housekeeping.gnome-settings-plugin.in: add new plugin capability to description * po/POTFILES.in: add new files 2008-12-28 Jens Granseuer * plugins/screensaver/gsd-screensaver-manager.c: (start_screensaver_cb), (gsd_screensaver_manager_start): spawn screensaver after a 30 second timeout instead of when idle so that it doesn't compete with other processes when the session starts (bug #564059). Also plug a few small leaks. 2008-12-28 Jens Granseuer Based on patch by: Jasper Lievisse Adriaanse * plugins/media-keys/gsd-media-keys-manager.c: (do_eject_action), (do_action): better support for Eject and Sleep actions on OpenBSD and FreeBSD (bug #565472) 2008-12-28 Jens Granseuer Patch by: Jasper Lievisse Adriaanse * plugins/typing-break/gsd-typing-break-manager.c: include signal.h to fix build on OpenBSD (bug #565470) 2008-12-28 Jens Granseuer Patch by: Frederic Peters * gnome-settings-daemon/main.c: (main): initialize thread system since ORBit no longer does it for us (#565515) ==================== 2.25.3 ==================== 2008-12-18 Bastien Nocera * NEWS: upd * configure.ac: 2.25.3 update gnome-desktop requirements for the new GnomeRR API * plugins/xrandr/Makefile.am: Fix distcheck 2008-12-07 Ray Strode Restore AccessX bits to original values on exit * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (struct GsdA11yKeyboardManagerPrivate): add new field to cache original AccessX bits. (start_a11y_keyboard_idle_cb): save bits. (restore_server_xkb_config), (gsd_a11y_keyboard_manager_stop): restore bits when stopping. 2008-12-07 Ray Strode Shutdown properly when bus goes away. Previously we were just letting libdbus call exit(1) for us. * gnome-settings-daemon/main.c (get_session_bus): Set up a filter function to catch disconection events. (bus_message_handler): quit event loop when disconnected from bus. 2008-12-07 Ray Strode Shutdown properly when killed. * gnome-settings-daemon/main.c (on_term_signal): top half of signal handling code. close a pipe when getting SIGTERM. (on_term_signal_pipe_closed), (watch_for_term_signal), (set_session_over_handler): bottom half. Quit event loop when term pipe gets closed. 2008-12-07 Ray Strode * gnome-settings-daemon/main.c: Rename pipefds to daemon_pipe_fds. This fits the naming style of the surrounding code better. Also, we're going to need another pipe, so better to use a specific name here. 2008-12-09 Jens Granseuer Patch by: Pedro Fragoso * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.h: * plugins/common/eggaccelerators.c: * plugins/common/eggaccelerators.h: * plugins/mouse/gsd-locate-pointer.h: only use top-level headers for glib and GTK+ (bug #563796) 2008-12-08 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (error_message): make libnotify optional again (bug #563226) (handle_fn_f7): fix memory leak, use g_debug instead of g_print 2008-12-07 Behdad Esfahbod * gnome-settings-daemon/main.c (daemon_detach): Don't call umask (bug #563543) 2008-12-04 Jens Granseuer * plugins/mouse/gsd-mouse-manager.c: (set_devicepresence_handler): fix crash with X servers that don't provide XInput (bug #562977) 2008-12-02 Federico Mena Quintero Use a DBus interface to tell the XRANDR manager to apply the stored configuration, instead of an X client message, so that we can pass errors back to the caller. * plugins/xrandr/gsd-xrandr-manager.xml: Trivial DBus interface to tell the XRANDR manager to apply the stored configuration. * plugins/xrandr/gsd-xrandr-manager.c (gsd_xrandr_manager_apply_configuration): Moved from on_client_message(). Now we are a DBus-Glib method, so that we can pass back errors to the remote caller. * plugins/xrandr/Makefile.am: Add the machinery to generate DBus glue. 2008-12-02 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (error_message): Renamed from error_dialog(); use libnotify instead of ugly dialogs for error messages. (gsd_xrandr_manager_start): Proxy the error from gnome_rr_screen_new() to our caller. (gsd_xrandr_manager_start): Display an error if we cannot apply the initially-loaded configuration. (generate_fn_f7_configs, get_allowed_rotations_for_output): Pass GError arguments to the gnome_rr_*() functions. (handle_fn_f7): Display an error if we cannot refresh the screen configuration or apply the new one. (output_rotation_item_activate_cb): Display an error if the rotation cannot be applied. Tue Dec 2 15:37:21 2008 Søren Sandmann * plugins/xrandr/gsd-xrandr-manager.c: Add support for fn-F7 type keys. ==================== 2.25.2 ==================== 2008-12-01 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.25.2 release. 2008-11-29 Jens Granseuer * plugins/keyboard/gsd-keyboard-xkb.c: (gsd_keyboard_xkb_init): fix check for xklavier device discovery 2008-11-29 Jens Granseuer * configure.ac: fix checks for various X11 libraries (bug #562661) * plugins/mouse/gsd-mouse-manager.c: (set_left_handed), (gsd_mouse_manager_idle_cb), (gsd_mouse_manager_stop): * plugins/xrandr/gsd-xrandr-manager.c: adapt ifdefs accordingly 2008-11-27 Sergey Udaltsov * configure.ac, plugins/keyboard/gsd-keyboard-xkb.c: introduce dependency on libxklavier 3.8. Use "new device" notification to reload XKB configuration when new keyboard is plugged in 2008-11-24 Behdad Esfahbod * gnome-settings-daemon/main.c (parse_args), (main): Fix --no-daemon (bug #562175) 2008-11-24 Jens Granseuer When multiple keys (keycodes) were mapped to the same keysym, g-s-d would only accept the first of those keycodes in the keymap as a valid shortcut. To fix this, instead of checking against a single keycode, we need to grab all keycodes that match the respective keysym (bug #561275). With thanks to Mario Limonciello * plugins/common/eggaccelerators.c: (egg_accelerator_parse_virtual): * plugins/common/eggaccelerators.h: possibly return multiple keycodes * plugins/common/gsd-keygrab.c: (grab_key_unsafe), (key_uses_keycode), (match_key): grab all matching keys * plugins/common/gsd-keygrab.h: * plugins/keybindings/gsd-keybindings-manager.c: (parse_binding), (bindings_get_entry), (same_keycode), (same_key), (key_already_used), (binding_register_keys), (gsd_keybindings_manager_stop): * plugins/media-keys/gsd-media-keys-manager.c: (update_kbd_cb), (init_kbd), (gsd_media_keys_manager_stop): update to handle changes in data structures 2008-11-23 Jens Granseuer Patch by: * configure.ac: add bundle_loader linker flag to fix compilation on MacOS X (bug #522673) 2008-11-20 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (find_by_time), (gsd_media_keys_manager_grab_media_player_keys): fix handling of time = GDK_CURRENT_TIME. Previously, apps that registered with GDK_CURRENT_TIME would be trumped by any app that registered with time != 0 (bug #559797) 2008-11-20 Jens Granseuer * plugins/mouse/gsd-mouse-manager.c: (set_devicepresence_handler): trap X errors so we don't crash on X servers that don't support DevicePresence (bug #560618) 2008-11-13 Jens Granseuer * data/desktop_gnome_keybindings.schemas.in: fix typo 2008-11-11 Matthias Clasen Bug 553434 – lockdown in the keybinding plugin * data/Makefile.am: Install the new schema file. * data/desktop_gnome_keybindings.schemas.in: Add schema for /desktop/gnome/keybindings/allowed_keys. * plugins/keybindings/gsd-keybinding-manager.c: Support locking down keybindings with a list of allowed keys. 2008-11-10 Behdad Esfahbod * gnome-settings-daemon/main.c (daemon_start): Check return value of pipe(). 2008-11-10 Behdad Esfahbod * gnome-settings-daemon/main.c (daemon_start), (daemon_detach), (daemon_terminate_parent), (main): Fork before gtk_init (bug #559695) 2008-11-09 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (do_sound_action): add debugging output for volume_step 2008-11-08 Jens Granseuer Patch by: William Grant * plugins/mouse/gsd-mouse-manager.c: (devicepresence_filter): listen for DeviceEnabled instead of DeviceAdded so we can be sure it has been initialized (bug #559827) 2008-11-06 Behdad Esfahbod * plugins/background/gsd-background-manager.c (setup_bg), (queue_draw_background), (gsd_background_manager_start): Delay constructing the GnomeBg object until we need it. This avoids unneeded change triggers caused by a bug in gnome-screensaver (fixed in trunk it seems). (bug #559639) 2008-11-06 Behdad Esfahbod * data/gnome-settings-daemon.schemas.in: Reshuffle plugin priorities a bit. Now that we do many of the plugins in idle callback, those can be put at the end. 2008-11-06 Behdad Esfahbod * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (maybe_show_status_icon), (ax_slowkeys_warning_post_bubble), (ax_stickykeys_warning_post_bubble), (gsd_a11y_keyboard_manager_stop), (gsd_a11y_keyboard_manager_ensure_status_icon), (gsd_a11y_keyboard_manager_init): Init status icon only when needed (bug #559558) 2008-11-06 Behdad Esfahbod * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (start_a11y_keyboard_idle_cb), (gsd_a11y_keyboard_manager_start): Start manager in idle callback (bug #559564) * plugins/media-keys/gsd-media-keys-manager.c (start_media_keys_idle_cb), (gsd_media_keys_manager_start): Start manager in idle callback (bug #559564). Leave the acme initialization in the main start function to force gstreamer cache up to date check before we let other applications start. 2008-11-06 Behdad Esfahbod * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (get_xkb_desc_rec): * plugins/common/gsd-keygrab.c (have_xkb): Remove more unnecessary X error traps and synchs (bug #559562) 2008-11-06 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (xkb_enabled), (gsd_a11y_keyboard_manager_start): remove unnecessary X error traps (bug #559562) 2008-11-05 Behdad Esfahbod * plugins/xsettings/fontconfig-monitor.c (fontconfig_cache_init): * plugins/xsettings/fontconfig-monitor.h: * plugins/xsettings/gsd-xsettings-manager.c (start_fontconfig_monitor): Only initialize fontconfig when starting up. A cache update is redundant there. (bug #559550) 2008-11-05 Behdad Esfahbod * plugins/keyboard/gsd-keyboard-manager.c (start_keyboard_idle_cb), (gsd_keyboard_manager_start): Start manager in idle callback (bug #559482) 2008-11-05 Behdad Esfahbod * plugins/keyboard/gsd-keyboard-xkb.c (gsd_keyboard_xkb_init): Add some performance logging annotations around libxklavier calls. 2008-11-05 Jens Granseuer * plugins/keyboard/gsd-keyboard-manager.c: (numlock_xkb_init): XkbQueryExtension and friends shouldn't cause errors, so no need to try and trap them (bug #559346) ==================== 2.25.1 ==================== 2008-11-04 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.25.1 release 2008-11-04 Behdad Esfahbod * gnome-settings-daemon/main.c (daemonize), (main): Use a pipe to communicate between child and parent process instead of a signal. Signals are not queued, so if the child tried to signal the parent before the parent got a chance to wait for it, the signal would be lost and parent wait indefinitely for a signal that would never arrive. 2008-11-04 Behdad Esfahbod * gnome-settings-daemon/main.c (daemonize): Don't close stderr. Otherwise we just lose all our warnings that will not end up in ~/.xsession-errors. Also fix indentation. 2008-11-03 Jens Granseuer * plugins/keyboard/gsd-keyboard-xkb.c: add missing include 2008-11-03 Behdad Esfahbod * gnome-settings-daemon/main.c (daemonize), (main): Make parent wait for initialization in children to finish before returning. This makes gnome-session to wait for initialization to be done before spawning other processes. This way, apps start up with the right xsettings and other settings, and don't have to handle change signals right after starting up. (bug #559168) 2008-11-03 Behdad Esfahbod * gnome-settings-daemon/gnome-settings-manager.c (_load_file), (gnome_settings_manager_start), (gnome_settings_manager_stop): * gnome-settings-daemon/gnome-settings-plugin-info.c (gnome_settings_plugin_info_set_enabled_key_name): * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (register_config_callback): * plugins/keybindings/gsd-keybindings-manager.c (register_config_callback), (gsd_keybindings_manager_start): * plugins/keyboard/gsd-keyboard-manager.c (gsd_keyboard_manager_start): * plugins/keyboard/gsd-keyboard-xkb.c (register_config_callback): * plugins/mouse/gsd-mouse-manager.c (register_config_callback): * plugins/typing-break/gsd-typing-break-manager.c (gsd_typing_break_manager_start): * plugins/xrandr/gsd-xrandr-manager.c (gsd_xrandr_manager_start): * plugins/xsettings/gsd-xsettings-manager.c (register_config_callback), (gnome_xsettings_manager_start): Preload gconf dirs when feasible (bug #559167) 2008-11-03 Behdad Esfahbod * plugins/clipboard/gsd-clipboard-manager.c (start_clipboard_idle_cb), (gsd_clipboard_manager_start): Start manager in idle callback (bug #559166) * plugins/mouse/gsd-mouse-manager.c (gsd_mouse_manager_idle_cb), (gsd_mouse_manager_start): Start manager in idle callback (bug #559166) * plugins/xsettings/fontconfig-monitor.c (fontconfig_cache_update), (update): * plugins/xsettings/fontconfig-monitor.h: * plugins/xsettings/gsd-xsettings-manager.c (start_fontconfig_monitor_idle_cb), (start_fontconfig_monitor), (stop_fontconfig_monitor): Start fontconfig monitors in idle callback. However, make sure fontconfig caches are up to date during initialization (bug #559166) 2008-11-03 Behdad Esfahbod * plugins/mouse/gsd-mouse-manager.c (set_mousetweaks_daemon): Don't run "mousetweaks -s" at startup time (#559165) All "mousetweaks -s" does is shutdown the already-running daemon. When g-s-d starts, there is no daemon running. So, remember that and do not try to shut the non-existing daemon down. 2008-11-03 Behdad Esfahbod * plugins/common/gsd-keygrab.c (setup_modifiers), (grab_key_real), (grab_key_unsafe): * plugins/common/gsd-keygrab.h: * plugins/keybindings/gsd-keybindings-manager.c (binding_register_keys): * plugins/media-keys/gsd-media-keys-manager.c (update_kbd_cb), (init_kbd): Don't trap errors around grab_key (bug #559164) Such that we can do a single gdk_flush for multiple keys. The only downside is that we cannot write out in the warning which key is being accessed by another app. Not that we really care. 2008-11-03 Behdad Esfahbod * plugins/font/gsd-font-manager.c (setup_dir), (empty_check_dir), (setup_font_dir), (setup_cursor_dir), (load_font_paths), (gsd_font_manager_start): Cleanup font module (bug #559163) The old code had several flaws: - It tried to create directories in user's home even if we didn't have any use for them. - It called mkfontdir and XSync even if there was no fonts installed. The new code does the following: - Only call mkfontdir and XSync if there's actually any fonts in the relevant dirs. - Remove the ~/.gnome2/share/fonts and/or ~/.gnome2/share/cursor-fonts if they are empty and no cursor font is set. 2008-11-03 Behdad Esfahbod * gnome-settings-daemon/gnome-settings-manager.c (_load_file): * gnome-settings-daemon/gnome-settings-plugin-info.c (gnome_settings_plugin_info_fill_from_file), (load_plugin_module): * plugins/font/gsd-font-manager.c (child_watch_cb), (spawn_with_input): * plugins/keyboard/gsd-keyboard-xkb.c (gsd_keyboard_xkb_init): * plugins/xrandr/gsd-xrandr-manager.c (gsd_xrandr_manager_start): * plugins/xsettings/gsd-xsettings-manager.c (child_watch_cb), (spawn_with_input), (start_fontconfig_monitor), (stop_fontconfig_monitor), (gnome_xsettings_manager_start), (gnome_xsettings_manager_stop): Improve performance logging annotations (bug #559162) 2008-11-03 Behdad Esfahbod * data/gnome-settings-daemon.schemas.in: Disable xrdb plugin by default (#bug #557807) 2008-11-02 Jens Granseuer * configure.ac: remove AM_MAINTAINER_MODE because it is deprecated and supposedly unsafe (bug #558503) 2008-11-01 Jens Granseuer Patch by: William Grant * plugins/mouse/gsd-mouse-manager.c: (devicepresence_filter), (set_devicepresence_handler), (set_mouse_settings), (gsd_mouse_manager_start), (gsd_mouse_manager_stop): listen for X device changes, and reconfigure the mouse if necessary so that the settings aren't ignored when hotplugging (bug #549267) 2008-10-29 Jens Granseuer Get rid of libgnome (bug #557808). * configure.ac: bump required gtk+ version to 2.13.1 * gnome-settings-daemon/main.c: (main): don't use g_program_init * plugins/a11y-keyboard/Makefile.am: * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (ax_response_callback), (ax_stickykeys_response), (ax_slowkeys_response), (on_slow_keys_action), (on_sticky_keys_action): replace gnome_help_display_desktop with gtk_show_uri 2008-10-29 Jens Granseuer * plugins/screensaver/gsd-screensaver-manager.c: (gsd_screensaver_manager_start): fix plugin activation, too 2008-10-29 Jens Granseuer * plugins/screensaver/gsd-screensaver-manager.c: (start_screensaver_idle_cb), (gsd_screensaver_manager_start): fix broken changes to screensaver plugin 2008-10-29 Jens Granseuer Remove ESD-based sound plugin (bug #557806). This means that g-s-d will no longer start a sound server (esd or PulseAudio) at session startup. This should be handled using the autostart mechanism of gnome-session instead. * configure.ac: * plugins/Makefile.am: * plugins/sound/Makefile.am: * plugins/sound/gsd-sound-manager.c: * plugins/sound/gsd-sound-manager.h: * plugins/sound/gsd-sound-plugin.c: * plugins/sound/gsd-sound-plugin.h: * plugins/sound/sound.gnome-settings-plugin.in: remove sound plugin 2008-10-29 Rodrigo Moya * plugins/screensaver/gsd-screensaver-manager.c (gsd_screensaver_manager_start): spawn screensaver process in idle callback as it was before. 2008-10-23 Jens Granseuer Based on a patch by: Bogdan Butnaru * plugins/media-keys/gsd-media-keys-window.c: (draw_waves), (draw_cross), (draw_action_volume): make the composited volume images more clear: draw waves matching current volume and show a cross when muted (bug #557307) 2008-10-23 Jens Granseuer * plugins/media-keys/actions/acme-volume-gstreamer.c: (acme_volume_gstreamer_finalize), (acme_volume_gstreamer_close_real), (acme_volume_gstreamer_open), (acme_volume_gstreamer_close), (acme_volume_gstreamer_init), (acme_volume_gstreamer_class_init): * plugins/media-keys/actions/acme-volume-gstreamer.h: clean up Volume initialization so that we don't get non-functional volume keys when the plugin starts up with an invalid configuration initially, even if the configuration is fixed afterwards (bug #552383) 2008-10-19 Matthias Clasen Bug 556797 – support the Gtk/ButtonImages XSetting * plugins/xsettings/gsd-xsettings-manager.c: Support the Gtk/ButtonImages xsetting. 2008-10-15 Matthias Clasen Bug 556307 – show the shutdown dialog when the power button is pressed * plugins/media-keys/gsd-media-keys-manager.c (do_exit_action): Show the shutdown dialog when the power button is pressed, not the logout dialog. 2008-10-12 Christian Persch Bug 555553 – format not a string literal and no format arguments * gnome-settings-daemon/gnome-settings-manager.c * gnome-settings-daemon/gnome-settings-module.c * gnome-settings-daemon/main.c * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c * plugins/xrdb/gsd-xrdb-manager.c: Use printf safely. 2008-10-06 Matthias Clasen Bug 555873 – fix gdm keyboard layout handling even more * plugins/keyboard/gsd-keyboard-xkb.c (apply_xkb_settings): Try harder to handle initial-login situations correctly, while not overwriting any user configuration. 2008-10-06 Matthias Clasen Bug 554525 – fix the picking up of the gdm layout * plugins/keyboard/gsd-keyboard-xkb.c (apply_xkb_settings): Active a specific group only after activating the right keyboard configuration. Because the other way around doesn't work. 2008-10-05 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (set_server_from_gconf): don't make togglekeys_enable depend on global AccessX state (bug #555009) 2008-10-04 Jens Granseuer Patch by: Eric Piel * plugins/xrandr/gsd-xrandr-manager.c: (output_rotation_item_activate_cb): ignore the "activate" signal for deselected items so that the rotation setting doesn't reset when the systray menu is opened (bug #554951) ==================== 2.24.0 ==================== 2008-09-23 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.24.0 release. 2008-09-22 Michael J. Chudobiak * plugins/housekeeping/gsd-housekeeping-manager.c: Made the housekeeping plugin less aggressive by default (bug #552680). Code freeze break approved by release team. 2008-09-16 Matthias Clasen * plugins/keyboard/gsd-keyboard-xkb.c: Remove an accidentally added debug printf. 2008-09-12 Jens Granseuer Also allow linking the module state to other boolean keys by using a string value that is the name of the key to use. Note that in this case the state won't be updated at runtime due to GConf limitations. * plugins/xsettings/gsd-xsettings-manager.c: (get_gtk_modules): enable linking to other keys 2008-09-12 Jens Granseuer Specify GTK modules to load in a GConf directory instead of the single /desktop/gnome/gtk-modules key. Apps can now easily install additional modules by dropping a key with the name of the module and a boolean value (enabled/disabled) into /apps/gnome_settings_daemon/gtk-modules/ (bug #539840). * plugins/xsettings/gsd-xsettings-manager.c: (get_gtk_modules), (gtk_modules_callback), (gnome_xsettings_manager_start), (gnome_xsettings_manager_stop): remove the old gtk-modules key in favor of a GConf directory 2008-09-12 Jens Granseuer * COPYING: add GPLv2 copyright notice explicitly so that newer versions of autotools don't declare us GPLv3 (bug #551956) 2008-09-11 Jens Granseuer Make the volume popup not crash when invoking it on any screen but the first when using a compositing manager (bug #551677) * plugins/media-keys/gsd-media-keys-window.c: (gsd_media_keys_window_real_realize), (gsd_media_keys_window_init): do not set the window colormap at init time where we'll only use the colormap of the default screen. Instead, whenever the window is realized, update the colormap to match the current screen. 2008-09-10 Jens Granseuer Patch by: Simon Zheng * gnome-settings-daemon/main.c: (main): fix the fix for read-only home directories from bug #530975 ==================== 2.23.92 ==================== 2008-09-08 Rodrigo Moya * NEWS: prepare for 2.23.92 release. 2008-09-06 Matthias Clasen Bug 551062 – try harder to use the keyboard layout passed by gdm * plugins/keyboard/gsd-keyboard-xkb.c: Be tolerant of variants when trying to match the gdm-provided keyboard layout to the existing keyboard configuration. ==================== 2.23.91 ==================== 2008-09-01 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.23.91 release. 2008-08-28 William Jon McCann * configure.ac: Belated post release version bump 2008-08-27 Jens Granseuer * plugins/xsettings/gsd-xsettings-manager.c: (setup_xsettings_managers): use g_warning instead of g_error when setup fails so we don't abort (bug #549483) 2008-08-26 William Jon McCann * plugins/a11y-keyboard/Makefile.am: * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c (dpi_from_pixels_and_mm), (get_dpi_from_x_server), (config_get_large_print), (config_set_large_print): * plugins/a11y-keyboard/test-a11y-preferences-dialog.c (test_window), (main): Use a scale factor instead of a fixed DPI. Add a test program. 2008-08-22 William Jon McCann * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (on_notification_closed): Oops. Missing comma. 2008-08-22 William Jon McCann * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (on_notification_closed): Fix a crash due to an incorrect signal handler definition. 2008-08-21 Jens Granseuer * plugins/keyboard/gsd-keyboard-xkb.c: (apply_xkb_settings): fix a constness warning 2008-08-19 Claude Paroz * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.glade: Removed the translatable property on stock gtk-close. ==================== 2.23.90 ==================== 2008-08-18 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.23.90 release. 2008-08-14 William Jon McCann * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c (get_dpi_from_x_server): Use gdk api to get dpi. 2008-08-13 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (status_icon_popup_menu): Create the RANDR configuration and labeler before the menu items. 2008-08-13 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (status_icon_popup_menu): Add a separator to the menu before "Configure display settings". 2008-08-13 Federico Mena Quintero * plugins/xrandr/gsd-xrandr-manager.c (status_icon_popup_menu): When the menu comes up, create a GnomeRRLabeler so that the user can identify which physical monitors we are talking about. This will actually be visible in the popup menu once we implement the rotation commands. (status_icon_popup_menu_selection_done_cb): Hide and destroy the GnomeRRLabeler. (struct GsdXrandrManagerPrivate): New field "labeler". 2008-08-12 Federico Mena Quintero * configure.ac: For LIBSOUNDS, check for libgnomeui, not just libgnome. 2008-08-12 Jens Granseuer Even if we can't properly remove a client message handler at least make sure everything works as expected when enabling/disabling the plugin at runtime * plugins/xrandr/gsd-xrandr-manager.c: (on_client_message), (gsd_xrandr_manager_start): pass the manager as user data instead of the screen because the manager will remain stable during the lifetime of the daemon; also, don't filter messages when the plugin is disabled 2008-08-12 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (status_icon_start): remove obsolete comment 2008-08-11 Jens Granseuer * configure.ac: require gnome-desktop 2.23.90 * plugins/xrandr/gsd-xrandr-manager.c: (gsd_xrandr_manager_start), (gsd_xrandr_manager_stop), (gsd_xrandr_manager_init): try harder to clean up in _stop so we can enable/disable the plugin on the fly; not quite there, yet 2008-08-10 Jens Granseuer Patch by: Matthias Clasen * plugins/xrandr/gsd-xrandr-manager.c: (gsd_xrandr_manager_start): fail on start if we couldn't set up xrandr (bug #546446) 2008-08-08 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (gsd_xrandr_manager_init): pass the manager as callback data so we don't crash with a NULL pointer in on_randr_event 2008-08-08 Jens Granseuer * plugins/xrandr/gsd-xrandr-manager.c: (gsd_xrandr_manager_start): remove warning that isn't 2008-08-05 Jens Granseuer * configure.ac: require glib >= 2.17.3 * plugins/xsettings/fontconfig-monitor.c: (monitor_files): use g_file_monitor instead of g_file_monitor_file/directory (bug #546372) 2008-08-05 Jens Granseuer * plugins/font/gsd-font-manager.c: (gsd_font_manager_class_init), (gsd_font_manager_init): remove some unneccessary boilerplate 2008-08-05 Jens Granseuer * plugins/a11y-keyboard/Makefile.am: put the glade file where all the others are 2008-08-05 Jens Granseuer * configure.ac: simplify libnotify check, fix fontconfig result output 2008-08-05 William Jon McCann * configure.ac: * plugins/a11y-keyboard/Makefile.am: * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c (get_int), (set_clear), (maybe_show_status_icon), (on_notification_closed), (on_slow_keys_action), (on_sticky_keys_action), (ax_slowkeys_warning_post_bubble), (ax_slowkeys_warning_post_dialog), (ax_slowkeys_warning_post), (ax_stickykeys_warning_post_bubble), (ax_stickykeys_warning_post_dialog), (ax_stickykeys_warning_post), (set_gconf_from_server), (keyboard_callback), (gsd_a11y_keyboard_manager_start), (gsd_a11y_keyboard_manager_stop), (on_preferences_dialog_response), (on_status_icon_activate), (gsd_a11y_keyboard_manager_init): * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.c (gsd_a11y_preferences_dialog_set_property), (gsd_a11y_preferences_dialog_get_property), (gsd_a11y_preferences_dialog_constructor), (gsd_a11y_preferences_dialog_dispose), (gsd_a11y_preferences_dialog_class_init), (on_response), (config_get_string), (config_get_bool), (dpi_from_pixels_and_mm), (get_dpi_from_x_server), (config_get_large_print), (config_set_large_print), (config_get_high_contrast), (config_set_high_contrast), (config_get_sticky_keys), (config_set_sticky_keys), (config_get_bounce_keys), (config_set_bounce_keys), (config_get_slow_keys), (config_set_slow_keys), (config_have_at_gconf_condition), (config_get_at_screen_reader), (config_get_at_screen_keyboard), (config_get_at_screen_magnifier), (config_set_at_screen_reader), (config_set_at_screen_keyboard), (config_set_at_screen_magnifier), (on_sticky_keys_checkbutton_toggled), (on_bounce_keys_checkbutton_toggled), (on_slow_keys_checkbutton_toggled), (on_high_contrast_checkbutton_toggled), (on_at_screen_reader_checkbutton_toggled), (on_at_screen_keyboard_checkbutton_toggled), (on_at_screen_magnifier_checkbutton_toggled), (on_large_print_checkbutton_toggled), (ui_set_sticky_keys), (ui_set_bounce_keys), (ui_set_slow_keys), (ui_set_high_contrast), (ui_set_at_screen_reader), (ui_set_at_screen_keyboard), (ui_set_at_screen_magnifier), (ui_set_large_print), (key_changed_cb), (setup_dialog), (gsd_a11y_preferences_dialog_init), (gsd_a11y_preferences_dialog_finalize), (gsd_a11y_preferences_dialog_new): * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.glade: * plugins/a11y-keyboard/gsd-a11y-preferences-dialog.h: Add status icon when a11y hotkeys are enabled. Display Universal Access Preferences when it is clicked. Fixes #526070 2008-08-04 Jens Granseuer * configure.ac: fix PulseAudio check to not output "no" twice ==================== 2.23.6 ==================== 2008-08-04 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.23.6 release. 2008-08-03 Jens Granseuer * plugins/common/gsd-keygrab.c: (setup_modifiers), (grab_key), (match_key): resolve NumLock dynamically and make sure we ignore it so using e.g. the media keys works even when NumLock is on (still bug #165343) Tue Jul 29 01:09:46 2008 Søren Sandmann * plugins/xrandr/gsd-xrandr-manager.c (start_or_stop_icon): Make the display notification icon configurable. 2008-07-26 Matthias Clasen Bug 544733 – use standard icon names in the volume OSD, initially * plugins/media-keys/actions/acme.glade: Use standard icon names for the OSD. 2008-07-26 Wouter Bolsterlee * configure.ac: Bump glib dependency to 2.15. Fixes bug #544737. 2008-07-25 Rob Bradford * configure.ac: libsounds needs to use gtk+-2.0 now libgnomeui is removed. 2008-07-24 James Sharpe * configure.ac: * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: * plugins/sound/gsd-sound-manager.c: Remove libgnomeui. (bug #544347) ==================== 2.23.5 ==================== Thu Jul 24 14:48:04 2008 Søren Sandmann * Downgrade intltool requirement to 0.37.1. This bug http://bugzilla.gnome.org/show_bug.cgi?id=537352 says that's what I'm supposed to do. * Bump version number to 2.23.5 * NEWS: Update this file. 2008-07-22 Lennart Poettering Fixes #539786 * plugins/xsettings/gsd-xsettings-manager.c: add three new xsettings for event sounds. 2008-07-16 Jens Granseuer Patch by: Damien Carbery * data/gnome-settings-daemon-uninstalled.pc.in: fix include path for building against the uninstalled package (bug #543289) 2008-07-15 Gerd Kohlberger * plugins/mouse/gsd-mouse-manager.c: (set_mousetweaks_daemon): Remove 'daemon' from the warning message (see bug #543095). 2008-07-15 Jens Granseuer * plugins/common/gsd-keygrab.c: (match_key): always remove Shift from the consumed modifiers if we're matching the lowercase symbol to make more shortcuts with Shift work (bug #542275) Wed Jul 9 11:48:02 2008 Søren Sandmann * plugins/xrandr/gsd-xrandr-manager.c: Call the new gnome_rr functions instead of the old ones. 2008-06-28 Jens Granseuer * plugins/common/gsd-keygrab.c: don't ignore any ModX modifiers. This should finally make g-s-d recognize keybindings with Super and Meta although we still don't handle the corresponding virtual modifiers (bug #165343) 2008-06-20 Jens Granseuer * plugins/common/gsd-keygrab.c: (match_key): fix accel check so that we don't match e.g. XF86RaiseVolume if + XF86RaiseVolume was pressed (bug #538699). Also fix build without XKB 2008-06-18 Jens Granseuer * Makefile.am: * configure.ac: require intltool >= 0.40 2008-06-18 Jens Granseuer * configure.ac: bump gnome-desktop requirement to 2.23.5 Tue Jun 17 19:41:55 2008 Søren Sandmann * Merge randr-12 branch into trunk Mon Jun 16 14:50:53 2008 Søren Sandmann * Port to new gnome-desktop API Mon Jun 16 14:30:13 2008 Søren Sandmann * Merge from trunk. 2008-06-17 Colin Walters http://bugzilla.gnome.org/show_bug.cgi?id=533198 * configure.ac: Detect PulseAudio at build time; if available, default to always starting it (ignore the legacy esd GConf key /desktop/gnome/sound/enable_esd). If you're a system administrator or OS builder and want to disable PulseAudio, you should preferably figure out what the problem you have with it is; but failing that, just remove it from the install image. * plugins/sound/gsd-sound-manager.c: If we're not compiled with legacy sound pref, always start sound. ==================== 2.23.4 ==================== 2008-06-17 Rodrigo Moya * configure.ac: * NEWS: update for 2.23.4 release. 2008-06-14 Jens Granseuer Based on a patch by: Brian Cameron * configure.ac: * plugins/sound/Makefile.am: * plugins/sound/gsd-sound-manager.c: (start_gnome_sound): if available use the esd_serverdir variable to locate the esd daemon so it can be started even if it's not in the PATH (bug #531868) 2008-06-13 Jens Granseuer Based on a patch by: Bastien Nocera * plugins/common/gsd-keygrab.c: (match_key): properly match keybindings that need Shift for resolving the keysym (bug #536581) 2008-06-07 Behdad Esfahbod (Commit this again) * configure.ac: Check for fontconfig instead of xft2. * plugins/xsettings/Makefile.am: * plugins/xsettings/gsd-xsettings-manager.c (fontconfig_callback), (gnome_xsettings_manager_start), (gnome_xsettings_manager_stop): Send a Fontconfig/Timestamp xsettings notification whenever fontconfig configurations change. (bug #490374) * plugins/xsettings/fontconfig-monitor.c: * plugins/xsettings/fontconfig-monitor.h: Monitor fontconfig configuration files using gio. ==================== 2.23.3 ====================== 2008-06-03 Jens Granseuer * configure.ac: use correct release number 2008-06-03 Jens Granseuer * NEWS: Update for 2.23.3 release. 2008-06-02 Behdad Esfahbod * configure.ac: * plugins/xsettings/Makefile.am: * plugins/xsettings/fontconfig-monitor.c: * plugins/xsettings/fontconfig-monitor.h: * plugins/xsettings/gsd-xsettings-manager.c (gnome_xsettings_manager_start), (gnome_xsettings_manager_stop): Revert previous change. Working on a slightly different design. (bug #490374) 2008-06-02 Behdad Esfahbod * configure.ac: Check for fontconfig instead of xft2. * plugins/xsettings/Makefile.am: * plugins/xsettings/gsd-xsettings-manager.c (fontconfig_callback), (gnome_xsettings_manager_start), (gnome_xsettings_manager_stop): Send a Fontconfig/Timestamp xsettings notification whenever fontconfig configurations change. (bug #490374) * plugins/xsettings/fontconfig-monitor.c: * plugins/xsettings/fontconfig-monitor.h: Monitor fontconfig configuration files using gio. 2008-06-02 Jens Granseuer * configure.ac: do not add stuff to GST_LIBS when gstreamer is disabled. Fixes build without gstreamer (bug #536177) 2008-06-02 Gerd Kohlberger * plugins/mouse/gsd-locate-pointer.c: (timeline_frame_cb): Keep animation centered below pointer. Bug #531665 2008-05-30 Jens Granseuer * plugins/font/gsd-font-manager.c: (load_xcursor_theme): fix a few leaks 2008-05-27 Jens Granseuer * gnome-settings-daemon/gnome-settings-manager.c: (_unload_plugin), (_unload_all): stop all plugins on shutdown 2008-05-27 Lucas Rocha * gnome-settings-daemon/main.c (set_session_over_handler, on_session_over, main): listen to "SessionOver" D-Bus signal from Session Manager to know when to shutdown. Bug #522017. 2008-05-14 William Jon McCann * plugins/mouse/gsd-mouse-manager.c (filter): Bummer. Revert part of last commit. 2008-05-14 William Jon McCann * plugins/mouse/gsd-mouse-manager.c (filter): Don't eat keypresses for multimedia key events Patch by Bastien Nocera 2008-05-13 Jens Granseuer * plugins/background/gsd-background-manager.c: (gsd_background_manager_start): reuse the GConf client we already have 2008-05-13 William Jon McCann * configure.ac: * plugins/background/Makefile.am: * plugins/background/gsd-background-manager.c (draw_background), (queue_draw_background), (on_bg_changed), (gconf_changed_callback), (watch_bg_preferences), (gsd_background_manager_start), (gsd_background_manager_stop): Use new gnome-desktop background preference loading api. Drop use of libbackground. 2008-05-08 Carlos Garnacho * plugins/media-keys/gsd-media-keys-window.c (gsd_media_keys_window_real_realize): New function, sets a fully transparent input shape, so that clicks go through the media keys windows. Bug #531862. (gsd_media_keys_window_class_init): The usual glue. 2008-05-08 Carlos Garnacho * plugins/mouse/gsd-locate-pointer.c (set_transparent_shape): new function, sets a fully transparent shape to the whole window. (timeline_finished_cb) (gsd_locate_pointer): set the window transparent once the animation is finished, and before it's shown for the first time. The shape will be changed afterwards while running the animation. This fixes some artifacts shown when showing/moving the window, bug #531861. (locate_pointer_expose): Plug a leak. 2008-05-02 Jens Granseuer Patch by: Brian Cameron * gnome-settings-daemon/main.c: (main): don't die when the user's home directory is read-only (bug #530975) 2008-05-02 Jens Granseuer Based on a patch by: Matthias Clasen * plugins/keyboard/gsd-keyboard-xkb.c: (apply_xkb_settings), (gsd_keyboard_xkb_init): if the user set a keyboard layout from the login screen, try to keep that setting (bug #531589) 2008-05-02 Jens Granseuer * plugins/background/gsd-background-manager.c: (gsd_background_manager_start): add a comment explaining why we are applying the prefs regardless of nautilus 2008-05-02 Jens Granseuer Patch by: Matthias Clasen * plugins/background/gsd-background-manager.c: (gsd_background_manager_start): eventually apply the settings even if nautilus is supposed to be handling the background to make people running without nautilus happy (bug #531487) 2008-04-29 Bastien Nocera * plugins/common/gsd-keygrab.c (have_xkb), (match_key): When checking whether a key matches our key event, check the keysym from the key event, to avoid triggering another keybindings with the same keycode, but different keysym, Fixes Eject being triggered when pressing the Stop key with the default inet keymap (Closes: #530356) 2008-04-23 Vincent Untz * configure.ac: post release version bump. ==================== 2.23.1.1 ==================== 2008-04-23 Vincent Untz * configure.in: * NEWS: Update for 2.23.1.1 release. 2008-04-21 Lucas Rocha Install .desktop for gnome-settings-daemon in a standard autostart directory as required by new gnome-session (bug #526984). * configure.ac: expand $libexecdir to be used on .desktop file. * acinclude.m4: added new m4 macro (AS_AC_EXPAND) for expanding variables. * data/Makefile.am, data/gnome-settings-daemon.desktop.in.in: install g-s-d .desktop file. 2008-04-21 Rodrigo Moya * configure.ac: post release version bump. ==== 2.23.1 ==== 2008-04-21 Rodrigo Moya * configure.in: * NEWS: Update for release. 2008-04-20 Jens Granseuer * plugins/media-keys/actions/acme-volume-alsa.c: (acme_volume_alsa_finalize), (acme_volume_alsa_class_init): * plugins/media-keys/actions/acme-volume-dummy.c: (acme_volume_dummy_finalize), (acme_volume_dummy_class_init): * plugins/media-keys/actions/acme-volume-gstreamer.c: (acme_volume_gstreamer_finalize), (acme_volume_gstreamer_class_init): * plugins/media-keys/actions/acme-volume-oss.c: (acme_volume_oss_finalize), (acme_volume_oss_class_init): * plugins/media-keys/actions/acme-volume.c: (acme_volume_class_init): drop redundant GType stuff 2008-04-19 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (bindings_get_entry): remove some code (and translatable strings) for error that can never happen 2008-04-18 Jens Granseuer * plugins/mouse/gsd-mouse-manager.c: (set_mousetweaks_daemon): when we can't launch the daemon reset the GConf keys before showing the error dialog. If we wait until after the dialog is closed, the user can still toggle the settings while it's open 2008-04-13 Jens Granseuer Extract some functionality used by several plugins into a separate shared helper library (bug #525426). * configure.ac: * plugins/Makefile.am: * plugins/common/Makefile.am: * plugins/common/gsd-keygrab.c: * plugins/common/gsd-keygrab.h: * plugins/common/eggaccelerators.c: * plugins/common/eggaccelerators.h: new shared components * plugins/keybindings/Makefile.am: * plugins/keybindings/eggaccelerators.c: * plugins/keybindings/eggaccelerators.h: * plugins/keybindings/gsd-keybindings-manager.c: (binding_register_keys), (keybindings_filter): * plugins/media-keys/Makefile.am: * plugins/media-keys/actions/Makefile.am: * plugins/media-keys/actions/acme.h: * plugins/media-keys/eggaccelerators.c: * plugins/media-keys/eggaccelerators.h: * plugins/media-keys/gsd-media-keys-manager.c: (update_kbd_cb), (init_kbd), (acme_filter_events): make keybindings and media-keys plugins use the shared components 2008-04-13 Sergey Udaltsov * plugins/keyboard/gsd-keyboard-xkb.c: dropped gconf backup 2008-04-12 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (do_grab): * plugins/media-keys/gsd-media-keys-manager.c: (grab_key): make some tiny optimizations and add some more comments on what's happening 2008-04-12 Jens Granseuer * gnome-settings-daemon/main.c: * plugins/media-keys/gsd-media-keys-manager.c: DBus API has been stable for a while; don't define DBUS_API_SUBJECT_TO_CHANGE anymore 2008-04-12 Jens Granseuer * gnome-settings-daemon/main.c: (acquire_name_on_proxy), (bus_register), (main): fix a few small leaks 2008-04-12 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (init_screens): drop redundant code 2008-04-11 Jens Granseuer * gnome-settings-daemon/main.c: turn into a daemon by default and make --no-daemon work 2008-04-11 Jens Granseuer * plugins/sound/gsd-sound-plugin.c: (impl_deactivate): fix typo 2008-04-11 Jens Granseuer Make xrandr, xrdb, and xsettings plugin deactivation work * plugins/xrandr/gsd-xrandr-manager.c: (apply_settings): cleanup * plugins/xrandr/gsd-xrandr-plugin.c: (impl_deactivate): * plugins/xrdb/gsd-xrdb-plugin.c: (impl_deactivate): * plugins/xsettings/gsd-xsettings-plugin.c: (impl_deactivate): stop manager on deactivation * plugins/xrdb/gsd-xrdb-manager.c: (gsd_xrdb_manager_start), (gsd_xrdb_manager_stop): * plugins/xsettings/gsd-xsettings-manager.c: (gsd_xsettings_error_quark), (find_translation_entry), (xsettings_callback), (register_config_callback), (terminate_cb), (setup_xsettings_managers), (gnome_xsettings_manager_start), (gnome_xsettings_manager_stop), (gnome_xsettings_manager_init): clean up properly on stop 2008-04-11 Jens Granseuer Make typing-break plugin deactivation work * plugins/typing-break/gsd-typing-break-manager.c: (register_config_callback), (gsd_typing_break_manager_start), (gsd_typing_break_manager_stop): clean up properly on stop * plugins/typing-break/gsd-typing-break-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-11 Jens Granseuer Make screensaver and sound plugin deactivation work (sort of). The screensaver is currently not reaped when deactivating the plugin, but since the plugin should go away anyway, it doesn't seem worth adding that right now. For the sound plugin, esd is currently not reaped when HAVE_ESD is set. Maybe we want to get rid of the esd API altogether? * plugins/sound/gsd-sound-manager.c: (apply_settings), (register_config_callback), (gsd_sound_manager_start), (gsd_sound_manager_stop): clean up a bit more on stop * plugins/screensaver/gsd-screensaver-plugin.c: (impl_deactivate): * plugins/sound/gsd-sound-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-11 Jens Granseuer Make mouse plugin deactivation work * plugins/mouse/gsd-mouse-manager.c: (register_config_callback), (gsd_mouse_manager_init), (gsd_mouse_manager_start), (gsd_mouse_manager_stop): clean up properly on stop * plugins/mouse/gsd-mouse-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-11 Jens Granseuer * plugins/keyboard/gsd-keyboard-xkb.c: (gsd_keyboard_xkb_shutdown): clear the user callback data even if initialiation failed * plugins/keyboard/gsd-xmodmap.c: (gsd_load_modmap_files): properly NULL-terminate g_build_filename 2008-04-11 Jens Granseuer Make media-keys plugin deactivation work * plugins/media-keys/gsd-media-keys-manager.c: (acme_error), (dialog_init), (init_kbd), (gsd_media_keys_manager_stop), (register_manager): clean up properly on stop * plugins/media-keys/gsd-media-keys-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-11 Jens Granseuer * plugins/keyboard/gsd-xmodmap.c: (check_button_callback), (gsd_load_modmap_files), (response_callback), (remove_string_from_list), (remove_button_clicked_callback), (load_button_clicked_callback), (gsd_modmap_dialog_call): fix memory leaks 2008-04-10 Jens Granseuer Make keyboard plugin deactivation work * plugins/keyboard/gsd-keyboard-manager.c: (register_config_callback), (gsd_keyboard_manager_start), (gsd_keyboard_manager_stop): * plugins/keyboard/gsd-keyboard-xkb.c: (register_config_callback), (gsd_keyboard_xkb_init), (gsd_keyboard_xkb_shutdown): * plugins/keyboard/gsd-keyboard-xkb.h: clean up properly on stop * plugins/keyboard/gsd-keyboard-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer Make keybinding plugin deactivation work * plugins/keybindings/gsd-keybindings-manager.c: (register_config_callback), (gsd_keybindings_manager_start), (gsd_keybindings_manager_stop): clean up properly on stop * plugins/keybindings/gsd-keybindings-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer * plugins/font/gsd-font-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer * plugins/dummy/gsd-dummy-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer * plugins/clipboard/gsd-clipboard-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer Make background plugin deactivation work * plugins/background/gsd-background-manager.c: (gsd_background_manager_start), (gsd_background_manager_stop): clean up properly on stop * plugins/background/gsd-background-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (gsd_a11y_keyboard_manager_stop): also remove GConf watch directory 2008-04-10 Jens Granseuer Make housekeeping plugin deactivation work * plugins/housekeeping/gsd-housekeeping-manager.c: (register_config_callback), (gsd_housekeeping_manager_start), (gsd_housekeeping_manager_stop), (gsd_housekeeping_manager_init): clean up properly on stop * plugins/housekeeping/gsd-housekeeping-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer Make a11y-keyboard plugin deactivation work * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (register_config_callback), (gsd_a11y_keyboard_manager_start), (gsd_a11y_keyboard_manager_stop): properly clean up on _stop * plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c: (impl_deactivate): stop manager on deactivation 2008-04-10 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (get_xkb_desc_rec), (set_server_from_gconf), (ax_slowkeys_warning_dialog_post), (ax_stickykeys_warning_dialog_post), (set_gconf_from_server), (cb_xkb_event_filter), (gsd_a11y_keyboard_manager_init): more cleanup 2008-04-10 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (grab_key_real): remove excessive key grab logging 2008-04-09 Jens Granseuer * plugins/keyboard/gsd-keyboard-manager.c: (numlock_xkb_init), (numlock_set_xkb_state), (numlock_gconf_state_key), (numlock_xkb_callback), (numlock_install_xkb_callback), (apply_settings), (gsd_keyboard_manager_start): split XKB initialization and calbback installation which allows us to get rid of some more special-casing and yet another static variable 2008-04-09 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (xkb_enabled), (get_xkb_desc_rec), (gsd_a11y_keyboard_manager_start): don't install any listeners or callbacks when XKB is not available 2008-04-09 Michael J. Chudobiak * plugins/housekeeping/gsd-housekeeping-manager.c: (gsd_housekeeping_manager_stop): Purge thumbnail cache on shutdown if and only if the max size or max age parameters have been set to zero (for paranoid people) (bug #526999). 2008-04-07 Jens Granseuer Currently, the percentage by which to lower or raise the volume when hitting the multimedia keys is taken from GConf, with 6 being the default. We don't have any settings dialogs to actually change it, though. If the user now selects a mixer that supports fewer volume levels than the GConf setting implies (100/6) it becomes impossible to change the volume (without fiddling with the GConf setting). This patch adds a "threshold" property to the AcmeVolume class that denotes the minimum percentage required to actually affect the volume. The plugin now uses the step size read from GConf or the mixer threshold, depending on which one is bigger. (bug #441910) * plugins/media-keys/actions/acme-volume-alsa.c: (acme_volume_alsa_get_threshold), (acme_volume_alsa_class_init): * plugins/media-keys/actions/acme-volume-dummy.c: (acme_volume_dummy_get_threshold), (acme_volume_dummy_class_init): * plugins/media-keys/actions/acme-volume-gstreamer.c: (acme_volume_gstreamer_get_threshold), (acme_volume_gstreamer_class_init): * plugins/media-keys/actions/acme-volume-oss.c: (acme_volume_oss_get_threshold), (acme_volume_oss_class_init), (acme_volume_oss_mixer_check): * plugins/media-keys/actions/acme-volume.c: (acme_volume_get_threshold): * plugins/media-keys/actions/acme-volume.h: add get_threshold method * plugins/media-keys/gsd-media-keys-manager.c: (do_sound_action): use gconf value or threshold, depending on what's bigger 2008-04-07 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (do_sound_action): only use the built-in default for volume_step if we get an error from GConf, not just when the value is 0 which might be what the user wants (see the discussion on the Thinkpad driver again) 2008-04-07 Jens Granseuer Remove the Thinkpad driver again. See bug #524425 for some discussion. * configure.ac: * plugins/media-keys/actions/Makefile.am: * plugins/media-keys/actions/acme-volume-thinkpad.c: * plugins/media-keys/actions/acme-volume-thinkpad.h: * plugins/media-keys/actions/acme-volume.c: (acme_volume_new): remove extra Thinkpad support 2008-04-06 Jens Granseuer * plugins/keyboard/gsd-keyboard-manager.c: (gsd_keyboard_get_hostname_key), (numlock_set_xkb_state), (numlock_gconf_state_key), (numlock_get_gconf_state), (numlock_set_gconf_state), (numlock_xkb_callback), (numlock_install_xkb_callback), (apply_settings), (gsd_keyboard_manager_start), (gsd_keyboard_manager_init): * plugins/keyboard/gsd-keyboard-xkb.c: (gsd_keyboard_xkb_init): * plugins/keyboard/gsd-keyboard-xkb.h: continued attempt at making XKB setup and error handling a bit less arcane and crufty 2008-04-06 Jens Granseuer * plugins/keyboard/gsd-keyboard-xkb.c: * plugins/keyboard/gsd-keyboard-xkb.h: initialize inited_ok or behaviour is undefined when xkb setup fails; don't export XklEngine 2008-04-06 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (do_action): make "Home" keybinding work again 2008-04-05 Jens Granseuer * configure.ac: * plugins/media-keys/actions/Makefile.am: hook up the Thinkpad support 2008-04-05 Jens Granseuer Patch by: Lorne Applebaum <4lorne@gmail.com> * plugins/media-keys/actions/acme-volume-thinkpad.c: * plugins/media-keys/actions/acme-volume-thinkpad.h: * plugins/media-keys/actions/acme-volume.c: (acme_volume_new): add a special volume subclass for better support of IBM Thinkpad hardware volume buttons (bug #524425) 2008-04-05 Jens Granseuer Patch by: Lorne Applebaum <4lorne@gmail.com> * plugins/media-keys/actions/acme-volume-dummy.h: fix TYPE macro and remove an unimplemented prototype 2008-04-01 Jens Granseuer * plugins/keyboard/gsd-keyboard-manager.c: (gsd_keyboard_manager_start): apply keyboard settings on startup, too (bug #525440) 2008-03-31 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (bindings_get_entry): fix various leaks and other memory management issues 2008-03-31 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (bindings_get_entry), (binding_register_keys): remove trailing newlines from messages since g_warning already takes care of those 2008-03-31 Jens Granseuer * plugins/keybindings/gsd-keybindings-manager.c: (do_grab): * plugins/media-keys/gsd-media-keys-manager.c: (grab_key): don't try to add grabs with invalid modifiers 2008-03-30 Gerd Kohlberger * plugins/mouse/gsd-mouse-manager.c: (set_mousetweaks_daemon): Set gconf keys back to false, if mousetweaks isn't installed. Bug #525042. 2008-03-30 Jens Granseuer * plugins/xsettings/gsd-xsettings-manager.c: add mapping for Gtk/Modules xsetting using GConf path /desktop/gnome/gtk-modules (bug #507386) 2008-03-30 Jens Granseuer * plugins/housekeeping/gsd-housekeeping-manager.c: change data types to match glib; avoid using time_t 2008-03-30 Jens Granseuer * plugins/media-keys/actions/acme-volume-dummy.c: (acme_volume_dummy_init), (acme_volume_dummy_class_init): change to use G_DEFINE_TYPE instead of open-coding it 2008-03-29 Jens Granseuer * configure.ac: fix profiling to be off by default 2008-03-29 Jens Granseuer * gnome-settings-daemon/main.c: mark string for translation 2008-03-29 Jens Granseuer * plugins/keybindings/eggaccelerators.c: (egg_accelerator_parse_virtual): * plugins/media-keys/eggaccelerators.c: (egg_accelerator_parse_virtual): readd a chunk that got lost in the last commit. *sigh*. Why do we have several differing copies of those files? 2008-03-29 Jens Granseuer * plugins/keybindings/eggaccelerators.c: (egg_accelerator_parse_virtual), (egg_virtual_accelerator_name), (egg_virtual_accelerator_label), (egg_keymap_resolve_virtual_modifiers), (egg_keymap_virtualize_modifiers), (reload_modmap), (egg_keymap_get_modmap): * plugins/keybindings/eggaccelerators.h: fix mismatched modifier mapping between egg and GTK (so that e.g. works) and replace some custom functionality with stock GTK 2008-03-29 Jens Granseuer * plugins/media-keys/eggaccelerators.c: (egg_accelerator_parse_virtual), (egg_virtual_accelerator_name), (egg_virtual_accelerator_label), (egg_keymap_resolve_virtual_modifiers), (egg_keymap_virtualize_modifiers), (reload_modmap), (egg_keymap_get_modmap): * plugins/media-keys/eggaccelerators.h: fix mismatched modifier mapping between egg and GTK (so that e.g. works) and replace some custom functionality with stock GTK 2008-03-29 Jens Granseuer * plugins/housekeeping/gsd-housekeeping-manager.c: (get_gconf_int_with_default): rename to better reflect what it does, and also use the default passed in if we don't get an int from GConf, or we'll end up with a value of 0 which is certainly not what we want (purge_thumbnail_cache): update callers 2008-03-28 Michael J. Chudobiak * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/housekeeping/Makefile.am: * plugins/housekeeping/gsd-housekeeping-manager.c: (thumb_data_free), (read_dir_for_purge), (purge_old_thumbnails), (sort_file_mtime), (get_gconf_int_with_nonzero_default), (purge_thumbnail_cache), (do_cleanup), (do_cleanup_once), (do_cleanup_soon), (bindings_callback), (register_config_callback), (gsd_housekeeping_manager_start), (gsd_housekeeping_manager_stop), (gsd_housekeeping_manager_class_init), (gsd_housekeeping_manager_init), (gsd_housekeeping_manager_new): * plugins/housekeeping/gsd-housekeeping-manager.h: * plugins/housekeeping/gsd-housekeeping-plugin.c: (gsd_housekeeping_plugin_init), (gsd_housekeeping_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_housekeeping_plugin_class_init): * plugins/housekeeping/gsd-housekeeping-plugin.h: * plugins/housekeeping/housekeeping.gnome-settings-plugin.in: Added a new "housekeeping" plugin to set limits on the size and age of the thumbnail cache (bug #523159). 2008-03-25 Jens Granseuer Patch by: Matthias Clasen * plugins/mouse/gsd-mouse-manager.c: (filter): don't eat key events; other plugins might need them as well (bug #523676) 2008-03-24 William Jon McCann * configure.ac: Add some stuff to the configuration summary. * plugins/media-keys/gsd-media-keys-manager.c: (gsd_media_keys_manager_start): Add a few more profiling points. 2008-03-24 William Jon McCann * gnome-settings-daemon/Makefile.am: * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (set_server_from_gconf), (gsd_a11y_keyboard_manager_start): * plugins/background/Makefile.am: * plugins/background/gsd-background-manager.c: (apply_prefs), (gsd_background_manager_start): * plugins/clipboard/gsd-clipboard-manager.c: (gsd_clipboard_manager_start): * plugins/dummy/gsd-dummy-manager.c: (gsd_dummy_manager_start): * plugins/font/gsd-font-manager.c: (load_xcursor_theme), (load_cursor), (gsd_font_manager_start): * plugins/keybindings/gsd-keybindings-manager.c: (gsd_keybindings_manager_start): * plugins/keyboard/gsd-keyboard-manager.c: (gsd_keyboard_manager_start): * plugins/media-keys/Makefile.am: * plugins/media-keys/gsd-media-keys-manager.c: (init_kbd), (gsd_media_keys_manager_start): * plugins/mouse/gsd-mouse-manager.c: (gsd_mouse_manager_start): * plugins/screensaver/gsd-screensaver-manager.c: (gsd_screensaver_manager_start): * plugins/sound/gsd-sound-manager.c: (start_gnome_sound), (reload_foreach_cb), (apply_settings), (gsd_sound_manager_start): * plugins/typing-break/gsd-typing-break-manager.c: (setup_typing_break), (gsd_typing_break_manager_start): * plugins/xrandr/gsd-xrandr-manager.c: (apply_settings): * plugins/xrdb/gsd-xrdb-manager.c: (apply_settings), (gsd_xrdb_manager_start): * plugins/xsettings/gsd-xsettings-manager.c: (xft_settings_set_xsettings), (xft_settings_set_xresources), (update_xft_settings), (gnome_xsettings_manager_start): Add profiling points to plugins. 2008-03-24 William Jon McCann * gnome-settings-daemon/gnome-settings-manager.c: (compare_location), (_load_file), (_load_dir): * gnome-settings-daemon/gnome-settings-plugin-info.c: (debug_info), (gnome_settings_plugin_info_fill_from_file), (gnome_settings_plugin_info_deactivate), (load_plugin_module), (gnome_settings_plugin_info_activate), (gnome_settings_plugin_info_is_active), (gnome_settings_plugin_info_get_enabled), (gnome_settings_plugin_info_is_available), (gnome_settings_plugin_info_get_name), (gnome_settings_plugin_info_get_description), (gnome_settings_plugin_info_get_authors), (gnome_settings_plugin_info_get_website), (gnome_settings_plugin_info_get_copyright), (gnome_settings_plugin_info_get_location), (gnome_settings_plugin_info_get_priority), (gnome_settings_plugin_info_set_priority): Fix a refcounting bug. Add a few more checks. Fix up a leak. Fixes #524183 2008-03-24 William Jon McCann * plugins/media-keys/gsd-media-keys-manager.c: (acme_filter_events): * plugins/sound/gsd-sound-manager.c: (start_gnome_sound): Fix two compiler warnings. 2008-03-24 William Jon McCann * gnome-settings-daemon/gnome-settings-manager.c: (gnome_settings_manager_start): * gnome-settings-daemon/gnome-settings-profile.c: (_gnome_settings_profile_log): * gnome-settings-daemon/gnome-settings-profile.h: * gnome-settings-daemon/main.c: (main): Add missing files. Add some more profiling points. 2008-03-24 William Jon McCann * configure.ac: * gnome-settings-daemon/Makefile.am: * gnome-settings-daemon/gnome-settings-manager.c: (_load_file), (_load_dir), (_load_all), (gnome_settings_manager_start): * gnome-settings-daemon/gnome-settings-plugin-info.c: (gnome_settings_plugin_info_fill_from_file), (load_plugin_module), (_activate_plugin): * gnome-settings-daemon/main.c: (bus_register), (main): Add some profiling code. Must specify --enable-profiling to configure. Can now be profiled like so: strace -ttt -f -o /tmp/logfile.strace gnome-settings-daemon python plot-timeline.py -o prettygraph.png /tmp/logfile.strace See: http://www.gnome.org/~federico/news-2006-03.html#09 2008-03-24 Jens Granseuer Patch by: Alexey Shabalin * plugins/sound/gsd-sound-manager.c: (apply_settings): now that "starting esd" can mean either esd or PulseAudio, check the GConf setting for starting the sound server even when esd is disabled (bug #523743) 2008-03-24 Jens Granseuer * plugins/dummy/Makefile.am: remove NULL definition so authors using this as the base for their own plugins don't get strange ideas 2008-03-20 William Jon McCann * plugins/media-keys/Makefile.am: * plugins/media-keys/gsd-media-keys-manager.c: (grab_key_real), (init_kbd), (acme_filter_events), (gsd_media_keys_manager_start): * plugins/media-keys/test-media-keys.c: (main): Add a tool to test media keys. 2008-03-16 William Jon McCann * plugins/sound/gsd-sound-manager.c: (reset_esd_pid), (start_gnome_sound), (wait_on_child), (stop_child), (stop_gnome_sound), (apply_settings), (gsd_sound_manager_dispose): Fix handling of child process. 2008-03-14 Jens Granseuer * plugins/media-keys/gsd-media-keys-window.c: (remove_hide_timeout): reset opacity when removing the timeout so that the fadeout is restarted when media keys are pressed while the popup is already fading out (bug #522499) 2008-03-13 Jens Granseuer * plugins/media-keys/actions/acme.glade: remove unused properties (and, in particular, an unused translated string) 2008-03-13 Jens Granseuer Patch by: Danny Baumann * plugins/media-keys/gsd-media-keys-window.c: (gsd_media_keys_window_new): set window type hint on the volume popup (bug #522232) 2008-03-11 Jens Granseuer * plugins/typing-break/gsd-typing-break-manager.c: (setup_typing_break): pass data to the timeout so shutting down the typing monitor works instead of segfaulting (bug #521786) (gsd_typing_break_manager_start): use g_timeout_add_seconds instead of g_timeout_add 2008-03-10 Rodrigo Moya * configure.ac: Post release version bump ==== 2.22.0 ==== 2008-03-10 Rodrigo Moya * NEWS: Update for release. 2008-03-08 Jens Granseuer * data/Makefile.am: * data/apps_gnome_settings_daemon_default_editor.schemas.in: * data/gnome-settings-daemon.schemas.in: remove obsolete settings for the removed default editor plugin 2008-03-01 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (ax_response_callback): don't pass the GError argument if we're not going to use it. Also remove some unnecessary casting 2008-02-29 William Jon McCann * gnome-settings-daemon/main.c: Disable debug by default again. 2008-02-29 Jens Granseuer * configure.ac: * plugins/mouse/Makefile.am: when building with XInput support, actually link against libXi, or we'll fail to load the plugin due to unresolved symbols (bug #519488) 2008-02-29 William Jon McCann * configure.ac: Post release version bump ==== 2.21.92 ==== 2008-02-29 William Jon McCann * NEWS: Update for release. 2008-02-29 William Jon McCann * configure.ac: Remove Werror. 2008-02-29 Jens Granseuer * gnome-settings-daemon/gnome-settings-manager.c: (register_manager), (gnome_settings_manager_start): minor clean-up 2008-02-28 William Jon McCann * gnome-settings-daemon/gnome-settings-manager.c: (gnome_settings_manager_error_quark), (_load_file), (gnome_settings_manager_awake), (gnome_settings_manager_start), (gnome_settings_manager_start_with_settings_prefix), (_set_settings_prefix), (gnome_settings_manager_set_property), (gnome_settings_manager_get_property), (gnome_settings_manager_class_init), (gnome_settings_manager_finalize), (gnome_settings_manager_new): * gnome-settings-daemon/gnome-settings-manager.h: * gnome-settings-daemon/gnome-settings-manager.xml: * gnome-settings-daemon/main.c: (main): When dbus activated only load the plugins when requested instead of at startup. Add a new method to start and set plugin settings prefix. This allows gdm to use dbus activation. It also fixes cases where g-s-d is activated and plugins are loaded unintentionally. 2008-02-29 Wouter Bolsterlee * plugins/sound/gsd-sound-manager.c (apply_settings): Add braces to fix amgiguous else. Avoids compiler warnings. 2008-02-28 Bastien Nocera * plugins/sound/gsd-sound-manager.c (reset_esd_pid), (start_gnome_sound), (stop_gnome_sound), (apply_settings), (gsd_sound_manager_stop): Start the sound server ourselves, as we need it to cache samples. If esd (or the PulseAudio esd compat bits) isn't available, just print an error, and don't try to cache the samples If you use PulseAudio instead of esound in your distribution, build with --disable-esd passed to configure (Closes: #518075) 2008-02-25 William Jon McCann * gnome-settings-daemon/main.c: (gsd_log_default_handler), (main): Add --debug command line option. Only print DEBUG level messages if --debug is used. 2008-02-25 William Jon McCann * gnome-settings-daemon/gnome-settings-plugin-info.c: (gnome_settings_plugin_info_fill_from_file): Don't warn on missing priority since we don't recommend that it be used. 2008-02-22 William Jon McCann * data/gnome-settings-daemon.schemas.in: Take a stab at defining the default load priorities. Fixes #518155 2008-02-22 William Jon McCann * data/gnome-settings-daemon.schemas.in: * gnome-settings-daemon/gnome-settings-manager.c: (_load_file): * gnome-settings-daemon/gnome-settings-plugin-info.c: (gnome_settings_plugin_info_set_priority): * gnome-settings-daemon/gnome-settings-plugin-info.h: Allow gconf to override priorities. Set sound plugin priority to 1 (highest). Fixes #515340 2008-02-22 William Jon McCann * gnome-settings-daemon/Makefile.am: * gnome-settings-daemon/gnome-settings-manager.c: (_load_info), (maybe_activate_plugin), (compare_location), (compare_priority), (on_plugin_activated), (on_plugin_deactivated), (_load_file), (_load_dir), (_load_all), (_unload_all), (gnome_settings_manager_start), (gnome_settings_manager_stop), (gnome_settings_manager_constructor), (gnome_settings_manager_class_init), (gnome_settings_manager_finalize): * gnome-settings-daemon/gnome-settings-manager.h: * gnome-settings-daemon/gnome-settings-manager.xml: * gnome-settings-daemon/gnome-settings-plugin-info.c: (gnome_settings_plugin_info_class_init), (gnome_settings_plugin_info_set_enabled_key_name), (_deactivate_plugin), (_activate_plugin): * gnome-settings-daemon/gnome-settings-plugin-info.h: * gnome-settings-daemon/gnome-settings-plugins-engine.c: * gnome-settings-daemon/gnome-settings-plugins-engine.h: Merge PluginsEngine functionality into Manager. Emit signals when plugins are activated or deactivated. Fixes #515341 2008-02-22 William Jon McCann * gnome-settings-daemon/Makefile.am: * gnome-settings-daemon/gnome-settings-manager.c: (gnome_settings_manager_start), (gnome_settings_manager_stop), (gnome_settings_manager_constructor), (gnome_settings_manager_finalize): * gnome-settings-daemon/gnome-settings-plugin-info.c: (gnome_settings_plugin_info_finalize), (gnome_settings_plugin_info_class_init), (gnome_settings_plugin_info_init), (gnome_settings_plugin_info_fill_from_file), (plugin_enabled_cb), (gnome_settings_plugin_info_set_enabled_key_name), (gnome_settings_plugin_info_new_from_file), (_deactivate_plugin), (gnome_settings_plugin_info_deactivate), (load_plugin_module), (_activate_plugin), (gnome_settings_plugin_info_activate), (gnome_settings_plugin_info_is_active), (gnome_settings_plugin_info_get_enabled), (gnome_settings_plugin_info_is_available), (gnome_settings_plugin_info_get_name), (gnome_settings_plugin_info_get_description), (gnome_settings_plugin_info_get_authors), (gnome_settings_plugin_info_get_website), (gnome_settings_plugin_info_get_copyright), (gnome_settings_plugin_info_get_location), (gnome_settings_plugin_info_get_priority): * gnome-settings-daemon/gnome-settings-plugin-info.h: * gnome-settings-daemon/gnome-settings-plugins-engine.c: (gnome_settings_plugins_engine_load), (maybe_activate_plugin), (compare_location), (compare_priority), (gnome_settings_plugins_engine_load_file), (gnome_settings_plugins_engine_load_dir), (gnome_settings_plugins_engine_load_all), (gnome_settings_plugins_engine_unload_all), (gnome_settings_plugins_engine_start), (gnome_settings_plugins_engine_garbage_collect), (gnome_settings_plugins_engine_stop), (gnome_settings_plugins_engine_get_plugins_list), (_set_gconf_prefix), (gnome_settings_plugins_engine_set_property), (gnome_settings_plugins_engine_get_property), (gnome_settings_plugins_engine_class_init), (gnome_settings_plugins_engine_init), (gnome_settings_plugins_engine_finalize), (gnome_settings_plugins_engine_new): * gnome-settings-daemon/gnome-settings-plugins-engine.h: Refactor the PluginInfo structure into a class. This will facilitate fixing bug #515341 2008-02-22 Bastien Nocera * configure.ac: Only enable ALSA and OSS support if we don't have GStreamer support, as the media-keys code doesn't have any fallbacks if GStreamer fails to load (see acme-volume.c's _new ()) 2008-02-19 Vincent Untz * plugins/keyboard/gsd-keyboard-manager.c: (gsd_keyboard_get_hostname_key): escape the hostname before using it in a gconf path since it might contain invalid characters. Fix bug #517259. 2008-02-19 Jens Granseuer * configure.ac: remove some unused stuff * plugins/sound/Makefile.am: add missing ESD_CFLAGS/LIBS 2008-02-19 Jens Granseuer * configure.ac: * plugins/xrandr/Makefile.am: * plugins/xrandr/gsd-xrandr-manager.c: (gsd_xrandr_manager_class_init), (gsd_xrandr_manager_init), (gsd_xrandr_manager_finalize): build with XRandR if available, makes setting screen geometry at login time work again (bug #517418) 2008-02-16 Jens Granseuer * gnome-settings-daemon/main.c: mark string as translatable 2008-02-14 Jens Granseuer * plugins/background/gsd-background-manager.c: (gsd_background_manager_start): at startup, don't apply background prefs twice and don't check for nautilus running since we're usually started first 2008-02-12 Kjartan Maraas * configure.ac: Fix for 515956. Build with Gio. ==== 2.21.91 ==== 2008-02-11 Rodrigo Moya * configure.ac: * NEWS: prepare for 2.21.91. 2008-02-11 Rodrigo Moya Fixes bug #513990 * plugins/background/gsd-background-manager.c: use GIO instead of gnome-vfs. * plugins/configure.ac: * plugins/Makefile.am: * plugins/default-editor/*: removed useless default editor plugin. 2008-02-11 Rodrigo Moya Patch by Wouter Bolsterlee * gnome-settings-daemon/gnome-settings-plugins-engine.c (gnome_settings_plugins_engine_load_all): assign return value from g_slist_sort to the plugins list variable. (bug #515340) 2008-02-10 Jens Granseuer * gnome-settings-daemon/main.c: update the default GConf prefix to match the changes from r112 or bug #514411 2008-02-09 Jens Granseuer Support for defining plugin start order got lost in the split from gnome-control-center, but it is essential for some plugins to work correctly. With this change the "Priority" keyword can be used in the ".gnome-settings-plugin" file to set plugin priorities. Priority can take values from 1 upwards, with 1 being maximum priority and 100 being the default if nothing is specified by the plugin. For multiple plugins with identical priority start order is undefined. (bug #515340) * gnome-settings-daemon/gnome-settings-plugins-engine.c: (gnome_settings_plugins_engine_load), (activate_plugin), (compare_location), (compare_priority), (gnome_settings_plugins_engine_load_file), (gnome_settings_plugins_engine_load_all), (gnome_settings_plugins_engine_init), (gnome_settings_plugins_engine_shutdown), (gnome_settings_plugins_engine_get_plugins_list), (gnome_settings_plugins_engine_get_plugin_copyright), (gnome_settings_plugins_engine_get_plugin_priority): * gnome-settings-daemon/gnome-settings-plugins-engine.h: add back support for defining plugin start order 2008-02-09 Jens Granseuer * plugins/media-keys/gsd-media-keys-manager.c: (gsd_media_keys_manager_stop): declare variables at the beginning of a block to make older compilers happy 2008-02-09 Jens Granseuer * plugins/clipboard/gsd-clipboard-manager.c: (gsd_clipboard_error_quark): fix copy'n'paste error (bug #515426) 2008-02-08 Sebastien Bacher * configure.ac: check for xinput (bug #514942) 2008-02-08 Jens Granseuer * plugins/background/gsd-background-manager.c: (gsd_background_manager_start), (gsd_background_manager_stop): * plugins/keybindings/gsd-keybindings-manager.c: (gsd_keybindings_manager_start): * plugins/media-keys/gsd-media-keys-manager.c: (gsd_media_keys_manager_stop): fix leaks * plugins/default-editor/gsd-default-editor-manager.c: (gsd_default_editor_manager_start): fix leak and pass the correct data to the mime type callback * plugins/xsettings/gsd-xsettings-manager.c: (gnome_xsettings_manager_start): unref the GConfClient only after we're done with it 2008-02-08 Jens Granseuer * plugins/clipboard/gsd-clipboard-manager.c: (gsd_kbd_a11y_error_quark), (gsd_clipboard_manager_start): make sure we return a GError if initialization fails 2008-02-08 Matthias Clasen * plugins/keyboard/gsd-keyboard-manager.c (gsd_keyboard_manager_start): Load the XKB settings initially. Fixes bug #511771. 2008-02-07 Jens Granseuer * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: (gsd_kbd_a11y_error_quark), (gsd_a11y_keyboard_manager_start): make sure we return a GError if initialization fails (bug #514926) 2008-02-06 Jens Granseuer * plugins/media-keys/gsd-media-keys-window.c: (volume_controls_set_visible), (window_set_icon_name), (window_set_icon_file), (volume_level_changed), (gsd_media_keys_window_class_init), (gsd_media_keys_window_init): release the glade XML file as soon as possible and keep track of the two widgets we need. This way we can also get rid of the custom finalize method 2008-02-06 Jens Granseuer * data/gnome-settings-daemon.schemas.in: use gnome_settings_daemon for the GConf path. This is what the other g-s-d settings use as well, and there is no good reason to use two separate paths (bug #514411) 2008-02-06 Jens Granseuer * configure.ac: add separate checks for libbackground * plugins/background/libbackground/*: delete files and use the external copy from gnome-control-center to avoid duplication 2008-02-05 Jens Granseuer Based on a patch by: Damien Carberry * configure.ac: * data/gnome-settings-daemon-uninstalled.pc.in: add uninstalled.pc file for building against an uninstalled copy of g-s-d (bug #511820) 2008-02-05 Jens Granseuer Based on a patch by: Damien Carberry * Makefile.am: * autogen.sh: * configure.ac: * plugins/a11y-keyboard/Makefile.am: * plugins/background/Makefile.am: * plugins/clipboard/Makefile.am: * plugins/default-editor/Makefile.am: * plugins/dummy/Makefile.am: * plugins/font/Makefile.am: * plugins/keybindings/Makefile.am: * plugins/keyboard/Makefile.am: * plugins/media-keys/Makefile.am: * plugins/media-keys/actions/Makefile.am: * plugins/mouse/Makefile.am: * plugins/screensaver/Makefile.am: * plugins/sound/Makefile.am: * plugins/typing-break/Makefile.am: * plugins/xrandr/Makefile.am: * plugins/xrdb/Makefile.am: * plugins/xsettings/Makefile.am: * src: rename the src folder to gnome-settings-daemon. This is needed so we can supply an uninstalled.pc file for g-s-d (see discussion in bug #511820) 2008-02-04 Jens Granseuer * plugins/screensaver/gsd-screensaver-manager.c: (gsd_screensaver_manager_start): don't crash when running the screensaver fails. The plugin relies on the GError it passes always being filled in if we couldn't start the module, so set it up properly in those cases (bug #514385) 2008-02-04 Luca Ferretti reviewed by: Jens Granseuer * data/apps_gnome_settings_daemon_default_editor.schemas.in: * data/apps_gnome_settings_daemon_keybindings.schemas.in: * data/apps_gnome_settings_daemon_screensaver.schemas.in: * data/desktop_gnome_font_rendering.schemas.in: * data/gnome-settings-daemon.schemas.in: Review short and long descriptions for GConf keys, bug #514047. 2008-02-02 Jens Granseuer * src/Makefile.am: remove duplicate CFLAGS (and NULL) 2008-02-01 Christian Persch * configure.ac: Install the settings plugin to $(libdir)/gnome-settings-daemon-2.0. Fixes install with libdir == libexecdir, bug #504203. 2008-02-01 Christian Persch Bug #513246. * acinclude.m4: * configure.ac: * plugins/a11y-keyboard/Makefile.am: * plugins/background/Makefile.am: * plugins/clipboard/Makefile.am: * plugins/default-editor/Makefile.am: * plugins/dummy/Makefile.am: * plugins/font/Makefile.am: * plugins/keybindings/Makefile.am: * plugins/keyboard/Makefile.am: * plugins/media-keys/Makefile.am: * plugins/media-keys/actions/Makefile.am: * plugins/mouse/Makefile.am: * plugins/screensaver/Makefile.am: * plugins/sound/Makefile.am: * plugins/typing-break/Makefile.am: * plugins/xrandr/Makefile.am: * plugins/xrdb/Makefile.am: * plugins/xsettings/Makefile.am: Use a flat directory instead of a directory hierarchy to install the plugins into. Install data files under $(pkgdatadir), not under $(libdir). * src/Makefile.am: * src/gnome-settings-plugins-engine.c: (gnome_settings_plugin_info_free), (gnome_settings_plugins_engine_load), (gnome_settings_plugins_engine_load_file), (gnome_settings_plugins_engine_load_dir): Don't scan the plugins directory recursively. Use GSlice for the plugin info struct. ==== 2.21.90.2 ==== 2008-01-30 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.21.90.2. 2008-01-30 Gabor Kelemen * data/apps_gnome_settings_daemon_keybindings.schemas.in: Change E-mail schema's descriptions to be more verbose and sensible. Fix #512766. 2008-01-30 Christian Persch * configure.ac: * plugins/a11y-keyboard/Makefile.am: * plugins/a11y-keyboard/a11y-keyboard.gnome-settings-plugin.desktop .in: * plugins/background/Makefile.am: * plugins/background/background.gnome-settings-plugin.desktop.in: * plugins/clipboard/Makefile.am: * plugins/clipboard/clipboard.gnome-settings-plugin.desktop.in: * plugins/default-editor/Makefile.am: * plugins/default-editor/default-editor.gnome-settings-plugin.deskt op.in: * plugins/dummy/Makefile.am: * plugins/dummy/dummy.gnome-settings-plugin.desktop.in: * plugins/font/Makefile.am: * plugins/font/font.gnome-settings-plugin.desktop.in: * plugins/keybindings/Makefile.am: * plugins/keybindings/keybindings.gnome-settings-plugin.desktop.in: * plugins/keyboard/Makefile.am: * plugins/keyboard/keyboard.gnome-settings-plugin.desktop.in: * plugins/media-keys/Makefile.am: * plugins/media-keys/media-keys.gnome-settings-plugin.desktop.in: * plugins/mouse/Makefile.am: * plugins/mouse/mouse.gnome-settings-plugin.desktop.in: * plugins/screensaver/Makefile.am: * plugins/screensaver/screensaver.gnome-settings-plugin.desktop.in: * plugins/sound/Makefile.am: * plugins/sound/libsounds/Makefile.am: * plugins/sound/sound.gnome-settings-plugin.desktop.in: * plugins/typing-break/Makefile.am: * plugins/typing-break/typing-break.gnome-settings-plugin.desktop.in: * plugins/xrandr/Makefile.am: * plugins/xrandr/xrandr.gnome-settings-plugin.desktop.in: * plugins/xrdb/Makefile.am: * plugins/xrdb/xrdb.gnome-settings-plugin.desktop.in: * plugins/xsettings/Makefile.am: * plugins/xsettings/xsettings.gnome-settings-plugin.desktop.in: * po/POTFILES.in: No need to use weird naming of .gnome-settings-daemon.in files. Bug #512048. 2008-01-29 Rodrigo Moya * data/org.gnome.SettingsDaemon.service.in: use correct binary path. ==== 2.21.90.1 ==== 2008-01-29 Rodrigo Moya * NEWS: * configure.ac: prepare for 2.21.90.1. 2008-01-29 Rodrigo Moya * src/Makefile.am: use plain $libexecdir for g-s-d binary. ==== 2.21.90 ==== 2008-01-28 Rodrigo Moya * configure.ac: * NEWS: prepare for 2.21.90. 2008-01-28 Wouter Bolsterlee * data/Makefile.am: Suppress verbose GConf schema installation output. 2008-01-28 Wouter Bolsterlee * src/Makefile.am: Don't use weird autofu stuff to install gnome-settings-daemon into another directory, but define gsddir and gsd_PROGRAMS instead. Fixes bug #504203. 2008-01-28 Wouter Bolsterlee * data/org.gnome.SettingsDaemon.service.in: * src/Makefile.am: Hopefully allow $(libdir) to be the same directory as $(libexecdir) by installing the gnome-settings-daemon binary into a subdirectory of $(libexecdir), i.e. $(libexecdir)/gnome-settings-daemon/gnome-settings-daemon. Fixes bug #504203. 2008-01-28 Wouter Bolsterlee * src/main.c: (main): Don't leak the GnomeProgram instance. 2008-01-28 Wouter Bolsterlee * configure.ac: * src/main.c: (main): Initialize GnomeProgram to avoid critical warnings from libgnome. Fixes bug #509770. 2008-01-26 Jens Granseuer * data/gnome-settings-daemon.pc.in: DBus API has been frozen for a while now. No longer define DBUS_API_SUBJECT_TO_CHANGE 2008-01-25 Soren Sandmann * plugins/background/gsd-background-manager.c (GNOME_DESKTOP_USE_UNSTABLE_API): Define this macro before including gnome-bg.h 2008-01-25 Jens Granseuer * plugins/xsettings/gsd-xsettings-manager.c: (xft_settings_set_xresources): don't try to reference a non-existing variable (left-over cruft from the patch for bug #505470) 2008-01-25 Jens Granseuer * data/gnome-settings-daemon.schemas.in: fix typo in typing break key. Bug #510429. 2008-01-25 Jens Granseuer Patch by: * configure.ac: readd check for XFT2 that got lost in the g-s-d split. Bug #510925. 2008-01-25 Christian Persch * plugins/xsettings/gsd-xsettings-manager.c: (xft_settings_set_xresources): Use g_ascii_dtostr instead of setlocale. Bug #505470. 2008-01-25 Christian Persch * plugins/media-keys/Makefile.am: Fix build with builddir != srcdir. BUg #509142. 2008-01-24 Jens Granseuer * configure.ac: quote function names in AC_DEFUN to fix "underquoted definition" autoconf warning 2008-01-23 Kjartan Maraas * plugins/mouse/gsd-locate-pointer.c: (timeline_frame_cb), (timeline_finished_cb): Fix a couple typos that broke the build. 2008-01-22 Carlos Garnacho * plugins/mouse/gsd-locate-pointer.c: Reworked, add a more appealing animation if there's a composite manager present, also use a similar animation for the non-composite case, so most of the code is shared. * plugins/mouse/gsd-timeline.[ch]: New files, object to control the "locate pointer" animation. * plugins/mouse/Makefile.am: Added these files to build. ==== 2.21.5.2 ==== 2008-01-15 Rodrigo Moya * configure.ac: * NEWS: prepare for 2.21.5.2. 2008-01-15 Rodrigo Moya * plugins/sound/Makefile.am: * plugins/sound/libsounds/Makefile.am: use a libtool library for x86_64 warnings. * configure.ac: automake fixes for allowing long file names in tar.gz. ==== 2.21.5.1 ==== 2008-01-15 Rodrigo Moya * configure.ac: * NEWS: prepare for 2.21.5.1. ==== 2.21.5 ==== 2008-01-15 Rodrigo Moya * NEWS: prepare for 2.21.5. 2008-01-14 Rodrigo Moya * data/gnome-settings-daemon.pc.in: reverted last patch. 2008-01-14 Rodrigo Moya * data/gnome-settings-daemon.pc.in: added dbusapidir variable, for the gnome-control-center module to access the .xml DBus interfaces file. 2008-01-14 Denis Washington * plugins/xrandr/Makefile.in: This was probably commited by accident, remove it. 2008-01-14 Denis Washington * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c: Only consider /desktop/gnome/accessibility/keyboard/enable as option for enabling keyboard a11y features from the keyboard, not as global switch to turn all a11y features on/off. 2008-01-14 Denis Washington Patch from Gerd Kohlberger (bug #503547) * plugins/mouse/gsd-mouse-manager.c: Mousetweaks support. 2008-01-14 Rodrigo Moya * plugins/media-keys/gsd-media-keys-manager.c: reverted patch from bug #165343. 2007-12-24 Christian Persch * plugins/xsettings/gsd-xsettings-manager.c: Add Gtk/IMModule XSetting. Bug #504182, patch by Akira TAGOH. 2007-12-22 William Jon McCann * plugins/xsettings/gsd-xsettings-manager.c: use new setting from libgnome to make toolbar icon size setting work (bug #401030) Merge from gnome-control-center. 2007-12-22 William Jon McCann * plugins/xsettings/Makefile.am: * plugins/xsettings/gnome-xsettings-manager.c: * plugins/xsettings/gnome-xsettings-manager.h: * plugins/xsettings/gnome-xsettings-plugin.c: * plugins/xsettings/gnome-xsettings-plugin.h: * plugins/xsettings/gsd-xsettings-manager.c: * plugins/xsettings/gsd-xsettings-plugin.c: Rename files to be consistent with other plugins. 2007-12-21 William Jon McCann * plugins/background/Makefile.am: * plugins/background/background.gnome-settings-plugin.desktop.in: * plugins/background/gsd-background-manager.c: (gsd_background_manager_init): * plugins/background/test-background.c: (idle), (main): Init gnome-vfs and use the correct name in the desktop file. 2007-12-21 William Jon McCann * configure.ac: * plugins/background/gsd-background-manager.c: (nautilus_is_running), (apply_prefs), (queue_apply), (background_callback), (on_bg_changed), (gsd_background_manager_start): Merge g-c-c patch for animated backgrounds. Require gnome-desktop 2.21.4. Patch from: Soeren Sandmann 2007-12-18 William Jon McCann * configure.ac: Post release version bump ==== 2.21.4 ==== 2007-12-18 William Jon McCann * NEWS: Update for release. 2007-12-18 William Jon McCann * configure.ac: Update version number. 2007-12-18 William Jon McCann * src/gnome-settings-manager.c: (gnome_settings_manager_awake): * src/main.c: Turn off daemonizing for now since it confused D-Bus service activation. 2007-12-18 William Jon McCann * src/Makefile.am: * src/gnome-settings-manager.c: (gnome_settings_manager_awake), (register_manager), (gnome_settings_manager_class_init), (gnome_settings_manager_new): * src/gnome-settings-manager.h: * src/gnome-settings-manager.xml: Provide the awake method and install the dbus api header. 2007-12-17 William Jon McCann * plugins/background/Makefile.am: * plugins/sound/Makefile.am: Fix distcheck. 2007-12-17 William Jon McCann * plugins/Makefile.am: * plugins/a11y-keyboard/a11y-keyboard.gnome-settings-plugin.desktop .in: * plugins/a11y-keyboard/gsd-a11y-keyboard-manager.h: * plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c: (gsd_a11y_keyboard_plugin_init), (gsd_a11y_keyboard_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_a11y_keyboard_plugin_class_init): * plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.h: Add a11y keyboard plugin. 2007-12-17 William Jon McCann * configure.ac: * plugins/Makefile.am: * plugins/typing-break/Makefile.am: * plugins/typing-break/gsd-typing-break-manager.c: (register_config_callback), (typing_break_timeout), (child_watch), (setup_typing_break), (typing_break_callback), (really_setup_typing_break), (gsd_typing_break_manager_start), (gsd_typing_break_manager_stop), (gsd_typing_break_manager_set_property), (gsd_typing_break_manager_get_property), (gsd_typing_break_manager_constructor), (gsd_typing_break_manager_dispose), (gsd_typing_break_manager_class_init), (gsd_typing_break_manager_init), (gsd_typing_break_manager_finalize), (gsd_typing_break_manager_new): * plugins/typing-break/gsd-typing-break-manager.h: * plugins/typing-break/gsd-typing-break-plugin.c: (gsd_typing_break_plugin_init), (gsd_typing_break_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_typing_break_plugin_class_init): * plugins/typing-break/gsd-typing-break-plugin.h: * plugins/typing-break/typing-break.gnome-settings-plugin.desktop.in: Add typing break plugin. 2007-12-17 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/sound/Makefile.am: * plugins/sound/gsd-sound-manager.c: (start_gnome_sound), (stop_gnome_sound), (reload_foreach_cb), (apply_settings), (register_config_callback), (sound_callback), (gsd_sound_manager_start), (gsd_sound_manager_stop), (gsd_sound_manager_set_property), (gsd_sound_manager_get_property), (gsd_sound_manager_constructor), (gsd_sound_manager_dispose), (gsd_sound_manager_class_init), (gsd_sound_manager_init), (gsd_sound_manager_finalize), (gsd_sound_manager_new): * plugins/sound/gsd-sound-manager.h: * plugins/sound/gsd-sound-plugin.c: (gsd_sound_plugin_init), (gsd_sound_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_sound_plugin_class_init): * plugins/sound/gsd-sound-plugin.h: * plugins/sound/sound.gnome-settings-plugin.desktop.in: * plugins/xrandr/Makefile.in: Add sound plugin 2007-12-17 William Jon McCann * data/gnome-settings-daemon.schemas.in: Add schemas for media keys. 2007-12-17 William Jon McCann * configure.ac: * plugins/Makefile.am: * plugins/dummy/gsd-dummy-manager.c: * plugins/media-keys/Makefile.am: * plugins/media-keys/actions/Makefile.am: * plugins/media-keys/actions/acme-volume-alsa.c: (acme_volume_alsa_finalize), (acme_volume_alsa_set_mute), (acme_volume_alsa_get_mute), (acme_volume_alsa_get_volume), (acme_volume_alsa_set_volume), (acme_volume_alsa_close_real), (acme_volume_alsa_open), (acme_volume_alsa_close), (acme_volume_alsa_init), (acme_volume_alsa_class_init): * plugins/media-keys/actions/acme-volume-alsa.h: * plugins/media-keys/actions/acme-volume-dummy.c: (acme_volume_dummy_finalize), (acme_volume_dummy_set_mute), (acme_volume_dummy_get_mute), (acme_volume_dummy_get_volume), (acme_volume_dummy_set_volume), (acme_volume_dummy_init), (acme_volume_dummy_class_init), (acme_volume_dummy_get_type): * plugins/media-keys/actions/acme-volume-dummy.h: * plugins/media-keys/actions/acme-volume-gstreamer.c: (acme_volume_gstreamer_finalize), (acme_volume_gstreamer_set_mute), (update_state), (acme_volume_gstreamer_get_mute), (acme_volume_gstreamer_get_volume), (acme_volume_gstreamer_set_volume), (acme_volume_gstreamer_close_real), (_acme_set_mixer), (acme_volume_gstreamer_open), (acme_volume_gstreamer_close), (acme_volume_gstreamer_init), (acme_volume_gstreamer_class_init): * plugins/media-keys/actions/acme-volume-gstreamer.h: * plugins/media-keys/actions/acme-volume-oss.c: (acme_volume_oss_finalize), (acme_volume_oss_vol_check), (acme_volume_oss_set_mute), (acme_volume_oss_get_mute), (acme_volume_oss_get_volume), (acme_volume_oss_set_volume), (acme_volume_oss_init), (acme_volume_oss_class_init), (acme_volume_oss_mixer_check): * plugins/media-keys/actions/acme-volume-oss.h: * plugins/media-keys/actions/acme-volume.c: (acme_volume_class_init), (acme_volume_init), (acme_volume_get_volume), (acme_volume_set_volume), (acme_volume_get_mute), (acme_volume_set_mute), (acme_volume_mute_toggle), (acme_volume_new): * plugins/media-keys/actions/acme-volume.h: * plugins/media-keys/actions/acme.glade: * plugins/media-keys/actions/acme.h: * plugins/media-keys/eggaccelerators.c: (is_alt), (is_ctl), (is_modx), (is_ctrl), (is_shft), (is_shift), (is_control), (is_release), (is_meta), (is_super), (is_hyper), (is_keycode), (egg_accelerator_parse_virtual), (egg_virtual_accelerator_name), (egg_keymap_resolve_virtual_modifiers), (egg_keymap_virtualize_modifiers), (reload_modmap), (egg_keymap_get_modmap): * plugins/media-keys/eggaccelerators.h: * plugins/media-keys/gsd-marshal.list: * plugins/media-keys/gsd-media-keys-manager.c: (init_screens), (acme_error), (get_term_command), (execute), (do_sleep_action), (dialog_init), (grab_key_real), (grab_key), (is_valid_shortcut), (update_kbd_cb), (init_kbd), (dialog_show), (do_unknown_action), (do_help_action), (do_mail_action), (do_media_action), (do_www_action), (do_exit_action), (do_eject_action), (do_sound_action), (find_by_application), (find_by_time), (gsd_media_keys_manager_grab_media_player_keys), (gsd_media_keys_manager_release_media_player_keys), (gsd_media_player_key_pressed), (do_multimedia_player_action), (do_action), (acme_get_screen_from_event), (acme_filter_events), (gsd_media_keys_manager_start), (gsd_media_keys_manager_stop), (gsd_media_keys_manager_set_property), (gsd_media_keys_manager_get_property), (gsd_media_keys_manager_constructor), (gsd_media_keys_manager_dispose), (gsd_media_keys_manager_class_init), (gsd_media_keys_manager_init), (gsd_media_keys_manager_finalize), (register_manager), (gsd_media_keys_manager_new): * plugins/media-keys/gsd-media-keys-manager.h: * plugins/media-keys/gsd-media-keys-manager.xml: * plugins/media-keys/gsd-media-keys-plugin.c: (gsd_media_keys_plugin_init), (gsd_media_keys_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_media_keys_plugin_class_init): * plugins/media-keys/gsd-media-keys-plugin.h: * plugins/media-keys/gsd-media-keys-window.c: (fade_timeout), (hide_timeout), (remove_hide_timeout), (add_hide_timeout), (update_window), (volume_controls_set_visible), (window_set_icon_name), (window_set_icon_file), (action_changed), (volume_level_changed), (volume_muted_changed), (gsd_media_keys_window_set_action), (gsd_media_keys_window_set_volume_muted), (gsd_media_keys_window_set_volume_level), (curved_rectangle), (load_pixbuf), (render_eject), (draw_eject), (draw_action_eject), (draw_waves), (draw_speaker), (render_speaker), (draw_volume_boxes), (draw_action_volume), (draw_action), (on_expose_event), (gsd_media_keys_window_real_show), (gsd_media_keys_window_real_hide), (gsd_media_keys_window_class_init), (gsd_media_keys_window_is_valid), (initialize_alpha_mode), (gsd_media_keys_window_init), (gsd_media_keys_window_finalize), (gsd_media_keys_window_new): * plugins/media-keys/gsd-media-keys-window.h: * plugins/media-keys/media-keys.gnome-settings-plugin.desktop.in: * plugins/media-keys/test-media-window.c: (update_state), (test_window), (main): * plugins/xrandr/Makefile.in: Add media keys plugin. 2007-12-17 William Jon McCann * configure.ac: * data/Makefile.am: * data/apps_gnome_settings_daemon_default_editor.schemas.in: * data/apps_gnome_settings_daemon_keybindings.schemas.in: * data/apps_gnome_settings_daemon_screensaver.schemas.in: * data/desktop_gnome_font_rendering.schemas.in: * plugins/default-editor/Makefile.am: * plugins/default-editor/gsd-default-editor-manager.c: (gsd_default_editor_manager_init): * plugins/keyboard/Makefile.am: * plugins/keyboard/gsd-keyboard-manager.c: * plugins/mouse/gsd-mouse-manager.c: * plugins/screensaver/gsd-screensaver-manager.c: (gsd_screensaver_manager_start): * plugins/xrandr/Makefile.in: * plugins/xrandr/gsd-xrandr-manager.c: * plugins/xrdb/Makefile.am: Add other schemas. Fix some zero length private data. Fix some install dirs. Add libgnomekbd deps. 2007-12-17 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/screensaver/Makefile.am: * plugins/screensaver/gsd-screensaver-manager.c: (key_toggled_cb), (gsd_screensaver_manager_start), (gsd_screensaver_manager_stop), (gsd_screensaver_manager_set_property), (gsd_screensaver_manager_get_property), (gsd_screensaver_manager_constructor), (gsd_screensaver_manager_dispose), (gsd_screensaver_manager_class_init), (gsd_screensaver_manager_init), (gsd_screensaver_manager_finalize), (gsd_screensaver_manager_new): * plugins/screensaver/gsd-screensaver-manager.h: * plugins/screensaver/gsd-screensaver-plugin.c: (gsd_screensaver_plugin_init), (gsd_screensaver_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_screensaver_plugin_class_init): * plugins/screensaver/gsd-screensaver-plugin.h: * plugins/screensaver/screensaver.gnome-settings-plugin.desktop.in: Add screensaver plugin. 2007-12-17 William Jon McCann * plugins/background/Makefile.am: * plugins/clipboard/Makefile.am: * plugins/default-editor/Makefile.am: * plugins/dummy/Makefile.am: * plugins/font/Makefile.am: * plugins/keybindings/Makefile.am: * plugins/mouse/Makefile.am: * plugins/xrandr/Makefile.am: * plugins/xrandr/Makefile.in: * plugins/xrdb/Makefile.am: * plugins/xsettings/Makefile.am: Install in subdirectories 2007-12-17 William Jon McCann * plugins/keyboard/Makefile.am: * plugins/keyboard/modmap-dialog.glade: Add missing glade file. 2007-12-17 William Jon McCann * plugins/font/gsd-font-manager.c: * src/gnome-settings-plugins-engine.c: (gnome_settings_plugins_engine_load_file), (gnome_settings_plugins_engine_activate_plugin), (gnome_settings_plugins_engine_deactivate_plugin): Fix an extraneous / in gconf path. Add a dummy var to pad out private data. 2007-12-16 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/background/Makefile.am: * plugins/background/background.gnome-settings-plugin.desktop.in: * plugins/background/gsd-background-manager.c: (applier_idle), (background_callback), (gsd_background_manager_start), (gsd_background_manager_stop), (gsd_background_manager_set_property), (gsd_background_manager_get_property), (gsd_background_manager_constructor), (gsd_background_manager_dispose), (gsd_background_manager_class_init), (gsd_background_manager_init), (gsd_background_manager_finalize), (gsd_background_manager_new): * plugins/background/gsd-background-manager.h: * plugins/background/gsd-background-plugin.c: (gsd_background_plugin_init), (gsd_background_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_background_plugin_class_init): * plugins/background/gsd-background-plugin.h: Add background plugin. 2007-12-16 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/default-editor/default-editor.gnome-settings-plugin.deskt op.in: * plugins/keybindings/Makefile.am: * plugins/keybindings/eggaccelerators.c: (is_alt), (is_ctl), (is_modx), (is_ctrl), (is_shft), (is_shift), (is_control), (is_release), (is_meta), (is_super), (is_hyper), (is_keycode), (egg_accelerator_parse_virtual), (egg_virtual_accelerator_name), (egg_keymap_resolve_virtual_modifiers), (egg_keymap_virtualize_modifiers), (reload_modmap), (egg_keymap_get_modmap): * plugins/keybindings/eggaccelerators.h: * plugins/keybindings/gsd-keybindings-manager.c: (get_screens_list), (entry_get_string), (parse_binding), (compare_bindings), (bindings_get_entry), (key_already_used), (grab_key), (do_grab), (binding_register_keys), (screen_exec_display_string), (get_exec_environment), (keybindings_filter), (bindings_callback), (register_config_callback), (gsd_keybindings_manager_start), (gsd_keybindings_manager_stop), (gsd_keybindings_manager_set_property), (gsd_keybindings_manager_get_property), (gsd_keybindings_manager_constructor), (gsd_keybindings_manager_dispose), (gsd_keybindings_manager_class_init), (gsd_keybindings_manager_init), (gsd_keybindings_manager_finalize), (gsd_keybindings_manager_new): * plugins/keybindings/gsd-keybindings-manager.h: * plugins/keybindings/gsd-keybindings-plugin.c: (gsd_keybindings_plugin_init), (gsd_keybindings_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_keybindings_plugin_class_init): * plugins/keybindings/gsd-keybindings-plugin.h: * plugins/keybindings/keybindings.gnome-settings-plugin.desktop.in: * plugins/keyboard/keyboard.gnome-settings-plugin.desktop.in: * plugins/mouse/mouse.gnome-settings-plugin.desktop.in: Add keybindings plugin. 2007-12-16 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/mouse/Makefile.am: * plugins/mouse/gsd-locate-pointer.c: (locate_pointer_expose), (setup_window), (create_window), (locate_pointer_timeout), (gsd_locate_pointer): * plugins/mouse/gsd-locate-pointer.h: * plugins/mouse/gsd-mouse-manager.c: (gsd_mouse_manager_stop), (gsd_mouse_manager_set_property), (gsd_mouse_manager_get_property), (gsd_mouse_manager_constructor), (gsd_mouse_manager_dispose), (gsd_mouse_manager_class_init), (supports_xinput_devices), (configure_button_layout), (xinput_device_has_buttons), (set_xinput_devices_left_handed), (set_left_handed), (set_motion_acceleration), (set_motion_threshold), (filter), (set_locate_pointer), (mouse_callback), (register_config_callback), (gsd_mouse_manager_init), (gsd_mouse_manager_start), (gsd_mouse_manager_finalize), (gsd_mouse_manager_new): * plugins/mouse/gsd-mouse-manager.h: * plugins/mouse/gsd-mouse-plugin.c: (gsd_mouse_plugin_init), (gsd_mouse_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_mouse_plugin_class_init): * plugins/mouse/gsd-mouse-plugin.h: * plugins/mouse/mouse.gnome-settings-plugin.desktop.in: Add mouse plugin. 2007-12-16 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/keyboard/Makefile.am: * plugins/keyboard/delayed-dialog.c: (gsd_delayed_show_dialog), (delayed_show_timeout), (message_filter): * plugins/keyboard/delayed-dialog.h: * plugins/keyboard/gsd-keyboard-manager.c: (xfree86_set_keyboard_autorepeat_rate), (xkb_set_keyboard_autorepeat_rate), (gsd_keyboard_get_hostname_key), (numlock_NumLock_modifier_mask), (numlock_set_xkb_state), (numlock_gconf_state_key), (numlock_get_gconf_state), (numlock_set_gconf_state), (numlock_xkb_callback), (numlock_install_xkb_callback), (apply_settings), (register_config_callback), (gsd_keyboard_manager_start), (gsd_keyboard_manager_stop), (gsd_keyboard_manager_set_property), (gsd_keyboard_manager_get_property), (gsd_keyboard_manager_constructor), (gsd_keyboard_manager_dispose), (gsd_keyboard_manager_class_init), (gsd_keyboard_manager_init), (gsd_keyboard_manager_finalize), (gsd_keyboard_manager_new): * plugins/keyboard/gsd-keyboard-manager.h: * plugins/keyboard/gsd-keyboard-plugin.c: (gsd_keyboard_plugin_init), (gsd_keyboard_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_keyboard_plugin_class_init): * plugins/keyboard/gsd-keyboard-plugin.h: * plugins/keyboard/gsd-keyboard-xkb.c: (gsd_keyboard_log_appender), (activation_error), (apply_settings), (apply_xkb_settings), (gsd_keyboard_xkb_analyze_sysconfig), (gsd_chk_file_list), (gsd_keyboard_xkb_chk_lcl_xmm), (gsd_keyboard_xkb_set_post_activation_callback), (gsd_keyboard_xkb_evt_filter), (register_config_callback), (gsd_keyboard_xkb_init), (gsd_keyboard_xkb_load): * plugins/keyboard/gsd-keyboard-xkb.h: * plugins/keyboard/gsd-xmodmap.c: (check_button_callback), (gsd_load_modmap_files), (response_callback), (get_selected_files_func), (remove_string_from_list), (remove_button_clicked_callback), (load_button_clicked_callback), (gsd_modmap_dialog_call): * plugins/keyboard/gsd-xmodmap.h: * plugins/keyboard/keyboard.gnome-settings-plugin.desktop.in: * plugins/xrandr/Makefile.in: Add the keyboard plugin. 2007-12-16 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/default-editor/Makefile.am: * plugins/default-editor/default-editor.gnome-settings-plugin.deskt op.in: * plugins/default-editor/gsd-default-editor-manager.c: (sync_changes_cb), (register_config_callback), (vfs_change_cb), (gsd_default_editor_manager_start), (gsd_default_editor_manager_stop), (gsd_default_editor_manager_set_property), (gsd_default_editor_manager_get_property), (gsd_default_editor_manager_constructor), (gsd_default_editor_manager_dispose), (gsd_default_editor_manager_class_init), (gsd_default_editor_manager_init), (gsd_default_editor_manager_finalize), (gsd_default_editor_manager_new): * plugins/default-editor/gsd-default-editor-manager.h: * plugins/default-editor/gsd-default-editor-plugin.c: (gsd_default_editor_plugin_init), (gsd_default_editor_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_default_editor_plugin_class_init): * plugins/default-editor/gsd-default-editor-plugin.h: * plugins/font/Makefile: * plugins/font/Makefile.in: Add default editor plugin 2007-12-16 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/font/Makefile: * plugins/font/Makefile.am: * plugins/font/Makefile.in: * plugins/font/delayed-dialog.c: (gnome_settings_delayed_show_dialog), (delayed_show_timeout), (message_filter): * plugins/font/delayed-dialog.h: * plugins/font/font.gnome-settings-plugin.desktop.in: * plugins/font/gsd-font-manager.c: (write_all), (child_watch_cb), (spawn_with_input), (load_xcursor_theme), (load_cursor), (gsd_font_manager_start), (gsd_font_manager_stop), (gsd_font_manager_set_property), (gsd_font_manager_get_property), (gsd_font_manager_constructor), (gsd_font_manager_dispose), (gsd_font_manager_class_init), (gsd_font_manager_init), (gsd_font_manager_finalize), (gsd_font_manager_new): * plugins/font/gsd-font-manager.h: * plugins/font/gsd-font-plugin.c: (gsd_font_plugin_init), (gsd_font_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_font_plugin_class_init): * plugins/font/gsd-font-plugin.h: Add font plugin 2007-12-14 William Jon McCann * data/gnome-settings-daemon.schemas.in: Add schemas for clipboard and xrandr. 2007-12-14 William Jon McCann * configure.ac: * plugins/Makefile.am: * plugins/clipboard/Makefile.am: * plugins/clipboard/clipboard.gnome-settings-plugin.desktop.in: * plugins/clipboard/gsd-clipboard-manager.c: (target_data_ref), (target_data_unref), (conversion_free), (send_selection_notify), (finish_selection_request), (clipboard_bytes_per_item), (save_targets), (find_content_target), (find_content_type), (find_conversion_requestor), (get_property), (receive_incrementally), (send_incrementally), (convert_clipboard_manager), (convert_clipboard_target), (collect_incremental), (convert_clipboard), (clipboard_manager_process_event), (clipboard_manager_event_filter), (clipboard_manager_watch_cb), (gsd_clipboard_manager_start), (gsd_clipboard_manager_stop), (gsd_clipboard_manager_set_property), (gsd_clipboard_manager_get_property), (gsd_clipboard_manager_constructor), (gsd_clipboard_manager_dispose), (gsd_clipboard_manager_class_init), (gsd_clipboard_manager_init), (gsd_clipboard_manager_finalize), (gsd_clipboard_manager_new): * plugins/clipboard/gsd-clipboard-manager.h: * plugins/clipboard/gsd-clipboard-plugin.c: (gsd_clipboard_plugin_init), (gsd_clipboard_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_clipboard_plugin_class_init): * plugins/clipboard/gsd-clipboard-plugin.h: * plugins/clipboard/list.c: (list_foreach), (list_prepend), (list_free), (list_find), (list_remove), (list_length), (list_copy): * plugins/clipboard/list.h: * plugins/clipboard/xutils.c: (init_atoms), (timestamp_predicate), (get_server_time): * plugins/clipboard/xutils.h: Port over the clipboard module. 2007-12-14 William Jon McCann * configure.ac: * plugins/xrdb/Makefile.am: * plugins/xrdb/data/Editres.ad: * plugins/xrdb/data/Emacs.ad: * plugins/xrdb/data/General.ad: * plugins/xrdb/data/Makefile.am: * plugins/xrdb/data/Motif.ad: * plugins/xrdb/data/Tk.ad: * plugins/xrdb/data/Xaw.ad: Add the .ad files. 2007-12-14 William Jon McCann * configure.ac: * plugins/Makefile.am: * plugins/xrandr/Makefile.am: * plugins/xrandr/Makefile.in: * plugins/xrandr/gsd-xrandr-manager.c: (get_rotation), (get_resolution), (get_rate), (find_closest_size), (apply_settings), (gsd_xrandr_manager_start), (gsd_xrandr_manager_stop), (gsd_xrandr_manager_set_property), (gsd_xrandr_manager_get_property), (gsd_xrandr_manager_constructor), (gsd_xrandr_manager_dispose), (gsd_xrandr_manager_class_init), (gsd_xrandr_manager_init), (gsd_xrandr_manager_finalize), (gsd_xrandr_manager_new): * plugins/xrandr/gsd-xrandr-manager.h: * plugins/xrandr/gsd-xrandr-plugin.c: (gsd_xrandr_plugin_init), (gsd_xrandr_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_xrandr_plugin_class_init): * plugins/xrandr/gsd-xrandr-plugin.h: * plugins/xrandr/xrandr.gnome-settings-plugin.desktop.in: Add xrandr plugin. 2007-12-14 William Jon McCann * configure.ac: * plugins/Makefile.am: * plugins/dummy/Makefile.am: * plugins/dummy/gsd-dummy-manager.c: (gsd_dummy_manager_start), (gsd_dummy_manager_stop), (gsd_dummy_manager_set_property), (gsd_dummy_manager_get_property), (gsd_dummy_manager_constructor), (gsd_dummy_manager_dispose), (gsd_dummy_manager_class_init), (gsd_dummy_manager_init), (gsd_dummy_manager_finalize), (gsd_dummy_manager_new): * plugins/dummy/gsd-dummy-manager.h: * plugins/dummy/gsd-dummy-plugin.c: (impl_activate), (impl_deactivate), (gsd_dummy_plugin_class_init): * plugins/dummy/gsd-dummy-plugin.h: Build the dummy. 2007-12-14 William Jon McCann * configure.ac: * data/gnome-settings-daemon.schemas.in: * plugins/Makefile.am: * plugins/dummy/Makefile.am: * plugins/dummy/dummy.gnome-settings-plugin.desktop.in: * plugins/dummy/gsd-dummy-manager.c: (gsd_xrdb_manager_start), (gsd_xrdb_manager_stop), (gsd_xrdb_manager_set_property), (gsd_xrdb_manager_get_property), (gsd_xrdb_manager_constructor), (gsd_xrdb_manager_dispose), (gsd_xrdb_manager_class_init), (gsd_xrdb_manager_init), (gsd_xrdb_manager_finalize), (gsd_xrdb_manager_new): * plugins/dummy/gsd-dummy-manager.h: * plugins/dummy/gsd-dummy-plugin.c: (gsd_dummy_plugin_init), (gsd_dummy_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_dummy_plugin_class_init): * plugins/dummy/gsd-dummy-plugin.h: * plugins/xrdb/Makefile.am: * plugins/xrdb/gsd-xrdb-manager.c: (append_color_define), (color_shade), (append_theme_colors), (scan_ad_directory), (compare_basenames), (scan_for_files), (append_file), (append_xresource_file), (write_all), (child_watch_cb), (spawn_with_input), (apply_settings), (theme_changed), (gsd_xrdb_manager_start), (gsd_xrdb_manager_stop), (gsd_xrdb_manager_set_property), (gsd_xrdb_manager_get_property), (gsd_xrdb_manager_constructor), (gsd_xrdb_manager_dispose), (gsd_xrdb_manager_class_init), (gsd_xrdb_manager_init), (gsd_xrdb_manager_finalize), (gsd_xrdb_manager_new): * plugins/xrdb/gsd-xrdb-manager.h: * plugins/xrdb/gsd-xrdb-plugin.c: (gsd_xrdb_plugin_init), (gsd_xrdb_plugin_finalize), (impl_activate), (impl_deactivate), (gsd_xrdb_plugin_class_init): * plugins/xrdb/gsd-xrdb-plugin.h: * plugins/xrdb/xrdb.gnome-settings-plugin.desktop.in: * plugins/xsettings/gnome-xsettings-manager.h: Port over the xrdb module. Also add a skeleton plugin dir. 2007-12-14 William Jon McCann * MAINTAINERS: * configure.ac: * src/main.c: (get_bus_proxy), (acquire_name_on_proxy), (get_session_bus), (bus_register), (main): Grab a name on the session bus. 2007-12-14 William Jon McCann * configure.ac, etc: Initial checkin. Previously lived in gdm module. unity-settings-daemon/MAINTAINERS0000664000000000000000000000054015172222611013710 0ustar Rodrigo Moya E-mail: rodrigo at gnome-db.org Userid: rodrigo Sebastien Bacher Email: seb128 at debian.org Userid: sbacher Thomas Wood Email: thos at gnome.org Userid: thos Jens Granseuer Email: jensgr at gmx.net Userid: jensg William Jon McCann Email: mccann at jhu.edu Userid: mccann Bastien Nocera Email: hadess at hadess dot net Userid: hadess unity-settings-daemon/Makefile.am0000664000000000000000000000044315172222611014251 0ustar NULL = SUBDIRS = \ gnome-settings-daemon \ plugins \ data \ po \ tests \ $(NULL) if ENABLE_MAN SUBDIRS += man endif # Honor aclocal flags ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} EXTRA_DIST = \ MAINTAINERS \ ChangeLog \ README \ $(NULL) DISTCLEANFILES = \ $(NULL) unity-settings-daemon/NEWS0000664000000000000000000030146215172222611012721 0ustar =============== Version 3.8.6.1 =============== - New release for build failures ============= Version 3.8.6 ============= Housekeeping: - Optimise for "do nothing" when cleaning thumbnails Keyboard: - Don't set the XKB group switching option when not needed Mouse: - Fix critical warnings with touchpad settings Wacom: - Make OSD work again with newer librsvg Power: - Stop X from turning our screen off XRandR: - Prevent guint32 overflow ============= Version 3.8.5 ============= Housekeeping: - Fixed a bug that would prevent files in the Trash from being purged Mouse: - Enable edge scrolling if two-finger scroll is unavailable Power: - Fix a crash when hibernating on low power Printers: - Translate printer warnings - Code cleanup - Do more things asynchronously - Poll remote CUPS servers for notifications Screensaver: - Support KDE variant of interface - Fix a crash Updates: - Fix a crash ============= Version 3.8.4 ============= - Fix possible crasher on startup - Fix battery warning notifications not going away after plugging the laptop - Make gnome-shell's monitoring of user-added applications faster by creating the directory for them - Fix possible crash in XRandR with overlapping screens ============= Version 3.8.3 ============= Media-keys: - Fix potential crash if gnome-shell crashes while coming up - Show shell search for search button Keyboard: - Remove the input source switcher helper - Introduce a SetInputSource DBus method Updates: - Fix potential crash ============= Version 3.8.2 ============= Media-keys: - Don't show a label for "analog-output" ports Color: - Remove warning for some laptop docks - Don't try to parse temporary files we generate Power: - Fix brightness not being restored on resume on some systems - Make "Turn off screen when inactive" switch work ============= Version 3.8.1 ============= Power: - Don't change the active state when running in a VM - Fix compilation on non-Linux platforms Cursor: - Fix possible crashes on older versions of X.org Media-keys: - Fix race condition with gnome-shell on startup - Fix broken startup notifications - Fix possible crash when changing the volume - Fix crash when the shell vanishes and reappears Keyboard: - Cancel outstanding D-Bus operations when stopping - Enforce the XKB group when changing layouts - Make sure to add the XKB US layout in GDM on empty configurations Mouse: - Enable two-finger scrolling by default Printers: - Fix deprecation compile-time warnings ============= Version 3.8.0 ============= Color: - Set the default profile locale to be en_US, not EN_us Power: - Fix state problems if gnome-shell crashes or is killed within the screensaver Cursor: - Fix crash with X.org prior to 1.14, requires a matching gnome-desktop release as well - Updated translations ============== Version 3.7.92 ============== Media keys: - Remove obsolete check for XInput2 - Use the shell's D-Bus interface to show OSDs - Fix warnings on startup trying to call gnome-shell Keyboard: - Fix extra layouts being forgotten on GDM's second launch - Fix dead keys and similar features being broken in legacy applications - Avoid delay switch to IBus input source the first time around Font: - Remove reference to font schema Updates: - Fix possible crashers on exit - Updated translations ============== Version 3.7.91 ============== Media keys: - Key grabbing is now done in gnome-shell, which fixes problems with keybindings not working in certain conditions Sound: - Fix possible crashes when starting in a clean home directory Cursor: - Disable code to make it popup the On-Screen Keyboard on touchscreens ============== Version 3.7.90 ============== - Set locale and IBus envvars on startup for our children - Remove background plugin, as background handling is now done in gnome-shell A11y settings: - Import GIO instead of GTK+/GDK - Do enable toolkit accessibility, even if we don't need it, for the benefit of third-party/legacy toolkits and apps Media keys: - Add other bindings to the whitelist Cursor: - Enable the on-screen keyboard when touch is used Keyboard: - Adapt to gnome-xkb-info API change Power: - Make blanking timeouts match - Show notifications when about to suspend from idle - Wake up the display when about to logout - Adapt to new GnomeIdleMonitor API - Don't change the brightness on inactive sessions Remote Display: - Disable animations on Xvnc as well - Re-enable animations if Vino is gone Sound: - Avoid polling non-existent directories Updates: - Fix crasher when firmware updates is disabled XSettings: - propagate the remember-recent-files GSetting to XSettings Wacom: - Bump req for GDK_FULLSCREEN_ON_ALL_MONITORS =============== Version 3.7.5.1 =============== Fix keyboard shortcut handling with XI 2.3 ============= Version 3.7.5 ============= A11Y Keyboard: - Disable everything on exit if no settings changed - Remove GTK+ fallback dialogues Color: - Set the correct metadata on the auto-created EDID profile - Switching to a new account shouldn't warn Daemon: - Also apply LC_PAPER Media Keys: - Use D-Bus API to lock the screen - Use F20 for the temporary mic mute key Power: - Add way to disable the backlight helper - Avoid dead-locking with gnome-shell on startup - Avoid possible crash when shutting down quickly or at startup - Drop explicit screen locking on suspend - Fix incorrect backlight level on restore - Handle dim idle the same way as other idles - Lots of test additions - Wake up the display when unplugging the AC too Remote DIsplay: - Detect SPICE sessions as well - Monitor Vino's Connected status Screenshot: - Save to GtkRecentManager on success - Lots of test additions. Updates: - Allow the shell time to initialize before checking for offline update failures Wacom: - Use regular fullscreen window for OSD And updated translations ============= Version 3.7.4 ============= Updates: - Support notification filtering Media-keys: - Save screenshots without using gnome-screenshot - Updated design for the on-screen OSD - Show output device when changing the volume - Add OSD support for the "Battery" key on certain laptops - Add support for the microphone mute key on certain keyboards - Move sound initialisation out of the critical startup path Color: - Addition to implement new mockups in gnome-control-center Housekeeping: - Fix purging not working Keyboard: - Don't migrate ibus xkb engines Power: - Add test suite - Fix Power settings panel not picking up the updated brightness - Fix dimming of the screen not working, and don't dim when inhibited - Fix timeouts being longer than configured in some cases - Aggressively blank the screen when the shield is down - Update idle configuration when plugging or unplugging the mains - Really turn off the screen on suspend for MacBook laptops - Allow overriding VM detection with the gnome.is_vm=[01] kernel command-line parameter Wacom: - Fix problems resetting touch buttons on 64-bit systems - Allow switching modes while OSD is active XRandR: - use default-monitors-setup for autoconfiguration even after boot ============= Version 3.7.3 ============= - Add implementation for Freedesktop.org ScreenSaver inhibition API - Disable animations on slow links (VNC for example) - Remove fallback mode handling code - Disable the smartcard plugin for now Daemon: - Many plugins ordering bug fixes - Use gnome-session properties instead of libsystemd-login - Allow whitelisting plugins, to make it easier for gdm to catch up - Install all the schemas, even the ones for which the plugins aren't installed - Add a way to replace the daemon - exit gracefully if the session name is already taken Power: - Remove unused settings keys - Do not attempt to suspend, dim or blank if running inside a VM - Port to GnomeIdleMonitor from gnome-desktop - Adjust sleep timer to blank timer in some cases - Check if action is available before taking action - Hide critical battery warning when power is plugged - Fix possible race with gnome-shell on startup Sound: - Fix sound plugin never working properly Media-keys: - Use the shared libgnome-volume-control code - Support launching gnome-calculator instead of gcalctool - Add default shortcuts for the magnifier - Add repeat to the brightness keys Keyboard: - Fix build without IBus - Fix potential infinite loop due to num-lock handling - Don't print warnings when calls are cancelled - Handle keyboard shortcuts with Caps Lock for switching inputs Mouse: - Fix natural horizontal scroll XRandR: - Add new follow-lid behavior and tie gsd-power lid-close to XRandR - Avoid crasher if XRandR calls fail on startup - Fix the "rotate" button not working - Swap axes for some (non-Wacom) tablets as well Wacom: - Avoid infinite recursion with a non-Wacom display - Fix handling of Cintiq 24HD mode-switch buttons - Mode switch LED fixes for some tablets - Add OSD help window (see gnome-control-center for how to launch it) Cursor: - Only show the cursor when the mouse gets used Housekeeping: - Implement automatic purging of trash, along with a D-Bus interface for it Print-notifications: - Don't show strange notifications when printing Updates: - Fix warning on startup with PackageKit < 0.8.1 ============= Version 3.7.1 ============= Daemon: - Provide a singleton SessionManager proxy object - Ensure session registration happens before other idles - Use logind for suspending and rebooting the system - Require logind for session tracking Input: - Clarify hotplug command exit value handling - Add trackball detection Keyboard: - Add default ibus engine for Indic locales - Don't apply global settings for every keyboard Mouse: - Re-enable touchpad when mouse isn't present Power: - Fix "no devices" error path in gsd-backlight-helper - Add a watchdog to keep X's builtin screen saver disabled - Fix a number of possible crashers Wacom: - Add support for touchstrips and touchrings without a modeswitch XSettings: - Optimise xsettings changes ============= Version 3.6.1 ============= Keyboard: - Allow grabbing the Menu key - Apply XKB variants and options for each IBus engine - Don't setup legacy toolkits if IBus is missing - Add default setup for some particular languages - Convert old libgnomekbd and IBus configurations - Add support for more modifiers only combinations - Fix input switching eating the modifiers keys in some cases Mouse: - Fix "Locate Pointer" eating the Ctrl key - Fix "Locate Pointer" animation showing when the Ctrl key has been used Updates: - Never show the user a message about cancelled transactions Wacom: - Fix LEDs switching for some tablet models Housekeeping: - Fix possible crashers on exit Color: - Fix possible crashers on exit ============= Version 3.6.0 ============= Keyboard: - Create sources from the X layouts if the configuration is empty - Always do that in GDM, so system-wide layouts work - Add modifiers-only shortcuts to switch input sources ============== Version 3.5.92 ============== Keyboard: - Don't block getting the IBus global engine - Don't touch the XKB layout if no input sources were configured - Fix gtk+ IM module getting set to IBus for XKB sources Media keys: - Make "toggle brightness" work Color: - Don't warn about non-existent DMI file Power: - Fix some instances where an external screen would turn off Wacom: - Require wacom 0.6 to fix bugs with some tablets ============== Version 3.5.91 ============== Mouse: - Fix natural-scroll not working until switched off and on again Keyboard: - Don't handle IBus for fallback, it will use the same UI it always did - Hook IBus support for legacy applications Power: - Do not attempt to change the brightness of an output that was disabled - Fix idle blank and sleep timeout ============== Version 3.5.90 ============== Power: - Fix D-Bus path of the screensaver Mouse: - Add support for natural scroll for touchpads Keyboard: - Apply XKB options Wacom: - Implement the "switch monitor" combination And updated translations ============= Version 3.5.6 ============= Build: - Add optional man page - List plugin schemas as children of the main schema Updates: - Remove unused code - Avoid compilation warnings due to PackageKit API changes Mouse: - If one device was ignored, we would ignore all the devices Smartcard: - Don't try to use smartcard drivers that didn't load Keyboard: - Require ibus 1.4.99 for ibus support Wacom: - Avoid a warning at login ============= Version 3.5.5 ============= * Add test applications for a number of plugins Color: - Fix notification-related memory leaks Keyboard: - Add support for switching to IBus input methods Wacom: - Fix crasher related to screen tablets - Do not rotate "pad" devices - Apply display rotation to device that's mapped to it - Make shortcuts that require Shift work as expected - Re-apply calibration and aspect-ratio when the screen changes but don't apply it to touch devices Housekeeping: - Fix notification-related memory leaks Updates: - Remove unused settings - Remove a number of unused notifications - Don't ever live-update packages in the session - Fix a number of memory leaks - Prevent crash if a device that requires a firmware is removed before the firmware search completes ============= Version 3.5.4 ============= Wacom: - Fix crasher related to screen matching (Olivier Fourdan) Printers: - Don't block the session with unreachable printers ============= Version 3.5.3 ============= Keyboard A11y: - Don't crash when changing large print in fallback mode - Link to an existing help page Housekeeping: - Support new XDG thumbnail directory locations Keyboard: - Don't crash if LANG is empty Media-keys: - Make keyboard shortcuts work again - Use systemd to shutdown or suspend if available Mouse: - Only inhibits mouse clicks and scrolls with syndaemon Power: - End the lid-close safety timer when the lid gets opened - Update fallback status icon on icon state change - Don't leak notifications - Avoid duplicate translations - Use systemd to shutdown or suspend if available - Don't enable backlight helper if GUdev is not available Updates: - Adapt to new upstream property name - Add a notification for offline updates Wacom: - Update display mapping on monitor changes - Flag unknown devices created from fallback - Add keep aspect ratio option - Use GnomeRROutput instead of GnomeRROutputInfo - Match built-in monitor XRandr: - Explicitly set clone state variable when generating monitor configs ============= Version 3.5.2 ============= - Remove ability to D-Bus activate (Ray Strode) Media-keys: - Get proper gnome-keyring environment (Bastien Nocera) - Simplify the OSD code (Bastien) - Add keybindings to switch input sources (Rui Matos) Mouse: - Fix applying settings to newly added touchpads (Owen Taylor) - Reduce default touchpad deactivation to 1s (Nicolas Dufresne) Housekeeping: - Split out 'ingnore unix mount' code (Bastien) Keyboard: - Always apply xmodmap (Sergey V. Udaltsov) - Lots of cleanups (Bastien) - Apply XKB layouts ourselfs and stop relying on libgnomekbd (Rui Matos) Power: - Disconnect from upower signals when needed (Richard Hughes) - Add org.gnome.settings-daemon.plugins.power.lid-close-suspend-with-extrnal-monitors key to allow forcing suspend on lid close (Paolo Bonzini) Print: - Fix setting of default media size (Marek Kasik) - Don't create an unused proxy object (Matthias Clasen) - Speed up initialization (Matthias) Updates: - Automatically download updates rather than installing them (Richard) Wacom: - Disable wacom support on s390 (Dan Horák) - Disable wacom support on non-linux (Antoine Jacoutot) - Don't put touchscreens in relative mode (Timo Aaltonen) - Make tablet configuration per-machine (Bastien) Color: - Be quiet about unloadable profiles (Richard) Translations: - Catalan - Crimean Tatar - Dutch - Galician - German - Hebrew - Italian - Kannada - Norwegian bokmål - Slovenian - Swedish ============= Version 3.4.0 ============= Wacom: - Check if the "last-stylus" property has been set (Olivier Fourdan) Translations: - Simplified Chinese (zh_CN) (YunQiang Su) - Hindi (Chandan Kumar) - Belarusian (Ihar Hrachyshka) - Brazilian Portuguese (Jonh Wendell) - French (Bruno Brouard) - Hebrew (Yaron Shahrabani) - Lithuanian (Žygimantas Beručka) - Portuguese (Duarte Loreto) - Telugu (Sasi Bhushan) - Traditional Chinese (Chao-Hsiung Liao) - Vietnamese (Nguyễn Thái Ngọc Duy) - Ukranian (Daniel Korostil) ============== Version 3.3.92 ============== Color: - Apply the color profile even if the device has an invalid EDID (Richard Hughes) - Create a color device even if the device has an invalid EDID (Richard Hughes) - Don't use the username in the profile ID, it's optional and not-required (Richard Hughes) Common: - Add hint on how to set the script path (Bastien Nocera) - Fix library linkage on Mageia (Jani Välimaa) - Support explicitly setting G_MESSAGES_DEBUG (Martin Pitt) Media Keys: - Avoid hard-coded shortcuts not working (Bastien Nocera) - Call Shutdown for the logout action (Bastien Nocera) Mouse: - Stop syndaemon when settings-daemon dies (Martin Pitt) Power: - Do not emit DBus interface change signals when doing the idle dim (Richard Hughes) - Don't print a message when no backlights are detected (Richard Hughes) - Failing to clear DPMS timeouts should not be fatal (Alexandre Rostovtsev) - Fix broken abs_to_percentage() logic (Cosimo Cecchi) - Lazily connect to gnome-screensaver (Martin Pitt) - Lock the screensaver if the lid is closed and lock is enabled (Richard Hughes) - Make the idle dim time 90 seconds to match OSX (Richard Hughes) Print Notifications: - Add test tool (Lars Uebernickel) - Don't unref floating GVariant (Marek Kasik) Wacom: - Add README about configuration storage (Bastien Nocera) XRandR: - Fix the rotate display button not working (Sjoerd Simons) - List external display only before internal only (Bastien Nocera) XSettings: - Add README.xsettings about overrides (Ryan Lortie) - Add test-xsettings program (Ryan Lortie) - Add xsettings_setting_get() accessor (Ryan Lortie) - Add XSETTINGS_VARIANT_TYPE_COLOR macro (Ryan Lortie) - Always call xsettings_setting_set() (Ryan Lortie) - Don't return XSettingsResult codes (Ryan Lortie) - Introduce 'tiers' of XSettings (Ryan Lortie) - Load overrides on startup (Ryan Lortie) - Remove global 'settings' list (Ryan Lortie) - Switch manager to GLib memory functions (Ryan Lortie) - Switch to GVariant for value storage (Ryan Lortie) - Use GHashTable in the xsettings manager (Ryan Lortie) - Wire overrides into GSettings (Ryan Lortie) Translations: - Belarusian (Ihar Hrachyshka, Kasia Bondarava) - British English (Bruce Cowan) - Bulgarian (Alexander Shopov) - Catalan (Joan Duran) - Catalan (Valencian) (Carles Ferrando) - Czech (Adam Matoušek, Marek Černocký) - Finnish (Timo Jyrinki) - Galician (Fran Diéguez) - Gujarati (Sweta Kothari) - Hungarian (Gabor Kelemen) - Korean (Changwoo Ryu) - Latvian (Anita Reitere) - Norwegian bokmål (Kjartan Maraas) - Russian (Yuri Myasoedov) - Serbian (Мирослав Николић) - Slovenian (Matej Urbančič) - Traditional Chinese (Cheng-Chia Tseng) - Vietnamese (Nguyễn Thái Ngọc Duy) - Punjabi (A S Alam) - Ukranian (Daniel Korostil) ============== Version 3.3.91 ============== Color: - Fix warning with non-present devices - Make displays without EDID data use the correct device ID - Create the correct device ID for EDIDs with no text data - Fix EDID checksum generation Power: - Emit a Changed() signal when the backlight changes - Don't overflow when pressing the keyboard brightness button Media-keys: - Make Alt+Print appear as Alt+Print not Alt+SysRq Wacom: - Add support for mode switch buttons, touchrings, touchstrips, and light up the LEDs appropriately - Add support for current tool ID from Wacom driver - Fix possible crasher setting pressure curve or display area - Force touchpads to use relative mode and ignore mode changes - Fix double-event generation - Fix installation problems with libexecdir == libdir - Make monitor == -1 reset the display configuration ================ Version 3.3.90.1 ================ Build: - Fix build with --enable-systemd ============== Version 3.3.90 ============== Build: - Remove last requirement for dbus-glib - Remove use of deprecated g_thread_init() - Fix linking with -Bsymbolic Wacom: - Add tablet button listing and settings - Add display mapping Keyboard: - Fix blinking num-lock in some circumstances Color: - Set _ICC_PROFILE correctly when there is no primary device specified Power: - Fix possible crasher in backlight helper on error ============= Version 3.3.5 ============= Build: - Remove unused date & time mechanism. gnome-control-center uses a different API, provided by systemd on some systems. A11y keyboard: - Reduce the number of settings updates on startup Power: - Require a newer upower - Optionally use systemd to shutdown when power is low - Use GDBusProxy-compatible PropertiesChanged signal - Fix "
" appearing in notification popups Wacom: - Add a way to get/set the screen associated with a tablet - Don't crash when using a generic tablet - Add support for the puck and touch device types - Add support for enumerating tablet buttons Printers: - Also notify for unknown error reasons - Unify printer name usage Color: - Set the brightness of the display if it was saved as metadata in the color profile Media keys, XSettings, Updates: - Fix possible crashes on exit Housekeeping, Wacom, XSettings: - Fix memory leaks Media keys: - Add screenshot keyboard shortcuts Keyboard: - Don't save num-lock state when caps-lock changes Automounter: - Optionally use systemd to check for active seat ============= Version 3.3.4 ============= Build: - Fix distribution of a pre-processed desktop file Daemon: - Fix --debug not working - Remove gnome_settings_session_get_screen() and gnome_settings_session_get_upower_client(), as the underlying functions return singletons Color: - Fix some screen setups not being color corrected XRandR: - Better handling of docking stations and plugging of external monitors (for suspend, and turning off monitors to work as designed) Wacom: - Fix loading of the plugin - Fix GSettings read/write for per-tablet/per-styli configs - Export more tablet and stylus metadata =============== Version 3.3.3.1 =============== Wacom: - Fix referenced module name (Frederic Peters) ============= Version 3.3.3 ============= Build: - Require GTK+ 3.3.4 (for key accel parsing) - Require XI2 (for wacom support) Common: - Remove unused X key event code (Bastien) Wacom: - Lots of infrastructure buildup that I can't really summarize here (Bastien Nocera) - Rename plugin to avoid name clash with libwacom (Bastien) - Use libwacom to get tablet metadata (Bastien) - Implement per-device and per-stylus settings (Bastien) Power: - Add the vendor name to the battery recall warning (Dominique Leuenberger) (#664418) - Add automatic dimming of keyboard backlight (Alex Murray) Print: - Prevent crashes when cups sends malformed D-Bus signals (Lars Uebernickel) (#665689) XSettings: - Set GtkShellShowsAppMenu xsetting when the shell is running (Colin Walters) Translations: Hebrew Norwegian bokmål Romanian Spanish ============= Version 3.3.2 ============= Common: - Remove left-over debug (Bastien Nocera) (#660073) - Fix handling of (Bastien Nocera) - Update required gnome-desktop version (Bastien Nocera) - Return opcode when detecting XInput2 (Bastien Nocera) - Add helper to get the input device node (Bastien Nocera) - Use XInput2 to capture and match keys (Bastien Nocera) - Use GTK+ functions instead of own impl (Bastien Nocera) (#663343) - Fix small memleak (Bastien Nocera) - Allow to grab 'Print' without modifiers (Florian Müllner) (#663623) - Require gsettings-desktop-schemas 3.3.0 (Bastien Nocera) A11y keyboard: - Port to GSettings (Bastien Nocera) (#631502) Automount: - Call bind_textdomain_codeset() (Bastien Nocera) Color: - Do not load all the color devices twice at startup (Richard Hughes) - Don't assign the same device more than once at startup (Richard Hughes) - Fix a crash if ~/.local is deleted at runtime (Richard Hughes) (#660664) - Simplify gcm_profile_store_mkdir_with_parents() (Bastien Nocera) - Cancel any in-progress directory searching on plugin unload (Richard Hughes) - Do not check for directory presence sync (Richard Hughes) - Fix critical warning if the user disables the internal LCD screen (Richard Hughes) - Reset the gamma tables when the screen configuration changes (Richard Hughes) (#660164) - Unbreak loading profiles at startup (Cosimo Cecchi) (#660790) - Do not prefix the EDID profile title with 'Default' (Richard Hughes) - Set model and vendor to 'unknown' if not specified or unavailable (Richard Hughes) Daemon: - Create a reference to a GnomePnpIds object to speed up loading (Richard Hughes) Datetime: - Fix build requirements (Bastien Nocera) Media keys: - Use a GCancellable for g_bus_get calls so that they can be cancelled (Rodrigo Moya) - Don't assert if the user sets the 'button-power' action to 'shutdown' (Richard Hughes) - Don't assert if the user sets the 'button-power' action to 'nothing' (Richard Hughes) - Only ever send signals to specific apps (Bastien Nocera) - Document the MediaPlayerKeyPressed signal (Bastien Nocera) - Add some D-Bus API documentation (Bastien Nocera) - Fix OSD touchpad icon names (Bastien Nocera) (#661179) - Fix suspend button not locking the screen (Bastien Nocera) (#660267) - Fix the suspend key not working (Bastien Nocera) (#660267) - Remove unused allowed-keys entry (Bastien Nocera) - Cache the volume change event sound (Bastien Nocera) - Update for GVC API (Bastien Nocera) - Print warning for real errors (Bastien Nocera) - Apply volume on the device the key came from (Bastien Nocera) (#340720) - Add custom shortcut type (Bastien Nocera) - Implement GConf keyboard shortcuts (Bastien Nocera) (#625228) - Redraw volume OSD when not composited (Marien Zwart) (#660990) - Update for gsd-keygrab API change (Bastien Nocera) (#663343) - Move some metacity shortcuts into g-s-d (Florian Müllner) (#663623) - Port custom keybindings to GSettings (Florian Müllner) (#631502) Power: - Use a GCancellable for g_bus_get calls so that they can be cancelled (Rodrigo Moya) - Do not revert to the pre-idle brightness if idle dimming is disabled (Richard Hughes) (#660434) - Remove some unused schema for enabling the sleep-inactive actions (Richard Hughes) (#660395) - Clarify what a value of 0 is for sleep-inactive-x-timeout (Richard Hughes) - Do not sleep-on-idle by default (Richard Hughes) - Simplify hiding/showing the status icon (Bastien Nocera) - Ensure the DPMS state is 'on' at startup (Richard Hughes) (#660482) - Close low-battery notification when plugged in (Florian Müllner) (#660942) - Remove the window filter when the plugin is unloaded (Richard Hughes) - Don't crash when setting the dim timeout when using NX (Richard Hughes) (#661000) - Call XSyncInitialize() in case GTK+ wasn't compiled with XSync support (Richard Hughes) - Emit 'Changed' signal to all listeners (Gary Ching-Pang Lin) - Fix "undefined symbol: WEXITSTATUS" error (Richard Hughes) (#662020) - Make non-urgent notifications transient (Florian Müllner) (#662711) Printers: - Fix build on systems without LC_PAPER (Bastien Nocera) (#660626) - Call setlocale() (Bastien Nocera) (#660632) - Exit gsd-printer when session ends (Marek Kasik) (#660158) - Correct signature when calling PrinterAddOptionDefault (Marek Kasik) - Don't show "Not connected?" when not needed (Marek Kasik) - Unown name on the system bus when session goes idle (Marek Kasik) (#660158) - Set requesting-user-name when getting job info (Marek Kasik) - Show printer-state-reasons only when printing my jobs (Marek Kasik) - Don't allow "/" in printer name (Marek Kasik) (#661774) - Make notifications resident (Marek Kasik) - Fix a leak (Marek Kasik) Smartcard: - Remove unnecessary translations (Bastien Nocera) Xrandr: - Use a GCancellable for g_bus_get calls so that they can be cancelled (Rodrigo Moya) Xsettings: - Remove workaround to deal with g-s-d not exiting correctly (Rodrigo Moya) - Plug mem leaks (Christian Persch) (#663239) Wacom: - Fix possible crasher (Bastien Nocera) (#661170) - Set cursor devices to be in relative mode by default (Jason Gerecke) (#662977) - Add classes to manage settings and properties (Bastien Nocera) Translations: - ast (Xandru Armesto) - de (Mario Blättermann) - eo (Kristjan SCHMIDT) - es (Daniel Mustieles, Jorge González) - gl (Fran Dieguez) - lt (Algimantas Margevičius) - nb (Kjartan Maraas) - nl (Redmar, Wouter Bolsterlee) - or (Manoj Kumar Giri) - sl (Matej Urbančič) - sv (Daniel Nylander) - te (krishnababu k) - uk (Daniel Korostil) - vi (Nguyễn Thái Ngọc Duy) ============= Version 3.2.0 ============= Power: - Correctly put the screen and computer to sleep when idle (Richard Hughes) (#659066) Translations: - ca (Joan Duran, Gil Forcada) - ca@valencia (Carles Ferrando) - da (Flemming Christensen) - eu (Inaki Larranaga Murgoitio) - hu (Gabor Kelemen) - ja (OKANO Takayoshi) - ko (Changwoo Ryu) - or (Manoj Kumar Giri) - ru (Alexandre Prokoudine, Yuri Myasoedov) ============== Version 3.1.92 ============== A11Y keyboard: - Show the a11y dialogue on right-click (Bastien Nocera) (#564171) Color: - Be less chatty when creating duplicate profiles (Richard Hughes) - Do not segfault when doing fast-user-switching into a new account (Richard Hughes) (#736846) - Use a username suffix on the profile ID (Richard Hughes) (#736846) - Do not show a warning when switching to a new user account (Richard Hughes) - Use the correct profiles when fast user switching (Richard Hughes) - Fix linking (Matthias Clasen) (#659086) Common: - Add helper to list disabled devices (Bastien Nocera) - Clean up X11 library dependencies (Bastien Nocera) (#657178) - Bump colord dependency (Rodrigo Moya) Datetime: - Allow chrony to be used on Fedora (Tomas Bzatek) (#655119) - Add NTP support for SUSE variants (Vincent Untz) (#654970) GConf: - Plug some memory leaks (Rodrigo Moya) - Disconnect callbacks when cleaning up (Rodrigo Moya) Keyboard: - Remember and apply NumLock status (Bastien Nocera) (#631989) Media keys: - Don't show a level when muted (Bastien Nocera) (#644537) - Fix keyboard brightness (Alex Murray) (#658689) - Use the same "Music" mime-type as g-c-c (Bastien Nocera) - There's no Beagle anymore (Bastien Nocera) - Use gtk_show_uri() to launch nautilus (Bastien Nocera) - Clean up app launching (Bastien Nocera) (#141379) - Clean up upower req (Bastien Nocera) - Remove unused empty LIBS linkage (Bastien Nocera) - Fix compile-time warning (Bastien Nocera) - Move keyboard brightness icon here (Bastien Nocera) - Remove OSD icons (Bastien Nocera) Mouse: - Add more debug for "touchpad disabled" (Bastien Nocera) - Try harder to re-enable devices (Bastien Nocera) (#656397) Power: - Make ABS_TO_PERCENTAGE warn on invalid input (Bastien Nocera) (#657364) - Correctly check for helper exit status (Bastien Nocera) - Avoid warnings without backlights (Bastien Nocera) - Do not connect to signals if we failed to connect (Richard Hughes) - Don't crash if we try to calculate the idle state before connected to gnome-session (Richard Hughes) (#657917) - Be less chatty when optional hardware is not attached (Richard Hughes) (#658613) - Fix a critical warning when getting the session inhibit state (Richard Hughes) - Do not handle the idle state transaction when the session is not active (Richard Hughes) (#658568) - Don't fall through the switch statement when shutting down (Richard Hughes) (#659202) - Do not leak the icon when getting device status (Richard Hughes) (#659213) - Protect against a potential SIGFE (Richard Hughes) (#659205) - Do not emit multiple 'Changed' signals when recalculating (Richard Hughes) (#659204) - Do not use G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES when we want to read properties (Richard Hughes) (#659066) - Fix compilation without libcanberra-gtk (Bastien Nocera) Printers: - Use the best PPD for new printer (Marek Kasik) (#658544) - Style fixes (Bastien Nocera) Updates: - Ignore virtual mountpoints when looking for external media (Richard Hughes) (#658282) - Use the correct icons in the notifications (Richard Hughes) Translations: - de (Mario Blättermann) - en_GB (Bruce Cowan) - es (Jorge González, Daniel Mustieles) - fi (Timo Jyrinki) - fr (Bruno Brouard) - he (Yaron Shahrabani) - it (Luca Ferretti) - ja (Jiro Matsuzawa) - lt (Aurimas Černius) - lv (Rudolfs Mazurs) - pl (Piotr Drąg) - pt (Duarte Loreto) - sl (Matej Urbančič) - sr (Мирослав Николић) ============== Version 3.1.91 ============== Common: - Don't list XINPUT_LIBS twice, move X11_LIBS from LDFLAGS to LIBADD (Stefan Sauer) Color: - Ensure the 'Recalibration required' notification has a custom app name (Richard Hughes) - Fix a critical warning on startup (Richard Hughes) - Do not notify to recalibrate on every startup (Richard Hughes) Daemon: - Fix possible double-free outside gnome-session (Bastien Nocera) Gconf: - Double check stuff we add to the hash table (Rodrigo Moya) (#658055) Housekeeping: - NULL-terminate the ignore-paths array (Bastien Nocera) (#657849) Power: - Do not exit gnome-settings-daemon if upower fails to load (Richard Hughes) - Fix impossible to hit error paths (Bastien Nocera) (#657364) - Fix BRIGHTESS_STEP_AMOUNT calculation macro (Kamal Mostafa) - Do most of the work in _start () (Bastien Nocera) (#657924) - Never idle-dim the display to a higher brightness level (Richard Hughes) (#658144) Printers: - Remove redundant code (Marek Kasik) Xsettings: - Handle rgba-order key (Bastien Nocera) (#657525) - Don't poke at an empty hashtable (Bastien Nocera) (#657464) - Fix a stray brace (Owen Taylor) Translations: - be (Ihar Hrachyshka) - cz (Marek Černocký) - pt_BR (Og B. Maciel) - ta (Dr.T.Vasudevan) ============== Version 3.1.90 ============== A11Y-keyboard: - Use GIO's DBus API instead of dbus-glib's (Rodrigo Moya) Color: - Don't use uninitialized GErrors (Matthias Clasen) - Do not set an age for display and printer profiles (Richard Hughes) - Remove the ability to disable notifications (Richard Hughes) - Do not search user-icc directories if they do not exist (Richard Hughes) (#657484) Daemon: - Add Unity to OnlyShowIn value for autostart desktop file (Michael Terry) (#654919) Media keys: - Don't go up to 11 (Bastien Nocera) (#649411) Mouse: - Be more careful to avoid segfaults (Matthias Clasen) (#657462) Power: - Ensure the critical battery beep is stopped when the AC is inserted (Richard Hughes) - Ensure we lock the screen before suspending on lid close (Richard Hughes) (#655924) - Add mention of bug 652183 (Bastien Nocera) Smartcard: - Use GIO's DBus API instead of dbus-glib's (Rodrigo Moya) Updates: - Do not log a warning if the firmware-missing file does not exist (Richard Hughes) - Do not log a warning at startup if getting the upgrade list is not supported (Richard Hughes) (#657483) Translations: - bg (Alexander Shopov) - id (Andika Triwidada) - pa (A S Alam) - ta (Dr.T.Vasudevan) - zh_CN (Aron Xu) ============= Version 3.1.5 ============= A11y-keyboard: - Enable plugin by default (Rodrigo Moya) (#656287) Automount: - Link against the private profiler library (Cosimo Cecchi) - Add some missing includes (Cosimo Cecchi) - Don't ship the .in file, just the .in.in one (Bastien Nocera) - Silence two trivial -Wformat-security warnings (Richard Hughes) Color: - Do not show multiple warnings if colord is not available at runtime (Richard Hughes) - Fix a potential crash when unloading the color plugin (Richard Hughes) - Fix a potential crash if creating the per-user ICC directory fails (Richard Hughes) - Make lcms2 a hard dependency (Richard Hughes) Housekeeping: - Use new g_format_size() instead of g_format_size_for_display() (Javier Jardón) Media keys: - Don't preserve the path after filling (Cosimo Cecchi) - Remove the half pixel offset from the progressbar fill (Cosimo Cecchi) - Always round the render coordinates for media icons (Cosimo Cecchi) Power: - Add the idle actions (Richard Hughes) - Show a status icon when in fallback mode (Richard Hughes) - Respect the idle-dim-ac and idle-dim-battery configuration keys (Richard Hughes) - Add a backlight helper, as xbacklight isn't always present (Richard Hughes) - Fall back to the backlight helper if xbacklight is not available (Richard Hughes) - Fix a potential crash when unloading the power plugin (Richard Hughes) - Ensure we return the new percentage when changing the brightness (Richard Hughes) Updates: - Do not use deprecated PackageKit #defines (Richard Hughes) Wacom: - Invert TPCButton setting (Peter Hutterer) (#656372) Translations: - es (Daniel Mustieles) - fa (Arash Mousavi) - gl (Fran Dieguez) - he (Yaron Shahrabani) - ru (Yuri Kozlov) - sl (Andrej Žnidaršič) - sv (Daniel Nylander) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) ============= Version 3.1.4 ============= A11y-keyboard: - Do proper cleanup when the plugin is stopped (Rodrigo Moya) Automount: - Turn the automount plugin in a separate binary (Cosimo Cecchi) (#653521) - Fix distcheck of .desktop.in.in file (Rodrigo Moya) Common: - Fix grabbing of multimedia keys (Chris Coulson) Daemon: - Set locale environment on gnome-session as early as possible (Rodrigo Moya) (#654182) - Plug memory leak (Rodrigo Moya) Datetime: - Use friendlier wording for date & time policykit prompt (Michael Terry) (#645951) Media keys: - Add button handling code from gnome-power-manager (Richard Hughes) Power: - Add power plugin to replace g-p-m (Richard Hughes) Translations: - be (Ihar Hrachyshka) - cz (Marek Černocký) - de (Mario Blättermann) - es (Daniel Mustieles, Jorge González, Sebi Kul, Francisco Molinero) - gl (Fran Dieguez) - he (Yaron Shahrabani) - lt (Aurimas Černius) - lv (Rudolfs Mazurs) - nb (Kjartan Maraas) - pa (A S Alam) - tr (Muhammet Kara) ============= Version 3.1.3 ============= Common: - Use defines instead of variables for ranges (Bastien Nocera) - Fix function keys not being grabbed (Bastien Nocera) (#649222) - Allow the "Pause" key to be used (Bastien Nocera) (#653524) Clipboard: - Fix incremental sending from the clipboard manager (Cosimo Cecchi) (#652609) Color: - Fix a potential buffer-overflow when converting to wide text (Richard Hughes) Keyboard: - Use the same kbd layout menu labels as Gnome Shell (Jeremy Bicha) (#652836) - Add missing "Settings" to the string (Bastien Nocera) - Fix menu items actions (Bastien Nocera) Media keys: - Use constant for icon size in OSD (Bastien Nocera) - Remove progress bar borders (Bastien Nocera) (#652321) Mouse: - Check device is a touchpad before enabling/disabling it (Rodrigo Moya) Translations: - be (Ihar Hrachyshka) - es (Jorge González) - gl (Fran Diéguez) - he (Yaron Shahrabani) - nb (Kjartan Maraas) - sl (Matej Urbančič) - sr (Мирослав Николић) ============= Version 3.1.2 ============= Common: - Don't try to convert show-keyboard-leds-indicator in gnome-settings-daemon.convert (Chris Coulson) - Add touchscreen detection (Bastien Nocera) - Add X property setting helper (Bastien Nocera) - Add code to detect accelerometers (Bastien Nocera) - Add better error reporting for egg key parsing (Bastien Nocera) - Add code to allow disabling input devices (Bastien Nocera) Color: - Add new color plugin (Richard Hughes) Cursor: - Hide cursor on tablets with only a touchscreen (Bastien Nocera) (#650604) - Show the cursor again on exit (Bastien Nocera) - Fix XFixes version checking (Bastien Nocera) - Ignore PS/2 mice as well (Bastien Nocera) - Fix checking for extension pointer (Bastien Nocera) Datetime: - Fix ntp logic on Debian to include ntpdate as well as ntpd (Michael Terry) (#644821) GConf: - Add missing schema for org.gnome.settings-daemon.plugins.gconf (Rodrigo Moya) (#652200) Keybindings: - Complete update to egg key parsing change (Florian Müllner) Media keys: - Only start D-Bus when _start() is called (Bastien Nocera) - Simplify touchpad OSD (Bastien Nocera) - Hardcode the "toggle touchpad" button (Bastien Nocera) - Remove old-style OSD (Bastien Nocera) - Always use the primary monitor for display (Bastien Nocera) (#650159) - Make sound changes quiet with Alt (Bastien Nocera) (#651704) Mouse: - Use new disable/enable device code (Bastien Nocera) Orientation: - Add orientation plugin (Bastien Nocera) Updates: - Fix a string that is hard to translate (Richard Hughes) (#645749) Wacom: - Enable wacom touch key by default (Peter Hutterer) - Use property settings helper in common/ (Bastien Nocera) - Typedef the Wacom device types (Bastien Nocera) Xrandr: - Switch touchscreen rotation as wel (Bastien Nocera) - Fix small memory leak on shutdown (Bastien Nocera) - Remove the functionality to call gcm-apply when outputs change (Richard Hughes) - Remove rotation handling for wacom tablets (Bastien Nocera) Translations: - bg (Alexander Shopov) - ca@valencia (Carles Ferrando) - cz (Marek Černocký) - de (Mario Blättermann) - es (Jorge González, Daniel Mustieles) - fa (Arash Mousavi) - gl (Fran Diéguez) - he (Yaron Shahrabani) - nb (Kjartan Maraas) - pl (Piotr Drąg) - sl (Matej Urbančič) ============= Version 3.1.1 ============= Common: - Add input-helper test application (Bastien Nocera) - Fix syndaemon never getting started (Edward Sheldrake) (#648885) - Add meaningful app names to notifications from plugins (Matthias Clasen) (#648911) Datetime: - Simplify NTP handling for distros (Bastien Nocera) - Fix setting NTP on Fedora 15 (Bastien Nocera) Media keys: - Show a popup when no media player is running (Bastien Nocera) - Use symbolic icon for Eject action (Bastien Nocera) (#649523) Mouse: - Clean up error handling (Bastien Nocera) - Don't crash if mouse has no FeedbackStates (Bastien Nocera) (#649539) Updates: - Fix the interface name (Richard Hughes) - Deal with absence of gnome-session gracefully (Matthias Clasen) Xrandr: - Never use a notification for errors (Bastien Nocera) (#648303) Translations: - es (Daniel Mustieles) - he (Yaron Shahrabani) - ug (Abduxukur Abdurixit) ============= Version 3.0.3 ============= Common: - Use defines instead of variables for ranges (Bastien Nocera) - Fix function keys not being grabbed (Bastien Nocera) (#649222) - Allow the "Pause" key to be used (Bastien Nocera) (#653524) - Fix grabbing of multimedia keys (Rodrigo Moya) Wacom: - Enable wacom touch key by default (Peter Hutterer) (#651020) Translations: - bg (Alexander Shopov) - ca (Gil Forcada) - ca@valencia (Carles Ferrando) - cz (Marek Černocký) - de (Mario Blättermann) - es (Daniel Mustieles) - gl (Fran Diéguez) - pl (Piotr Drąg) - sl (Matej Urbančič) - sr (Мирослав Николић) - sv (Daniel Nylander) ============= Version 3.0.2 ============= Common: - Fix syndaemon never getting started (Edward Sheldrake) (#648885) - Fix example input device script (Bastien Nocera) - Don't try to convert show-keyboard-leds-indicator in gnome-settings-daemon.convert (Chris Coulson) Date & Time: - Fix setting NTP on Fedora 15 (Bastien Nocera) (#648556) Media keys: - Use symbolic icon for Eject action (Bastien Nocera) (#649523) Mouse: - Don't pass NULL to device_is_touchpad (Matthias Clasen) (#649214) - Clean up error handling (Bastien Nocera) - Don't crash if mouse has no FeedbackStates (Bastien Nocera) (#649539) XRandr: - Never use a notification for errors (Bastien Nocera) (#648303) Translations: - fa (Arash Mousavi) - ug (Abduxukur Abdurixit) ============= Version 3.0.1 ============= Updates: Fix firmware auto-installation Media-keys: Fix possible crash when sound device is removed Updated translations =============== Version 3.0.0.1 =============== Keyboard: Fix crash showing the keyboard layout in fallback mode Updated translations ============= Version 3.0.0 ============= Common: - Change default inactive sleep on battery to suspend (William Jon McCann) Keyboard: - Clarify actual units used for repeat rate (Bastien Nocera) (#646241) Printers: - Cancel CUPS' subscription policy (Marek Kasik) - Make CUPS' subscriptions expirable (Marek Kasik) - Remove old subscriptions (Marek Kasik) XSettings: - Try a few times to start the xsettings manager (Rodrigo Moya) (#634988) Translations: - bn (Jamil Ahmed) - ca (Jordi Serratosa) - cz (Marek Černocký) - da (Ask H. Larsen) - de (Christian Kirbach, Wolfgang Stöggl) - en_GB (Bruce Cowan) - eu (Iñaki Larrañaga Murgoitio) - he (Yaron Shahrabani) - hi (Rajesh Ranjan) - hu (Gabor Kelemen) - id (Dirgita) - ja (Takayuki KUSANO) - ko (Changwoo Ryu) - lv (Rudolfs Mazurs) - ml (Ani Peter) - nl (Wouter Bolsterlee, Hannie Dumoleyn) - pl (Piotr Drąg) - pt_BR (Djavan Fagundes) - ru (Yuri Myasoedov) - sr (Miroslav Nikolić) - sv (Daniel Nylander) - ta (Dr.T.Vasudevan) - ug (Abduxukur Abdurixit) - vi (Nguyễn Thái Ngọc Duy) - zh_CN (Aron Xu) =============== Version 2.91.93 =============== Power: - Don't suspend the computer when idle by default - Add back "interactive" option Date & Time: - Check for the correct PolicyKit action Accessibility settings: - Enable plugin by default, so that screen readers and on-screen keyboards work out-of-the-box And loads of translations =============== Version 2.91.92 =============== Common: - Update priority of a few plugins (Bastien Nocera) - gdk_display_get_device_manager() retval handling (Bastien Nocera) (#685020) - Improve CUPS detection (Saleem Abdulrasool) (#644063) - Make sure G_LOG_DOMAIN is set to the plugin name for each plugin (Richard Hughes) - Make sure we mop up stray idle handlers (Bastien Nocera) - Simplify input helper (Bastien Nocera) - Launch a custom script on input devices (Peter Hutterer) (#635486) Daemon: - Fix possible crasher on exit (Bastien Nocera) (#639347) Media keys: - Update gvc copy/paste from control-center (Bastien Nocera) - Make volume go up to 11 (Bastien Nocera) (#631030) - Simplify volume keys handling (Sjoerd Simons) (#640963) Mouse: - Fix possible memory leak (Bastien Nocera) - Implement touchpad motion settings (Bastien Nocera) (#642474) - Fix shape handling in locate-pointer (Gerd Kohlberger) (#645092) - Handle touchpad handedness changing (Bastien Nocera) - Don't apply any settings if XInput isn't present (Bastien Nocera) - Separate device dependent calls (Bastien Nocera) - Remove duplicated calls on start (Bastien Nocera) - Remove unused supports_xinput_devices() call (Bastien Nocera) - Make sure syndaemon is killed when touchpad disappears (Bastien Nocera) - Hook up input device customisation script (Bastien Nocera) - Fix double-free when handling one-button touchpad (Bastien Nocera) - Fix crash in GHashTable usage (Bastien Nocera) Power: - Set the default display off time to be same as session idle time (William Jon McCann) Updates: - g_get_real_time() returns microseconds, not seconds since the epoch (Richard Hughes) - Ensure te user gets the updates notification if it's never been shown (Richard Hughes) - Ensure the user gets notified of normal updates at the correct interval (Richard Hughes) Translations: - ar (Khaled Hosny) - de (Mario Blättermann) - el (Γιώργος Στεφανάνης) - et (Mattias Põldaru) - fr (Cyril Arnaud, Gérard Baylard, Alain Lojewski and Claude Paroz) - gl (Fran Diéguez) - he (Yaron Shahrabani) - hu (Gabor Kelemen) - lt (Gintautas Miliauskas) - lv (Rudolfs Mazurs) - pl (Piotr Drąg) - ro (Lucian Adrian Grijincu) - sl (Matej Urbančič, Andrej Žnidaršič) - sr (Miroslav Nikolić) - sv (Daniel Nylander) =============== Version 2.91.91 =============== Automount: - Fix crash when unlocking the screen saver - Don't queue volumes when session is inactive Housekeeping: - Use nautilus's D-Bus API to empty the trash Media keys: - Add magnifier in/out keybindings - Fix larger text/smaller text keybindings Mouse: - Make locate pointer feature work with GTK+ 3 Printers: - Use new CUPS D-Bus API Updates: - Use auto-download updates when possible XSettings: - Also accept .gtk-module for GTK+ modules - Don't set Xft.lcdfilter, it's broken - Use "text-scaling-factor" key instead of DPI =============== Version 2.91.90 =============== A11Y Settings: - Add new plugin (Bastien Nocera) Automount: - Look if the session is active before automounting new volumes (Cosimo Cecchi) - Disable automounting while screen is locked (Martin Pitt, Cosimo Cecchi) Background: - Stop pending fades if new ones initiated (Ray Strode) Date & Time: - Add Debian support to NTP service activation (Milan Bouchet-Valat) (#641598) - Fix gsd_datetime_check_tz_name() never working (Bastien Nocera) (#674999) Keyboard: - Update for new libgnomekbd API (Sergey V. Udaltsov) - Match shell behaviour for visibility (Bastien Nocera) - Explicitly calling gtk_widget_show_all for kbd layout (Sergey V. Udaltsov) Media keys: - Fix crash when keybindings change (Bastien Nocera) - Add more Universal Access keybindings (Bastien Nocera) (#641279) Mouse: - Use event driven mode for syndaemon (Pauli Nieminen) (#639623) - Use syndaemon -K to ignore Ctrl+C and other combos (Peter Hutterer) (#639487) Print notification: - Go back to using name in notifications (William Jon McCann) - Check that cups is recent enough (Marek Kasik) Updates: - Add an updates plugin to integrate with PackageKit (Richard Hughes) XSettings: - Fix memleak, using wrong unref function (Bastien Nocera) Translations: - ar (Khaled Hosny) - es (Daniel Mustieles, Jorge González) - gl (Fran Diéguez) - he (Yaron Shahrabani) - it (Luca Ferretti) - ko (Changwoo Ryu) - nb (Kjartan Maraas) - pa (A S Alam) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) ============== Version 2.91.9 ============== XSettings: - Initialize gtk-modules setting (Dan Winship) - Support GTK/AutoMnemonics setting (Matthias Clasen) Date & Time: - Use a single polkit action for this (Thomas Wood) Media keys: - Prevent volume underflow (Sjoerd Simons, Bastien Nocera) - Use symbolic icons for OSD (Matthias Clasen, Bastien Nocera) Keybindings: - Rename Accessibility keybindings to 'Universal Access' (William Jon McCann) - Mark Accessibility keybindings as system (William Jon McCann) Keyboard: - Don't create kbd indicators in the shell (Sergey V. Udaltsov) - Remove $GDM_KEYBOARD_LAYOUT handling (Bastien Nocera) - Fix control-center invocation (Yanko Kaneti) Housekeeping: - Fix an untranslatable string (Cosimo Cecchi) Print notification: - New plugin for print notifications (Marek Kasik) - Appearance and wording tweaks (William Jon McCann) - Translations: Arabic Estonian Galician Hebrew Italian Japanese Norwegian bokmål Simplified Chinese Spanish ============== Version 2.91.8 ============== - Connect to the right GnomeRRScreen signal ============== Version 2.91.7 ============== - Adapt to new gnome-desktop API (Giovanni Campagna) - Remove unused macros (Federico Mena Quintero) - Translations: - de (Paul Seyfert) - es (Jorge González) - et (Ivar Smolin, Mattias Põldaru) - gl (Fran Diéguez) - nb (Torstein Adolf Winterseth) - pa (A S Alam ) - sv (Daniel Nylander) - vi (Nguyễn Thái, Nguyen Vu Hung) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) ================ Version 2.91.6.2 ================ - Fix a crasher with GTK+ 2.91.7 (Cosimo Cecchi) ================ Version 2.91.6.1 ================ - Suppress warnings due to gdk_error_trap_pop (Cosimo Cecchi) - Fix build with GTK+ 2.91.7 (Cosimo Cecchi) ============== Version 2.91.6 ============== - Port to GtkStyleContext (Bastien Nocera) - Suspend by default on battery power (Colin Walters) - Timezone and NTP improvements (Bastien Nocera) - Port to GtkAppChooserButton (Cosimo Cecchi) - Port background code to GDBus (Dan Williams) - Support multiple smartcard drivers (Ray Strode) - Background plugin misc fixes (Tomas Bzatek, Owen W. Taylor) ================ Version 2.91.5.1 ================ - Handle rename of org.gnome.media-handling (Owen W. Taylor) ============== Version 2.91.5 ============== - Add automount plugin (Tomas Bzatek) - Don't pass NULL strings to g_variant_new() (Bastien Nocera) - Properly handle gnome-session EndSession signals (Cosimo Cecchi) ============== Version 2.91.4 ============== - Add Wacom configuration plugin (Peter Hutterer) - Add support for the XF86TouchpadOn/Off keys (Bastien Nocera) - Move some gnome-power-manager settings, so it can be used in the control center (Richard Hughes) - Only ever call g_bus_own_name() once for the main D-Bus name (BN) - Register with gnome-session to avoid timeouts, and transition problems on login (BN) - Fix possible warnings or crashers when _stop() is called without _start() having been completed (William Jon McCann) ============== Version 2.91.3 ============== - Remove xrdb plugin (Bastien Nocera) - Remove outdated GConf schemas (BN) - Handle a11y toggle shortcut keys in media-keys (BN) - Make volume down work when muted (BN) - Export the "cursor-blink-timeout" XSetting - Add test-system-timezone test program - Fix possible crasher in media-keys (William Jon McCann) - Make media-keys not crash when there are no listeners (BN) - Use a notification for the low space waring in housekeeping (WJMcC) - Make libnotify a hard-dependency (BN) - Add a real test application for housekeeping (BN) - Port daemon and xrandr plugin to GDBus (BN) - Fix possible warnings in keyboard plugin (BN) - Fix logout key shortcut not asking for a confirmation (BN) - Don't warn about low space when over 1GB is free (BN) ================ Version 2.91.2.1 ================ - Require a newer gnome-desktop with GSettings support for the background plugin (Tomas Bzatek) ============== Version 2.91.2 ============== - Migration to GSettings (Bastien Nocera, Rodrigo Moya, Gerd Kohlberger, Carlos García Campos) - Use MIME types for URL handlers (Rodrigo Moya) - Fix the GSD_API_VERSION definition in configure.ac (Matthias Clasen) - Update PolicyKit minimum requirement (Bastien Nocera) - Remove typing break plugin (Bastien Nocera) - Update the required version of gnome-desktop3/GTK3 (Bastien Nocera) - Require libnotify 0.6.0 (William Jon McCann) - KEY_SCROLL_METHOD is an enum not an int (Alban Browaeys) (#631963) - Don't use gdk_drawable_get_screen (Alban Browaeys) (#631931) - Fix version substitution in pkg-config file (Bastien Nocera) (#631866) - Remove status icon for monitors (Bastien Nocera) (#631995) - Make XInput a hard requirement (Bastien Nocera) - Use canberra-gtk for GTK3 (Bastien Nocera) - More network filesystems not to monitor (Josselin Mouette) (#606421) - Fix loading plugins information (Bastien Nocera) (#631933) - For media key, use the default application for audio/ogg (Rodrigo Moya) - Set priority for plugins based on settings (Bastien Nocera) - Never daemonise the "daemon" (Bastien Nocera) - Use Gdk to get events about input devices being added (Bastien Nocera) - Cleanup macro magic in plugin.h (Paolo Borelli) (#591798) - Update gnome-media cut'n'paste code (Bastien Nocera) (#612024) - Add gnome-settings-daemon man page (Joshua Cummings) (#588716) - Remove horrible xmodmap fallback code (Bastien Nocera) (#150542) - Remove outdated plugin (Bastien Nocera) - Use g_timeout_add_seconds (Bastien Nocera) (#582703) - Keyboard plugin improvements (Sergey V. Udaltsov) - Don't choke if there are old plugins laying around (William Jon McCann) - Check for touchpad before running syndaemon (Hernando Torque) (#632122) - Add icon to the "Keep settings" dialogue (Bastien Nocera) (#579021) - Add support for the enable-animation setting (Bastien Nocera) (#630535) - Export Xft.lcdfilter for OO.o's benefit (Chris Coleman) (#631924) - Remove XFree86 4.3.0 check (Bastien Nocera) (#632569) - Make fontconfig a hard dependency (Bastien Nocera) - Add GConf<->GSettings bridge plugin (Rodrigo Moya) - Show a touchpad-disabled if no touchpad (Bastien Nocera) - Make the "log out" key really do that (Bastien Nocera) - If the stored configuration fails at startup, use the fallback configurations (Gary Lin) - Add ability to hard-code media keys (Bastien Nocera) (#623223) - Use $(sysconfigdir) for .ad files, since they are settings (Rodrigo Moya) - Enable maintainer mode (Rodrigo Moya) - Don't display the gnome-settings-daemon autostart in the startup applications list (Rodrigo Moya) - Add settings key for disabling boot time configuration (Martin Pitt, Rodrigo Moya) (#631388) - Don't access free'd memory if a volume is unmounted whilst the dialog is running (Rodrigo Moya) - Port to GDBus (Bastien Nocera) - Add support for more multimedia keys (Bastien Nocera) - Handle video out keys in media-keys (Ray Strode) (#623223) - Use virtual modifier for the Windows key (Ray Strode) - Simplify the default XRandR behaviour (Bastien Nocera) (#634092) - Add middle-button-enabled key (Bastien Nocera) (#633863) - Prepare for the demise of size_request (Matthias Clasen) (#633320) - Translations: - ca (Carles Ferrando) - de (Mario Blättermann) - es (Jorge González) - gl (Fran Diéguez) - he (Yaron Shahrabani) - ja (Takayuki KUSANO) - ko (Changwoo Ryu) - nb (Kjartan Maraas) - pa (A S Alam ) ============== Version 2.91.0 ============== - Give a name to the keyboard status icon (Matthias Clasen) (#610319) - Fix include directory to match API version (Bastien Nocera) - Add daemon path to pkg-config files (Bastien Nocera) - Don't switch mouse buttons for XTest devices (Bastien Nocera) (#627084) - Remove GtkObject usage (Matthias Clasen) (#630678) - Use gtk3 draw event instead of expose-event (William Jon McCann) (#630975) - Use gdk-pixbuf header (William Jon McCann) (#630975) - Don't use GdkColormap (William Jon McCann) - Use cairo regions to set input shape (William Jon McCann) - Adapt to GnomeBG API changes (William Jon McCann) - Use an empty region to ignore events (William Jon McCann) - Don't destroy the cairo context in draw handler (William Jon McCann) - Adapt to libgnomekbd API changes (Sergey V. Udaltsov) - Translations: - ar (Khaled Hosny) - bg (Damyan Ivanov) - ca (Joan Duran) - cz (Petr Kovar) - gl (Fran Diéguez) =============== Version 2.90.1 =============== - Apply keyboard a11y settings for newly plugged keyboards - Loads of compilation fixes for GTK3 - Fix crasher when certain items are copied to the clipboard - Silent build by default Display: - Don't try to activate display configurations where all the outputs are off - Don't cycle through custom display configurations on XF86Display button press - Add logging infrastructure ================ Version 2.31.5.1 ================ - Include fixes from 2.31.4.2 - Translations: - nb (Kjartan Maraas) ============== Version 2.31.5 ============== - Depend on gnome-desktop-3.0 (Rodrigo Moya) - Translations: - es (Jorge González) - gl (Fran Diéguez) - he (Yaron Shahrabani) - sl (Matej Urbančič) ================ Version 2.31.4.2 ================ - Fix the binary name in the datetime DBus .service file (Thomas Wood) - Translations: - gl (Fran Diéguez) - he (Yaron Shahrabani) ================ Version 2.31.4.1 ================ - Fix the datetime DBus .service file (Thomas Wood) ============== Version 2.31.4 ============== - Fix build for --disable-smartcard-support (Ray Strode) (#617748) - Use gtk+-3.0 (Rodrigo Moya) - Fix launching the display configuration tool (Matthias Clasen) - Move clock service from gnome-panel (Rodrigo Moya, Thomas Wood) - Define plugindir in .pc file (Rodrigo Moya) - Translations: - et (Ivar Smolin) - lv (Rudols Mazurs) - nb (Kjartan Maraas) ============== Version 2.31.3 ============== - Fixed icon names, prefixed with kbd- (Sergey Udaltsov) - Use "show layout" dialog from libgnomekbd (Sergey Udaltsov) - Translations: - et (Ivar Smolin) - he (Yaron Shahrabani) - sl (Matej Urbančič) ============== Version 2.31.2 ============== - Fix installation of the xrandr helper binary (Jens Granseur) (#617782) - Always dist smartcard.gnome-settings-plugin (Ray Strode) (#617748) - Adjust XF86Display timestamps if they are out of order with RANDR timestamps (Chase Douglas) (#610482) - Don't install template files into the icon theme (Matthias Clasen) - Fix loading OSD icons when there's no SVG version (Bastien Nocera) (#618023) - Only check for baobob if we're about to show a dialog (Ross Burton) - Translations: - de (Mario Blättermann) - en@shaw (Thomas Thurman) - es (Jorge González) - gl (Fran Diéguez) - or (Manoj Kumar Giri) ============== Version 2.31.1 ============== - Create the directory for the system's RANDR configuration (Federico Mena Quintero) - Add the logic needed for the "Make Default" button in gnome-display-properties (Federico Mena Quintero) - Use $sysconfdir for /etc installation (Rodrigo Moya) - Replace deprecated GTK_WIDGET_STATE (Andre Klapper) - Compile with -DGSEAL_ENABLE (Andre Klapper) (#612588) - Use Layouts instead of Groups (Sergey Udaltsov) (#553108) - Add smartcard plugin (Ray Strode) - Software LED indicators (Sergey Udaltsov) (#616380) - Use LED icons instead of files (Sergey Udaltsov) - Translations: - de (Mario Blättermann) - en_GB (Philip Withnall) - es (Jorge Gonzalez) - gl (Francisco Diéguez) - mr (Sandeep Shedmake) - sk (Pavol Šimo) - sl (Matej Urbančič) - te (krishnababu k) ============== Version 2.30.1 ============== - Fix keyboard indicator displaying (Martin Pitt) (#613666) - Default to system settings for handling multiple keyboard layouts (Martin Pitt) - Introduce gconf key that allows hiding the indicator (Sergey Udaltsov) (#612240) (#613666) - Translations: - ca (Jordi Serratosa) - ca@valencia (Carles Ferrando) - crh (Reşat SABIQ) - et (Ivar Smolin) - kn (Shankar Prasad) - sl (Pavol Šimo) - th (Theppitak Karoonboonyanan) ============== Version 2.30.0 ============== - Protect XInput code by ifdefs if XInput isn't available (Daniel Macks) (#611670) - Don't play a sound when the volume doesn't change (Bastien Nocera) (#610001) - Fix linking with pedantic linkers (Bastien Nocera) (#610244) - Remove unused do_sleep_action function (Bastien Nocera) - Apply all keyboard settings to new keyboards (Bastien Nocera) (#610245) - Ensure the window is realized before we invalidate it (Richard Hughes) (#604918) - Replace "eject" spawn with GIO code (Bastien Nocera) (#580779) - Don't spawn xrdb (Martin Pitt) (#586276) - Add translator hint (Jens Granseuer) (#613647) - Disable font plugin by default (Bastien Nocera) (#613604) - Translations: - bn (Jamil Ahmed) - da (Ask H. Larsen) - et (Ivar Smolin) - eu (Inaki Larranaga Murgoitio) - he (Nikos Bakaoukas) - hu (Gabor Kelemen) - ko (Changwoo Ryu) - lt (Gintautas Miliauskas) - nl (Hannie Dumoleyn, Reinout van Schouwen) - nn (Torstein Adolf Winterseth) - pa (A S Alam) - pt (Duarte Loreto) - ro (Adi Roiban) - sl (Pavol Šimo) - sr (Miloš Popović) - uk (Maxim V. Dziumanenko) =============== Version 2.29.92 =============== - Translations: - bg (Alexander Shopov) - ca (Joan Duran) - en_GB (Bruce Cowan) - fi (Timo Jyrinki) - hu (Gabor Kelemen) - it (Luca Ferretti) - nb (Kjartan Maraas) - pt_BR (Antonio Fernandes C. Neto) - sv (Daniel Nylander) =============== Version 2.29.91 =============== - Fn-F8 should disable/enable touch points (Peter Hutterer) (#594831) - Always set the position of outputs, even if they are already turned on (Federico Mena Quintero) - Apply keyboard settings to newly plugged in devices (Federico Mena Quintero) (#610245) - Translations: - de (Jochen Skulj, Mario Blättermann) - es (Jorge González) - gl (Fran Diéguez) - ro (Lucian Adrian Grijincu) - sl (Matej Urbančič) - ta (vasudeven) - ru (Leonid Kanter) - zh_CN (Ray Wang) - zh_HK & zh_TW (Chao-Hsiung Liao) =============== Version 2.29.90 =============== - Add gthread-2.0 to required modules for the daemon (Jens Granseuer) (#608217) - Centralize the use of gnome_rr_config_apply_with_time (Federico Mena Quintero) - Translations: - et (Ivar Smolin) - sl (Matej Urbančič) ============== Version 2.29.6 ============== - Don't allow left-handed setting for single-button touchpads (Peter Hutterer) - Don't die on X servers without XKB (Matthias Clasen) (#604651) - Translations: - bg (Alexander Shopov) - bn (Jamil Ahmed) - es (Jorge González) - nb (Kjartan Maraas) - ta (vasudeven) ============== Version 2.29.5 ============== - Fix variant handling in $GDM_KEYBOARD_LAYOUT (Martin Pitt) (#596897) - Tighten check for XInput (Jens Granseuer) - Fix bluriness in level bar, and popup (Bastien Nocera) (#567249) - Remove unused variable (Bastien Nocera) (#599904) - Honour libexecdir when spawning gsd-locate-pointer (Jens Granseuer) (#599209) - Allow left-handed setting for touchpads (Peter Hutterer) - Use a rounded instead of curved rectangle (William Jon McCann) - Improve the media keys overlay design (William Jon McCann) (#596136) - Add brightness to the media-keys popup (Bastien Nocera) (#599677) - Fix for GSEAL goal (Bastien Nocera) (#599861) - Avoid volumes going over 100% (Bastien Nocera) (#600770) - Make OSD display more generic (Bastien Nocera) (#600951) - Support loading -rtl and -ltr variants of icons (Bastien Nocera) (#600984) - Relicense gsd-media-keys-window.[ch] to LGPL (Bastien Nocera) (#600986) - Hide the status icon before unreffing it (Matthias Clasen) (#601696) - Make eject behave better on OpenBSD (Jasper Lievisse Adriaanse) (#598573) - Export libexecdir in .pc file (DJ Lucas) (#596388) - Run gnome-color-manager apply program when the outputs change (Richard Hughes) - Factor out function to get keycodes from keysym names (Federico Mena Quintero) - Handle the XF86RotateWindows hotkey by rotating a laptop's display (Federico Mena Quintero) - Respond to monitor configuration changes when in charge (Matthias Clasen) (#601203) - Filter invalid layouts before looking for the index of one passed by gdm (Vincent Untz) (#585868) - Add linsysfs to list of virtual filesystems (Coleman Kane) (#604396) - Remove sleep keybindings (Bastien Nocera) (#170175) - Start an on-screen-display window (OSD) (Federico Mena Quintero) - Split the composited and non-composited code for the expose-event handler (Federico Mena Quintero) - Use a hand-drawn frame instead of a GtkBuilder frame (Federico Mena Quintero) - Using GkbdStatus for the automatic notification icon (Sergey V. Udaltsov) - Implement popup menu for the notification icon (Sergey V. Udaltsov) - Add extra API required by GsdMediaKeysWindow (Federico Mena Quintero) - Add timed exit option (William Jon McCann) - Fixes for new libxklavier (Sergey V. Udaltsov) - Translations: - ast (Xandru Armesto Fernandez) - en@shaw (Thomas Thurman) - es (Jorge González) - et (Mattias Põldaru, Ivar Smolin) - ja (Takayuki KUSANO) - nb (Kjartan Maraas) - nds (Nils-Christoph Fiedler) - ru (Leonid Kanter) - sl (Matej Urbančič) - sv (Daniel Nylander) - uk (Maxim V. Dziumanenko) - vi (Nguyễn Thái Ngọc Duy) - zh_CN (Aron Xu) ============== Version 2.28.1 ============== - Try harder to use the keyboard layout passed by gdm (Vincent Untz) - Translations: - ca (Joan Duran) - el (Kostas Papadimas) - or (Manoj Kumar Giri) - pl (Tomasz Dominikowski) - ru (Andrey Grigoriev, Alexandre Prokoudine) - sl (Matej Urbančič) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) ============== Version 2.28.0 ============== - Fix incomplete function declaration (Vincent Untz) - Don't install the dummy plugin whilst keeping the Makefile.am almost intact for copy/paste (Bastien Nocera) (#578538) - Fix Touchpad left-handed issues (Bastien Nocera) (#594617) - Add sound effect to volume key handling (Bastien Nocera) (#404683) - Remove useless custom eject icon (Bastien Nocera) - Validate xsettings GConf keys read from the configuration (Jens Granseuer) (#594821) - Fix compiler warnings (Jens Granseuer) - Translations: - as (Amitakhya Phukan) - cz (Petr Kovar) - da (Ask H. Larsen) - de (Mario Blättermann) - en_GB (Bruce Cowan) - hi (Rajesh Ranjan) - hu (Gabor Kelemen) - it (Luca Ferretti) - ja (Takayuki KUSANO) - kn (Shankar Prasad) - mai (Rajesh Ranjan) - ml (Ani) - mr (Sandeep Shedmake) - or (Manoj Kumar Giri) - pa (A S Alam ) - pl (Piotr Drąg) - ro (Adi Roiban, Dumitru Mișu Moldovan) - sr (Miloš Popović) - te (krishnababu k) - uk (Maxim V. Dziumanenko) =============== Version 2.27.92 =============== - Make 'Locate Pointer a separate process (Matthias Clasen) (#524499) - Skip button mappings only for core devices (Peter Hutterer) - Translations: - ar (Khaled Hosny) - bn (Jamil Ahmed) - bn_IN (Runa Bhattacharjee) - ca (Gil Forcada) - ca@valencia (Carles Ferrando) - et (Ivar Smolin) - eu (Inaki Larranaga Murgoitio) - gu (Sweta Kothari) - he (Yaron Shahrabani) - kn (Shankar Prasad) - lt (Gintautas Miliauskas) - nb (Kjartan Maraas) - pt (Duarte Loreto) - te (krishnababu k) - tr (Baris Cicek) =============== Version 2.27.91 =============== - Update gnome-volume-control code (Bastien Nocera) - Update cut'n'paste from gnome-media (Bastien Nocera) - Update volume control code for new API (Bastien Nocera) - Translations: - bg (Alexander Shopov) - fi (Tommi Vainikainen) - ga (Seán de Búrca) - ko (Changwoo Ryu) - pt_BR (Henrique P. Machado) =============== Version 2.27.90 =============== - Update gnome-volume-control from gnome-media (Bastien Nocera) (#589825) - Fix crash in gvc_mixer_stream_is_running() (Chris Coulson) (#590073) - Add '-k' option to syndaemon call for 'Disable touchpad while typing' (C de-Avillez) (#590588) - Low disk space warning bug-fixes (Chris Coulson) (#591153) - Translations: - br (Denis Arnaud) - es (Jorge González) - et (Ivar Smolin, Priit Laes and Mattias Põldaru) - fr (Nicolas Repentin and Claude Paroz) - gl (Antón Méixome) - nb (Kjartan Maraas) - or (Manoj Kumar Giri) - sv (Daniel Nylander) - ta (drtvasudevan) - zh_CN (Ray Wang) ============== Version 2.27.5 ============== - Only use applicable configurations for switching with the XF86Display hotkey (Federico Mena Quintero) - Only use applicable configurations when auto-configuring outputs during hotplug (Federico Mena Quintero) - Really lay out displays from left to right when using the XF86Display hotkey (Federico Mena Quintero) - For the XF86Display hotkey, preserve the cycle order when sanitizing the configurations (Federico Mena Quintero) - Remove last libglade dependency (Felix Riemann) - Improved low disk space warning (Chris Coulson) (#573980) - Fix compiler warnings (Jens Granseuer) - Translations: - es (Jorge González) - et (Ivar Smolin) - fr (Claude Paroz) - he (Yaron Sharabani) - sv (Daniel Nylander) - ta (drtvasudevan) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) ============== Version 2.27.4 ============== - Remove screensaver plugin, it's autostarted now (Matthias Clasen) - Don't take too long in RANDR D-Bus method implementation (Federico Mena Quintero) - Add support for Synaptics touchpads (Matthias Clasen) - Don't spawn more than one syncdaemon (Matthias Clasen) - Depend on gnome-desktop >= 2.26.3 (Rodrigo Moya) - Update gnome-volume-control code from master (Bastien Nocera) - Fix order of arguments to strstr (Federico Mena Quintero) - Depend on libxklavier 4.0 (Sergey V. Udaltsov) - Remove libglade dependency from media-keys and keyboard plugins (Felix Riemann) - Translations: - he (Yaron Shahrabani) - hu (Gabor Kelemen) - in_BN (Runa Bhattacharjee) - uk (Maxim V. Dziumanenko) ============== Version 2.27.3 ============== - Make the RANDR tray icon's per-monitor labels explicitly black (Federico Mena Quintero) (#556050) - Include config.h so that the notifications code in housekeeping plugin can actually be built (Jens Granseuer) (#584217) - Use "screen reader" instead of "screenreader" in schema (Gabor Kelemen) (#572911) - Lots of RANDR fixes and improvements (Federico Mena Quintero) - Nicer handling of broken XKB configuration in gconf (Sergey Udaltsov) (#585259) - Make 'locate pointer' deal with wm/cm changes (Matthias Clasen) (#585209) - Be more careful when comparing two key structs (Matthias Clasen) (#580616) - Translations: - da (Ask H. Larsen) - es (Jorge Gonzalez) - et (Ivar Smolin) - nb (Kjartan Maraas) - sv (Daniel Nylander) - ta (drtvasudevan) ============== Version 2.27.1 ============== - Use ngettext for the reset dialog (Jens Granseuer) (#575409) - Replace deprecated gtk_status_icon_set_tooltip (Thomas H.P. Andersen) (#578480) - Updated translations: - ca (Jordi Mas i Hernandez) - es (Jorge Gonzalez) - nb (Kjartan Maraas) - sl (Matej Urban) - zh_CN (Deng Xiyue) ============== Version 2.26.1 ============== - Fix crash when closing the lid on some laptops (Jens Granseuer) (#576875) - Fix crash when closing a11y notification bubble (Jens Granseuer) (#576535) (use of libnotify >= 0.4.5 highly recommended) - Fix problems with saving/restoring screen setup (Federico Mena Quintero) - Make the screen resolution confirmation dialog always appear in front of the settings window (Federico Mena Quintero) (#576006) - Increase confirmation timeout to 30 seconds to give slower devices (like projectors) time to adjust - Avoid some GConf roundtrips (Jens Granseuer) (#578539, #578542) - Build fixes (Jens Granseuer, yselkowitz@users.sourceforge.net) - Updated translations: - ar (Khaled Hosny) - as (Amitakhya Phukan) - kn (Shankar Prasad) - nb (Kjartan Maraas) - sr (Miloš Popović) - sr@latin (Miloš Popović) ============== Version 2.26.0 ============== - Make build work with -Wl,-z,defs (Christopher Taylor) (#574452) - Updated translations: - as (Amitakhya Phukan) - ca (Gil Forcada) - cs (Petr Kovar) - da (Kenneth Nielsen) - de (Mario Blättermann) - el (Kostas Papadimas) - eu (Inaki Larranaga Murgoitio) - gl (Ignacio Casal Quinteiro) - gu (Ankitkumar Patel) - he (Yair Hershkovitz) - hi (Rajesh Ranjan) - it (Luca Ferretti) - ja (Takeshi AIHANA) - lt (Gintautas Miliauskas) - ml (Ani Peter) - mr (Sandeep Shedmake) - or (Manoj Kumar Giri) - ro (Mișu Moldovan) - ru (Nickolay V. Shmyrev) - ta (I. Felix) - te (Krishnababu K) =============== Version 2.25.92 =============== - don't print warnings for disabled custom shortcuts (Jens Granseuer) - revert screen resolution change if the user closes the confirmation window using the close icon or by pressing escape (Jens Granseuer) (#571492) - add missing keys for a11y shortcut keys to GConf schemas (Jens Granseuer) (#572807) - install gnome-settings-daemon-plugin.h for custom plugin developement (Jens Granseuer) (#573610) - Updated translations: - bg (Alexander Shopov) - en_GB (Philip Withnall) - es (Jorge Gonzalez) - fi (Ilkka Tuohela) - fr (Claude Paroz) - gu (Sweta Kothari) - hu (Gabor Kelemen) - ko (Changwoo Ryu) - nl (Wouter Bolsterlee) - pl (Tomasz Dominikowski) - pt (Duarte Loreto) - pt_BR (Krix Apolinário, Vladimir Melo) - sv (Daniel Nylander) - th (Theppitak Karoonboonyanan) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) =============== Version 2.25.91 =============== - Have gnome-session restart g-s-d if it crashes (Matthias Clasen) - Add --without-libnotify to disable notifications (Nirbheek Chauchan) - Avoid warnings due to notifications on nonexisting status icons (Matthias Clasen) - Fix crash with invalid keyboard shortcuts (Jens Granseuer) - fix label for "Don't show this message again" checkbox (Luca Ferretti) (#517821) - HIG fix for button labels (Luca Ferretti) (#571819) - Don't use legacy icons for keyboard and mouse (Luca Ferretti) (#571823) - Fix alignment of the composited media window (Leo Iannacone) (#567249) - Updated translations: - ast (Mikel González) - ca (Gil Forcada) - da (Kenneth Nielsen) - es (Jorge Gonzalez) - eu (Iñaki Larrañaga Murgoitio) - ja (Takeshi AIHANA) - nl (Wouter Bolsterlee) - pl (Tomasz Dominikowski) - ro (Jani Monoses) - sv (Daniel Nylander) - vi (Clytie Siddall) =============== Version 2.25.90 =============== - Initialize thread system (Frederic Peters) (#565515) - Better support for Eject and Sleep actions on BSD (Jasper Lievisse Adriaanse) (#565472) - Spawn screensaver after a 30 second timeout instead of when idle so that it doesn't compete with other processes when the session starts (Jens Granseuer) (#564059) - Add low diskspace notification (Vincent Untz) (#557647) - Support hotkeys for a11y tools (Matthias Clasen) (#565310) - Quiet xrdb when there are duplicate rules in the .ad files (Bastien Nocera) (#566610) - Add debugging output when de/registering media players (Jens Granseuer) (#564433) - Add a new sound plugin that tells PulseAudio to drop its sample cache when the sound theme changes (Lennart Poettering) (#545386) - Don't pop up an error message when there's no randr configuration file (Federico Mena Quintero) - Ungrab keys when key-related plugins are disabled (Jens Granseuer) (#567867) - Use PulseAudio directly to change the volume (Bastien Nocera) (#567177) - Don't draw_background immediately when nautilus is disabled, GnomeBG will send a signal (Ray Strode) - Add crossfade transition when switching backgrounds (Ray Strode) (#552857) - Use XF86Explorer to launch the file manager (Bastien Nocera) - Fix possible crash when pressing Fn-F7 (Andres Freund) (#568713) - Delay drawing the background until SessionRunning (Ray Stode) - Ask for confirmation with a timeout after changing the randr configuration (Federico Mena Quintero) (#545115) - Require gnome-desktop 2.25.6 (Jen Granseuer) - Plug leaks - Build fixes - Updated translations: - es (Jorge González) - et (Mattias Põldaru) - he (Yuval Tanny) - hu (Gabor Kelemen) - it (Luca Ferretti) - ko (Changwoo Ryu) - nb (Kjartan Maraas) - pt_BR (Krix Apolinário) - sv (Daniel Nylander) - zh_CN (甘露(Gan Lu)) ============== Version 2.25.3 ============== - Add support for fn-f7 type keys (Søren Sandmann) - Use D-Bus instead of an X client mesage in the xrandr plugin, so the front-end can get error messages as well (Federico Mena Quintero) - Fix crash when the X server doesn't have the XInput extension (Jens Granseuer) (#562977) - Don't call umask (Behdad Esfahbod) (#563543) - Shut the daemon down properly when the SIGTERM signal is received or the D-Bus bus goes away (Ray Strode) - Restore AccessX bits to original values on exit, fixes sticky keys coming on when gnome-settings-daemon has exited (Ray Strode) - Use only top-level glib and gtk+ headers (Pedro Fragoso) (#563796) ============== Version 2.25.2 ============== - No need to trap XkbQueryExtension and friends errors (Jens Granseuer) (#559346) - Add some performance annotations around libxklavier calls (Behdad Esfahbod) - Start managers in idle callbacks (Behdad Esfahbod) (#559482, #559564) - Only initialize fontconfig when starting up (Behdad Esfahbod) (#559550) - Remove unnecessary X error traps (Jens Granseuer) (#559562) - Init a11y status icon only when needed (Behdad Esfahbod) (#559558) - Reshufle plugin priorities a bit (Behdad Esfhabod) - Delay constructing the GnomeBg object until we need it (Behdad Esfahbod) (#559639) - Listen for DeviceEnabled instead of DeviceAdded to be sure the mouse has been initialized (William Grant) (#559827) - Add debugging output for volume_step (Jens Granseuer) - Fork before gtk_init (Behdad Esfahbod) (#559695) - Lockdown in the keybinding plugin (Matthias Clasen) (#553434) - Trap X errors so we don't crash on X servers that don't support DevicePresence (Jens Granseuer) (#560618) - Fix handling of time = GDK_CURRENT_TIME (Jens Granseuer) (#559797) - Add bundle_loader linker flag to fix compilation on MacOS X (dmack@netspace.org) (#522673) - Grab all keycodes that match the respective keysim (Mario Limonciello) (#561275) - Fix --no-daemon (Behdad Esfahbod) - Depend on libxklavier 3.8 (Sergey Udaltsov) - Fix checks for various X libraries (Jens Granseuer) - Fix check for xklavier device discovery (Jens Granseuer) ============== Version 2.25.1 ============== - Ignore the 'activate' signal for deselected items so that the rotation setting doesn't reset when the systray menu is opened (Eric Piel) (#554951) - Don't make togglekeys_enable depend on global AccessX state (Jens Granseuer) (#555009) - Fix picking up of the GDM layout (Matthias Clasen) (#554525 and #555873) - Use printf safely (Christian Persch) (#555553) - Show the shutdown dialog when the power button is pressed (Matthias Clasen) (#556307) - Support the Gtk/ButtonImages XSetting (Matthias Clasen) (#556797) - Clean-up volume initialization (Jens Granseuer) (#552383) - Make the composited volume images more clear (Bogdan Butnaru) (#557307) - Spawn screensaver process in idle callback (Rodrigo Moya) - Remove sound plugin (Jens Granseuer) (#557806) - Replace gnome_help_display_desktop with gtk_show_uri (Jens Granseuer) (#557808) - Listen for X device changes and reconfigure the mouse if necessary (William Grant) (#549267) - Remove AM_MAINTAINER_MODE (Jens Granseuer) (#558503) - Disable xrdb plugin by default (Behdad Esfahbod) (#557807) - Improve performance logging annotations (Behdad Esfahbod) (#559162) - Cleanup font module (Behdad Esfahbod) (#559163) - Don't trap errors around grab_key (Behdad Esfahbod) (#559164) - Don't run 'mousetweaks -s' at startup (Behdad Esfahbod) (#559165) - Start fontconfig monitors, mouse and clipboard managers in idle callbacks (Behdad Esfahbod) (#559166) - Preload gconf dirs when feasible (Behdad Esfahbod) (#559167) - Wait for initialization processes to be done before spawning other processes (Behdad Esfahbod) (#559168) - Don't close stderr to not lose warnings (Behdad Esfahbod) - Use a pipe to communicate between children and parent process instead of a signal (Behdad Esfahbod) - Updated translations: - et (Priit Laes) - mk (Jovan Naumovski) - pt_BR (Leonardo Ferreira Fontenelle) - sk (Marcel Telka) ============== Version 2.24.0 ============== - Fix the fix for read-only home directories (Simon Zheng) (#530975) - Make the volume popup not crash when invoking it on any screen but the first when using a compositing manager (Jens Granseuer) (#551677) - Add GPLv2 copyright notice explicitly so that newer versions of autotools don't declare us GPLv3 (Jens Granseuer) (#551956) - Specify GTK modules to load in a GConf directory instead of the single /desktop/gnome/gtk-modules key (Jens Granseuer) (#539840) - Also allow linking the module state to other boolean keys by using a string value that is the name of the key to use (Jens Granseuer) - Made the housekeeping plugin less aggressive by default (Michael J. Chudobiak) (#552680) - Updated translations: - af (Friedel Wolff) - ar (Khaled Hosny) - bn_IN (Runa Bhattacharjee) - ca (Gil Forcada) - da (Kenneth Nielsen) - el (Kostas Papadimas) - et (Priit Laes) - he (Yair Hershkovitz) - hu (Gabor Kelemen) - it (Luca Ferretti) - kn (Shankar Prasad) - lt (Gintautas Miliauskas) - ml (Praveen Arimbrathodiyil) - mr (Sandeep Shedmake) - pl (Wadim Dziedzic) - pt_BR (Leonardo Ferreira Fontenelle) - ro (Mişu Moldovan) - ta (Tirumurthi Vasudevan) - zh_CN (Funda Wang) =============== Version 2.23.92 =============== - Try harder to use the keyboard layout passed by GDM (Matthias Clasen) (#551062) - Updated translations: - bg (Alexander Shopov) - de (Hendrik Richter) - en_GB (Philip Withnall) - ga (Seán de Búrca) - ko (Changwoo Ryu) - nl (Reinout van Schouwen) - pt (Duarte Loreto) - sv (Daniel Nylander) =============== Version 2.23.91 =============== - Removed translatable property on stock gtk-close (Claude Paroz) - Fix a constness warning (Jens Granseuer) - Fix a crash due to an incorrect signal handler definition (William Jon McCann) - Use a scale factor instead of a fixed DPI (William Jon McCann) - Use g_warning instead of g_error when setup fails so we don't abort (Jens Granseuer) (#549483) - Updated translations: - cs (Petr Kovar) - eu (Inaki Larranaga Murgoitio) - fi (Ilkka Tuohela) - fr (Claude Paroz) - ja (Takeshi AIHANA) - nb (Kjartan Maraas) - pt_BR (Leonardo Ferreira Fontenelle) - th (Theppitak Karoonboonyanan) - vi (Nguyễn Thái Ngọc Duy) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) =============== Version 2.23.90 =============== - PulseAudio check to not ouput "no" twice (Jens Granseuer) - Add status icon when a11y hotkeys are enabled, and display Universal Access preferences when it is clicked (William Jon McCann) (#526070) - Simplify libnotify check, fix fontconfig result output (Jens Granseuer) - Put the Glade file where all the others are (jens Granseuer) - Remove some unnecessary boilerplate (Jens Granseuer) - Use g_file_monitor instead of g_file_monitor_file/_directory (Jens Granseuer) (#546372) - Remove warning that isn't (Jens Granseuer) - Fixed crash in randr startup (Jens Granseuer) - Fail xrandr initialization if we couldn't start xrandr (Matthias Clasen) (#546446) - Try harder to clean up xrandr in _stop so we can enable/disable the plugin on the fly (Jens Granseuer) - For LIBSOUNDS, check for libgnomeui, not just libgnome (Federico Mena Quintero) - Add sexy labels when setting up dual monitors (Federico Mena Quintero) - Add a separator to the menu before "Configure display settings" (Federico Mena Quintero) - Use GDK to get DPI (William Jon McCann) - Updated translations: - ar (Djihed Afifi) - es (Jorge Gonzalez) - et (Priit Laes) - fi (Ilkka Tuohela) - gl (Ignacio Casal Quinteiro) - ja (Takeshi AIHANA) - he (Yair Hershkovitz) - ml (Praveen Arimbrathodiyil) - nb (Kjartan Maraas) - pt (Duarte Loreto) - pt_BR (Leonardo Ferreira Fontenelle) - th (Theppitak Karoonboonyanan) ============== Version 2.23.6 ============== - Remove libgnomeui dependency (James Sharpe) (#544347) - Bump glib dependency to 2.15 (Wouter Bolsterlee) (#544737) - Use standard icon names for the OSD (Matthias Clasen) (#544733) - Make the display notification icon configurable (Søren Sandmann) - Resolve NumLock dynamically (Jens Granseuer) (#165343) - Updated translations: - ar (Djihed Afifi) - es (Jorge Gonzalez) - gl (Ignacio Casal Quinteiro) - nb (Kjartan Maraas) - pt_BR (Leonardo Ferreira Fontenelle) ============== Version 2.23.5 ============== - New settings for event sounds (Lennart Poettering) (#539786) - Fix include path for building against uninstalled package. (Damien Carbery) (#543289) - Remove 'daemon' from the warning message (Gerd Kohlberger) (#543095) - Make more shortcuts with shift work (Jens Granseuer) (#542275) - Update RandR code to use new gnome-desktop API (Soren Sandmann) - Fix accelerator check (Jens Granseuer) (#538699) - Detect and enable PulseAudio (Colin Walters) (#533198) ============== Version 2.23.4 ============== - Check for fontconfig instead of xft2 (Behdad Esfahbod) - Send a Fontconfig/Timestamp xsettings notification whenever fontconfig configurations change (Behdad Esfahbod) (#490374) - Properly match keybindings that need Shift for resolving the keysym (Jens Granseuer, Bastien Nocera) (#536581) - If available use the esd_serverdir variable to locate the esd daemon so it can be started even if it's not in the PATH (Jens Granseuer, Brian Cameron) (#531868) - Updated translations: - ar (Djihed Afifi) - th (Theppitak Karoonboonyanan) ============== Version 2.23.3 ============== - Execute the correct action when there are multiple keyboard shortcuts with the same keycode but different keysyms (Bastien Nocera) (#530356) - Fix wallpaper handling for people running a session without nautilus (Matthias Clasen) (#531487) - Try to keep the keyboard layout from gdm (Matthias Clasen) (#531589) - Don't die when the user's home directory is read-only (Brian Cameron) (#530975) - Fix artifacts from the locate pointer animation in non-composited mode (Carlos Garnacho) (#531861) - Pass clicks to the media popup window through to the underlying window (Carlos Garnacho) (#531862) - Use new gnome-desktop background API and get rid of libbackground (William Jon McCann) - Don't eat keypresses for multimedia key events in the mouse plugin (Bastien Nocera) - Shutdown when receiving the "SessionOver" signal from gnome-session (Lucas Rocha, Jens Granseuer) (#522017) - Fix memory leaks in the font plugin (Jens Granseuer) - Move the locate pointer animation with the mouse cursor (Gerd Kohlberger) (#531665) - Fix build without GStreamer (Jens Granseuer) (#536177) - Updated translation: - ar (Djihed Afifi) - bg (Yavor Doganov) - es (Jorge Gonzalez) - gl (Ignacio Casal Quinteiro) - nb (Kjartan Maraas) - th (Theppitak Karoonboonyanan) - vi (Clytie Siddall) ================ Version 2.23.1.1 ================ - Install .desktop for gnome-settings-daemon in a standard autostart directory (Lucas Rocha) - Updated translations: - nb (Kjartan Maraas) ============== Version 2.23.1 ============== - Sound server startup based on GConf setting, even when esd is disabled (Alexey Shabalin) (#523743) - Added a new "housekeeping" plugin to set limits on the size and age of the thumbnail cache (Michael J. Chudobiak) (#523159) - Fix mismatched modifier maping between egg and GTK (Jens Granseuer) - Replace some custom functionality with stock GTK (Jens Granseuer) - Mark string for translation (Jens Granseuer) - Use G_DEFINE_TYPE instead of open-coding (Jens Granseuer) - Change data types to match glib, avoid using time_t (Jens Granseuer) - Add mapping for Gtk/Modules xsetting using GConf (Jens Granseuer) (#507386) - Set GConf keys back to false if mousetweaks is not installed (Gerd Kohlberger) (#525042) - Don't try to add grabas with invalid modifiers (Jens Granseuer) - Remove trailing newlines from messages since g_warning already takes care of those (Jens Granseuer) - Fix various leaks (Jens Granseuer) - Fix TYPE macro and remove unimplemented prototype (Lorne Applebaum) - Add a special volume subclass for better support of IBM Thinkpad hardware volume buttons (Lorne Applebaum) (#524425) - Initialize inited_ok or behaviour is undefined when xkb setup fails (Jens Granseuer) - Continued attempt at making XKB setup and error handling a bit less arcane and crufty (Jens Granseuer) - Only use the built-in default for volume_step if we get an error from GConf, not just when the value is 0 which might be what the user wants (Jens Granseuer) - Adds a "threshold" property to the AcmeVolume class that denotes the minimum percentage required to actually affect the volume (Jens Granseuer) - Don't install any listeners or callbacks when XKB is not available (Jens Granseuer) - Remove excessive key grab logging (Jens Granseuer) - Make plugins deactivation work (Jens Granseuer) - Properly null-terminate g_build_filename (Jens Granseuer) - Turn into a daemon by default and make --no-daemon work (Jens Granseuer) - DBus API has been stable for a while; don't define DBUS_API_SUBJECT_TO_CHANGE anymore (Jens Granseuer) - Drop GConf backup for xkb (Sergey Udaltsov) - Extract some functionality used by several plugins into a separate shared helper library (Jens Granseuer) (#525426) - Reset GConf keys when we can't launch the daemon (Jens Granseuer) - Updated translations: - bn_IN (Runa Bhattacharjee) - es (Jorge Gonzalez) - et (Priit Laes) - nn (Eskild Hustvedt) - sk (Marcel Telka) - te (Sunil Mohan Adapa) ============== Version 2.22.1 ============== - Fix segfault when shutting down the typing break monitor (Jens Granseuer) (#521786) - Set window type hint on the volume popup (Jens Granseuer) (#522232) - Remove unused properties from actions GUI (Jens Granseuer) - Reset opacity when removing the timeout (Jens Granseuer) (#522499) - Fix handling of child process (William Jon McCann) - Add a tool to test media keys (William Jon McCann) - Add some profiling code (William Jon McCann) - Fix compiler warnings (William Jon McCann) - Fix leaks (William Jon McCann) (#524183) - Add more stuff to the configuration summary (William Jon McCann) - Don't eat key events (Jens Granseuer) (#523676) - Apply keyboard settings on startup (Jens Granseuer) (#525440) - Make "Home" keybinding work again (Jens Granseuer) - Updated translations: - bn_IN (Runa Bhattacharjee) - et (Priit Laes) - nn (Eskild Hustvedt) - sk (Marcel Telka) - te (Sunil Mohan Adapa) - vi (Nguyễn Thái Ngọc Duy) ============== Version 2.22.0 ============== - Actually link against libXi when building with XInput support (Jens Granseuer) (#519488) - Disable debug by default (William Jon McCann) - Don't pass GError's if we're not going to use them (Jens Graseuer) - Remove obsolete settings for the removed default editor plugin (Jens Granseuer) - Updated translations: - da (Kenneth Nielsen) - el (Kostas Papadimas) - en_GB (Philip Withnall) - es (Jorge Gonzalez) - et (Priit Laes) - hu (Gabor Kelemen) - it (Luca Ferretti) - lt (Gintautas Miliauskas) - mk (Arangel Angov) - nb (Kjartan Maraas) - nl (Vincent van Adrighem) - ru (Leonid Kanter) - uk (Maxim Dziumanenko) - zh_HK (Chao-Hsiung Liao) - zh_TW (Chao-Hsiung Liao) =============== Version 2.21.92 =============== - Only print debug messages if --debug is used - Only load plugins when requested not at every start - Fixed #515340, Add a way to prioritise plugin load (William Jon McCann) - Fixed #515341, Signal when plugins finish loading (William Jon McCann) - Fixed #517259, Escape hostname for use in gconf key (Vincent Untz) - Fixed #517418, gnome-display-properties resolution change will not be used after logout or reboot (Jens Granseuer) - Fixed #518075, Sound plugin should start pulseaudio itself (Bastien Nocera) Translations: - Updated fr: Claude Paroz - Updated de: Hendrik Brandt - Updated nl: Vincent van Adrighem - Updated be@latin: Ihar Hrachyshka - Updated pt_BR: Jonh Wendell - Updated pt: Duarte Loreto - Updated ca: Gil Forcada - Updated *: Matthias Clasen - Updated oc: Yannig Marchegay - Updated sv: Daniel Nylander - Updated ja: Takeshi AIHANA - Updated cs: Petr Kovar - Updated ar: Djihed Afifi - Updated it: Luca Ferretti - Updated es: Jorge Gonzalez - Updated th: Theppitak Karoonboonyanan - Updated eu: Inaki Larranaga Murgoitio - Updated fi: bug #518255, Ilkka Tuohela - Updated gl: Ignacio Casal Quinteiro - Updated nb: Kjartan Maraas - Updated pl: Artur Flinta =============== Version 2.21.91 =============== - Use a flat directory instead of a hierarchy to install plugins into (Christian Persch) (#513246) - Don't scan the plugins directory recursively (Christian Persch) (#513246) - Install the settings plugin to a versioned directory to fix install with libdir == libexecdir (Christan Persch) (#504203) - Review short and long descriptions for GConf keys (Luca Ferretti) (#514047) - Don't crash when running the screensaver fails (Jens Granseuer) (#514385) - Rename src folder to gnome-settings-daemon (Damien Carberry, Jens Granseuer) (#511820) - Add uninstalled.pc file for building against an uninstalled copy of g-s-d (Damien Carberry, Jens Granseuer) (#511820) - Add separate checks for libbackground and use external copy (Jens Granseuer) - Use gnome_settings_daemon for the GConf path (Jens Granseuer) (#514411) - Release the Glade XML ASAP and keep track of the 2 widgets we need (Jens Granseuer) - Make sure we return a GError if initialization fails (Jens Granseuer) (#514926) - Load the XKB settings initially (Matthias Clasen) (#511771) - Fix leaks (Jens Granseuer) - Unref the GConfClient only after done with it (Jens Granseuer) - Check for xinput (Sebastien Bacher) (#514942) - Fix copy'n'paste error (Jens Granseuer) (#515426) - Declare variables at the beginning of a block to make older compilers happy (Jens Granseuer) - Add back support for defining plugin start order (Jens Granseuer) - Assign return value from g_slist_sort to the plugins list variable (Wouter Bolsterlee) (#515340) - Replace gnome_vfs usage with GIO (Rodrigo Moya) (#513990) ================= Version 2.21.90.2 ================= - Use correct binary path in DBus service file (Rodrigo Moya) - Updated translations: - sv (Daniel Nylander) ================= Version 2.21.90.1 ================= - Use plain $libexecdir for g-s-d binary (Rodrigo Moya) =============== Version 2.21.90 =============== - Add a more appealing animation for locate pointer feature if composite is available (Carlos Garnacho) - Quote function names in AC_DEFUN to fix autoconf warnings (Jens Granseuer) - Fix build with builddir != srcdir (Christian Persch) (#509142) - Use g_ascii_dtostr instead of setlocale (Christian Persch) (#505470) - Read check for XFT2 that got loast in the g-s-d split (Jens Granseuer) (#510925) - Fix typo in typing break key (Jens Granseuer) (#510429) - Define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-bg.h (Jens Granseuer) - No longer define DBUS_API_SUBJECT_TO_CHANGE (Jens Granseuer) - Initialize GnomeProgram to avoid critical warnings from libgnome (Wouter Bolsterlee) (#509770) - Hopefully allow $(libdir) to be the same directory as $(libexecdir) by installing the gnome-settings-daemon binary into a subdirectory of $(libexecdir) (Wouter Bolsterlee) (#504203) - Don't use weird autofoo stuff to install gnome-settings-daemon into another directory (Wouter Bolsterlee) (#504203) - Suppress verbose GConf schema installation output (Wouter Bolsterlee) ================ Version 2.21.5.2 ================ - Use libtool for building static libs also (Rodrigo Moya) - Automake fixes for allowing long file names (Rodrigo Moya) - Updated translations: - nb (Kjartan Maraas) ================ Version 2.21.5.1 ================ - Added translations from gnome-control-center module (Rodrigo Moya) (#509651) =============== Version 2.21.5 =============== - Support animated backgrounds (Soren Sandmann) - Init gnome-vfs and use correct name in desktop file (William Jon McCann) - Use new setting from libgnome to make toolbar icon size setting work (William Jon McCann) - Add Gtk/IMModule XSetting (Akira TAGOH) (#504182) - Reverted patch for SUPER key modifier (Rodrigo Moya) - Support mousetweaks (Gerd Kohlberger) (#503547) - Only consider /desktop/gnome/accessibility/keyboard/enable as option for enabling keyboard a11y features from the keyboard, not as global switch to turn all a11y features on/off (Denis Washington) =============== Version 2.21.4 =============== Initial development release of new gnome-settings-daemon design. unity-settings-daemon/README0000664000000000000000000000000015172222611013062 0ustar unity-settings-daemon/acinclude.m40000664000000000000000000000726015172222611014412 0ustar dnl EXTRA_COMPILE_WARNINGS dnl Turn on many useful compiler warnings dnl For now, only works on GCC AC_DEFUN([EXTRA_COMPILE_WARNINGS],[ dnl ****************************** dnl More compiler warnings dnl ****************************** AC_ARG_ENABLE(compile-warnings, AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@], [Turn on compiler warnings]),, [enable_compile_warnings="m4_default([$1],[yes])"]) warnCFLAGS= if test "x$GCC" != xyes; then enable_compile_warnings=no fi warning_flags= realsave_CFLAGS="$CFLAGS" case "$enable_compile_warnings" in no) warning_flags= ;; minimum) warning_flags="-Wall" ;; yes) warning_flags="-Wall -Wmissing-prototypes" ;; maximum|error) warning_flags="-Wall -Wmissing-prototypes -Wnested-externs -Wpointer-arith" CFLAGS="$warning_flags $CFLAGS" for option in -Wno-sign-compare; do SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $option" AC_MSG_CHECKING([whether gcc understands $option]) AC_TRY_COMPILE([], [], has_option=yes, has_option=no,) CFLAGS="$SAVE_CFLAGS" AC_MSG_RESULT($has_option) if test $has_option = yes; then warning_flags="$warning_flags $option" fi unset has_option unset SAVE_CFLAGS done unset option if test "$enable_compile_warnings" = "error" ; then warning_flags="$warning_flags -Werror" fi ;; *) AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) ;; esac CFLAGS="$realsave_CFLAGS" AC_MSG_CHECKING(what warning flags to pass to the C compiler) AC_MSG_RESULT($warning_flags) AC_ARG_ENABLE(iso-c, AC_HELP_STRING([--enable-iso-c], [Try to warn if code is not ISO C ]),, [enable_iso_c=no]) AC_MSG_CHECKING(what language compliance flags to pass to the C compiler) complCFLAGS= if test "x$enable_iso_c" != "xno"; then if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-ansi[\ \ ]*) ;; *) complCFLAGS="$complCFLAGS -ansi" ;; esac case " $CFLAGS " in *[\ \ ]-pedantic[\ \ ]*) ;; *) complCFLAGS="$complCFLAGS -pedantic" ;; esac fi fi AC_MSG_RESULT($complCFLAGS) WARN_CFLAGS="$warning_flags $complCFLAGS" AC_SUBST(WARN_CFLAGS) ]) dnl as-ac-expand.m4 0.2.0 -*- autoconf -*- dnl autostars m4 macro for expanding directories using configure's prefix dnl (C) 2003, 2004, 2005 Thomas Vander Stichele dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) dnl example: dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local AC_DEFUN([AS_AC_EXPAND], [ EXP_VAR=[$1] FROM_VAR=[$2] dnl first expand prefix and exec_prefix if necessary prefix_save=$prefix exec_prefix_save=$exec_prefix dnl if no prefix given, then use /usr/local, the default prefix if test "x$prefix" = "xNONE"; then prefix="$ac_default_prefix" fi dnl if no exec_prefix given, then use prefix if test "x$exec_prefix" = "xNONE"; then exec_prefix=$prefix fi full_var="$FROM_VAR" dnl loop until it doesn't change anymore while true; do new_full_var="`eval echo $full_var`" if test "x$new_full_var" = "x$full_var"; then break; fi full_var=$new_full_var done dnl clean up full_var=$new_full_var AC_SUBST([$1], "$full_var") dnl restore prefix and exec_prefix prefix=$prefix_save exec_prefix=$exec_prefix_save ]) unity-settings-daemon/autogen.sh0000775000000000000000000000200215172222611014207 0ustar #!/bin/sh # Run this to generate all the initial makefiles, etc. test -n "$srcdir" || srcdir=$(dirname "$0") test -n "$srcdir" || srcdir=. olddir=$(pwd) cd $srcdir (test -f configure.ac) || { echo "*** ERROR: Directory '$srcdir' does not look like the top-level project directory ***" exit 1 } # shellcheck disable=SC2016 PKG_NAME=$(autoconf --trace 'AC_INIT:$1' configure.ac) if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then echo "*** WARNING: I am going to run 'configure' with no arguments." >&2 echo "*** If you wish to pass any to it, please specify them on the" >&2 echo "*** '$0' command line." >&2 echo "" >&2 fi aclocal --install || exit 1 glib-gettextize --force --copy || exit 1 intltoolize --force --copy --automake || exit 1 autoreconf --verbose --force --install || exit 1 cd "$olddir" if [ "$NOCONFIGURE" = "" ]; then $srcdir/configure "$@" || exit 1 if [ "$1" = "--help" ]; then exit 0 else echo "Now type 'make' to compile $PKG_NAME" || exit 1 fi else echo "Skipping configure process." fi unity-settings-daemon/configure.ac0000664000000000000000000005165115172222611014512 0ustar AC_PREREQ([2.60]) AC_INIT([unity-settings-daemon], [1.0]) AC_CONFIG_SRCDIR([gnome-settings-daemon/gnome-settings-manager.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.9 tar-ustar dist-xz no-dist-gzip check-news]) AM_MAINTAINER_MODE([enable]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) m4_define([gsd_api_version_major],[1]) m4_define([gsd_api_version_minor],[0]) m4_define([gsd_api_version],[gsd_api_version_major.gsd_api_version_minor]) GSD_API_VERSION="gsd_api_version" AC_SUBST(GSD_API_VERSION) AC_STDC_HEADERS AC_PROG_CXX AM_PROG_CC_C_O AC_PROG_LIBTOOL AC_HEADER_STDC AC_SUBST(VERSION) AC_CONFIG_HEADERS([config.h]) IT_PROG_INTLTOOL([0.37.1]) GETTEXT_PACKAGE=unity-settings-daemon AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Name of default gettext domain]) AM_GLIB_GNU_GETTEXT GSD_INTLTOOL_PLUGIN_RULE='%.gnome-settings-plugin: %.gnome-settings-plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' AC_SUBST([GSD_INTLTOOL_PLUGIN_RULE]) dnl --------------------------------------------------------------------------- dnl - Dependencies dnl --------------------------------------------------------------------------- GLIB_REQUIRED_VERSION=2.35.3 GIO_REQUIRED_VERSION=${GLIB_REQUIRED_VERSION} GTK_REQUIRED_VERSION=3.7.8 GCONF_REQUIRED_VERSION=2.6.1 GNOME_DESKTOP_REQUIRED_VERSION=3.7.90 GDK_PIXBUF_REQUIRED_VERSION=2.23.0 LIBNOTIFY_REQUIRED_VERSION=0.7.3 UPOWER_GLIB_REQUIRED_VERSION=0.9.1 PA_REQUIRED_VERSION=2.0 LIBWACOM_REQUIRED_VERSION=0.7 LIBRSVG_REQUIRED_VERSION=2.36.2 UPOWER_REQUIRED_VERSION=0.9.11 IBUS_REQUIRED_VERSION=1.4.99 GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION=3.7.2.1 GSETTINGS_UNITY_SCHEMAS_REQUIRED_VERSION=0.0.1 XRANDR_REQUIRED_VERSION=1.3 XEXT_REQUIRED_VERSION=1.1 NM_REQUIRED_VERSION=1.0 EXTRA_COMPILE_WARNINGS(yes) PKG_CHECK_MODULES(SETTINGS_DAEMON, gtk+-3.0 >= $GTK_REQUIRED_VERSION gio-2.0 >= $GIO_REQUIRED_VERSION gmodule-2.0 gthread-2.0 gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION gsettings-unity-schemas >= $GSETTINGS_UNITY_SCHEMAS_REQUIRED_VERSION ) PKG_CHECK_MODULES(SETTINGS_PLUGIN, gtk+-3.0 >= $GTK_REQUIRED_VERSION gio-2.0 >= $GIO_REQUIRED_VERSION libnotify >= $LIBNOTIFY_REQUIRED_VERSION gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION gsettings-unity-schemas >= $GSETTINGS_UNITY_SCHEMAS_REQUIRED_VERSION x11 ) GSD_PLUGIN_LDFLAGS="-export_dynamic -module -avoid-version -no-undefined" AC_SUBST([GSD_PLUGIN_LDFLAGS]) AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums]) dnl ================================================================ dnl GSettings stuff dnl ================================================================ GLIB_GSETTINGS dnl --------------------------------------------------------------------------- dnl - Check for gnome-desktop dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION) dnl --------------------------------------------------------------------------- dnl - Check for LCMS2 dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(LCMS, lcms2 >= 2.2, have_new_lcms=yes, have_new_lcms=no) if test x$have_new_lcms = xyes; then AC_DEFINE(HAVE_NEW_LCMS,1,[Got new lcms2]) else PKG_CHECK_MODULES(LCMS, lcms2) fi dnl --------------------------------------------------------------------------- dnl - Check for libnotify dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED_VERSION, [have_libnotify=yes], have_libnotify=no) if test "x$have_libnotify" = xno ; then AC_MSG_ERROR([libnotify is required to build unity-settings-daemon]) fi AC_SUBST(LIBNOTIFY_CFLAGS) AC_SUBST(LIBNOTIFY_LIBS) dnl --------------------------------------------------------------------------- dnl - GUdev integration (default enabled) dnl --------------------------------------------------------------------------- GUDEV_PKG="" AC_ARG_ENABLE(gudev, AS_HELP_STRING([--disable-gudev],[Disable GUdev support (not optional on Linux platforms)]), enable_gudev=$enableval) if test x$enable_gudev != xno; then PKG_CHECK_MODULES(GUDEV, gudev-1.0, have_gudev="yes", have_gudev="no") if test "x$have_gudev" = "xyes"; then AC_DEFINE(HAVE_GUDEV, 1, [define if GUdev is available]) GUDEV_PKG="gudev-1.0" else if test x$enable_gudev = xyes; then AC_MSG_ERROR([GUdev enabled but not found]) fi fi else have_gudev=no fi AM_CONDITIONAL(HAVE_GUDEV, test x$have_gudev = xyes) dnl --------------------------------------------------------------------------- dnl - common dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(COMMON, x11 kbproto xi) dnl --------------------------------------------------------------------------- dnl - libunity-settings-daemon dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(LIBUNITY_SETTINGS_DAEMON, gtk+-3.0 >= $GTK_REQUIRED_VERSION glib-2.0 >= GLIB_REQUIRED_VERSION gio-2.0 >= $GIO_REQUIRED_VERSION gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION gsettings-unity-schemas >= $GSETTINGS_UNITY_SCHEMAS_REQUIRED_VERSION gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQUIRED_VERSION xrandr >= $XRANDR_REQUIRED_VERSION xext >= $XEXT_REQUIRED_VERSION x11) PKG_CHECK_MODULES(CHECK_GL_TEXTURE_SIZE, gl x11) dnl --------------------------------------------------------------------------- dnl - automount dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(AUTOMOUNT, x11 kbproto) dnl --------------------------------------------------------------------------- dnl - XTest dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(XTEST, x11 xtst) AC_SUBST(XTEST_CFLAGS) AC_SUBST(XTEST_LIBS) dnl --------------------------------------------------------------------------- dnl - background dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(BACKGROUND, gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQUIRED_VERSION gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION x11) dnl --------------------------------------------------------------------------- dnl - mouse dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(MOUSE, x11 xi) dnl --------------------------------------------------------------------------- dnl - cursor dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(CURSOR, xfixes gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION) dnl --------------------------------------------------------------------------- dnl - xsettings dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(XSETTINGS, fontconfig) dnl --------------------------------------------------------------------------- dnl - Keyboard plugin stuff dnl --------------------------------------------------------------------------- AC_ARG_ENABLE(ibus, AS_HELP_STRING([--disable-ibus], [Disable IBus support]), enable_ibus=$enableval, enable_ibus=yes) if test "x$enable_ibus" = "xyes" ; then IBUS_MODULE="ibus-1.0 >= $IBUS_REQUIRED_VERSION" AC_DEFINE(HAVE_IBUS, 1, [Defined if IBus support is enabled]) else IBUS_MODULE= fi AM_CONDITIONAL(HAVE_IBUS, test "x$enable_ibus" == "xyes") AC_ARG_ENABLE(fcitx, AS_HELP_STRING([--disable-fcitx], [Disable Fcitx support]), enable_fcitx=$enableval, enable_fcitx=yes) if test "x$enable_fcitx" = "xyes" ; then FCITX_MODULE="fcitx-config fcitx-gclient" AC_DEFINE(HAVE_FCITX, 1, [Defined if Fcitx support is enabled]) AC_CHECK_PROG(HAVE_GPERF, gperf, yes) if test "x$HAVE_GPERF" != "xyes" ; then AC_MSG_ERROR([gperf needed for Fcitx support]) fi else FCITX_MODULE= fi AM_CONDITIONAL(HAVE_FCITX, test "x$enable_fcitx" == "xyes") PKG_CHECK_MODULES(KEYBOARD, accountsservice xkbfile xkeyboard-config $IBUS_MODULE $FCITX_MODULE gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION) XKB_BASE=$($PKG_CONFIG --variable xkb_base xkeyboard-config) AC_SUBST(XKB_BASE) dnl --------------------------------------------------------------------------- dnl - Housekeeping plugin stuff dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(GIOUNIX, [gio-unix-2.0]) dnl --------------------------------------------------------------------------- dnl - media-keys plugin stuff dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 libnotify alsa $FCITX_MODULE]) PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= $PA_REQUIRED_VERSION]) AM_CONDITIONAL(HAVE_INTROSPECTION, false) dnl --------------------------------------------------------------------------- dnl - xrandr plugin stuff dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(XRANDR, [gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION]) dnl --------------------------------------------------------------------------- dnl - orientation plugin stuff dnl --------------------------------------------------------------------------- if test x$have_gudev != xno; then PKG_CHECK_MODULES(ORIENTATION, [gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION gudev-1.0]) fi dnl --------------------------------------------------------------------------- dnl - sound plugin stuff dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(SOUND, [libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION]) # --------------------------------------------------------------------------- # Power # --------------------------------------------------------------------------- PKG_CHECK_MODULES(POWER, upower-glib >= $UPOWER_REQUIRED_VERSION gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION $GUDEV_PKG libcanberra-gtk3 libnotify x11 xext xtst) if test x$have_gudev != xno; then PKG_CHECK_MODULES(BACKLIGHT_HELPER, glib-2.0 >= $GLIB_REQUIRED_VERSION gudev-1.0 ) fi dnl --------------------------------------------------------------------------- dnl - color dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(COLOR, [colord >= 0.1.9 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION libcanberra-gtk3]) dnl --------------------------------------------------------------------------- dnl - wacom (disabled for s390/s390x and non Linux platforms) dnl --------------------------------------------------------------------------- case $host_os in linux*) if test "$host_cpu" = s390 -o "$host_cpu" = s390x; then have_wacom=no else if test x$enable_gudev != xno; then PKG_CHECK_MODULES(WACOM, [libwacom >= $LIBWACOM_REQUIRED_VERSION x11 xi xtst gudev-1.0 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION xorg-wacom librsvg-2.0 >= $LIBRSVG_REQUIRED_VERSION]) else AC_MSG_ERROR([GUdev is necessary to compile Wacom support]) fi have_wacom=yes fi ;; *) have_wacom=no ;; esac AM_CONDITIONAL(HAVE_WACOM, test x$have_wacom = xyes) dnl ============================================== dnl PackageKit section dnl ============================================== have_packagekit=false AC_ARG_ENABLE(packagekit, AC_HELP_STRING([--disable-packagekit], [turn off PackageKit support]), [case "${enableval}" in yes) WANT_PACKAGEKIT=yes ;; no) WANT_PACKAGEKIT=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-packagekit) ;; esac], [WANT_PACKAGEKIT=yes]) dnl Default value if test x$WANT_PACKAGEKIT = xyes ; then PK_REQUIRED_VERSION=0.7.4 PKG_CHECK_MODULES(PACKAGEKIT, glib-2.0 packagekit-glib2 >= $PK_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION gudev-1.0 libnotify >= $LIBNOTIFY_REQUIRED_VERSION, [have_packagekit=true AC_DEFINE(HAVE_PACKAGEKIT, 1, [Define if PackageKit should be used])], [have_packagekit=false]) fi AM_CONDITIONAL(HAVE_PACKAGEKIT, test "x$have_packagekit" = "xtrue") AC_SUBST(PACKAGEKIT_CFLAGS) AC_SUBST(PACKAGEKIT_LIBS) dnl ============================================== dnl smartcard section dnl ============================================== have_smartcard_support=false AC_ARG_ENABLE(smartcard-support, AC_HELP_STRING([--disable-smartcard-support], [turn off smartcard support]), [case "${enableval}" in yes) WANT_SMARTCARD_SUPPORT=yes ;; no) WANT_SMARTCARD_SUPPORT=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-smartcard-support) ;; esac], [WANT_SMARTCARD_SUPPORT=no]) if test x$WANT_SMARTCARD_SUPPORT = xyes ; then AC_MSG_ERROR(Smartcard support is broken in this version) NSS_REQUIRED_VERSION=3.11.2 PKG_CHECK_MODULES(NSS, nss >= $NSS_REQUIRED_VERSION, [have_smartcard_support=true AC_DEFINE(SMARTCARD_SUPPORT, 1, [Define if smartcard support should be enabled])], [have_smartcard_support=false]) fi AM_CONDITIONAL(SMARTCARD_SUPPORT, test "x$have_smartcard_support" = "xtrue") AC_SUBST(NSS_CFLAGS) AC_SUBST(NSS_LIBS) AC_ARG_WITH(nssdb, AC_HELP_STRING([--with-nssdb], [where system NSS database is])) NSS_DATABASE="" if test "x$have_smartcard_support" = "xtrue"; then if ! test -z "$with_nssdb" ; then NSS_DATABASE="$with_nssdb" else NSS_DATABASE="${sysconfdir}/pki/nssdb" fi else if ! test -z "$with_nssdb" ; then AC_MSG_WARN([nssdb specified when smartcard support is disabled]) fi fi AC_SUBST(NSS_DATABASE) dnl --------------------------------------------------------------------------- dnl Sharing plugin dnl --------------------------------------------------------------------------- AC_ARG_ENABLE(network-manager, AS_HELP_STRING([--disable-network-manager], [Disable NetworkManager support]), enable_network_manager=$enableval, enable_network_manager=yes) if test "x$enable_network_manager" = "xyes" ; then NM_MODULE="libnm >= $NM_REQUIRED_VERSION" AC_DEFINE(HAVE_NETWORK_MANAGER, 1, [Defined if NetworkManager support is enabled]) else NM_MODULE= fi PKG_CHECK_MODULES(SHARING, gio-2.0 $NM_MODULE) # --------------------------------------------------------------------------- # Rfkill # --------------------------------------------------------------------------- AC_ARG_ENABLE(rfkill, AS_HELP_STRING([--disable-rfkill], [disable rfkill support (default: enabled)]),, enable_rfkill=yes, enabled_rfkill=no) if test x"$enable_rfkill" != x"no" ; then AC_CHECK_HEADERS([linux/rfkill.h],, AC_MSG_ERROR([RFKill headers not found but rfkill support requested])) fi AM_CONDITIONAL(BUILD_RFKILL, [test x"$enable_rfkill" = x"yes"]) # --------------------------------------------------------------------------- # Enable Profiling # --------------------------------------------------------------------------- AC_ARG_ENABLE(profiling, [AC_HELP_STRING([--enable-profiling], [turn on profiling])], , enable_profiling=no) if test "x$enable_profiling" = "xyes"; then AC_DEFINE(ENABLE_PROFILING,1,[enable profiling]) fi # --------------------------------------------------------------------------- # Plugins # --------------------------------------------------------------------------- plugindir='$(libdir)/unity-settings-daemon-gsd_api_version' AC_SUBST([plugindir]) PLUGIN_CFLAGS="-DG_LOG_DOMAIN=\"\\\"\$(plugin_name)-plugin\\\"\" -DPLUGIN_NAME=\"\\\"\$(plugin_name)\\\"\" " AC_SUBST(PLUGIN_CFLAGS) AC_ARG_ENABLE(man, [AS_HELP_STRING([--enable-man], [generate man pages [default=yes]])],, enable_man=yes) if test "$enable_man" != no; then AC_PATH_PROG([XSLTPROC], [xsltproc]) if test -z "$XSLTPROC"; then AC_MSG_ERROR([xsltproc is required for --enable-man]) fi fi AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) dnl --------------------------------------------------------------------------- dnl - Finish dnl --------------------------------------------------------------------------- # Turn on the additional warnings last, so warnings don't affect other tests. AC_ARG_ENABLE(more-warnings, [AC_HELP_STRING([--enable-more-warnings], [Maximum compiler warnings])], set_more_warnings="$enableval",[ if test -d $srcdir/.git; then set_more_warnings=yes else set_more_warnings=no fi ]) AC_MSG_CHECKING(for more warnings) if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then AC_MSG_RESULT(yes) CFLAGS="\ -Wall \ -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \ -Wnested-externs -Wpointer-arith \ -Wcast-align -Wsign-compare \ $CFLAGS" for option in -Wno-strict-aliasing -Wno-sign-compare; do SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $option" AC_MSG_CHECKING([whether gcc understands $option]) AC_TRY_COMPILE([], [], has_option=yes, has_option=no,) if test $has_option = no; then CFLAGS="$SAVE_CFLAGS" fi AC_MSG_RESULT($has_option) unset has_option unset SAVE_CFLAGS done unset option else AC_MSG_RESULT(no) fi # # Enable Debug # AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [turn on debugging])], , enable_debug=yes) if test "$enable_debug" = "yes"; then DEBUG_CFLAGS="-DG_ENABLE_DEBUG" else if test "x$enable_debug" = "xno"; then DEBUG_CFLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS" else DEBUG_CFLAGS="" fi fi AC_SUBST(DEBUG_CFLAGS) AC_OUTPUT([ Makefile gnome-settings-daemon/Makefile plugins/Makefile plugins/a11y-keyboard/Makefile plugins/a11y-settings/Makefile plugins/automount/Makefile plugins/background/Makefile plugins/clipboard/Makefile plugins/color/Makefile plugins/common/Makefile plugins/cursor/Makefile plugins/dummy/Makefile plugins/power/Makefile plugins/housekeeping/Makefile plugins/keyboard/Makefile plugins/media-keys/Makefile plugins/media-keys/gvc/Makefile plugins/mouse/Makefile plugins/orientation/Makefile plugins/remote-display/Makefile plugins/rfkill/Makefile plugins/screensaver-proxy/Makefile plugins/sharing/Makefile plugins/smartcard/Makefile plugins/sound/Makefile plugins/updates/Makefile plugins/wacom/Makefile plugins/xrandr/Makefile plugins/xsettings/Makefile data/Makefile data/unity-settings-daemon.pc data/unity-settings-daemon-uninstalled.pc data/libunity-settings-daemon.pc po/Makefile.in man/Makefile tests/Makefile ]) dnl --------------------------------------------------------------------------- dnl - Show summary dnl --------------------------------------------------------------------------- echo " untiy-settings-daemon $VERSION ============================= prefix: ${prefix} exec_prefix: ${exec_prefix} libdir: ${libdir} bindir: ${bindir} sbindir: ${sbindir} sysconfdir: ${sysconfdir} sysconfsubdir: ${sysconfsubdir} localstatedir: ${localstatedir} plugindir: ${plugindir} datadir: ${datadir} source code location: ${srcdir} compiler: ${CC} cflags: ${CFLAGS} Maintainer mode: ${USE_MAINTAINER_MODE} Session tracking: ${SESSION_TRACKING} LCMS DICT support: ${have_new_lcms} NetworkManager support: ${enable_network_manager} IBus support: ${enable_ibus} Fcitx support: ${enable_fcitx} Libnotify support: ${have_libnotify} PackageKit support: ${have_packagekit} Smartcard support: ${have_smartcard_support} Cups support: ${enable_cups} Wacom support: ${have_wacom} RFKill support: ${enable_rfkill} ${NSS_DATABASE:+\ System nssdb: ${NSS_DATABASE} }\ Profiling support: ${enable_profiling} " unity-settings-daemon/data/0000775000000000000000000000000015172222611013125 5ustar unity-settings-daemon/data/Makefile.am0000664000000000000000000000457715172222611015176 0ustar NULL = apidir = $(includedir)/unity-settings-daemon-$(GSD_API_VERSION)/unity-settings-daemon api_DATA = gsd-enums.h gsettings_ENUM_NAMESPACE = com.canonical.unity.settings-daemon gsettings_ENUM_FILES = $(top_srcdir)/data/$(api_DATA) gschema_in_files = \ com.canonical.unity.settings-daemon.peripherals.gschema.xml.in.in \ com.canonical.unity.settings-daemon.peripherals.wacom.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.color.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.datetime.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.housekeeping.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.keyboard.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.media-keys.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.orientation.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.power.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.print-notifications.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.sharing.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.xrandr.gschema.xml.in.in \ com.canonical.unity.settings-daemon.plugins.xsettings.gschema.xml.in.in gsettings_SCHEMAS = $(gschema_in_files:.xml.in.in=.xml) gsettingsdir = $(datadir)/glib-2.0/schemas %.gschema.xml.in: %.gschema.xml.in.in $(AM_V_GEN) sed -e "s|\@GETTEXT_PACKAGE\@|$(GETTEXT_PACKAGE)|g" $< > $@ @INTLTOOL_XML_NOMERGE_RULE@ @GSETTINGS_RULES@ @INTLTOOL_DESKTOP_RULE@ desktopdir = $(sysconfdir)/xdg/autostart desktop_in_files = unity-settings-daemon.desktop.in.in desktop_DATA = $(desktop_in_files:.desktop.in.in=.desktop) unity-settings-daemon.desktop.in: unity-settings-daemon.desktop.in.in $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@.tmp && mv $@.tmp $@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = unity-settings-daemon.pc libunity-settings-daemon.pc @INTLTOOL_XML_NOMERGE_RULE@ EXTRA_DIST = \ $(convert_DATA) \ $(gschema_in_files) \ $(desktop_in_files) \ $(gsettings_ENUM_FILES) \ unity-settings-daemon.pc.in \ libunity-settings-daemon.pc.in \ $(api_DATA) \ $(NULL) DISTCLEANFILES = \ $(desktop_DATA) \ unity-settings-daemon.desktop.in \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in \ $(gsettings_SCHEMAS:.xml=.valid) unity-settings-daemon/data/com.canonical.unity.settings-daemon.peripherals.gschema.xml.in.in0000664000000000000000000002271415172222611027565 0ustar 0

Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 'none' Smartcard removal action Set this to one of “none”, “lock-screen”, or “force-logout”. The action will get performed when the smartcard used for log in is removed. true 0 'on' Possible values are “on”, “off”, and “custom”. 400 100 '' Keyboard Bell Custom Filename File name of the bell sound to be played. true Remember NumLock state When set to true, GNOME will remember the state of the NumLock LED between sessions. 'unknown' NumLock state The remembered state of the NumLock LED. false Highlights the current location of the pointer when the Control key is pressed and released. 400 Double click time Length of a double click in milliseconds. 8 Drag threshold Distance before a drag is started. 'two-finger-scrolling' Select the touchpad scroll method Select the touchpad scroll method. Supported values are: “disabled”, “edge-scrolling”, “two-finger-scrolling”. false Whether the tablet’s orientation is locked, or rotated automatically. '' Device hotplug custom command Command to be run when a device is added or removed. An exit value of 1 means that the device will not be handled further by gnome-settings-daemon. false Mouse button orientation Swap left and right mouse buttons for left-handed mice. -1 Single Click Acceleration multiplier for mouse motion. A value of -1 is the system default. -1 Motion Threshold Distance in pixels the pointer must move before accelerated mouse motion is activated. A value of -1 is the system default. false Middle button emulation Enables middle mouse button emulation through simultaneous left and right button click. true 30 Key Repeat Interval Delay between repeats in milliseconds. 500 Initial Key Repeat Delay Initial key repeat delay in milliseconds. false Disable touchpad while typing Set this to TRUE if you have problems with accidentally hitting the touchpad while typing. true Enable horizontal scrolling Set this to TRUE to allow horizontal scrolling by the same method selected with the scroll_method key. false Enable mouse clicks with touchpad Set this to TRUE to be able to send mouse clicks by tapping on the touchpad. true Enable touchpad Set this to TRUE to enable all touchpads. 'mouse' Touchpad button orientation Swap left and right mouse buttons for left-handed mice with “left”, “right” for right-handed, “mouse” to follow the mouse setting. -1 Single Click Acceleration multiplier for mouse motion. A value of -1 is the system default. -1 Motion Threshold Distance in pixels the pointer must move before accelerated mouse motion is activated. A value of -1 is the system default. false Natural scrolling Set this to TRUE to enable natural (reverse) scrolling for touchpads. 0 Mouse wheel emulation button. 0 to disable the feature. unity-settings-daemon/data/com.canonical.unity.settings-daemon.peripherals.wacom.gschema.xml.in.in0000664000000000000000000002454115172222611030672 0ustar true Wacom stylus absolute mode Enable this to set the tablet to absolute mode. [-1, -1, -1, -1] Wacom tablet area Set this to x1, y1 and x2, y2 of the area usable by the tools. false Wacom tablet aspect ratio Enable this to restrict the Wacom tablet area to match the aspect ratio of the output. 'none' Wacom tablet rotation Set this to “none”, “cw” for 90 degree clockwise, “half” for 180 degree, and “ccw” for 90 degree counterclockwise. true Wacom touch feature Enable this to move the cursor when the user touches the tablet. [0, 0, 100, 100] Wacom stylus pressure curve Set this to x1, y1 and x2, y2 of the pressure curve applied to the stylus. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] Wacom stylus button mapping Set this to the logical button mapping. -1 Wacom stylus pressure threshold Set this to the pressure value at which a stylus click event is generated. [0, 0, 100, 100] Wacom eraser pressure curve Set this to x1, y1 and x2, y2 of the pressure curve applied to the eraser. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] Wacom eraser button mapping Set this to the logical button mapping. -1 Wacom eraser pressure threshold Set this to the pressure value at which an eraser click event is generated. 'none' Wacom button action type The type of action triggered by the button being pressed. '' Key combination for the custom action The keyboard shortcut generated when the button is pressed for custom actions. ['', ''] Key combinations for a touchring or touchstrip custom action The keyboard shortcuts generated when a touchring or touchstrip is used for custom actions (up followed by down). '' Button label for OLED display. Label will be rendered to OLED display belonging to the button ["", "", ""] 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not true Wacom stylus absolute mode Enable this to set the tablet to absolute mode for unity-settings-daemon. [-1, -1, -1, -1] Wacom tablet area Set this to x1, y1 and x2, y2 of the area usable by the tools. false Wacom tablet aspect ratio Enable this to restrict the Wacom tablet area to match the aspect ratio of the output. 'none' Wacom tablet rotation Set this to “none”, “cw” for 90 degree clockwise, “half” for 180 degree, and “ccw” for 90 degree counterclockwise. true Wacom touch feature Enable this to move the cursor when the user touches the tablet. false Wacom tablet PC feature Enable this to only report stylus events when the tip is pressed. ["", "", ""] Wacom display mapping EDID information of monitor to map tablet to. Must be in the format [vendor, product, serial]. ["","",""] disables mapping. [0, 0, 100, 100] Wacom stylus pressure curve Set this to x1, y1 and x2, y2 of the pressure curve applied to the stylus. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] Wacom stylus button mapping Set this to the logical button mapping. -1 Wacom stylus pressure threshold Set this to the pressure value at which a stylus click event is generated. [0, 0, 100, 100] Wacom eraser pressure curve Set this to x1, y1 and x2, y2 of the pressure curve applied to the eraser. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] Wacom eraser button mapping Set this to the logical button mapping. -1 Wacom eraser pressure threshold Set this to the pressure value at which an eraser click event is generated. 'none' Wacom button action type The type of action triggered by the button being pressed. '' Key combination for the custom action The keyboard shortcut generated when the button is pressed for custom actions. ['', ''] Key combinations for a touchring or touchstrip custom action The keyboard shortcuts generated when a touchring or touchstrip is used for custom actions (up followed by down). unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.color.gschema.xml.in.in0000664000000000000000000000570615172222611030047 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 The duration a display profile is valid This is the number of days after which the display color profile is considered invalid. 0 The duration a printer profile is valid This is the number of days after which the printer color profile is considered invalid. false If the night light mode is enabled Night light mode changes the color temperature of your display when the sun has gone down or at preset times. 4000 Temperature of the display when enabled This temperature in Kelvin is used to modify the screen tones when night light mode is enabled. Higher values are bluer, lower redder. true Use the sunrise and sunset Calculate the sunrise and sunset times automatically, from the current location. 20.00 The start time When “night-light-schedule-automatic” is disabled, use this start time in hours from midnight. 6.00 The end time When “night-light-schedule-automatic” is disabled, use this end time in hours from midnight. (91,181) The last detected position When location services are available this represents the last detected location. The default value is an invalid value to ensure it is always updated at startup. unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.datetime.gschema.xml.in.in0000664000000000000000000000130215172222611030511 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.gschema.xml.in.in0000664000000000000000000002277415172222611026736 0ustar ['all'] List of plugins that are allowed to be loaded A list of strings representing the plugins that are allowed to be loaded (default: “all”). This is only evaluated on startup. 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not ././@LongLink0000644000000000000000000000014600000000000007774 Lustar unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.housekeeping.gschema.xml.in.inunity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.housekeeping.gschema.xml.in.i0000664000000000000000000000422415172222611031233 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not [] Mount paths to ignore Specify a list of mount paths to ignore when they run low on space. 0.05 Free percentage notify threshold Percentage free space threshold for initial warning of low disk space. If the percentage free space drops below this, a warning will be shown. 0.01 Subsequent free space percentage notify threshold Specify the percentage that the free disk space should reduce by before issuing a subsequent warning. 1 Free space notify threshold Specify an amount in GB. If the amount of free space is more than this, no warning will be shown. 10 Minimum notify period for repeated warnings Specify a time in minutes. Subsequent warnings for a volume will not appear more often than this period. unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.keyboard.gschema.xml.in.in0000664000000000000000000000130215172222611030515 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.media-keys.gschema.xml.in.in0000664000000000000000000002231115172222611030750 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not [] Custom keybindings List of custom keybindings 'XF86Calculator' Launch calculator Binding to launch the calculator. 'XF86Tools' Launch settings Binding to launch GNOME settings. 'XF86Mail' Launch email client Binding to launch the email client. 'XF86Eject' Eject Binding to eject an optical disc. '' Launch help browser Binding to launch the help browser. 'XF86Explorer' Home folder Binding to open the Home folder. 'XF86AudioMedia' Launch media player Binding to launch the media player. 'XF86AudioNext' Next track Binding to skip to next track. 'XF86AudioPause' Pause playback Binding to pause playback. 'XF86AudioPlay' Play (or play/pause) Binding to start playback (or toggle play/pause). '<Control><Alt>Delete' Log out Binding to log out. 'XF86AudioPrev' Previous track Binding to skip to previous track. '<Control><Alt>l' Lock screen Binding to lock the screen. 'XF86Search' Search Binding to launch the search tool. 'XF86AudioStop' Stop playback Binding to stop playback. '<Super>p' Video output Binding to switch the video output device. 'XF86AudioLowerVolume' Volume down Binding to lower the volume. 'XF86AudioMute' Volume mute/unmute Binding to mute/unmute the volume. 'XF86AudioRaiseVolume' Volume up Binding to raise the volume. 'XF86AudioMicMute' Microphone mute/unmute Binding to mute/unmute the microphone. 'Print' Take a screenshot Binding to take a screenshot. '<Alt>Print' Take a screenshot of a window Binding to take a screenshot of a window. '<Shift>Print' Take a screenshot of an area Binding to take a screenshot of an area. '<Ctrl>Print' Copy a screenshot to clipboard Binding to copy a screenshot to clipboard. '<Ctrl><Alt>Print' Copy a screenshot of a window to clipboard Binding to copy a screenshot of a window to clipboard. '<Ctrl><Shift>Print' Copy a screenshot of an area to clipboard Binding to copy a screenshot of an area to clipboard. '<Ctrl><Shift><Alt>R' Record a short video of the screen Binding to record a short video of the screen '<Primary><Alt>t' Launch terminal Binding to launch the terminal. 'XF86WWW' Launch web browser Binding to launch the web browser. '<Alt><Super>8' Toggle magnifier Binding to show the screen magnifier '<Alt><Super>s' Toggle screen reader Binding to start the screen reader '' Toggle on-screen keyboard Binding to show the on-screen keyboard '' Increase text size Binding to increase the text size '' Decrease text size Binding to decrease the text size '' Toggle contrast Binding to toggle the interface contrast '<Alt><Super>equal' Magnifier zoom in Binding for the magnifier to zoom in '<Alt><Super>minus' Magnifier zoom out Binding for the magnifier to zoom out 30 Maximum length of screen recordings The maximum length of single screen cast recordings in seconds or 0 for unlimited '' Name Name of the custom binding '' Binding Binding for the custom binding '' Command Command to run when the binding is invoked unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.orientation.gschema.xml.in.in0000664000000000000000000000131015172222611031247 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.power.gschema.xml.in.in0000664000000000000000000002056115172222611030061 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 30 The brightness of the screen when idle This is the laptop panel screen brightness used when the session is idle. true Dim the screen after a period of inactivity If the screen should be dimmed to save power when the computer is idle. 1200 Sleep timeout computer when on AC The amount of time in seconds the computer on AC power needs to be inactive before it goes to sleep. A value of 0 means never. 'suspend' Whether to hibernate, suspend or do nothing when inactive The type of sleeping that should be performed when the computer is inactive. 1200 Sleep timeout computer when on battery The amount of time in seconds the computer on battery power needs to be inactive before it goes to sleep. A value of 0 means never. 'suspend' Whether to hibernate, suspend or do nothing when inactive The type of sleeping that should be performed when the computer is inactive. 'suspend' Laptop lid close action on battery The action to take when the laptop lid is closed and the laptop is on battery power. 'suspend' Laptop lid close action when on AC The action to take when the laptop lid is closed and the laptop is on AC power. false Laptop lid, when closed, will suspend even if there is an external monitor plugged in With no external monitors plugged in, closing a laptop's lid will suspend the machine (as set by the lid-close-battery-action and lid-close-ac-action keys). By default, however, closing the lid when an external monitor is present will not suspend the machine, so that one can keep working on that monitor (e.g. for docking stations or media viewers). Set this key to False to keep the default behavior, or to True to suspend the laptop whenever the lid is closed and regardless of external monitors. true Enable the ALS sensor If the ambient light sensor functionality is enabled. 'suspend' Power button action The action to take when the system power button is pressed. This action is hard-coded (and the setting ignored) on virtual machines (power off) and tablets (suspend). 'suspend' Suspend button action The action to take when the system suspend button is pressed. 'hibernate' Hibernate button action The action to take when the system hibernate button is pressed. 'hibernate' Sleep button action The action to take when the system sleep (non-specific type) button is pressed. 'interactive' Power button action The action to take when the system power button is pressed. 'hibernate' Battery critical low action The action to take when the battery is critically low. 10 Percentage considered low The percentage of the battery when it is considered low. Only valid when use-time-for-policy is false. 3 Percentage considered critical The percentage of the battery when it is considered critical. Only valid when use-time-for-policy is false. 2 Percentage action is taken The percentage of the battery when the critical action is performed. Only valid when use-time-for-policy is false. 1200 The time remaining when low The time remaining in seconds of the battery when it is considered low. Only valid when use-time-for-policy is true. 300 The time remaining when critical The time remaining in seconds of the battery when it is considered critical. Only valid when use-time-for-policy is true. 120 The time remaining when action is taken The time remaining in seconds of the battery when critical action is taken. Only valid when use-time-for-policy is true. true Whether to use time-based notifications If time based notifications should be used. If set to false, then the percentage change is used instead, which may fix a broken ACPI BIOS. true If we should show the recalled battery warning for a broken battery If we should show the recalled battery warning for a broken battery. Set this to false only if you know your battery is okay. ././@LongLink0000644000000000000000000000015500000000000007774 Lustar unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.print-notifications.gschema.xml.in.inunity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.print-notifications.gschema.x0000664000000000000000000000133015172222611031356 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.sharing.gschema.xml.in.in0000664000000000000000000000216115172222611030354 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not [] On which connections the service is enabled The list of NetworkManager connections (each one represented with its UUID) on which this service is enabled and started. unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.xrandr.gschema.xml.in.in0000664000000000000000000000355415172222611030226 0ustar '/etc/gnome-settings-daemon/xrandr/monitors.xml' File for default configuration for RandR The XRandR plugin will look for a default configuration in the file specified by this key. This is similar to the ~/.config/monitors.xml that normally gets stored in users’ home directories. If a user does not have such a file, or has one that does not match the user’s setup of monitors, then the file specified by this key will be used instead. 'follow-lid' Whether to turn off specific monitors after boot “clone” will display the same thing on all monitors, “dock” will switch off the internal monitor, “do-nothing” will use the default Xorg behaviour (extend the desktop in recent versions). The default, “follow-lid”, will choose between “do-nothing” and “dock” depending on whether the lid is (respectively) open or closed. 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not unity-settings-daemon/data/com.canonical.unity.settings-daemon.plugins.xsettings.gschema.xml.in.in0000664000000000000000000000667115172222611030763 0ustar 0 Priority to use for this plugin Priority to use for this plugin in unity-settings-daemon startup queue true Activation of this plugin Whether this plugin would be activated by unity-settings-daemon or not 'grayscale' Antialiasing The type of antialiasing to use when rendering fonts. Possible values are: “none” for no antialiasing, “grayscale” for standard grayscale antialiasing, and “rgba” for subpixel antialiasing (LCD screens only). 'slight' Hinting The type of hinting to use when rendering fonts. Possible values are: “none” for no hinting and “slight” for fitting only to the Y-axis like Microsoft’s ClearType, DirectWrite and Adobe’s proprietary font rendering engine. Ignores native hinting within the font, generates hints algorithmically. Used on Ubuntu by default. Recommended. The meaning of “medium” and “full” depends on the font format (.ttf, .otf, .pfa/.pfb) and the installed version of FreeType. They usually try to fit glyphs to both the X and the Y axis (except for .otf: Y-only). This can lead to distortion and/or inconsistent rendering depending on the quality of the font, the font format and the state of FreeType’s font engines. 'rgb' RGBA order The order of subpixel elements on an LCD screen; only used when antialiasing is set to “rgba”. Possible values are: “rgb” for red on left (most common), “bgr” for blue on left, “vrgb” for red on top, “vbgr” for red on bottom. [] List of explicitly disabled GTK+ modules A list of strings representing the GTK+ modules that will not be loaded, even if enabled by default in their configuration. [] List of explicitly enabled GTK+ modules A list of strings representing the GTK+ modules that will be loaded, usually in addition to conditional and forcibly disabled ones. {} A dictionary of XSETTINGS to override This dictionary maps XSETTINGS names to overrides values. The values must be either strings, signed int32s or (in the case of colors), 4-tuples of uint16 (red, green, blue, alpha; 65535 is fully opaque). unity-settings-daemon/data/gnome-settings-daemon.convert0000664000000000000000000001234715172222611020742 0ustar [com.canonical.unity.settings-daemon.peripherals.smartcard] removal-action = /desktop/gnome/peripherals/smartcard/removal_action [com.canonical.unity.settings-daemon.peripherals.touchpad] disable-while-typing = /desktop/gnome/peripherals/touchpad/disable_while_typing horiz-scroll-enabled = /desktop/gnome/peripherals/touchpad/horiz_scroll_enabled scroll-method = /desktop/gnome/peripherals/touchpad/scroll_method tap-to-click = /desktop/gnome/peripherals/touchpad/tap_to_click touchpad-enabled = /desktop/gnome/peripherals/touchpad/touchpad_enabled motion-acceleration = /desktop/gnome/peripherals/mouse/motion_acceleration motion-threshold = /desktop/gnome/peripherals/mouse/motion_threshold [com.canonical.unity.settings-daemon.plugins.a11y-keyboard] active = /apps/gnome_settings_daemon/plugins/a11y-keyboard/active priority = /apps/gnome_settings_daemon/plugins/a11y-keyboard/priority [com.canonical.unity.settings-daemon.plugins.background] active = /apps/gnome_settings_daemon/plugins/background/active priority = /apps/gnome_settings_daemon/plugins/background/priority [com.canonical.unity.settings-daemon.plugins.clipboard] active = /apps/gnome_settings_daemon/plugins/clipboard/active priority = /apps/gnome_settings_daemon/plugins/clipboard/priority [com.canonical.unity.settings-daemon.plugins.font] active = /apps/gnome_settings_daemon/plugins/font/active priority = /apps/gnome_settings_daemon/plugins/font/priority [com.canonical.unity.settings-daemon.plugins.housekeeping] active = /apps/gnome_settings_daemon/plugins/housekeeping/active free-percent-notify = /apps/gnome_settings_daemon/plugins/housekeeping/free_percent_notify free-percent-notify-again = /apps/gnome_settings_daemon/plugins/housekeeping/free_percent_notify_again free-size-gb-no-notify = /apps/gnome_settings_daemon/plugins/housekeeping/free_size_gb_no_notify ignore-paths = /apps/gnome_settings_daemon/plugins/housekeeping/ignore_paths min-notify-period = /apps/gnome_settings_daemon/plugins/housekeeping/min_notify_period priority = /apps/gnome_settings_daemon/plugins/housekeeping/priority [com.canonical.unity.settings-daemon.plugins.keyboard] active = /apps/gnome_settings_daemon/plugins/keyboard/active priority = /apps/gnome_settings_daemon/plugins/keyboard/priority [com.canonical.unity.settings-daemon.plugins.media-keys] active = /apps/gnome_settings_daemon/plugins/keybindings/active calculator = /apps/gnome_settings_daemon/keybindings/calculator email = /apps/gnome_settings_daemon/keybindings/email eject = /apps/gnome_settings_daemon/keybindings/eject help = /apps/gnome_settings_daemon/keybindings/help home = /apps/gnome_settings_daemon/keybindings/home logout = /apps/gnome_settings_daemon/keybindings/power media = /apps/gnome_settings_daemon/keybindings/media next = /apps/gnome_settings_daemon/keybindings/next pause = /apps/gnome_settings_daemon/keybindings/pause play = /apps/gnome_settings_daemon/keybindings/play previous = /apps/gnome_settings_daemon/keybindings/previous priority = /apps/gnome_settings_daemon/plugins/keybindings/priority screensaver = /apps/gnome_settings_daemon/keybindings/screensaver search = /apps/gnome_settings_daemon/keybindings/search stop = /apps/gnome_settings_daemon/keybindings/stop touchpad = /apps/gnome_settings_daemon/keybindings/touchpad volume-down = /apps/gnome_settings_daemon/keybindings/volume_down volume-mute = /apps/gnome_settings_daemon/keybindings/volume_mute volume-up = /apps/gnome_settings_daemon/keybindings/volume_up www = /apps/gnome_settings_daemon/keybindings/www screenshot = /apps/metacity/global_keybindings/run_command_screenshot window-screenshot = /apps/metacity/global_keybindings/run_command_window_screenshot terminal = /apps/metacity/global_keybindings/run_command_terminal [com.canonical.unity.settings-daemon.plugins.mouse] active = /apps/gnome_settings_daemon/plugins/mouse/active priority = /apps/gnome_settings_daemon/plugins/mouse/priority [com.canonical.unity.settings-daemon.peripherals.mouse] locate-pointer = /desktop/gnome/peripherals/mouse/locate_pointer double-click = /desktop/gnome/peripherals/mouse/double_click drag-threshold = /desktop/gnome/peripherals/mouse/drag_threshold left-handed = /desktop/gnome/peripherals/mouse/left_handed motion-acceleration = /desktop/gnome/peripherals/mouse/motion_acceleration motion-threshold = /desktop/gnome/peripherals/mouse/motion_threshold [com.canonical.unity.settings-daemon.plugins.smartcard] active = /apps/gnome_settings_daemon/plugins/smartcard/active priority = /apps/gnome_settings_daemon/plugins/smartcard/priority [com.canonical.unity.settings-daemon.plugins.sound] active = /apps/gnome_settings_daemon/plugins/sound/active priority = /apps/gnome_settings_daemon/plugins/sound/priority [com.canonical.unity.settings-daemon.plugins.xrandr] active = /apps/gnome_settings_daemon/plugins/xrandr/active default-configuration-file = /apps/gnome_settings_daemon/xrandr/default_configuration_file priority = /apps/gnome_settings_daemon/plugins/xrandr/priority [com.canonical.unity.settings-daemon.plugins.xsettings] active = /apps/gnome_settings_daemon/plugins/xsettings/active antialiasing = /desktop/gnome/font_rendering/antialiasing hinting = /desktop/gnome/font_rendering/hinting priority = /apps/gnome_settings_daemon/plugins/xsettings/priority rgba-order = /desktop/gnome/font_rendering/rgba_order unity-settings-daemon/data/gsd-enums.h0000664000000000000000000000765015172222611015210 0ustar /* * Copyright © 2010 Bastien Nocera * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Authors: * Bastien Nocera */ #ifndef __gsd_enums_h__ #define __gsd_enums_h__ typedef enum { GSD_FONT_ANTIALIASING_MODE_NONE, GSD_FONT_ANTIALIASING_MODE_GRAYSCALE, GSD_FONT_ANTIALIASING_MODE_RGBA } GsdFontAntialiasingMode; typedef enum { GSD_FONT_HINTING_NONE, GSD_FONT_HINTING_SLIGHT, GSD_FONT_HINTING_MEDIUM, GSD_FONT_HINTING_FULL } GsdFontHinting; typedef enum { GSD_FONT_RGBA_ORDER_RGBA, GSD_FONT_RGBA_ORDER_RGB, GSD_FONT_RGBA_ORDER_BGR, GSD_FONT_RGBA_ORDER_VRGB, GSD_FONT_RGBA_ORDER_VBGR } GsdFontRgbaOrder; typedef enum { GSD_SMARTCARD_REMOVAL_ACTION_NONE, GSD_SMARTCARD_REMOVAL_ACTION_LOCK_SCREEN, GSD_SMARTCARD_REMOVAL_ACTION_FORCE_LOGOUT } GsdSmartcardRemovalAction; typedef enum { GSD_TOUCHPAD_SCROLL_METHOD_DISABLED, GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING, GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING } GsdTouchpadScrollMethod; typedef enum { GSD_BELL_MODE_ON, GSD_BELL_MODE_OFF, GSD_BELL_MODE_CUSTOM } GsdBellMode; typedef enum { GSD_TOUCHPAD_HANDEDNESS_RIGHT, GSD_TOUCHPAD_HANDEDNESS_LEFT, GSD_TOUCHPAD_HANDEDNESS_MOUSE } GsdTouchpadHandedness; typedef enum { GSD_XRANDR_BOOT_BEHAVIOUR_DO_NOTHING, GSD_XRANDR_BOOT_BEHAVIOUR_CLONE, GSD_XRANDR_BOOT_BEHAVIOUR_DOCK, GSD_XRANDR_BOOT_BEHAVIOUR_FOLLOW_LID } GsdXrandrBootBehaviour; typedef enum { GSD_WACOM_ROTATION_NONE, GSD_WACOM_ROTATION_CW, GSD_WACOM_ROTATION_CCW, GSD_WACOM_ROTATION_HALF } GsdWacomRotation; typedef enum { GSD_WACOM_ACTION_TYPE_NONE, GSD_WACOM_ACTION_TYPE_CUSTOM, GSD_WACOM_ACTION_TYPE_SWITCH_MONITOR, GSD_WACOM_ACTION_TYPE_HELP } GsdWacomActionType; typedef enum { GSD_POWER_ACTION_BLANK, GSD_POWER_ACTION_SUSPEND, GSD_POWER_ACTION_SHUTDOWN, GSD_POWER_ACTION_HIBERNATE, GSD_POWER_ACTION_INTERACTIVE, GSD_POWER_ACTION_NOTHING, GSD_POWER_ACTION_LOGOUT, } GsdPowerActionType; typedef enum { GSD_POWER_BUTTON_ACTION_NOTHING, GSD_POWER_BUTTON_ACTION_SUSPEND, GSD_POWER_BUTTON_ACTION_HIBERNATE, GSD_POWER_BUTTON_ACTION_INTERACTIVE } GsdPowerButtonActionType; typedef enum { GSD_UPDATE_TYPE_ALL, GSD_UPDATE_TYPE_SECURITY, GSD_UPDATE_TYPE_NONE } GsdUpdateType; typedef enum { GSD_NUM_LOCK_STATE_UNKNOWN, GSD_NUM_LOCK_STATE_ON, GSD_NUM_LOCK_STATE_OFF } GsdNumLockState; typedef enum { GSD_INPUT_SOURCES_SWITCHER_OFF, GSD_INPUT_SOURCES_SWITCHER_SHIFT_L, GSD_INPUT_SOURCES_SWITCHER_ALT_L, GSD_INPUT_SOURCES_SWITCHER_CTRL_L, GSD_INPUT_SOURCES_SWITCHER_SHIFT_R, GSD_INPUT_SOURCES_SWITCHER_ALT_R, GSD_INPUT_SOURCES_SWITCHER_CTRL_R, GSD_INPUT_SOURCES_SWITCHER_ALT_SHIFT_L, GSD_INPUT_SOURCES_SWITCHER_ALT_SHIFT_R, GSD_INPUT_SOURCES_SWITCHER_CTRL_SHIFT_L, GSD_INPUT_SOURCES_SWITCHER_CTRL_SHIFT_R, GSD_INPUT_SOURCES_SWITCHER_SHIFT_L_SHIFT_R, GSD_INPUT_SOURCES_SWITCHER_ALT_L_ALT_R, GSD_INPUT_SOURCES_SWITCHER_CTRL_L_CTRL_R, GSD_INPUT_SOURCES_SWITCHER_ALT_SHIFT, GSD_INPUT_SOURCES_SWITCHER_CTRL_SHIFT, GSD_INPUT_SOURCES_SWITCHER_ALT_CTRL, GSD_INPUT_SOURCES_SWITCHER_CAPS, GSD_INPUT_SOURCES_SWITCHER_SHIFT_CAPS, GSD_INPUT_SOURCES_SWITCHER_ALT_CAPS, GSD_INPUT_SOURCES_SWITCHER_CTRL_CAPS, } GsdInputSourcesSwitcher; #endif /* __gsd_enums_h__ */ unity-settings-daemon/data/libunity-settings-daemon.pc.in0000664000000000000000000000052515172222611021016 0ustar prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ libexecdir=@libexecdir@ Name: libunity-settings-daemon Description: Helper library for accessing settings Requires: glib-2.0 gdk-3.0 Version: @VERSION@ Libs: -L${libdir} -lunity-settings-daemon Cflags: -I${includedir}/unity-settings-daemon-@GSD_API_VERSION@ unity-settings-daemon/data/unity-settings-daemon-uninstalled.pc.in0000664000000000000000000000063415172222611022650 0ustar prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ binary=${pc_top_builddir}/unity-settings-daemon/unity-settings-daemon Name: unity-settings-daemon Description: Utility library for accessing unity-settings-daemon over DBUS Requires: glib-2.0 Version: @VERSION@ Libs: ${pc_top_builddir}/${pcfiledir}/../unity-settings-daemon/libgsd.la Cflags: -I${pc_top_builddir}/${pcfiledir}/.. unity-settings-daemon/data/unity-settings-daemon.desktop.in.in0000664000000000000000000000035715172222611022006 0ustar [Desktop Entry] Type=Application _Name=Unity Settings Daemon Exec=@libexecdir@/unity-settings-daemon-localeexec OnlyShowIn=Unity; NoDisplay=true X-GNOME-Autostart-Phase=Initialization X-GNOME-Autostart-Notify=true X-GNOME-AutoRestart=true unity-settings-daemon/data/unity-settings-daemon.pc.in0000664000000000000000000000066115172222611020330 0ustar prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ libexecdir=@libexecdir@ plugindir=${libdir}/unity-settings-daemon-@GSD_API_VERSION@ binary=${libexecdir}/unity-settings-daemon Name: unity-settings-daemon Description: Utility library for accessing unity-settings-daemon over DBUS Requires: glib-2.0 Version: @VERSION@ Libs: -L${libdir} Cflags: -I${includedir}/unity-settings-daemon-@GSD_API_VERSION@ unity-settings-daemon/debian/0000775000000000000000000000000015172222611013436 5ustar unity-settings-daemon/debian/changelog0000664000000000000000000010177715172222611015325 0ustar unity-settings-daemon (26.10.1ubuntu) stonking; urgency=medium * Change *.install files to have all files installed into correct packages: By default debhelper installed packages' files in paths which were different from what is currently in archive. To fix that changes in d/*.install and d/not-installed were required, * Fix failing gcm-self-test in launchpad builds, * Fix build error on s390x and ppc64el due to missing DMI information on launchpad build host, * Change d/rules to include doc files correctly between ibunity-settings-daemon1 and libunity-settings-daemon-dev * Fix compilation errors: * incompatible pointer types, * missing return types, * improper callback types, * wrong arguments to gtk_box_pack_start(), * missing headers, * Fix outdated display panel vendor names in sefltests, * Migrate from CDBS to DebHelper (remove cdbs and dh-migration from build-depends) (LP: #2143760), * Add python-is-python3 to build-depends, * Fix conflicts with gnome-settings-daemon when installing udev rules for rfkill plugin, * Fix build error due to POTFILES, * Fix plugin link errors due to missing linkage against libunity-settings-daemon.so during build -- Tomasz Jeruzalski Wed, 22 Apr 2026 21:46:17 +0200 unity-settings-daemon (15.04.1+21.10.20220802-0ubuntu6) questing; urgency=medium * Ignore new compiler errors incompatible-pointer-types, implicit-int, & return-mismatch * Stop using gnome CDBS rules since they are no longer provided * Ensure we run dh_translations * Use the non-deprecated libgdk-pixbuf-2.0-dev (LP: #2118581) -- Jeremy Bícha Sun, 21 Sep 2025 14:32:26 -0400 unity-settings-daemon (15.04.1+21.10.20220802-0ubuntu5) noble; urgency=medium * No-change rebuild for CVE-2024-3094 -- Steve Langasek Sun, 31 Mar 2024 08:30:39 +0000 unity-settings-daemon (15.04.1+21.10.20220802-0ubuntu4) noble; urgency=medium * No-change rebuild against libcanberra t64. -- Matthias Klose Sun, 24 Mar 2024 14:46:39 +0100 unity-settings-daemon (15.04.1+21.10.20220802-0ubuntu3) noble; urgency=medium * No-change rebuild against libglib2.0-0t64 -- Steve Langasek Mon, 11 Mar 2024 23:47:02 +0000 unity-settings-daemon (15.04.1+21.10.20220802-0ubuntu2) noble; urgency=medium * No-change rebuild against libglib2.0-0t64 -- Steve Langasek Fri, 08 Mar 2024 07:53:41 +0000 unity-settings-daemon (15.04.1+21.10.20220802-0ubuntu1) kinetic; urgency=medium * Update for gnome-desktop 43 thumbnail API changes -- Jeremy Bicha Tue, 02 Aug 2022 10:16:01 -0400 unity-settings-daemon (15.04.1+21.10.20220207-0ubuntu1) jammy; urgency=medium * No-change rebuild against latest libwacom -- Jeremy Bicha Mon, 07 Feb 2022 09:53:59 -0500 unity-settings-daemon (15.04.1+21.10.20210715-0ubuntu1) impish; urgency=medium [ Khurshid Alam ] * Touchpad scroll-method was migrated before from u-s-d to gesetting- desktop-schemas. Now that gsettings-desktop-schemas removed that schema, port it back under unity-settings-daemon schemas (LP: #1933646) -- Sebastien Bacher Thu, 15 Jul 2021 08:25:34 +0000 unity-settings-daemon (15.04.1+20.04.20200325-0ubuntu2) hirsute; urgency=medium * com.canonical.unity.settings-daemon.plugins.power.gschema.xml.in.in: Set default power button action to interactive. This got changed during migration from gnome-settings-daemon schemas. -- Khurshid Alam Thu, 15 Apr 2021 10:43:37 +0200 unity-settings-daemon (15.04.1+20.04.20200325-0ubuntu1) focal; urgency=medium [ iain.lane@canonical.com ] * Stop shipping a GNOME schema (LP: #1869022) -- iain@orangesquash.org.uk Wed, 25 Mar 2020 17:16:20 +0000 unity-settings-daemon (15.04.1+20.04.20200311-0ubuntu1) focal; urgency=medium [ Khurshid Alam ] * Port rest of the schemas gnome-settings-daemon-common to com.canonical.unity.settings-daemon. LP: #1842324 (LP: #1842324) -- Sebastien Bacher Wed, 11 Mar 2020 16:32:29 +0000 unity-settings-daemon (15.04.1+19.10.20190921-0ubuntu3) focal; urgency=medium [ Khurshid Alam ] * Fix gnome-update-wallpaper-cache build -- Sebastien Bacher Wed, 26 Feb 2020 23:42:39 +0100 unity-settings-daemon (15.04.1+19.10.20190921-0ubuntu2) focal; urgency=medium [ Khurshid Alam ] * Copy background drawing code from libgnome-desktop (LP: #1863584) -- Sebastien Bacher Tue, 25 Feb 2020 21:18:10 +0100 unity-settings-daemon (15.04.1+19.10.20190921-0ubuntu1) eoan; urgency=medium [ Khurshid Alam ] * Port media keys to use com.canonical.unity.settings-daemon (LP: #1842324) -- Sebastien Bacher Sat, 21 Sep 2019 10:59:14 +0000 unity-settings-daemon (15.04.1+19.04.20190209-0ubuntu3.2) eoan; urgency=medium * power: Remove 'on AC' check from warning-levels UPower already does this for us, to avoid warning levels being set when the batteries didn't notice the AC yet. -- Khurshid Alam Tue, 25 Jun 2019 13:46:17 +0200 unity-settings-daemon (15.04.1+19.04.20190209-0ubuntu3.1) eoan; urgency=medium * Fix airplane mode switch not appearing -- Khurshid Alam Fri, 21 Jun 2019 10:30:34 +0200 unity-settings-daemon (15.04.1+19.04.20190209-0ubuntu3) eoan; urgency=medium * Unity-control-center has been ported away from libnm-glib to libnm 1.2. -- Khurshid Alam Fri, 17 May 2019 09:28:07 +0200 unity-settings-daemon (15.04.1+19.04.20190209-0ubuntu2) disco; urgency=medium [ Khurshid Alam ] * Unity uses legacy key-grabber code. But since artful unity isn't the default session anymore and DESKTOP_SESSION changed from ubuntu to unity. Fixes LP: #1755106 LP: #1188569 LP: #1727842 -- Sebastien Bacher Fri, 01 Mar 2019 17:53:16 +0100 unity-settings-daemon (15.04.1+19.04.20190209-0ubuntu1) disco; urgency=medium [ Khurshid Alam ] * Transition from gnome-settings-daemon-schemas to gnome-settings- daemon-common. Fixes LP: #1811118 (LP: #1811118) -- Jeremy Bicha Sat, 09 Feb 2019 02:33:41 +0000 unity-settings-daemon (15.04.1+19.04.20181122-0ubuntu1) disco; urgency=medium [ Khurshid Alam ] * Add sharing plugin (LP: #1741027) -- Marco Trevisan (Treviño) Thu, 22 Nov 2018 00:21:48 +0000 unity-settings-daemon (15.04.1+18.04.20180413-0ubuntu4) disco; urgency=medium [ Dariusz Gadomski ] * gnome-settings-daemon/display-name.c: - some vendors record the screen ratio (e.g 16/9) in the EDID instead of including the screen size, detect those cases and display the product name instead of the screen diagonal. (lp: #1755490) -- Sebastien Bacher Tue, 20 Nov 2018 16:07:31 +0100 unity-settings-daemon (15.04.1+18.04.20180413-0ubuntu2) cosmic; urgency=medium [ Kai-Heng Feng ] * power: Choose correct backlight device on laptops with hybrid graphics (LP: #1683445) Backported from gnome-settings-daemon commit ed7c2744 -- Sebastien Bacher Tue, 03 Jul 2018 11:27:01 +0200 unity-settings-daemon (15.04.1+18.04.20180413-0ubuntu1) bionic; urgency=medium [ Marco Trevisan (Treviño) ] * gsd-rr-config: rename monitor config files to unity-monitors.xml* (LP: #1763806) * debian: - build-depends on dh-migrations and run dh_migrations on post-install - add debian/unity-settings-daemon.migrations to install migration files * scripts/01-usd-migration-monitors-xml.sh: - Move monitors.xml to unity-monitors.xml if migration is needed (LP: #1763806) [ Robert Ancell ] * Support new AccountsService method of setting background file. -- Marco Trevisan (Treviño) Fri, 13 Apr 2018 21:33:54 +0000 unity-settings-daemon (15.04.1+18.04.20180216-0ubuntu1) bionic; urgency=medium * No-change rebuild against latest gnome-desktop3 -- Jeremy Bicha Fri, 16 Feb 2018 01:57:58 +0000 unity-settings-daemon (15.04.1+18.04.20180214.1-0ubuntu1) bionic; urgency=medium [ Khurshid Alam ] * gtk_icon_info_free has been deprecated since gtk-3.8. Replace it with g_object_unref (LP: #1747154) [ Robert Ancell ] * Remove obsolete --enable-systemd compile flag -- Jeremy Bicha Wed, 14 Feb 2018 12:41:27 +0000 unity-settings-daemon (15.04.1+17.10.20171003-0ubuntu1) artful; urgency=medium * XSettings: under unity use com.ubuntu.user-interface.desktop keys for scaling settings -- Marco Trevisan (Treviño) Tue, 03 Oct 2017 06:05:23 +0000 unity-settings-daemon (15.04.1+17.04.20170619-0ubuntu3) artful; urgency=medium * debian/control: use 'X-Ubuntu-Use-Langpack: yes' since the indicator is now in universe, this way the translations are still available on launchpad and exported to the langpacks -- Sebastien Bacher Wed, 06 Sep 2017 16:47:19 +0200 unity-settings-daemon (15.04.1+17.04.20170619-0ubuntu2) artful; urgency=medium * remove debian/unity-settings-daemon.gsettings-override: the key combination is already upstream's default. -- Didier Roche Mon, 07 Aug 2017 15:11:27 +0200 unity-settings-daemon (15.04.1+17.04.20170619-0ubuntu1) artful; urgency=medium * Rename ubuntu-session systemd target to unity-session to inline with new session name: - ship unity-settings-daemon service symlink in the new systemd target. - Breaks against older version of ubuntu-session, now that unity-session provides that new systemd target name. -- Didier Roche Mon, 19 Jun 2017 11:04:53 +0200 unity-settings-daemon (15.04.1+17.04.20170418-0ubuntu1) zesty; urgency=medium * Fix calculator keyboard key by adapting to gnome-calculator 3.24 .desktop rename (LP: #1676431) -- Jeremy Bicha Tue, 18 Apr 2017 11:58:34 +0000 unity-settings-daemon (15.04.1+17.04.20170328-0ubuntu1) zesty; urgency=medium [ Chris Coulson ] * Filter out outputs that don't have any corresponding CRTCs or modes. (LP: #1542699) -- Łukasz Zemczak Tue, 28 Mar 2017 08:18:02 +0000 unity-settings-daemon (15.04.1+17.04.20170322-0ubuntu1.1) zesty; urgency=medium * Revert drop updates plugin (LP: #1675612) -- Robert Ancell Fri, 24 Mar 2017 16:40:30 +1300 unity-settings-daemon (15.04.1+17.04.20170322-0ubuntu1) zesty; urgency=medium * Drop updates plugin (handled by GNOME Software, dropped by gnome- settings-daemon now, and long-disabled in Ubuntu) * Drop dependency on gnome-common to fix FTBFS (backported from gnome- settings-daemon) -- Jeremy Bicha Wed, 22 Mar 2017 20:00:38 +0000 unity-settings-daemon (15.04.1+16.10.20161003-0ubuntu1) yakkety; urgency=medium [ Dmitry Shachnev ] * Upstart: Split XDG_CURRENT_DESKTOP properly and start only on Unity sessions [ Iain Lane ] * Check XDG_CURRENT_DESKTOP properly in the keyboard plugin (LP: #1554878) -- iain@orangesquash.org.uk Mon, 03 Oct 2016 10:15:27 +0000 unity-settings-daemon (15.04.1+16.10.20160819-0ubuntu2) yakkety; urgency=medium * Add systemd user unit. * Install u-s-d.service into ubuntu-session.target.wants and keep u-s-d.conf as a stub until unity7 gets a systemd service. -- Martin Pitt Mon, 22 Aug 2016 15:07:09 +0200 unity-settings-daemon (15.04.1+16.10.20160819-0ubuntu1) yakkety; urgency=medium [ Alberts Muktupāvels ] * Use automatic scaling in GNOME Flashback session. -- Dmitry Shachnev Fri, 19 Aug 2016 17:47:36 +0000 unity-settings-daemon (15.04.1+16.10.20160615-0ubuntu1) yakkety; urgency=medium [ Kai-Heng Feng ] * SettingsManager: Queue up signals before getting D-Bus connection. (LP: #1571640) [ Marco Trevisan (Treviño) ] * GsdPowerManager: use proper return value for upower_kbd_toggle wherever we use it (LP: #1592816) -- Marco Trevisan (Treviño) Wed, 15 Jun 2016 15:55:39 +0000 unity-settings-daemon (15.04.1+16.10.20160613-0ubuntu1) yakkety; urgency=medium [ Marco Trevisan (Treviño) ] * PowerManager: connect to keyboard BrightnessChanged signal to update the cached current value properly (LP: #1510344) * GsdPowerManager: don't cache kbd backlight current value (LP: #1583861) * common: backport g-s-d commits for having single shared dbus proxies * ScreensaverProxy: redirect supported calls to gnome screensaver APIs (LP: #1415265, #1584161) [ Robert Ancell ] * Correctly check value of XDG_CURRENT_DESKTOP. * Remove code for disabling plugin under GNOME Shell - they don't use u-s-d. * Drop print notifications - not used under Unity. [ Sebastien Bacher ] * power: '0' keyboard backlight is a valid value (LP: #1510344) * Don't hit an xerror when a device is removed while being configured (LP: #1503758) * wacom: don't segfault when a device is removed while being configured. (LP: #1439427) * power: fix crasher when the plugin is unloaded (LP: #1567116) * power: Add sound notification on power plug/unplug -- Marco Trevisan (Treviño) Mon, 13 Jun 2016 11:31:26 +0000 unity-settings-daemon (15.04.1+16.04.20160209-0ubuntu1) xenial; urgency=medium * Restore the scaling on the greeter, the menu placement is correct now (LP: #1286878) -- Sebastien Bacher Tue, 09 Feb 2016 10:03:45 +0000 unity-settings-daemon (15.04.1+16.04.20160201-0ubuntu1) xenial; urgency=medium [ CI Train Bot ] * No-change rebuild. -- Łukasz Zemczak Mon, 01 Feb 2016 12:39:42 +0000 unity-settings-daemon (15.04.1+16.04.20160121-0ubuntu2) xenial; urgency=medium * Multiarchify the library packages. -- Matthias Klose Thu, 28 Jan 2016 18:08:04 +0100 unity-settings-daemon (15.04.1+16.04.20160121-0ubuntu1) xenial; urgency=medium * Revert part of the previous upload, since it broke keyboard shortcuts in some applications. -- Iain Lane Thu, 21 Jan 2016 11:03:46 +0000 unity-settings-daemon (15.04.1+16.04.20160119-0ubuntu1) xenial; urgency=medium [ William Hua ] * plugins/keyboard/gsd-keyboard-manager.c: - Fix shortcuts for non-latin keyboard layouts in certain programs, but only when the user's layout switching shortcuts are not Shift_L, Shift_R, Shift_L, or Shift_R (LP: #1226962) [ Rui Matos ] * power: Fix a crash when reading invalid backlight values [ Sebastien Bacher ] * keyboard: Avoid warning when bell-custom-file changes -- Iain Lane Tue, 19 Jan 2016 17:08:48 +0000 unity-settings-daemon (15.04.1+16.04.20151214-0ubuntu1) xenial; urgency=medium [ David Henningsson ] * Update PulseAudio port names to fix LP: #1521664 (LP: #1521664) -- Sebastien Bacher Mon, 14 Dec 2015 10:02:41 +0000 unity-settings-daemon (15.04.1+16.04.20151118.1-0ubuntu2) xenial; urgency=high * Fix build-dependencies to use new libystemd-dev package.name. -- Dimitri John Ledkov Mon, 07 Dec 2015 10:54:09 +0000 unity-settings-daemon (15.04.1+16.04.20151118.1-0ubuntu1) xenial; urgency=medium [ Shih-Yuan Lee (FourDollars) ] * power: On raw backlight types, clamp the value to a minumum (LP: #1381625) gsd-rr: Apply the similar method from power plugin to fix the lowest brightness issue. (LP: #1381625) (LP: #1381625) -- Shih-Yuan Lee Wed, 18 Nov 2015 09:36:58 +0000 unity-settings-daemon (15.04.1+16.04.20151106-0ubuntu1) xenial; urgency=medium [ CI Train Bot ] * New rebuild forced. [ Lars Uebernickel ] * power: disconnect signals from rr_screen (LP: #1508327) [ Mitsuya Shibata ] * unity-settings-daemon should initialize org.gnome.desktop.input- sources for fcitx as same as ibus when sources property is empty. (LP: #1465535) [ Sebastien Bacher ] * remove g_warning debug leftover * wacom: backport upstream change to use correct device types * xsettings: disconnect signal from plugin_settings -- Sebastien Bacher Fri, 06 Nov 2015 14:40:42 +0000 unity-settings-daemon (15.04.1+15.10.20151021-0ubuntu1) wily; urgency=medium [ Lars Uebernickel ] * power: disconnect from device's "notify" signals (LP: #1436861) -- Sebastien Bacher Wed, 21 Oct 2015 11:05:04 +0000 unity-settings-daemon (15.04.1+15.10.20151012-0ubuntu1) wily; urgency=medium [ "Jan Alexander Steffens (heftig)" ] * xsettings: Export cursor theme on X RESOURCE_MANAGER and notify X on changes (LP: #1505161) [ Marco Trevisan (Treviño) ] * xsettings: Export cursor theme on X RESOURCE_MANAGER and notify X on changes (LP: #1505161) -- Marco Trevisan (Treviño) Mon, 12 Oct 2015 14:39:35 +0000 unity-settings-daemon (15.04.1+15.10.20151008-0ubuntu1) wily; urgency=medium [ Bastien Nocera ] * housekeeping: Don't follow symlinks to subdirectories, that can lead to data being deleted that shouldn't * media-keys: Postpone initialisation of libcanberra [ Carlos Garnacho ] * [xsettings] backport some small fixes from upstream, should fix issues where settings changes are delayed [ Cosimo Cecchi ] * housekeeping: Don't follow symlinks to subdirectories, that can lead to data being deleted that shouldn't [ Florian Müllner ] * [xsettings] backport some small fixes from upstream, should fix issues where settings changes are delayed [ Jan Alexander Steffens (heftig) ] * [xsettings] backport some small fixes from upstream, should fix issues where settings changes are delayed [ Kalev Lember ] * [xsettings] backport some small fixes from upstream, should fix issues where settings changes are delayed [ Matthias Clasen ] * [xsettings] backport some small fixes from upstream, should fix issues where settings changes are delayed [ Peter Hutterer ] * Backport changes from upstream git and https://bugzilla.gnome.org/show_bug.cgi?id=724789 to better handle XError [ Ryan Lortie ] * [xsettings] backport some small fixes from upstream, should fix issues where settings changes are delayed [ Sebastien Bacher ] * [orientation] tweaked version of upstream fix for settings updates * [xrandr] slightly updated version of an upstream bugfix for a segfault issue (LP: #1298024) -- Sebastien Bacher Thu, 08 Oct 2015 16:15:07 +0000 unity-settings-daemon (15.04.1+15.10.20151001-0ubuntu1) wily; urgency=medium [ Robert Ancell ] * Fix shell watch callback not being destroyed. (LP: #1501576) [ William Hua ] * Don't call fcitx_input_method_activate (). It breaks fcitx' "extra key for trigger input method" shortcut. (LP: #1494331) -- Sebastien Bacher Thu, 01 Oct 2015 09:45:25 +0000 unity-settings-daemon (15.04.1+15.10.20150930-0ubuntu1) wily; urgency=medium [ Rui Matos ] * Backport upstream commit (LP: #1496656) -- Sebastien Bacher Wed, 30 Sep 2015 15:47:07 +0000 unity-settings-daemon (15.04.1+15.10.20150917-0ubuntu1) wily; urgency=medium [ Michael Terry ] * Notice when unplugging a closed laptop and apply the correct policy. (LP: #1456745) -- Iain Lane Thu, 17 Sep 2015 09:49:32 +0000 unity-settings-daemon (15.04.1+15.10.20150825-0ubuntu1) wily; urgency=medium [ Alberto Milone ] * Make touchscreen mapping non-blocking, and kill it if it takes more than 3 seconds; finally, in case of failure, try again after a few seconds. This helps on resume from S3 (LP: #1471708). (LP: #1471708) -- CI Train Bot Tue, 25 Aug 2015 09:09:33 +0000 unity-settings-daemon (15.04.1+15.10.20150818-0ubuntu1) wily; urgency=medium [ Carlos Garnacho ] * Cherry-pick upstream changes for relocated peripheral settings (LP: #1475949) [ Tim Lunn ] * Cherry-pick upstream changes for relocated peripheral settings (LP: #1475949) [ darkxst ] * Cherry-pick upstream changes for relocated peripheral settings (LP: #1475949) -- CI Train Bot Tue, 18 Aug 2015 12:11:23 +0000 unity-settings-daemon (15.04.1+15.10.20150720-0ubuntu1) wily; urgency=medium [ Lars Uebernickel ] * mouse: allow force-disabling touchpad (LP: #1454950) * xsettings: include needed libs for test program -- CI Train Bot Mon, 20 Jul 2015 15:39:14 +0000 unity-settings-daemon (15.04.1+15.10.20150630.1-0ubuntu1) wily; urgency=medium [ CI Train Bot ] * New rebuild forced. [ Dmitry Shachnev ] * xsettings: fix some settings not being updated with the latest glib [ Marco Trevisan (Treviño) ] * AutoMount: also try to connect to Unity Session and delay automounts when locked (LP: #1438870) -- CI Train Bot Tue, 30 Jun 2015 15:48:02 +0000 unity-settings-daemon (15.04.1+15.04.20150408-0ubuntu1) vivid; urgency=medium [ Sebastien Bacher ] * Don't scale under unity-greeter, it creates issues. That can be revisited once bug #1286878 and #1434094 are resolved but that's not going to be for this cycle (LP: #1434094, #1286878) -- CI Train Bot Wed, 08 Apr 2015 14:46:48 +0000 unity-settings-daemon (15.04.1+15.04.20150401-0ubuntu1) vivid; urgency=medium [ Ryan Tandy ] * gsd_idle_monitor_get_idletime() has to return a value. Use the correct macro for that. Fixes r4073. (LP: #1416081) [ Sebastien Bacher ] * let the label wrap as they should in the mount dialog -- CI Train Bot Wed, 01 Apr 2015 10:40:40 +0000 unity-settings-daemon (15.04.1+15.04.20150324.1-0ubuntu1) vivid; urgency=medium [ CI Train Bot ] * New rebuild forced. [ Sebastien Bacher ] * use timestamp provided by compiz to run keybinding commands so focus works (LP: #1433648) -- CI Train Bot Tue, 24 Mar 2015 16:09:44 +0000 unity-settings-daemon (15.04.1+15.04.20150318-0ubuntu1) vivid; urgency=medium [ Ryan Tandy ] * Don't call XSyncQueryCounter with a null counter. Avoids a crash under FreeNX/X2Go which don't support the IDLETIME counter. (LP: #1416081) [ Sebastien Bacher ] * Open the battery info dialog when using the corresponding hotkey. The current code was trying to display a notification with the info but we don't have design on how that should look like with notify- osd so go back to what we were doing before (LP: #1432976) * Restore code that set the scaling factor according the screen dpi, but only when not under and Unity session. That was desactived in r4020 because Unity is handling those values, but this is not the case under ubiquity or unity-greeter. (LP: #1286878) -- CI Train Bot Wed, 18 Mar 2015 12:07:44 +0000 unity-settings-daemon (15.04.1+15.04.20150313-0ubuntu1) vivid; urgency=medium [ William Hua ] * Remove fcitx-data from Recommends and check if the required file, config.desc, is available at runtime. Trying to dist-upgrade currently pulls in the fcitx-bin which is higher priority than ibus. (LP: #1430971) -- CI Train Bot Fri, 13 Mar 2015 12:54:01 +0000 unity-settings-daemon (15.04.1+15.04.20150310-0ubuntu1) vivid; urgency=medium [ William Hua ] * Basic Fcitx support. (LP: #1363150) -- CI Train Bot Tue, 10 Mar 2015 17:22:52 +0000 unity-settings-daemon (15.04.1+15.04.20150205-0ubuntu1) vivid; urgency=medium [ Sebastien Bacher ] * housekeeping: set labels width, so they wrap instead of stretching the dialog -- Ubuntu daily release Thu, 05 Feb 2015 11:19:40 +0000 unity-settings-daemon (15.04.1+15.04.20150107-0ubuntu1) vivid; urgency=low [ Hui Wang ] * show correct microphone mute icon (LP: #1381856, #1389099) -- Ubuntu daily release Wed, 07 Jan 2015 16:55:42 +0000 unity-settings-daemon (15.04.1+15.04.20141128-0ubuntu1) vivid; urgency=low [ Bastien Nocera ] * Remove recall check, upower doesn't support this any more and it was causing a crash. (LP: #1397135) -- Ubuntu daily release Fri, 28 Nov 2014 09:48:43 +0000 unity-settings-daemon (15.04.1+15.04.20141127-0ubuntu1) vivid; urgency=medium [ Iain Lane ] * Add patch from Tim Lunn to support upower 0.99 properly. (LP: #1394063) [ Dmitry Shachnev ] * Add Gtk/DecorationLayout XSettings export (based on org.gnome.desktop.wm.preferences button-layout GSettings key). -- Ubuntu daily release Thu, 27 Nov 2014 11:42:11 +0000 unity-settings-daemon (15.04.0+15.10.20141030-0ubuntu1) vivid; urgency=medium [ Tim Lunn ] * Query logind instead of upower for "can suspend/hibernate", and rebuild against upower 0.99. (LP: #1330037) [ Martin Pitt ] * Add missing Vcs-Bzr: control field. -- Martin Pitt Thu, 30 Oct 2014 17:29:53 +0100 unity-settings-daemon (14.04.0+14.10.20141014-0ubuntu1) utopic; urgency=low [ Lars Uebernickel ] * Idle monitor: fix ref counting bugs (LP: #1380278) -- Ubuntu daily release Tue, 14 Oct 2014 15:25:59 +0000 unity-settings-daemon (14.04.0+14.10.20141010-0ubuntu1) utopic; urgency=low [ Tim Lunn ] * Copy in Idle Monitor from 3.10 and hook up dbus interface (LP: #1377847) -- Ubuntu daily release Fri, 10 Oct 2014 08:06:04 +0000 unity-settings-daemon (14.04.0+14.10.20140922-0ubuntu3) utopic; urgency=medium * Rebuild for gnome-desktop 3.12 (LP: #1372346) * debian/control: Drop depends gnome-settings-daemon-schemas (<< 3.10), gnome-settings-daemon 3.12 reverts all removed keys * Fix merge of git patch for xkb get/free info_vars -- Tim Lunn Mon, 29 Sep 2014 20:05:27 +1000 unity-settings-daemon (14.04.0+14.10.20140922-0ubuntu2) utopic; urgency=medium * debian/control: - Move -dev dependencies from libunity-settings-daemon1 to libunity-settings-daemon-dev and add it to the correct section (LP: #1372728) -- Robert Ancell Wed, 24 Sep 2014 15:38:13 +1200 unity-settings-daemon (14.04.0+14.10.20140922-0ubuntu1) utopic; urgency=low [ Robert Ancell ] * Move libgnome-desktop RandR code into u-s-d since newer versions remove this unstable API (LP: #1372240) [ Rui Matos ] * Apply git patch that pulls in code removed from gnome-desktop3 3.12 [ Bastien Nocera ] * common: Check the exit status of hotplug scripts correctly [ Tim Lunn ] * Apply git patch that pulls in code removed from gnome-desktop3 3.12 -- Ubuntu daily release Mon, 22 Sep 2014 11:29:11 +0000 unity-settings-daemon (14.04.0+14.10.20140605-0ubuntu2) utopic; urgency=medium * No-change rebuild against new colord -- Iain Lane Tue, 10 Jun 2014 11:36:54 +0100 unity-settings-daemon (14.04.0+14.10.20140605-0ubuntu1) utopic; urgency=low [ Alberto Milone ] * gsd-xrandr-manager.c: do not try to map an invalid touch device on initialisation Fixes LP: #1326636 (LP: #1326636) -- Ubuntu daily release Thu, 05 Jun 2014 10:21:46 +0000 unity-settings-daemon (14.04.0+14.10.20140604-0ubuntu1) utopic; urgency=medium [ Alberto Milone ] * gsd-xrandr-manager.c: - Add support for mapping the main touchscreen onto the laptop display (LP: #1287341). This makes sure that the input device knows exactly the area that represents the display when the screen configuration changes. Note: this doesn't cover the tablet use case. - Add support for matching displays with touch input devices according to the reported size. This is particularly useful on systems that don't use embedded display connectors i.e. all-in-one systems such as the Dell Optiplex 9030 AIO. - This work is a partial backport of the upstream work on touchscreens. When we finally sync with the upstream code we can drop this. -- Ubuntu daily release Wed, 04 Jun 2014 15:42:47 +0000 unity-settings-daemon (14.04.0+14.04.20140414-0ubuntu1) trusty; urgency=low [ Dmitry Shachnev ] * Backport g-s-d patch to fix consecutive xkb grp: options not being stripped, thanks Роман Донченко. -- Ubuntu daily release Mon, 14 Apr 2014 10:13:11 +0000 unity-settings-daemon (14.04.0+14.04.20140407-0ubuntu1) trusty; urgency=low [ William Hua ] * Revert regression caused by commit 4033. (LP: #1302353) -- Ubuntu daily release Mon, 07 Apr 2014 14:55:36 +0000 unity-settings-daemon (14.04.0+14.04.20140404-0ubuntu1) trusty; urgency=low [ William Hua ] * Add a private DBus method that allows us to change the current input source without saving it in GSettings. This is needed for indicator- keyboard to temporarily switch input sources on the lock screen without affecting the user's session input source. -- Ubuntu daily release Fri, 04 Apr 2014 16:20:28 +0000 unity-settings-daemon (14.04.0+14.04.20140402-0ubuntu1) trusty; urgency=low [ Jackson Doak ] * define XF86AudioMicMute as a mic mute key [ William Hua ] * Treat IBus engines with 'default' layouts as 'us'. (LP: #1298740) -- Ubuntu daily release Wed, 02 Apr 2014 11:06:42 +0000 unity-settings-daemon (14.04.0+14.04.20140310-0ubuntu2) trusty; urgency=medium * unity-settings-demon.user-session.upstart: Use XDG_CURRENT_DESKTOP as the instance specifier for gnome-session upstart jobs, since other sessions apart from ubuntu will need to use u-s-d (LP: #1224217) -- Tim Lunn Wed, 12 Mar 2014 16:45:51 +1100 unity-settings-daemon (14.04.0+14.04.20140310-0ubuntu1) trusty; urgency=low [ David Henningsson ] * Fix what-did-you-plug-in dialog showing up behind other windows. Simplify launching of "unity-control-center sound". (LP: #1287584) -- Ubuntu daily release Mon, 10 Mar 2014 17:25:56 +0000 unity-settings-daemon (14.04.0+14.04.20140228-0ubuntu1) trusty; urgency=low [ Sebastien Bacher ] * Backport some small upstream bugfixes * Enforce schemas from the same serie, some ppa are shipping newer versions of gnome-settings-daemon which drop keys and that's leading to reports against unity-settings-daemon. That way users are warned and get to choose what option they want. [ Luke Yelavich ] * Look for gtk-modules related files in the correct location. -- Ubuntu daily release Fri, 28 Feb 2014 17:08:18 +0000 unity-settings-daemon (14.04.0+14.04.20140225-0ubuntu1) trusty; urgency=low [ Lars Uebernickel ] * media-keys: add support for allow-amplified-volume When that key is set, the maximum volume is PA_VOLUME_UI_MAX instead of PA_VOLUME_NORM. This makes it consistent with the sound indicator and system settings. -- Ubuntu daily release Tue, 25 Feb 2014 09:33:38 +0000 unity-settings-daemon (14.04.0+14.04.20140221.1-0ubuntu1) trusty; urgency=low [ Iain Lane ] * Instead of autodetecting the scaling factor, default to 1 if the key is set to '0'. unity-control-center should be calculating the value and setting this key accordingly, otherwise the Unity and gtk values can get out of sync. -- Ubuntu daily release Fri, 21 Feb 2014 18:45:23 +0000 unity-settings-daemon (14.04.0+14.04.20140221-0ubuntu1) trusty; urgency=low [ Iain Lane ] * Always use gnome-screenshot directly, not the gnome-shell screenshot interface. We aren't using the legacy keygrabber under Unity, but neither can we use gnome-shell's interface since Unity doesn't implement it. (LP: #1282649) -- Ubuntu daily release Fri, 21 Feb 2014 13:48:58 +0000 unity-settings-daemon (14.04.0+14.04.20140219-0ubuntu1) trusty; urgency=low [ David Henningsson ] * Handle unknown audio jack devices. [ William Hua ] * Revert the legacy key grabber. (LP: #1226962) [ Sebastien Bacher ] * backport upstream change to support hi-dpi screens/scaling. You can change the scaling value by writting the "org.gnome.desktop.interface scaling-factor" gsettings key -- Ubuntu daily release Wed, 19 Feb 2014 10:44:06 +0000 unity-settings-daemon (14.04.0-0ubuntu2) trusty; urgency=medium * Change power notifications from popups (expire never), to notify-osd bubbles (default timeout). * Start on gnome-session (ubuntu instance) only (for now). -- Dimitri John Ledkov Mon, 17 Feb 2014 11:35:35 +0000 unity-settings-daemon (14.04.0-0ubuntu1) trusty; urgency=low * Fork gnome-settings-daemon so we can maintain it for Unity 7 until it is replaced by the Unity 8 equivalent. -- Robert Ancell Fri, 07 Feb 2014 11:44:36 +0000 unity-settings-daemon/debian/control0000664000000000000000000001176515172222611015053 0ustar Source: unity-settings-daemon Section: gnome Priority: optional Maintainer: Ubuntu Desktop Team Build-Depends: debhelper-compat (= 13), dh-sequence-translations, gtk-doc-tools, dh-autoreconf, autotools-dev, intltool (>= 0.37.1), libdbus-glib-1-dev (>= 0.74), libglib2.0-dev (>= 2.35.3), libgtk-3-dev (>= 3.7.8), libgdk-pixbuf-2.0-dev (>= 2.23.0), libnm-dev (>= 1.0) [linux-any], libnotify-dev (>= 0.7.0), libxt-dev, libxi-dev, libfontconfig1-dev, libxext-dev, libx11-dev, libxtst-dev, gsettings-desktop-schemas-dev (>= 3.15.4), gsettings-unity-schemas-dev (>= 0.0.7+21.10.20210712-0ubuntu1), libgnome-desktop-3-dev (>= 3.7.90), libpulse-dev (>= 1:2.0), libasound2-dev, librsvg2-dev (>= 2.36.2), libcanberra-gtk3-dev, libpolkit-gobject-1-dev, libaccountsservice-dev (>= 0.6.34), libappindicator3-dev (>= 0.4.90), hwdata, libupower-glib-dev (>= 0.99.1), libcolord-dev (>= 0.1.12), liblcms2-dev, libnss3-dev, libgudev-1.0-dev, libwacom-dev (>= 0.7), xserver-xorg-input-wacom, libgnomekbd-dev (>= 3.5.1), libxklavier-dev, libsystemd-dev (>= 183), libibus-1.0-dev (>= 1.5.0), fcitx-libs-dev, gperf, libgl1-mesa-dev, libxkbfile-dev, xkb-data, python-is-python3 Standards-Version: 3.9.3 Vcs-Bzr: https://code.launchpad.net/~unity-settings-daemon-team/unity-settings-daemon/trunk X-Ubuntu-Use-Langpack: yes Package: unity-settings-daemon Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, accountsservice (>= 0.6.34), gsettings-desktop-schemas (>= 3.15.4), gsettings-ubuntu-schemas (>= 0.0.7+21.10.20210712-0ubuntu1), nautilus-data (>= 2.91.3-1), unity-settings-daemon-schemas (>= ${source:Version}), Recommends: ibus (>= 1.5.0), pulseaudio, systemd-services Pre-Depends: ${misc:Pre-Depends} Breaks: rhythmbox (<< 0.11.5), banshee (<< 0.13.2+dfsg-7), totem (<< 2.22.0), gnome-control-center (<< 1:3.6.3-0ubuntu35), gnome-session (<< 3.9.90-0ubuntu6), gnome-screensaver (<< 2.28.0), gnome-color-manager (<< 3.0), unity (<< 7.3.2), unity-greeter (<< 0.2.1-0ubuntu1), indicator-datetime (<< 12.10.3daily13.03.26), ubuntu-session (<< 3.24.1-0ubuntu3~), Suggests: x11-xserver-utils, gnome-screensaver, metacity | x-window-manager Description: daemon handling the Unity session settings This package contains the daemon which is responsible for setting the various parameters of a Unity session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: unity-settings-daemon-dev Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libdbus-glib-1-dev (>= 0.74), libglib2.0-dev (>= 2.35.3) Description: Headers for building applications communicating with unity-settings-daemon This package contains header files required to build applications that communicate with the Unity settings daemon over D-Bus. Package: unity-settings-daemon-schemas Architecture: all Depends: ${misc:Depends} Replaces: gnome-settings-daemon (<< 3.20.1-2ubuntu1~) Breaks: gnome-settings-daemon (<< 3.20.1-2ubuntu1~) Description: Shared schemas for gnome-settings-daemon This package contains the gsettings schemas used by unity-settings-daemon. Package: libunity-settings-daemon1 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: ${shlibs:Depends}, ${misc:Depends} Description: Helper library for accessing settings This package contains a helper library for unity-control-center Package: libunity-settings-daemon-dev Section: libdevel Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends}, libunity-settings-daemon1 (= ${binary:Version}), libglib2.0-dev, libgtk-3-dev, libgdk-pixbuf-2.0-dev, libgnome-desktop-3-dev Description: Helper library for accessing settings (development files) This package contains a headers for using libunity-settings-daemon unity-settings-daemon/debian/copyright0000664000000000000000000000554615172222611015403 0ustar This package was debianized by Sebastien Bacher on Wed, 16 Jan 2008 11:12:19 +0100. It was downloaded from http://ftp.acc.umu.se/pub/GNOME/sources/gnome-settings-daemon Upstream Authors: Jonathan Blandford William Jon McCann Copyright: Copyright © 2001 Ximian, Inc. Copyright (C) 2007 William Jon McCann Copyright (C) 2000 Helix Code, Inc Copyright © 2007 Matthias Clasen Copyright (C) 2007 Rodrigo Moya Copyright (C) 2007 Anders Carlsson Copyright © 2004 Red Hat, Inc. Copyright 2002 Sun Microsystems, Inc. Copyright © 2005,2006 Novell, Inc. Copyright © 2007 The GNOME Foundation Copyright (C) 2002-2005 - Paolo Maggi Copyright (C) 2002 Red Hat, Inc. Copyright 1998, 2001 Tim Janik Copyright � 2001 Udaltsoft Copyright (C) 2001, 2002, 2003 Bastien Nocera Copyright (C) 2003 Ross Burton Copyright © 2001 Jonathan Blandford License: This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA On Debian systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL'. eggaccelerators.h, eggaccelerators.c License: This package is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA On Debian systems, the complete text of the GNU Lesser General Public License can be found in `/usr/share/common-licenses/LGPL'. The Debian packaging is (C) 2008, Sebastien Bacher and is licensed under the GPL, see above. unity-settings-daemon/debian/gnome-update-wallpaper-cache.c0000664000000000000000000000406715172222611021224 0ustar /* * Copyright (C) 2010 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License version 3.0 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authored by Didier Roche * * Bug: https://bugs.launchpad.net/bugs/530024 */ #include #include #define GNOME_DESKTOP_USE_UNSTABLE_API #include static GOptionEntry entries[] = { { NULL } }; main (int argc, char *argv[]) { GOptionContext *context = NULL; GError *error = NULL; GdkScreen *screen; GdkRectangle rect; GnomeBG *bg; GSettings *settings; GdkPixbuf *pixbuf; gdk_init (&argc, &argv); context = g_option_context_new ("- refresh wallpaper cache"); g_option_context_add_main_entries (context, entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("option parsing failed: %s\n", error->message); g_option_context_free(context); g_error_free (error); return (1); } if (context) g_option_context_free (context); /* cache only the first monitor */ screen = gdk_screen_get_default (); gdk_screen_get_monitor_geometry (screen, 0, &rect); bg = gnome_bg_new (); settings = g_settings_new ("org.gnome.desktop.background"); gnome_bg_load_from_preferences (bg, settings); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, rect.width, rect.height); gnome_bg_draw (bg, pixbuf, screen, FALSE); g_object_unref (settings); return (0); } unity-settings-daemon/debian/libunity-settings-daemon1.install0000664000000000000000000000006315172222611022044 0ustar debian/tmp/usr/lib/*/libunity-settings-daemon.so.* unity-settings-daemon/debian/libunity-settings-daemon1.symbols0000664000000000000000000001367315172222611022101 0ustar libunity-settings-daemon.so.1 libunity-settings-daemon1 #MINVER# gsd_idle_monitor_add_idle_watch@Base 14.04.0 gsd_idle_monitor_add_user_active_watch@Base 14.04.0 gsd_idle_monitor_get_core@Base 14.10 gsd_idle_monitor_get_for_device@Base 14.10 gsd_idle_monitor_get_idletime@Base 14.04.0 gsd_idle_monitor_get_type@Base 14.04.0 gsd_idle_monitor_handle_xevent_all@Base 14.10 gsd_idle_monitor_init_dbus@Base 14.10 gsd_idle_monitor_remove_watch@Base 14.04.0 gsd_pnp_ids_get_pnp_id@Base 14.04.0 gsd_pnp_ids_get_type@Base 14.04.0 gsd_pnp_ids_new@Base 14.04.0 gsd_rr_config_applicable@Base 14.04.0 gsd_rr_config_apply_from_filename_with_time@Base 14.04.0 gsd_rr_config_apply_with_time@Base 14.04.0 gsd_rr_config_ensure_primary@Base 14.04.0 gsd_rr_config_equal@Base 14.04.0 gsd_rr_config_get_backup_filename@Base 14.04.0 gsd_rr_config_get_clone@Base 14.04.0 gsd_rr_config_get_intended_filename@Base 14.04.0 gsd_rr_config_get_outputs@Base 14.04.0 gsd_rr_config_get_type@Base 14.04.0 gsd_rr_config_load_current@Base 14.04.0 gsd_rr_config_load_filename@Base 14.04.0 gsd_rr_config_match@Base 14.04.0 gsd_rr_config_new_current@Base 14.04.0 gsd_rr_config_new_stored@Base 14.04.0 gsd_rr_config_sanitize@Base 14.04.0 gsd_rr_config_save@Base 14.04.0 gsd_rr_config_set_clone@Base 14.04.0 gsd_rr_crtc_can_drive_output@Base 14.04.0 gsd_rr_crtc_get_current_mode@Base 14.04.0 gsd_rr_crtc_get_current_rotation@Base 14.04.0 gsd_rr_crtc_get_gamma@Base 14.04.0 gsd_rr_crtc_get_id@Base 14.04.0 gsd_rr_crtc_get_position@Base 14.04.0 gsd_rr_crtc_get_rotations@Base 14.04.0 gsd_rr_crtc_get_type@Base 14.04.0 gsd_rr_crtc_set_config_with_time@Base 14.04.0 gsd_rr_crtc_set_gamma@Base 14.04.0 gsd_rr_crtc_supports_rotation@Base 14.04.0 gsd_rr_error_quark@Base 14.04.0 gsd_rr_mode_get_freq@Base 14.04.0 gsd_rr_mode_get_height@Base 14.04.0 gsd_rr_mode_get_id@Base 14.04.0 gsd_rr_mode_get_type@Base 14.04.0 gsd_rr_mode_get_width@Base 14.04.0 gsd_rr_output_can_clone@Base 14.04.0 gsd_rr_output_get_backlight@Base 14.04.0 gsd_rr_output_get_backlight_max@Base 14.04.0 gsd_rr_output_get_backlight_min@Base 14.04.0 gsd_rr_output_get_connector_type@Base 14.04.0 gsd_rr_output_get_crtc@Base 14.04.0 gsd_rr_output_get_current_mode@Base 14.04.0 gsd_rr_output_get_display_name@Base 14.04.0 gsd_rr_output_get_edid_data@Base 14.04.0 gsd_rr_output_get_height_mm@Base 14.04.0 gsd_rr_output_get_id@Base 14.04.0 gsd_rr_output_get_ids_from_edid@Base 14.04.0 gsd_rr_output_get_is_primary@Base 14.04.0 gsd_rr_output_get_name@Base 14.04.0 gsd_rr_output_get_position@Base 14.04.0 gsd_rr_output_get_preferred_mode@Base 14.04.0 gsd_rr_output_get_type@Base 14.04.0 gsd_rr_output_get_width_mm@Base 14.04.0 gsd_rr_output_info_get_aspect_ratio@Base 14.04.0 gsd_rr_output_info_get_display_name@Base 14.04.0 gsd_rr_output_info_get_geometry@Base 14.04.0 gsd_rr_output_info_get_name@Base 14.04.0 gsd_rr_output_info_get_preferred_height@Base 14.04.0 gsd_rr_output_info_get_preferred_width@Base 14.04.0 gsd_rr_output_info_get_primary@Base 14.04.0 gsd_rr_output_info_get_product@Base 14.04.0 gsd_rr_output_info_get_refresh_rate@Base 14.04.0 gsd_rr_output_info_get_rotation@Base 14.04.0 gsd_rr_output_info_get_serial@Base 14.04.0 gsd_rr_output_info_get_type@Base 14.04.0 gsd_rr_output_info_get_vendor@Base 14.04.0 gsd_rr_output_info_is_active@Base 14.04.0 gsd_rr_output_info_is_connected@Base 14.04.0 gsd_rr_output_info_set_active@Base 14.04.0 gsd_rr_output_info_set_geometry@Base 14.04.0 gsd_rr_output_info_set_primary@Base 14.04.0 gsd_rr_output_info_set_refresh_rate@Base 14.04.0 gsd_rr_output_info_set_rotation@Base 14.04.0 gsd_rr_output_is_connected@Base 14.04.0 gsd_rr_output_is_laptop@Base 14.04.0 gsd_rr_output_list_modes@Base 14.04.0 gsd_rr_output_set_backlight@Base 14.04.0 gsd_rr_output_supports_mode@Base 14.04.0 gsd_rr_screen_get_crtc_by_id@Base 14.04.0 gsd_rr_screen_get_dpms_mode@Base 14.04.0 gsd_rr_screen_get_output_by_id@Base 14.04.0 gsd_rr_screen_get_output_by_name@Base 14.04.0 gsd_rr_screen_get_ranges@Base 14.04.0 gsd_rr_screen_get_timestamps@Base 14.04.0 gsd_rr_screen_get_type@Base 14.04.0 gsd_rr_screen_list_clone_modes@Base 14.04.0 gsd_rr_screen_list_crtcs@Base 14.04.0 gsd_rr_screen_list_modes@Base 14.04.0 gsd_rr_screen_list_outputs@Base 14.04.0 gsd_rr_screen_new@Base 14.04.0 gsd_rr_screen_refresh@Base 14.04.0 gsd_rr_screen_set_dpms_mode@Base 14.04.0 gsd_rr_screen_set_primary_output@Base 14.04.0 gsd_rr_screen_set_size@Base 14.04.0 gsd_bg_get_type@Base 14.04.0 gsd_bg_new@Base 14.04.0 gsd_bg_load_from_preferences@Base 14.04.0 gsd_bg_save_to_preferences@Base 14.04.0 gsd_bg_set_filename@Base 14.04.0 gsd_bg_set_placement@Base 14.04.0 gsd_bg_set_rgba@Base 14.04.0 gsd_bg_set_draw_background@Base 14.04.0 gsd_bg_get_placement@Base 14.04.0 gsd_bg_get_draw_background@Base 14.04.0 gsd_bg_get_rgba@Base 14.04.0 gsd_bg_get_filename@Base 14.04.0 gsd_bg_draw@Base 14.04.0 gsd_bg_create_surface@Base 14.04.0 gsd_bg_get_image_size@Base 14.04.0 gsd_bg_create_thumbnail@Base 14.04.0 gsd_bg_is_dark@Base 14.04.0 gsd_bg_has_multiple_sizes@Base 14.04.0 gsd_bg_changes_with_time@Base 14.04.0 gsd_bg_create_frame_thumbnail@Base 14.04.0 gsd_bg_set_surface_as_root@Base 14.04.0 gsd_bg_set_surface_as_root_with_crossfade@Base 14.04.0 gsd_bg_get_surface_from_root@Base 14.04.0 gsd_bg_crossfade_get_type@Base 14.04.0 gsd_bg_crossfade_new@Base 14.04.0 gsd_bg_crossfade_set_start_surface@Base 14.04.0 gsd_bg_crossfade_set_end_surface@Base 14.04.0 gsd_bg_crossfade_start@Base 14.04.0 gsd_bg_crossfade_is_started@Base 14.04.0 gsd_bg_crossfade_stop@Base 14.04.0 gsd_bg_slide_show_get_type@Base 14.04.0 gsd_bg_slide_show_new@Base 14.04.0 gsd_bg_slide_show_load@Base 14.04.0 gsd_bg_slide_show_load_async@Base 14.04.0 gsd_bg_slide_show_get_slide@Base 14.04.0 gsd_bg_slide_show_get_current_slide@Base 14.04.0 gsd_bg_slide_show_get_start_time@Base 14.04.0 gsd_bg_slide_show_get_total_duration@Base 14.04.0 gsd_bg_slide_show_get_has_multiple_sizes@Base 14.04.0 gsd_bg_slide_show_get_num_slides@Base 14.04.0 unity-settings-daemon/debian/not-installed0000664000000000000000000000046315172222611016141 0ustar usr/lib/udev/rules.d/61-unity-settings-daemon-rfkill.rules usr/lib/${DEB_HOST_MULTIARCH}/libunity-settings-daemon.{a,la} usr/lib/${DEB_HOST_MULTIARCH}/unity-settings-daemon-1.0/*.{a,la} usr/share/locale usr/share/man/man1/unity-settings-daemon.1 usr/share/unity-settings-daemon-1.0/input-device-example.sh unity-settings-daemon/debian/rules0000775000000000000000000000101315172222611014511 0ustar #!/usr/bin/make -f CONFIGURE_EXTRA_FLAGS = --disable-packagekit --enable-ibus --enable-fcitx --enable-network-manager %: dh $@ --with autoreconf,translations override_dh_auto_configure: dh_auto_configure -- $(CONFIGURE_EXTRA_FLAGS) override_dh_installdocs: dh_installdocs -plibunity-settings-daemon1 dh_installdocs --link-doc=libunity-settings-daemon1 -plibunity-settings-daemon-dev dh_installdocs -punity-settings-daemon dh_installdocs -punity-settings-daemon-schemas dh_installdocs -punity-settings-daemon-dev unity-settings-daemon/debian/source/0000775000000000000000000000000015172222611014736 5ustar unity-settings-daemon/debian/source/format0000664000000000000000000000000415172222611016143 0ustar 1.0 unity-settings-daemon/debian/source_unity-settings-daemon.py0000664000000000000000000000157415172222611021646 0ustar import os, apport.packaging, re from apport.hookutils import * def add_info(report): # the issue is not in the unity-settings-daemon code so reassign if "Stacktrace" in report and "/usr/lib/gnome-settings-daemon-3.0" in report["Stacktrace"]: for words in report["Stacktrace"].split(): if words.startswith("/usr/lib/unity-settings-daemon-3.0"): if apport.packaging.get_file_package(words) != 'unity-settings-daemon': report.add_package_info(apport.packaging.get_file_package(words)) return # update the title to reflect the component and tab component = re.compile("lib(\w*).so").search(words).groups(1)[0] report['Title'] = '[%s]: %s' % (component, report.get('Title', report.standard_title())) report['Tags'] = '%s %s' % (report.get('Tags', ""), component) break # Stop on the first .so that's the interesting one unity-settings-daemon/debian/unity-settings-daemon-dev.install0000664000000000000000000000010615172222611022046 0ustar usr/include usr/lib/*/pkgconfig usr/lib/*/libunity-settings-daemon.so unity-settings-daemon/debian/unity-settings-daemon-schemas.install0000664000000000000000000000004415172222611022714 0ustar debian/*/usr/share/glib-*/schemas/* unity-settings-daemon/debian/unity-settings-daemon.install0000664000000000000000000000152015172222611021273 0ustar data/unity-settings-daemon.desktop /usr/share/upstart/xdg/autostart/unity-settings-daemon.desktop etc usr/lib/*/unity-settings-daemon-1.0/*.so /usr/lib/unity-settings-daemon-1.0/ usr/lib/*/unity-settings-daemon-1.0/*.gnome-settings-plugin /usr/lib/unity-settings-daemon-1.0 usr/libexec/* /usr/lib/unity-settings-daemon/ usr/share/unity-settings-daemon usr/share/polkit-1 usr/share/icons/hicolor/16x16/apps/usd-xrandr.png usr/share/icons/hicolor/22x22/apps/usd-xrandr.png usr/share/icons/hicolor/24x24/apps/usd-xrandr.png usr/share/icons/hicolor/32x32/apps/usd-xrandr.png usr/share/icons/hicolor/scalable/apps/usd-xrandr.svg debian/source_unity-settings-daemon.py /usr/share/apport/package-hooks debian/user/unity-settings-daemon.service /usr/lib/systemd/user/ debian/user/unity-settings-daemon.override /usr/share/upstart/systemd-session/upstart/ unity-settings-daemon/debian/unity-settings-daemon.links0000664000000000000000000000042315172222611020746 0ustar usr/lib/unity-settings-daemon/unity-settings-daemon usr/bin/unity-settings-daemon # needed until unity7 gets a systemd unit with Requires=u-s-d /usr/lib/systemd/user/unity-settings-daemon.service /usr/lib/systemd/user/unity-session.target.wants/unity-settings-daemon.service unity-settings-daemon/debian/unity-settings-daemon.maintscript0000664000000000000000000000065315172222611022170 0ustar rm_conffile /etc/gnome/config/Editres.ad 3.6.3-0ubuntu3~ rm_conffile /etc/gnome/config/Emacs.ad 3.6.3-0ubuntu3~ rm_conffile /etc/gnome/config/General.ad 3.6.3-0ubuntu3~ rm_conffile /etc/gnome/config/Motif.ad 3.6.3-0ubuntu3~ rm_conffile /etc/gnome/config/Tk.ad 3.6.3-0ubuntu3~ rm_conffile /etc/gnome/config/Xaw.ad 3.6.3-0ubuntu3~ rm_conffile /etc/dbus-1/system.d/org.gnome.SettingsDaemon.DateTimeMechanism.conf 3.6.4-0ubuntu7~ unity-settings-daemon/debian/unity-settings-daemon.migrations0000664000000000000000000000003215172222611021776 0ustar scripts/*-usd-migration-* unity-settings-daemon/debian/unity-settings-daemon.postinst0000664000000000000000000000077315172222611021521 0ustar #! /bin/sh set -e #DEBHELPER# # Remove obsolete conffiles case "$1" in configure) if dpkg --compare-versions "$2" lt-nl "2.24.1"; then rm -rf /etc/gnome/config/xrdb fi if dpkg --compare-versions "$2" lt-nl "2.26.1"; then rm -f /etc/xdg/autostart/gnome-settings-daemon.desktop fi if dpkg --compare-versions "$2" lt-nl "3.6.3-0ubuntu3"; then if [ -d /etc/gnome/config ]; then rmdir --ignore-fail-on-non-empty /etc/gnome/config fi fi esac unity-settings-daemon/debian/unity-settings-daemon.user-session.desktop0000664000000000000000000000020215172222611023730 0ustar [Desktop Entry] Type=Application Name=Unity Settings Daemon Exec=/usr/lib/unity-settings-daemon/unity-settings-daemon Hidden=true unity-settings-daemon/debian/unity-settings-daemon.user-session.upstart0000664000000000000000000000064515172222611023774 0ustar description "The Unity Settings Daemon" author "Dimitri John Ledkov " start on started dbus and starting gnome-session stop on stopping gnome-session pre-start script for DESKTOP in $(echo "$XDG_CURRENT_DESKTOP" | sed 's/:/ /g') do if [ "x$DESKTOP" = "xUnity" ]; then exit 0 fi done stop end script respawn exec /usr/lib/unity-settings-daemon/unity-settings-daemon unity-settings-daemon/debian/user/0000775000000000000000000000000015172222611014414 5ustar unity-settings-daemon/debian/user/unity-settings-daemon.override0000664000000000000000000000013515172222611022423 0ustar # FIXME: can be moved to "manual" once unity7 gets a systemd service file # manual exec true unity-settings-daemon/debian/user/unity-settings-daemon.service0000664000000000000000000000024615172222611022247 0ustar [Unit] Description=Unity Settings Daemon PartOf=graphical-session.target [Service] ExecStart=/usr/lib/unity-settings-daemon/unity-settings-daemon Restart=on-failure unity-settings-daemon/gnome-settings-daemon/0000775000000000000000000000000015172222611016420 5ustar unity-settings-daemon/gnome-settings-daemon/Makefile.am0000664000000000000000000001227715172222611020465 0ustar NULL = BUILT_SOURCES = $(NULL) INCLUDES = \ -DDATADIR=\""$(datadir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ -DGNOME_SETTINGS_PLUGINDIR=\""$(plugindir)"\" \ -I$(top_srcdir)/plugins/common/ \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ $(SETTINGS_DAEMON_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(GNOME_DESKTOP_CFLAGS) \ $(NULL) privlibdir = $(pkglibdir)-$(GSD_API_VERSION) lib_LTLIBRARIES = libunity-settings-daemon.la libexec_PROGRAMS = check_gl_texture_size libunity_settings_daemon_la_SOURCES = \ gsd-pnp-ids.c \ gsd-pnp-ids.h \ gsd-rr.c \ gsd-rr.h \ gsd-rr-config.c \ gsd-rr-config.h \ gsd-rr-output-info.c \ gsd-rr-private.h \ display-name.c \ edid-parse.c \ edid.h \ gsd-idle-monitor.c \ gsd-idle-monitor.h \ gsd-bg.c \ gsd-bg.h \ gsd-bg-crossfade.c \ gsd-bg-crossfade.h \ gsd-bg-slide-show.c \ gsd-bg-slide-show.h nodist_libunity_settings_daemon_la_SOURCES = \ $(dbus_idle_built_sources) libunity_settings_daemon_include_HEADERS = \ gsd-pnp-ids.h \ gsd-rr.h \ gsd-rr-config.h \ gsd-idle-monitor.h \ gsd-bg.h \ gsd-bg-crossfade.h \ gsd-bg-slide-show.h libunity_settings_daemon_includedir = $(includedir)/unity-settings-daemon-$(GSD_API_VERSION)/libunity-settings-daemon libunity_settings_daemon_la_CFLAGS = \ -DLIBEXECDIR=\""$(libexecdir)\"" \ -DPNP_IDS=\""$(datadir)/hwdata/pnp.ids"\" \ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ $(LIBUNITY_SETTINGS_DAEMON_CFLAGS) libunity_settings_daemon_la_LIBADD = \ -lm \ $(LIBUNITY_SETTINGS_DAEMON_LIBS) libunity_settings_daemon_la_LDFLAGS = \ -version-info 1:0:0 \ -export-symbols-regex \^gsd_.* BUILT_SOURCES = $(dbus_idle_built_sources) dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml $(AM_V_GEN)gdbus-codegen \ --interface-prefix org.gnome.Mutter \ --c-namespace MetaDBus \ --generate-c-code meta-dbus-idle-monitor \ --c-generate-object-manager \ $(srcdir)/idle-monitor.xml check_gl_texture_size_CPPFLAGS = \ $(CHECK_GL_TEXTURE_SIZE_CFLAGS) check_gl_texture_size_LDADD = \ $(CHECK_GL_TEXTURE_SIZE_LIBS) privlib_LTLIBRARIES = \ libgsd.la \ $(NULL) session_manager_dbus_built_sources = gsd-session-manager-glue.c gsd-session-manager-glue.h BUILT_SOURCES += $(session_manager_dbus_built_sources) $(session_manager_dbus_built_sources) : Makefile.am org.gnome.SessionManager.xml gdbus-codegen \ --interface-prefix org.gnome.SessionManager. \ --generate-c-code gsd-session-manager-glue \ --c-namespace Gsd \ --annotate "org.gnome.SessionManager" \ "org.gtk.GDBus.C.Name" SessionManager \ $(srcdir)/org.gnome.SessionManager.xml screen_saver_dbus_built_sources = gsd-screen-saver-glue.c gsd-screen-saver-glue.h BUILT_SOURCES += $(screen_saver_dbus_built_sources) $(screen_saver_dbus_built_sources) : Makefile.am org.gnome.ScreenSaver.xml gdbus-codegen \ --interface-prefix org.gnome.ScreenSaver. \ --generate-c-code gsd-screen-saver-glue \ --c-namespace Gsd \ --annotate "org.gnome.ScreenSaver" \ "org.gtk.GDBus.C.Name" ScreenSaver \ $(srcdir)/org.gnome.ScreenSaver.xml libgsd_la_SOURCES = \ $(session_manager_dbus_built_sources) \ $(screen_saver_dbus_built_sources) \ gnome-settings-profile.c \ gnome-settings-profile.h \ gnome-settings-bus.c \ gnome-settings-bus.h \ gnome-settings-plugin.c \ gnome-settings-plugin.h \ $(NULL) libgsd_la_CPPFLAGS = \ $(DISABLE_DEPRECATED_CFLAGS) \ $(NULL) libgsd_la_CFLAGS = \ $(NULL) libgsd_la_LIBADD = \ $(SETTINGS_DAEMON_LIBS) \ $(GIOUNIX_LIBS) \ $(NULL) libgsd_la_LDFLAGS = \ -export-dynamic \ -avoid-version \ -no-undefined \ $(NULL) gsddir = $(libexecdir) gsd_PROGRAMS = \ unity-settings-daemon gsd_SCRIPTS = \ unity-settings-daemon-localeexec EXTRA_DIST = \ unity-settings-daemon-localeexec.in \ org.gnome.SessionManager.xml \ org.gnome.ScreenSaver.xml \ idle-monitor.xml \ $(NULL) unity-settings-daemon-localeexec: unity-settings-daemon-localeexec.in $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" -e "s|\@prefix\@|$(prefix)|" $< > $@.tmp && mv $@.tmp $@ apidir = $(includedir)/unity-settings-daemon-$(GSD_API_VERSION)/unity-settings-daemon api_DATA = \ gnome-settings-plugin.h unity_settings_daemon_SOURCES = \ main.c \ gnome-settings-manager.c \ gnome-settings-manager.h \ gnome-settings-plugin.c \ gnome-settings-plugin.h \ gnome-settings-plugin-info.c \ gnome-settings-plugin-info.h \ gnome-settings-module.c \ gnome-settings-module.h \ $(NULL) unity_settings_daemon_CPPFLAGS = \ $(AM_CPPFLAGS) unity_settings_daemon_CFLAGS = \ $(AM_CFLAGS) unity_settings_daemon_LDFLAGS = \ $(AM_LDFLAGS) unity_settings_daemon_LDADD = \ libgsd.la \ libunity-settings-daemon.la \ $(SETTINGS_DAEMON_LIBS) \ $(LIBNOTIFY_LIBS) \ $(GNOME_DESKTOP_LIBS) \ $(NULL) CLEANFILES = $(gsd_SCRIPTS) \ $(dbus_idle_built_sources) # vim: ts=8 unity-settings-daemon/gnome-settings-daemon/check_gl_texture_size.c0000664000000000000000000000370015172222611023135 0ustar #include #include #include #include #include #include int main (int argc, char **argv) { Display *dpy = XOpenDisplay (NULL); Window win; int attribSingle[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; int attribDouble[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; XSetWindowAttributes attr; unsigned long mask; GLXContext ctx = NULL; XVisualInfo *visinfo; int exit_status = EXIT_SUCCESS; GLint max_texture_size = 0; if (!dpy) { /* We have, for some reason, been unable to connect to X * Bail cleanly, and leave a little note */ fprintf (stderr, "check_gl_texture_size: Unable to open display %s", getenv("DISPLAY")); exit (EXIT_FAILURE); } visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), attribSingle); if (!visinfo) visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), attribDouble); if (visinfo) ctx = glXCreateContext (dpy, visinfo, NULL, GL_TRUE); if (!visinfo) { exit_status = EXIT_FAILURE; goto child_out; } if (!ctx) { XFree (visinfo); exit_status = EXIT_FAILURE; goto child_out; } attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, 100, 100, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); if (!glXMakeCurrent (dpy, win, ctx)) { exit_status = EXIT_FAILURE; goto child_out; } glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size); printf ("%u", max_texture_size); child_out: XCloseDisplay (dpy); exit (exit_status); } unity-settings-daemon/gnome-settings-daemon/display-name.c0000664000000000000000000000773215172222611021160 0ustar /* * Copyright 2007 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Author: Soren Sandmann */ #include #include #include #include #include #include #include #include "gsd-pnp-ids.h" #include "edid.h" static const char * find_vendor (const char *code) { const char *vendor_name; GsdPnpIds *pnp_ids; pnp_ids = gsd_pnp_ids_new (); vendor_name = gsd_pnp_ids_get_pnp_id (pnp_ids, code); g_object_unref (pnp_ids); if (vendor_name) return vendor_name; return code; } static const double known_diagonals[] = { 12.1, 13.3, 15.6 }; static char * diagonal_to_str (double d) { int i; for (i = 0; i < G_N_ELEMENTS (known_diagonals); i++) { double delta; delta = fabs(known_diagonals[i] - d); if (delta < 0.1) return g_strdup_printf ("%0.1lf\"", known_diagonals[i]); } return g_strdup_printf ("%d\"", (int) (d + 0.5)); } char * make_display_size_string (int width_mm, int height_mm) { char *inches = NULL; if (width_mm > 0 && height_mm > 0) { double d = sqrt (width_mm * width_mm + height_mm * height_mm); inches = diagonal_to_str (d / 25.4); } return inches; } static gboolean has_aspect_as_size(int width_mm, int height_mm) { return (width_mm == 1600 && height_mm == 900) || (width_mm == 1600 && height_mm == 1000) || (width_mm == 160 && height_mm == 90) || (width_mm == 160 && height_mm == 100) || (width_mm == 16 && height_mm == 9) || (width_mm == 16 && height_mm == 10); } char * make_display_name (const MonitorInfo *info) { const char *vendor; int width_mm, height_mm; char *suffix, *ret; if (info) { vendor = find_vendor (info->manufacturer_code); } else { /* Translators: "Unknown" here is used to identify a monitor for which * we don't know the vendor. When a vendor is known, the name of the * vendor is used. */ vendor = C_("Monitor vendor", "Unknown"); } if (info && info->width_mm != -1 && info->height_mm) { width_mm = info->width_mm; height_mm = info->height_mm; } else if (info && info->n_detailed_timings) { width_mm = info->detailed_timings[0].width_mm; height_mm = info->detailed_timings[0].height_mm; } else { width_mm = -1; height_mm = -1; } // are we dealing with aspect coded in EDID size fields? if (has_aspect_as_size(width_mm, height_mm)) { suffix = g_strdup(info->dsc_product_name); } else if (width_mm != -1 && height_mm != -1) { double d = sqrt (width_mm * width_mm + height_mm * height_mm); suffix = diagonal_to_str (d / 25.4); } else { suffix = NULL; } if (!suffix) return g_strdup (vendor); ret = g_strdup_printf ("%s %s", vendor, suffix); g_free (suffix); return ret; } unity-settings-daemon/gnome-settings-daemon/edid-parse.c0000664000000000000000000003140715172222611020606 0ustar /* * Copyright 2007 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Author: Soren Sandmann */ #include "edid.h" #include #include #include #include static int get_bit (int in, int bit) { return (in & (1 << bit)) >> bit; } static int get_bits (int in, int begin, int end) { int mask = (1 << (end - begin + 1)) - 1; return (in >> begin) & mask; } static int decode_header (const uchar *edid) { if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0) return TRUE; return FALSE; } static int decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info) { int is_model_year; /* Manufacturer Code */ info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6); info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3; info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7); info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4); info->manufacturer_code[3] = '\0'; info->manufacturer_code[0] += 'A' - 1; info->manufacturer_code[1] += 'A' - 1; info->manufacturer_code[2] += 'A' - 1; /* Product Code */ info->product_code = edid[0x0b] << 8 | edid[0x0a]; /* Serial Number */ info->serial_number = edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24; /* Week and Year */ is_model_year = FALSE; switch (edid[0x10]) { case 0x00: info->production_week = -1; break; case 0xff: info->production_week = -1; is_model_year = TRUE; break; default: info->production_week = edid[0x10]; break; } if (is_model_year) { info->production_year = -1; info->model_year = 1990 + edid[0x11]; } else { info->production_year = 1990 + edid[0x11]; info->model_year = -1; } return TRUE; } static int decode_edid_version (const uchar *edid, MonitorInfo *info) { info->major_version = edid[0x12]; info->minor_version = edid[0x13]; return TRUE; } static int decode_display_parameters (const uchar *edid, MonitorInfo *info) { /* Digital vs Analog */ info->is_digital = get_bit (edid[0x14], 7); if (info->is_digital) { int bits; static const int bit_depth[8] = { -1, 6, 8, 10, 12, 14, 16, -1 }; static const Interface interfaces[6] = { UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT }; bits = get_bits (edid[0x14], 4, 6); info->connector.digital.bits_per_primary = bit_depth[bits]; bits = get_bits (edid[0x14], 0, 3); if (bits <= 5) info->connector.digital.interface = interfaces[bits]; else info->connector.digital.interface = UNDEFINED; } else { int bits = get_bits (edid[0x14], 5, 6); static const double levels[][3] = { { 0.7, 0.3, 1.0 }, { 0.714, 0.286, 1.0 }, { 1.0, 0.4, 1.4 }, { 0.7, 0.0, 0.7 }, }; info->connector.analog.video_signal_level = levels[bits][0]; info->connector.analog.sync_signal_level = levels[bits][1]; info->connector.analog.total_signal_level = levels[bits][2]; info->connector.analog.blank_to_black = get_bit (edid[0x14], 4); info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3); info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2); info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1); info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0); } /* Screen Size / Aspect Ratio */ if (edid[0x15] == 0 && edid[0x16] == 0) { info->width_mm = -1; info->height_mm = -1; info->aspect_ratio = -1.0; } else if (edid[0x16] == 0) { info->width_mm = -1; info->height_mm = -1; info->aspect_ratio = 100.0 / (edid[0x15] + 99); } else if (edid[0x15] == 0) { info->width_mm = -1; info->height_mm = -1; info->aspect_ratio = 100.0 / (edid[0x16] + 99); info->aspect_ratio = 1/info->aspect_ratio; /* portrait */ } else { info->width_mm = 10 * edid[0x15]; info->height_mm = 10 * edid[0x16]; } /* Gamma */ if (edid[0x17] == 0xFF) info->gamma = -1.0; else info->gamma = (edid[0x17] + 100.0) / 100.0; /* Features */ info->standby = get_bit (edid[0x18], 7); info->suspend = get_bit (edid[0x18], 6); info->active_off = get_bit (edid[0x18], 5); if (info->is_digital) { info->connector.digital.rgb444 = TRUE; if (get_bit (edid[0x18], 3)) info->connector.digital.ycrcb444 = 1; if (get_bit (edid[0x18], 4)) info->connector.digital.ycrcb422 = 1; } else { int bits = get_bits (edid[0x18], 3, 4); ColorType color_type[4] = { MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR }; info->connector.analog.color_type = color_type[bits]; } info->srgb_is_standard = get_bit (edid[0x18], 2); /* In 1.3 this is called "has preferred timing" */ info->preferred_timing_includes_native = get_bit (edid[0x18], 1); /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */ info->continuous_frequency = get_bit (edid[0x18], 0); return TRUE; } static double decode_fraction (int high, int low) { double result = 0.0; int i; high = (high << 2) | low; for (i = 0; i < 10; ++i) result += get_bit (high, i) * pow (2, i - 10); return result; } static int decode_color_characteristics (const uchar *edid, MonitorInfo *info) { info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7)); info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4)); info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3)); info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1)); info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7)); info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5)); info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3)); info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1)); return TRUE; } static int decode_established_timings (const uchar *edid, MonitorInfo *info) { static const Timing established[][8] = { { { 800, 600, 60 }, { 800, 600, 56 }, { 640, 480, 75 }, { 640, 480, 72 }, { 640, 480, 67 }, { 640, 480, 60 }, { 720, 400, 88 }, { 720, 400, 70 } }, { { 1280, 1024, 75 }, { 1024, 768, 75 }, { 1024, 768, 70 }, { 1024, 768, 60 }, { 1024, 768, 87 }, { 832, 624, 75 }, { 800, 600, 75 }, { 800, 600, 72 } }, { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1152, 870, 75 } }, }; int i, j, idx; idx = 0; for (i = 0; i < 3; ++i) { for (j = 0; j < 8; ++j) { int byte = edid[0x23 + i]; if (get_bit (byte, j) && established[i][j].frequency != 0) info->established[idx++] = established[i][j]; } } return TRUE; } static int decode_standard_timings (const uchar *edid, MonitorInfo *info) { int i; for (i = 0; i < 8; i++) { int first = edid[0x26 + 2 * i]; int second = edid[0x27 + 2 * i]; if (first != 0x01 && second != 0x01) { int w = 8 * (first + 31); int h = 0; switch (get_bits (second, 6, 7)) { case 0x00: h = (w / 16) * 10; break; case 0x01: h = (w / 4) * 3; break; case 0x02: h = (w / 5) * 4; break; case 0x03: h = (w / 16) * 9; break; } info->standard[i].width = w; info->standard[i].height = h; info->standard[i].frequency = get_bits (second, 0, 5) + 60; } } return TRUE; } static void decode_lf_string (const uchar *s, int n_chars, char *result) { int i; for (i = 0; i < n_chars; ++i) { if (s[i] == 0x0a) { *result++ = '\0'; break; } else if (s[i] == 0x00) { /* Convert embedded 0's to spaces */ *result++ = ' '; } else { *result++ = s[i]; } } } static void decode_display_descriptor (const uchar *desc, MonitorInfo *info) { switch (desc[0x03]) { case 0xFC: decode_lf_string (desc + 5, 13, info->dsc_product_name); break; case 0xFF: decode_lf_string (desc + 5, 13, info->dsc_serial_number); break; case 0xFE: decode_lf_string (desc + 5, 13, info->dsc_string); break; case 0xFD: /* Range Limits */ break; case 0xFB: /* Color Point */ break; case 0xFA: /* Timing Identifications */ break; case 0xF9: /* Color Management */ break; case 0xF8: /* Timing Codes */ break; case 0xF7: /* Established Timings */ break; case 0x10: break; } } static void decode_detailed_timing (const uchar *timing, DetailedTiming *detailed) { int bits; StereoType stereo[] = { NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT, TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN, FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE }; detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000; detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4); detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8); detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4); detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8); detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8; detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8; detailed->v_front_porch = get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4; detailed->v_sync = get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4; detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8; detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8; detailed->right_border = timing[0x0f]; detailed->top_border = timing[0x10]; detailed->interlaced = get_bit (timing[0x11], 7); /* Stereo */ bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0); detailed->stereo = stereo[bits]; /* Sync */ bits = timing[0x11]; detailed->digital_sync = get_bit (bits, 4); if (detailed->digital_sync) { detailed->connector.digital.composite = !get_bit (bits, 3); if (detailed->connector.digital.composite) { detailed->connector.digital.serrations = get_bit (bits, 2); detailed->connector.digital.negative_vsync = FALSE; } else { detailed->connector.digital.serrations = FALSE; detailed->connector.digital.negative_vsync = !get_bit (bits, 2); } detailed->connector.digital.negative_hsync = !get_bit (bits, 0); } else { detailed->connector.analog.bipolar = get_bit (bits, 3); detailed->connector.analog.serrations = get_bit (bits, 2); detailed->connector.analog.sync_on_green = !get_bit (bits, 1); } } static int decode_descriptors (const uchar *edid, MonitorInfo *info) { int i; int timing_idx; timing_idx = 0; for (i = 0; i < 4; ++i) { int index = 0x36 + i * 18; if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00) { decode_display_descriptor (edid + index, info); } else { decode_detailed_timing ( edid + index, &(info->detailed_timings[timing_idx++])); } } info->n_detailed_timings = timing_idx; return TRUE; } static void decode_check_sum (const uchar *edid, MonitorInfo *info) { int i; uchar check = 0; for (i = 0; i < 128; ++i) check += edid[i]; info->checksum = check; } MonitorInfo * decode_edid (const uchar *edid) { MonitorInfo *info = g_new0 (MonitorInfo, 1); decode_check_sum (edid, info); if (decode_header (edid) && decode_vendor_and_product_identification (edid, info) && decode_edid_version (edid, info) && decode_display_parameters (edid, info) && decode_color_characteristics (edid, info) && decode_established_timings (edid, info) && decode_standard_timings (edid, info) && decode_descriptors (edid, info)) { return info; } else { g_free (info); return NULL; } } unity-settings-daemon/gnome-settings-daemon/edid.h0000664000000000000000000001012715172222611017477 0ustar /* edid.h * * Copyright 2007, 2008, Red Hat, Inc. * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Author: Soren Sandmann */ #ifndef EDID_H #define EDID_H typedef unsigned char uchar; typedef struct MonitorInfo MonitorInfo; typedef struct Timing Timing; typedef struct DetailedTiming DetailedTiming; typedef enum { UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT } Interface; typedef enum { UNDEFINED_COLOR, MONOCHROME, RGB, OTHER_COLOR } ColorType; typedef enum { NO_STEREO, FIELD_RIGHT, FIELD_LEFT, TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN, FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE } StereoType; struct Timing { int width; int height; int frequency; }; struct DetailedTiming { int pixel_clock; int h_addr; int h_blank; int h_sync; int h_front_porch; int v_addr; int v_blank; int v_sync; int v_front_porch; int width_mm; int height_mm; int right_border; int top_border; int interlaced; StereoType stereo; int digital_sync; union { struct { int bipolar; int serrations; int sync_on_green; } analog; struct { int composite; int serrations; int negative_vsync; int negative_hsync; } digital; } connector; }; struct MonitorInfo { int checksum; char manufacturer_code[4]; int product_code; unsigned int serial_number; int production_week; /* -1 if not specified */ int production_year; /* -1 if not specified */ int model_year; /* -1 if not specified */ int major_version; int minor_version; int is_digital; union { struct { int bits_per_primary; Interface interface; int rgb444; int ycrcb444; int ycrcb422; } digital; struct { double video_signal_level; double sync_signal_level; double total_signal_level; int blank_to_black; int separate_hv_sync; int composite_sync_on_h; int composite_sync_on_green; int serration_on_vsync; ColorType color_type; } analog; } connector; int width_mm; /* -1 if not specified */ int height_mm; /* -1 if not specified */ double aspect_ratio; /* -1.0 if not specififed */ double gamma; /* -1.0 if not specified */ int standby; int suspend; int active_off; int srgb_is_standard; int preferred_timing_includes_native; int continuous_frequency; double red_x; double red_y; double green_x; double green_y; double blue_x; double blue_y; double white_x; double white_y; Timing established[24]; /* Terminated by 0x0x0 */ Timing standard[8]; int n_detailed_timings; DetailedTiming detailed_timings[4]; /* If monitor has a preferred * mode, it is the first one * (whether it has, is * determined by the * preferred_timing_includes * bit. */ /* Optional product description */ char dsc_serial_number[14]; char dsc_product_name[14]; char dsc_string[14]; /* Unspecified ASCII data */ }; MonitorInfo *decode_edid (const uchar *data); char *make_display_name (const MonitorInfo *info); char *make_display_size_string (int width_mm, int height_mm); #endif unity-settings-daemon/gnome-settings-daemon/edid_parse.c0000664000000000000000000003140715172222611020670 0ustar /* * Copyright 2007 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Author: Soren Sandmann */ #include "edid.h" #include #include #include #include static int get_bit (int in, int bit) { return (in & (1 << bit)) >> bit; } static int get_bits (int in, int begin, int end) { int mask = (1 << (end - begin + 1)) - 1; return (in >> begin) & mask; } static int decode_header (const uchar *edid) { if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0) return TRUE; return FALSE; } static int decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info) { int is_model_year; /* Manufacturer Code */ info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6); info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3; info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7); info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4); info->manufacturer_code[3] = '\0'; info->manufacturer_code[0] += 'A' - 1; info->manufacturer_code[1] += 'A' - 1; info->manufacturer_code[2] += 'A' - 1; /* Product Code */ info->product_code = edid[0x0b] << 8 | edid[0x0a]; /* Serial Number */ info->serial_number = edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24; /* Week and Year */ is_model_year = FALSE; switch (edid[0x10]) { case 0x00: info->production_week = -1; break; case 0xff: info->production_week = -1; is_model_year = TRUE; break; default: info->production_week = edid[0x10]; break; } if (is_model_year) { info->production_year = -1; info->model_year = 1990 + edid[0x11]; } else { info->production_year = 1990 + edid[0x11]; info->model_year = -1; } return TRUE; } static int decode_edid_version (const uchar *edid, MonitorInfo *info) { info->major_version = edid[0x12]; info->minor_version = edid[0x13]; return TRUE; } static int decode_display_parameters (const uchar *edid, MonitorInfo *info) { /* Digital vs Analog */ info->is_digital = get_bit (edid[0x14], 7); if (info->is_digital) { int bits; static const int bit_depth[8] = { -1, 6, 8, 10, 12, 14, 16, -1 }; static const Interface interfaces[6] = { UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT }; bits = get_bits (edid[0x14], 4, 6); info->connector.digital.bits_per_primary = bit_depth[bits]; bits = get_bits (edid[0x14], 0, 3); if (bits <= 5) info->connector.digital.interface = interfaces[bits]; else info->connector.digital.interface = UNDEFINED; } else { int bits = get_bits (edid[0x14], 5, 6); static const double levels[][3] = { { 0.7, 0.3, 1.0 }, { 0.714, 0.286, 1.0 }, { 1.0, 0.4, 1.4 }, { 0.7, 0.0, 0.7 }, }; info->connector.analog.video_signal_level = levels[bits][0]; info->connector.analog.sync_signal_level = levels[bits][1]; info->connector.analog.total_signal_level = levels[bits][2]; info->connector.analog.blank_to_black = get_bit (edid[0x14], 4); info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3); info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2); info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1); info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0); } /* Screen Size / Aspect Ratio */ if (edid[0x15] == 0 && edid[0x16] == 0) { info->width_mm = -1; info->height_mm = -1; info->aspect_ratio = -1.0; } else if (edid[0x16] == 0) { info->width_mm = -1; info->height_mm = -1; info->aspect_ratio = 100.0 / (edid[0x15] + 99); } else if (edid[0x15] == 0) { info->width_mm = -1; info->height_mm = -1; info->aspect_ratio = 100.0 / (edid[0x16] + 99); info->aspect_ratio = 1/info->aspect_ratio; /* portrait */ } else { info->width_mm = 10 * edid[0x15]; info->height_mm = 10 * edid[0x16]; } /* Gamma */ if (edid[0x17] == 0xFF) info->gamma = -1.0; else info->gamma = (edid[0x17] + 100.0) / 100.0; /* Features */ info->standby = get_bit (edid[0x18], 7); info->suspend = get_bit (edid[0x18], 6); info->active_off = get_bit (edid[0x18], 5); if (info->is_digital) { info->connector.digital.rgb444 = TRUE; if (get_bit (edid[0x18], 3)) info->connector.digital.ycrcb444 = 1; if (get_bit (edid[0x18], 4)) info->connector.digital.ycrcb422 = 1; } else { int bits = get_bits (edid[0x18], 3, 4); ColorType color_type[4] = { MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR }; info->connector.analog.color_type = color_type[bits]; } info->srgb_is_standard = get_bit (edid[0x18], 2); /* In 1.3 this is called "has preferred timing" */ info->preferred_timing_includes_native = get_bit (edid[0x18], 1); /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */ info->continuous_frequency = get_bit (edid[0x18], 0); return TRUE; } static double decode_fraction (int high, int low) { double result = 0.0; int i; high = (high << 2) | low; for (i = 0; i < 10; ++i) result += get_bit (high, i) * pow (2, i - 10); return result; } static int decode_color_characteristics (const uchar *edid, MonitorInfo *info) { info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7)); info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4)); info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3)); info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1)); info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7)); info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5)); info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3)); info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1)); return TRUE; } static int decode_established_timings (const uchar *edid, MonitorInfo *info) { static const Timing established[][8] = { { { 800, 600, 60 }, { 800, 600, 56 }, { 640, 480, 75 }, { 640, 480, 72 }, { 640, 480, 67 }, { 640, 480, 60 }, { 720, 400, 88 }, { 720, 400, 70 } }, { { 1280, 1024, 75 }, { 1024, 768, 75 }, { 1024, 768, 70 }, { 1024, 768, 60 }, { 1024, 768, 87 }, { 832, 624, 75 }, { 800, 600, 75 }, { 800, 600, 72 } }, { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1152, 870, 75 } }, }; int i, j, idx; idx = 0; for (i = 0; i < 3; ++i) { for (j = 0; j < 8; ++j) { int byte = edid[0x23 + i]; if (get_bit (byte, j) && established[i][j].frequency != 0) info->established[idx++] = established[i][j]; } } return TRUE; } static int decode_standard_timings (const uchar *edid, MonitorInfo *info) { int i; for (i = 0; i < 8; i++) { int first = edid[0x26 + 2 * i]; int second = edid[0x27 + 2 * i]; if (first != 0x01 && second != 0x01) { int w = 8 * (first + 31); int h = 0; switch (get_bits (second, 6, 7)) { case 0x00: h = (w / 16) * 10; break; case 0x01: h = (w / 4) * 3; break; case 0x02: h = (w / 5) * 4; break; case 0x03: h = (w / 16) * 9; break; } info->standard[i].width = w; info->standard[i].height = h; info->standard[i].frequency = get_bits (second, 0, 5) + 60; } } return TRUE; } static void decode_lf_string (const uchar *s, int n_chars, char *result) { int i; for (i = 0; i < n_chars; ++i) { if (s[i] == 0x0a) { *result++ = '\0'; break; } else if (s[i] == 0x00) { /* Convert embedded 0's to spaces */ *result++ = ' '; } else { *result++ = s[i]; } } } static void decode_display_descriptor (const uchar *desc, MonitorInfo *info) { switch (desc[0x03]) { case 0xFC: decode_lf_string (desc + 5, 13, info->dsc_product_name); break; case 0xFF: decode_lf_string (desc + 5, 13, info->dsc_serial_number); break; case 0xFE: decode_lf_string (desc + 5, 13, info->dsc_string); break; case 0xFD: /* Range Limits */ break; case 0xFB: /* Color Point */ break; case 0xFA: /* Timing Identifications */ break; case 0xF9: /* Color Management */ break; case 0xF8: /* Timing Codes */ break; case 0xF7: /* Established Timings */ break; case 0x10: break; } } static void decode_detailed_timing (const uchar *timing, DetailedTiming *detailed) { int bits; StereoType stereo[] = { NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT, TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN, FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE }; detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000; detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4); detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8); detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4); detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8); detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8; detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8; detailed->v_front_porch = get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4; detailed->v_sync = get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4; detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8; detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8; detailed->right_border = timing[0x0f]; detailed->top_border = timing[0x10]; detailed->interlaced = get_bit (timing[0x11], 7); /* Stereo */ bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0); detailed->stereo = stereo[bits]; /* Sync */ bits = timing[0x11]; detailed->digital_sync = get_bit (bits, 4); if (detailed->digital_sync) { detailed->connector.digital.composite = !get_bit (bits, 3); if (detailed->connector.digital.composite) { detailed->connector.digital.serrations = get_bit (bits, 2); detailed->connector.digital.negative_vsync = FALSE; } else { detailed->connector.digital.serrations = FALSE; detailed->connector.digital.negative_vsync = !get_bit (bits, 2); } detailed->connector.digital.negative_hsync = !get_bit (bits, 0); } else { detailed->connector.analog.bipolar = get_bit (bits, 3); detailed->connector.analog.serrations = get_bit (bits, 2); detailed->connector.analog.sync_on_green = !get_bit (bits, 1); } } static int decode_descriptors (const uchar *edid, MonitorInfo *info) { int i; int timing_idx; timing_idx = 0; for (i = 0; i < 4; ++i) { int index = 0x36 + i * 18; if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00) { decode_display_descriptor (edid + index, info); } else { decode_detailed_timing ( edid + index, &(info->detailed_timings[timing_idx++])); } } info->n_detailed_timings = timing_idx; return TRUE; } static void decode_check_sum (const uchar *edid, MonitorInfo *info) { int i; uchar check = 0; for (i = 0; i < 128; ++i) check += edid[i]; info->checksum = check; } MonitorInfo * decode_edid (const uchar *edid) { MonitorInfo *info = g_new0 (MonitorInfo, 1); decode_check_sum (edid, info); if (decode_header (edid) && decode_vendor_and_product_identification (edid, info) && decode_edid_version (edid, info) && decode_display_parameters (edid, info) && decode_color_characteristics (edid, info) && decode_established_timings (edid, info) && decode_standard_timings (edid, info) && decode_descriptors (edid, info)) { return info; } else { g_free (info); return NULL; } } unity-settings-daemon/gnome-settings-daemon/gnome-settings-bus.c0000664000000000000000000001314015172222611022315 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2006-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include "gnome-settings-bus.h" #define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager" #define GNOME_SESSION_DBUS_OBJECT "/org/gnome/SessionManager" #define GNOME_SCREENSAVER_DBUS_NAME "org.gnome.ScreenSaver" #define GNOME_SCREENSAVER_DBUS_OBJECT "/org/gnome/ScreenSaver" GsdSessionManager * gnome_settings_bus_get_session_proxy (void) { static GsdSessionManager *session_proxy; GError *error = NULL; if (session_proxy != NULL) { g_object_ref (session_proxy); } else { session_proxy = gsd_session_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, GNOME_SESSION_DBUS_NAME, GNOME_SESSION_DBUS_OBJECT, NULL, &error); if (error) { g_warning ("Failed to connect to the session manager: %s", error->message); g_error_free (error); } else { g_object_add_weak_pointer (G_OBJECT (session_proxy), (gpointer*)&session_proxy); } } return session_proxy; } GsdScreenSaver * gnome_settings_bus_get_screen_saver_proxy (void) { static GsdScreenSaver *screen_saver_proxy; GError *error = NULL; if (screen_saver_proxy != NULL) { g_object_ref (screen_saver_proxy); } else { screen_saver_proxy = gsd_screen_saver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, GNOME_SCREENSAVER_DBUS_NAME, GNOME_SCREENSAVER_DBUS_OBJECT, NULL, &error); if (error) { g_warning ("Failed to connect to the screen saver: %s", error->message); g_error_free (error); } else { g_object_add_weak_pointer (G_OBJECT (screen_saver_proxy), (gpointer*)&screen_saver_proxy); } } return screen_saver_proxy; } char * gnome_settings_get_chassis_type (void) { char *ret = NULL; GError *error = NULL; GVariant *inner; GVariant *variant = NULL; GDBusConnection *connection; connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (connection == NULL) { g_warning ("system bus not available: %s", error->message); g_error_free (error); goto out; } variant = g_dbus_connection_call_sync (connection, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.DBus.Properties", "Get", g_variant_new ("(ss)", "org.freedesktop.hostname1", "Chassis"), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_debug ("Failed to get property '%s': %s", "Chassis", error->message); g_error_free (error); goto out; } g_variant_get (variant, "(v)", &inner); ret = g_variant_dup_string (inner, NULL); g_variant_unref (inner); out: g_clear_object (&connection); g_clear_pointer (&variant, g_variant_unref); return ret; } unity-settings-daemon/gnome-settings-daemon/gnome-settings-bus.h0000664000000000000000000000255115172222611022326 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2010-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GNOME_SETTINGS_BUS_H #define __GNOME_SETTINGS_BUS_H #include #include "gsd-session-manager-glue.h" #include "gsd-screen-saver-glue.h" G_BEGIN_DECLS GsdSessionManager *gnome_settings_bus_get_session_proxy (void); GsdScreenSaver *gnome_settings_bus_get_screen_saver_proxy (void); char * gnome_settings_get_chassis_type (void); G_END_DECLS #endif /* __GNOME_SETTINGS_BUS_H */ unity-settings-daemon/gnome-settings-daemon/gnome-settings-manager.c0000664000000000000000000004176415172222611023153 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "gnome-settings-plugin.h" #include "gnome-settings-plugin-info.h" #include "gnome-settings-manager.h" #include "gnome-settings-profile.h" #include "gsd-pnp-ids.h" #define DEFAULT_SETTINGS_PREFIX "com.canonical.unity.settings-daemon" #define PLUGIN_EXT ".gnome-settings-plugin" #define GNOME_SETTINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNOME_TYPE_SETTINGS_MANAGER, GnomeSettingsManagerPrivate)) static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " " " " " ""; typedef struct { const char *signal; const char *name; } SignalCache; struct GnomeSettingsManagerPrivate { guint owner_id; GDBusNodeInfo *introspection_data; GDBusConnection *connection; GSettings *settings; char **whitelist; GsdPnpIds *pnp_ids; GSList *plugins; GQueue *signal_queue; }; static void gnome_settings_manager_class_init (GnomeSettingsManagerClass *klass); static void gnome_settings_manager_init (GnomeSettingsManager *settings_manager); static void gnome_settings_manager_finalize (GObject *object); G_DEFINE_TYPE (GnomeSettingsManager, gnome_settings_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void signal_cache_free (SignalCache *cache) { if (cache == NULL) { return; } g_free (cache->signal); g_free (cache->name); g_free (cache); } /* * This function is unsafe because it might lead to freeing arbitrary memory * if called on incorrectly casted pointer. */ static void signal_cache_free_unsafe (void *data) { if (data == NULL) { return; } SignalCache *cache = (SignalCache*) data; if (cache->name != NULL) { g_free (cache->name); } if (cache->signal != NULL) { g_free (cache->signal); } g_free (cache); } GQuark gnome_settings_manager_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("gnome_settings_manager_error"); } return ret; } static void maybe_activate_plugin (GnomeSettingsPluginInfo *info, gpointer user_data) { if (gnome_settings_plugin_info_get_enabled (info)) { gboolean res; res = gnome_settings_plugin_info_activate (info); if (res) { g_debug ("Plugin %s: active", gnome_settings_plugin_info_get_location (info)); } else { g_debug ("Plugin %s: activation failed", gnome_settings_plugin_info_get_location (info)); } } else { g_debug ("Plugin %s: inactive", gnome_settings_plugin_info_get_location (info)); } } static gint compare_location (GnomeSettingsPluginInfo *a, GnomeSettingsPluginInfo *b) { const char *loc_a; const char *loc_b; loc_a = gnome_settings_plugin_info_get_location (a); loc_b = gnome_settings_plugin_info_get_location (b); if (loc_a == NULL || loc_b == NULL) { return -1; } return strcmp (loc_a, loc_b); } static int compare_priority (GnomeSettingsPluginInfo *a, GnomeSettingsPluginInfo *b) { int prio_a; int prio_b; prio_a = gnome_settings_plugin_info_get_priority (a); prio_b = gnome_settings_plugin_info_get_priority (b); return prio_a - prio_b; } static void emit_signal (GnomeSettingsManager *manager, const char *signal, const char *name) { GError *error = NULL; GQueue *signal_queue = manager->priv->signal_queue; /* Queue up signal if there's no D-Bus connection */ if (manager->priv->connection == NULL) { g_debug ("Connection is null, cannot emit signal, queue instead"); SignalCache *cache = g_new0 (SignalCache, 1); cache->signal = g_strdup (signal); cache->name = g_strdup (name); g_queue_push_tail (signal_queue, cache); return; } if (g_dbus_connection_emit_signal (manager->priv->connection, NULL, GSD_DBUS_PATH, GSD_DBUS_NAME, signal, g_variant_new ("(s)", name), &error) == FALSE) { g_debug ("Error emitting signal: %s", error->message); g_error_free (error); } } static void on_plugin_activated (GnomeSettingsPluginInfo *info, GnomeSettingsManager *manager) { const char *name; name = gnome_settings_plugin_info_get_location (info); g_debug ("GnomeSettingsManager: emitting plugin-activated %s", name); emit_signal (manager, "PluginActivated", name); } static void on_plugin_deactivated (GnomeSettingsPluginInfo *info, GnomeSettingsManager *manager) { const char *name; name = gnome_settings_plugin_info_get_location (info); g_debug ("GnomeSettingsManager: emitting plugin-deactivated %s", name); emit_signal (manager, "PluginDeactivated", name); } static gboolean contained (const char * const *items, const char *item) { while (*items) { if (g_strcmp0 (*items++, item) == 0) { return TRUE; } } return FALSE; } static gboolean is_schema (const char *schema) { return contained (g_settings_list_schemas (), schema); } static gboolean is_whitelisted (char **whitelist, const char *plugin_name) { if (whitelist == NULL || whitelist[0] == NULL || g_strcmp0 (whitelist[0], "all") == 0) return TRUE; return contained ((const char * const *) whitelist, plugin_name); } static void _load_file (GnomeSettingsManager *manager, const char *filename) { GnomeSettingsPluginInfo *info; char *key_name; GSList *l; g_debug ("Loading plugin: %s", filename); gnome_settings_profile_start ("%s", filename); info = gnome_settings_plugin_info_new_from_file (filename); if (info == NULL) { goto out; } l = g_slist_find_custom (manager->priv->plugins, info, (GCompareFunc) compare_location); if (l != NULL) { goto out; } if (!is_whitelisted (manager->priv->whitelist, gnome_settings_plugin_info_get_location (info))) { g_debug ("Plugin %s ignored as it's not whitelisted", gnome_settings_plugin_info_get_location (info)); goto out; } key_name = g_strdup_printf ("%s.plugins.%s", DEFAULT_SETTINGS_PREFIX, gnome_settings_plugin_info_get_location (info)); /* Ignore unknown schemas or else we'll assert */ if (is_schema (key_name)) { manager->priv->plugins = g_slist_prepend (manager->priv->plugins, g_object_ref (info)); g_signal_connect (info, "activated", G_CALLBACK (on_plugin_activated), manager); g_signal_connect (info, "deactivated", G_CALLBACK (on_plugin_deactivated), manager); gnome_settings_plugin_info_set_settings_prefix (info, key_name); } else { g_warning ("Ignoring unknown module '%s'", key_name); } /* Priority is set in the call above */ g_free (key_name); out: if (info != NULL) { g_object_unref (info); } gnome_settings_profile_end ("%s", filename); } static void _load_dir (GnomeSettingsManager *manager, const char *path) { GError *error; GDir *d; const char *name; g_debug ("Loading settings plugins from dir: %s", path); gnome_settings_profile_start (NULL); error = NULL; d = g_dir_open (path, 0, &error); if (d == NULL) { g_warning ("%s", error->message); g_error_free (error); return; } while ((name = g_dir_read_name (d))) { char *filename; if (!g_str_has_suffix (name, PLUGIN_EXT)) { continue; } filename = g_build_filename (path, name, NULL); if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { _load_file (manager, filename); } g_free (filename); } g_dir_close (d); gnome_settings_profile_end (NULL); } static void _load_all (GnomeSettingsManager *manager) { gnome_settings_profile_start (NULL); /* load system plugins */ _load_dir (manager, GNOME_SETTINGS_PLUGINDIR G_DIR_SEPARATOR_S); manager->priv->plugins = g_slist_sort (manager->priv->plugins, (GCompareFunc) compare_priority); g_slist_foreach (manager->priv->plugins, (GFunc) maybe_activate_plugin, NULL); gnome_settings_profile_end (NULL); } static void _unload_plugin (GnomeSettingsPluginInfo *info, gpointer user_data) { if (gnome_settings_plugin_info_get_enabled (info)) { gnome_settings_plugin_info_deactivate (info); } g_object_unref (info); } static void _unload_all (GnomeSettingsManager *manager) { g_slist_foreach (manager->priv->plugins, (GFunc) _unload_plugin, NULL); g_slist_free (manager->priv->plugins); manager->priv->plugins = NULL; } static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GnomeSettingsManager *manager) { GDBusConnection *connection; GError *error = NULL; GQueue *signal_queue = manager->priv->signal_queue; connection = g_bus_get_finish (res, &error); if (connection == NULL) { g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; g_dbus_connection_register_object (connection, GSD_DBUS_PATH, manager->priv->introspection_data->interfaces[0], NULL, NULL, NULL, NULL); /* Emit queued up signals after got D-Bus connection */ if (!g_queue_is_empty (signal_queue)) { g_debug ("Emit queued up signals"); while (!g_queue_is_empty (signal_queue)) { SignalCache *cache = g_queue_pop_head (signal_queue); emit_signal (manager, cache->signal, cache->name); signal_cache_free (cache); } } } static void register_manager (GnomeSettingsManager *manager) { manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (manager->priv->introspection_data != NULL); g_bus_get (G_BUS_TYPE_SESSION, NULL, (GAsyncReadyCallback) on_bus_gotten, manager); } gboolean gnome_settings_manager_start (GnomeSettingsManager *manager, GError **error) { gboolean ret; g_debug ("Starting settings manager"); ret = FALSE; gnome_settings_profile_start (NULL); if (!g_module_supported ()) { g_warning ("gnome-settings-daemon is not able to initialize the plugins."); g_set_error (error, GNOME_SETTINGS_MANAGER_ERROR, GNOME_SETTINGS_MANAGER_ERROR_GENERAL, "Plugins not supported"); goto out; } manager->priv->signal_queue = g_queue_new (); g_debug ("loading PNPIDs"); manager->priv->pnp_ids = gsd_pnp_ids_new (); gnome_settings_profile_start ("initializing plugins"); manager->priv->settings = g_settings_new (DEFAULT_SETTINGS_PREFIX ".plugins"); manager->priv->whitelist = g_settings_get_strv (manager->priv->settings, "whitelisted-plugins"); _load_all (manager); gnome_settings_profile_end ("initializing plugins"); ret = TRUE; out: gnome_settings_profile_end (NULL); return ret; } void gnome_settings_manager_stop (GnomeSettingsManager *manager) { g_debug ("Stopping settings manager"); _unload_all (manager); if (manager->priv->owner_id > 0) { g_bus_unown_name (manager->priv->owner_id); manager->priv->owner_id = 0; } /* This will be called from both stop_manager and dispose, so we need to * prevent the queue being freed twice */ if (manager->priv->signal_queue != NULL) { g_queue_free_full (manager->priv->signal_queue, signal_cache_free_unsafe); manager->priv->signal_queue = NULL; } g_clear_pointer (&manager->priv->whitelist, g_strfreev); g_clear_object (&manager->priv->settings); g_clear_object (&manager->priv->pnp_ids); } static void gnome_settings_manager_dispose (GObject *object) { GnomeSettingsManager *manager; manager = GNOME_SETTINGS_MANAGER (object); gnome_settings_manager_stop (manager); G_OBJECT_CLASS (gnome_settings_manager_parent_class)->dispose (object); } static void gnome_settings_manager_class_init (GnomeSettingsManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = gnome_settings_manager_dispose; object_class->finalize = gnome_settings_manager_finalize; g_type_class_add_private (klass, sizeof (GnomeSettingsManagerPrivate)); } static void gnome_settings_manager_init (GnomeSettingsManager *manager) { manager->priv = GNOME_SETTINGS_MANAGER_GET_PRIVATE (manager); } static void gnome_settings_manager_finalize (GObject *object) { GnomeSettingsManager *manager; g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_SETTINGS_MANAGER (object)); manager = GNOME_SETTINGS_MANAGER (object); g_return_if_fail (manager->priv != NULL); G_OBJECT_CLASS (gnome_settings_manager_parent_class)->finalize (object); } GnomeSettingsManager * gnome_settings_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GNOME_TYPE_SETTINGS_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); register_manager (manager_object); } return GNOME_SETTINGS_MANAGER (manager_object); } unity-settings-daemon/gnome-settings-daemon/gnome-settings-manager.h0000664000000000000000000000563315172222611023153 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GNOME_SETTINGS_MANAGER_H #define __GNOME_SETTINGS_MANAGER_H #include G_BEGIN_DECLS #define GNOME_TYPE_SETTINGS_MANAGER (gnome_settings_manager_get_type ()) #define GNOME_SETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GNOME_TYPE_SETTINGS_MANAGER, GnomeSettingsManager)) #define GNOME_SETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GNOME_TYPE_SETTINGS_MANAGER, GnomeSettingsManagerClass)) #define GNOME_IS_SETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNOME_TYPE_SETTINGS_MANAGER)) #define GNOME_IS_SETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GNOME_TYPE_SETTINGS_MANAGER)) #define GNOME_SETTINGS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GNOME_TYPE_SETTINGS_MANAGER, GnomeSettingsManagerClass)) typedef struct GnomeSettingsManagerPrivate GnomeSettingsManagerPrivate; typedef struct { GObject parent; GnomeSettingsManagerPrivate *priv; } GnomeSettingsManager; typedef struct { GObjectClass parent_class; void (* plugin_activated) (GnomeSettingsManager *manager, const char *name); void (* plugin_deactivated) (GnomeSettingsManager *manager, const char *name); } GnomeSettingsManagerClass; typedef enum { GNOME_SETTINGS_MANAGER_ERROR_GENERAL } GnomeSettingsManagerError; #define GNOME_SETTINGS_MANAGER_ERROR gnome_settings_manager_error_quark () GQuark gnome_settings_manager_error_quark (void); GType gnome_settings_manager_get_type (void); GnomeSettingsManager * gnome_settings_manager_new (void); gboolean gnome_settings_manager_start (GnomeSettingsManager *manager, GError **error); void gnome_settings_manager_stop (GnomeSettingsManager *manager); G_END_DECLS #endif /* __GNOME_SETTINGS_MANAGER_H */ unity-settings-daemon/gnome-settings-daemon/gnome-settings-module.c0000664000000000000000000001054515172222611023017 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2005 - Paolo Maggi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include "gnome-settings-module.h" #include typedef struct _GnomeSettingsModuleClass GnomeSettingsModuleClass; struct _GnomeSettingsModuleClass { GTypeModuleClass parent_class; }; struct _GnomeSettingsModule { GTypeModule parent_instance; GModule *library; char *path; GType type; }; typedef GType (*GnomeSettingsModuleRegisterFunc) (GTypeModule *); G_DEFINE_TYPE (GnomeSettingsModule, gnome_settings_module, G_TYPE_TYPE_MODULE) static gboolean gnome_settings_module_load (GTypeModule *gmodule) { GnomeSettingsModule *module; GnomeSettingsModuleRegisterFunc register_func; gboolean res; module = GNOME_SETTINGS_MODULE (gmodule); g_debug ("Loading %s", module->path); module->library = g_module_open (module->path, 0); if (module->library == NULL) { g_warning ("%s", g_module_error ()); return FALSE; } /* extract symbols from the lib */ res = g_module_symbol (module->library, "register_gnome_settings_plugin", (void *) ®ister_func); if (! res) { g_warning ("%s", g_module_error ()); g_module_close (module->library); return FALSE; } g_assert (register_func); module->type = register_func (gmodule); if (module->type == 0) { g_warning ("Invalid gnome settings plugin in module %s", module->path); return FALSE; } return TRUE; } static void gnome_settings_module_unload (GTypeModule *gmodule) { GnomeSettingsModule *module = GNOME_SETTINGS_MODULE (gmodule); g_debug ("Unloading %s", module->path); g_module_close (module->library); module->library = NULL; module->type = 0; } const gchar * gnome_settings_module_get_path (GnomeSettingsModule *module) { g_return_val_if_fail (GNOME_IS_SETTINGS_MODULE (module), NULL); return module->path; } GObject * gnome_settings_module_new_object (GnomeSettingsModule *module) { g_debug ("Creating object of type %s", g_type_name (module->type)); if (module->type == 0) { return NULL; } return g_object_new (module->type, NULL); } static void gnome_settings_module_init (GnomeSettingsModule *module) { g_debug ("GnomeSettingsModule %p initialising", module); } static void gnome_settings_module_finalize (GObject *object) { GnomeSettingsModule *module = GNOME_SETTINGS_MODULE (object); g_debug ("GnomeSettingsModule %p finalizing", module); g_free (module->path); G_OBJECT_CLASS (gnome_settings_module_parent_class)->finalize (object); } static void gnome_settings_module_class_init (GnomeSettingsModuleClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); object_class->finalize = gnome_settings_module_finalize; module_class->load = gnome_settings_module_load; module_class->unload = gnome_settings_module_unload; } GnomeSettingsModule * gnome_settings_module_new (const char *path) { GnomeSettingsModule *result; if (path == NULL || path[0] == '\0') { return NULL; } result = g_object_new (GNOME_TYPE_SETTINGS_MODULE, NULL); g_type_module_set_name (G_TYPE_MODULE (result), path); result->path = g_strdup (path); return result; } unity-settings-daemon/gnome-settings-daemon/gnome-settings-module.h0000664000000000000000000000410115172222611023013 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2005 - Paolo Maggi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef GNOME_SETTINGS_MODULE_H #define GNOME_SETTINGS_MODULE_H #include G_BEGIN_DECLS #define GNOME_TYPE_SETTINGS_MODULE (gnome_settings_module_get_type ()) #define GNOME_SETTINGS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_SETTINGS_MODULE, GnomeSettingsModule)) #define GNOME_SETTINGS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_SETTINGS_MODULE, GnomeSettingsModuleClass)) #define GNOME_IS_SETTINGS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_SETTINGS_MODULE)) #define GNOME_IS_SETTINGS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), GNOME_TYPE_SETTINGS_MODULE)) #define GNOME_SETTINGS_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNOME_TYPE_SETTINGS_MODULE, GnomeSettingsModuleClass)) typedef struct _GnomeSettingsModule GnomeSettingsModule; GType gnome_settings_module_get_type (void) G_GNUC_CONST; GnomeSettingsModule *gnome_settings_module_new (const gchar *path); const char *gnome_settings_module_get_path (GnomeSettingsModule *module); GObject *gnome_settings_module_new_object (GnomeSettingsModule *module); G_END_DECLS #endif unity-settings-daemon/gnome-settings-daemon/gnome-settings-plugin-info.c0000664000000000000000000003746615172222611023774 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #include "gnome-settings-plugin-info.h" #include "gnome-settings-module.h" #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #define GNOME_SETTINGS_PLUGIN_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNOME_TYPE_SETTINGS_PLUGIN_INFO, GnomeSettingsPluginInfoPrivate)) #define PLUGIN_GROUP "GNOME Settings Plugin" #define PLUGIN_PRIORITY_MAX 1 #define PLUGIN_PRIORITY_DEFAULT 100 struct GnomeSettingsPluginInfoPrivate { char *file; GSettings *settings; char *location; GTypeModule *module; char *name; char *desc; char **authors; char *copyright; char *website; GnomeSettingsPlugin *plugin; int enabled : 1; int active : 1; /* A plugin is unavailable if it is not possible to activate it due to an error loading the plugin module (e.g. for Python plugins when the interpreter has not been correctly initializated) */ int available : 1; /* Priority determines the order in which plugins are started and * stopped. A lower number means higher priority. */ guint priority; }; enum { ACTIVATED, DEACTIVATED, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0, }; G_DEFINE_TYPE (GnomeSettingsPluginInfo, gnome_settings_plugin_info, G_TYPE_OBJECT) static void gnome_settings_plugin_info_finalize (GObject *object) { GnomeSettingsPluginInfo *info; g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (object)); info = GNOME_SETTINGS_PLUGIN_INFO (object); g_return_if_fail (info->priv != NULL); if (info->priv->plugin != NULL) { g_debug ("Unref plugin %s", info->priv->name); g_object_unref (info->priv->plugin); /* info->priv->module must not be unref since it is not possible to finalize * a type module */ } g_free (info->priv->file); g_free (info->priv->location); g_free (info->priv->name); g_free (info->priv->desc); g_free (info->priv->website); g_free (info->priv->copyright); g_strfreev (info->priv->authors); if (info->priv->settings != NULL) { g_object_unref (info->priv->settings); } G_OBJECT_CLASS (gnome_settings_plugin_info_parent_class)->finalize (object); } static void gnome_settings_plugin_info_class_init (GnomeSettingsPluginInfoClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gnome_settings_plugin_info_finalize; signals [ACTIVATED] = g_signal_new ("activated", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GnomeSettingsPluginInfoClass, activated), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals [DEACTIVATED] = g_signal_new ("deactivated", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GnomeSettingsPluginInfoClass, deactivated), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_class_add_private (klass, sizeof (GnomeSettingsPluginInfoPrivate)); } static void gnome_settings_plugin_info_init (GnomeSettingsPluginInfo *info) { info->priv = GNOME_SETTINGS_PLUGIN_INFO_GET_PRIVATE (info); } static void debug_info (GnomeSettingsPluginInfo *info) { g_debug ("GnomeSettingsPluginInfo: name='%s' file='%s' location='%s'", info->priv->name, info->priv->file, info->priv->location); } static gboolean gnome_settings_plugin_info_fill_from_file (GnomeSettingsPluginInfo *info, const char *filename) { GKeyFile *plugin_file = NULL; char *str; int priority; gboolean ret; gnome_settings_profile_start ("%s", filename); ret = FALSE; info->priv->file = g_strdup (filename); plugin_file = g_key_file_new (); if (! g_key_file_load_from_file (plugin_file, filename, G_KEY_FILE_NONE, NULL)) { g_warning ("Bad plugin file: %s", filename); goto out; } if (! g_key_file_has_key (plugin_file, PLUGIN_GROUP, "IAge", NULL)) { g_debug ("IAge key does not exist in file: %s", filename); goto out; } /* Check IAge=2 */ if (g_key_file_get_integer (plugin_file, PLUGIN_GROUP, "IAge", NULL) != 0) { g_debug ("Wrong IAge in file: %s", filename); goto out; } /* Get Location */ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Module", NULL); if ((str != NULL) && (*str != '\0')) { info->priv->location = str; } else { g_free (str); g_warning ("Could not find 'Module' in %s", filename); goto out; } /* Get Name */ str = g_key_file_get_locale_string (plugin_file, PLUGIN_GROUP, "Name", NULL, NULL); if (str != NULL) { info->priv->name = str; } else { g_warning ("Could not find 'Name' in %s", filename); goto out; } /* Get Description */ str = g_key_file_get_locale_string (plugin_file, PLUGIN_GROUP, "Description", NULL, NULL); if (str != NULL) { info->priv->desc = str; } else { g_debug ("Could not find 'Description' in %s", filename); } /* Get Authors */ info->priv->authors = g_key_file_get_string_list (plugin_file, PLUGIN_GROUP, "Authors", NULL, NULL); if (info->priv->authors == NULL) { g_debug ("Could not find 'Authors' in %s", filename); } /* Get Copyright */ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Copyright", NULL); if (str != NULL) { info->priv->copyright = str; } else { g_debug ("Could not find 'Copyright' in %s", filename); } /* Get Website */ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Website", NULL); if (str != NULL) { info->priv->website = str; } else { g_debug ("Could not find 'Website' in %s", filename); } /* Get Priority */ priority = g_key_file_get_integer (plugin_file, PLUGIN_GROUP, "Priority", NULL); if (priority >= PLUGIN_PRIORITY_MAX) { info->priv->priority = priority; } else { info->priv->priority = PLUGIN_PRIORITY_DEFAULT; } g_key_file_free (plugin_file); debug_info (info); /* If we know nothing about the availability of the plugin, set it as available */ info->priv->available = TRUE; ret = TRUE; out: gnome_settings_profile_end ("%s", filename); return ret; } GnomeSettingsPluginInfo * gnome_settings_plugin_info_new_from_file (const char *filename) { GnomeSettingsPluginInfo *info; gboolean res; info = g_object_new (GNOME_TYPE_SETTINGS_PLUGIN_INFO, NULL); res = gnome_settings_plugin_info_fill_from_file (info, filename); if (! res) { g_object_unref (info); info = NULL; } return info; } static void plugin_enabled_cb (GSettings *settings, const gchar *key, GnomeSettingsPluginInfo *info) { if (g_strcmp0 (key, "active") == 0) { if (g_settings_get_boolean (settings, "active")) gnome_settings_plugin_info_activate (info); else gnome_settings_plugin_info_deactivate (info); } } void gnome_settings_plugin_info_set_settings_prefix (GnomeSettingsPluginInfo *info, const char *settings_prefix) { int priority; info->priv->settings = g_settings_new (settings_prefix); info->priv->enabled = g_settings_get_boolean (info->priv->settings, "active"); priority = g_settings_get_int (info->priv->settings, "priority"); if (priority > 0) info->priv->priority = priority; g_signal_connect (G_OBJECT (info->priv->settings), "changed", G_CALLBACK (plugin_enabled_cb), info); } static void _deactivate_plugin (GnomeSettingsPluginInfo *info) { gnome_settings_plugin_deactivate (info->priv->plugin); g_signal_emit (info, signals [DEACTIVATED], 0); } gboolean gnome_settings_plugin_info_deactivate (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), FALSE); if (!info->priv->active || !info->priv->available) { return TRUE; } _deactivate_plugin (info); /* Update plugin state */ info->priv->active = FALSE; return TRUE; } static gboolean load_plugin_module (GnomeSettingsPluginInfo *info) { char *path; char *dirname; gboolean ret; ret = FALSE; g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), FALSE); g_return_val_if_fail (info->priv->file != NULL, FALSE); g_return_val_if_fail (info->priv->location != NULL, FALSE); g_return_val_if_fail (info->priv->plugin == NULL, FALSE); g_return_val_if_fail (info->priv->available, FALSE); gnome_settings_profile_start ("%s", info->priv->location); dirname = g_path_get_dirname (info->priv->file); g_return_val_if_fail (dirname != NULL, FALSE); path = g_module_build_path (dirname, info->priv->location); g_free (dirname); g_return_val_if_fail (path != NULL, FALSE); info->priv->module = G_TYPE_MODULE (gnome_settings_module_new (path)); g_free (path); if (!g_type_module_use (info->priv->module)) { g_warning ("Cannot load plugin '%s' since file '%s' cannot be read.", info->priv->name, gnome_settings_module_get_path (GNOME_SETTINGS_MODULE (info->priv->module))); g_object_unref (G_OBJECT (info->priv->module)); info->priv->module = NULL; /* Mark plugin as unavailable and fails */ info->priv->available = FALSE; goto out; } info->priv->plugin = GNOME_SETTINGS_PLUGIN (gnome_settings_module_new_object (GNOME_SETTINGS_MODULE (info->priv->module))); g_type_module_unuse (info->priv->module); ret = TRUE; out: gnome_settings_profile_end ("%s", info->priv->location); return ret; } static gboolean _activate_plugin (GnomeSettingsPluginInfo *info) { gboolean res = TRUE; if (!info->priv->available) { /* Plugin is not available, don't try to activate/load it */ return FALSE; } if (info->priv->plugin == NULL) { res = load_plugin_module (info); } if (res) { gnome_settings_plugin_activate (info->priv->plugin); g_signal_emit (info, signals [ACTIVATED], 0); } else { g_warning ("Error activating plugin '%s'", info->priv->name); } return res; } gboolean gnome_settings_plugin_info_activate (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), FALSE); if (! info->priv->available) { return FALSE; } if (info->priv->active) { return TRUE; } if (_activate_plugin (info)) { info->priv->active = TRUE; return TRUE; } return FALSE; } gboolean gnome_settings_plugin_info_is_active (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), FALSE); return (info->priv->available && info->priv->active); } gboolean gnome_settings_plugin_info_get_enabled (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), FALSE); return (info->priv->enabled); } gboolean gnome_settings_plugin_info_is_available (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), FALSE); return (info->priv->available != FALSE); } const char * gnome_settings_plugin_info_get_name (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), NULL); return info->priv->name; } const char * gnome_settings_plugin_info_get_description (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), NULL); return info->priv->desc; } const char ** gnome_settings_plugin_info_get_authors (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), (const char **)NULL); return (const char **)info->priv->authors; } const char * gnome_settings_plugin_info_get_website (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), NULL); return info->priv->website; } const char * gnome_settings_plugin_info_get_copyright (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), NULL); return info->priv->copyright; } const char * gnome_settings_plugin_info_get_location (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), NULL); return info->priv->location; } int gnome_settings_plugin_info_get_priority (GnomeSettingsPluginInfo *info) { g_return_val_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info), PLUGIN_PRIORITY_DEFAULT); return info->priv->priority; } void gnome_settings_plugin_info_set_priority (GnomeSettingsPluginInfo *info, int priority) { g_return_if_fail (GNOME_IS_SETTINGS_PLUGIN_INFO (info)); info->priv->priority = priority; } unity-settings-daemon/gnome-settings-daemon/gnome-settings-plugin-info.h0000664000000000000000000000747415172222611023775 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __GNOME_SETTINGS_PLUGIN_INFO_H__ #define __GNOME_SETTINGS_PLUGIN_INFO_H__ #include #include G_BEGIN_DECLS #define GNOME_TYPE_SETTINGS_PLUGIN_INFO (gnome_settings_plugin_info_get_type()) #define GNOME_SETTINGS_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNOME_TYPE_SETTINGS_PLUGIN_INFO, GnomeSettingsPluginInfo)) #define GNOME_SETTINGS_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNOME_TYPE_SETTINGS_PLUGIN_INFO, GnomeSettingsPluginInfoClass)) #define GNOME_IS_SETTINGS_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNOME_TYPE_SETTINGS_PLUGIN_INFO)) #define GNOME_IS_SETTINGS_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_SETTINGS_PLUGIN_INFO)) #define GNOME_SETTINGS_PLUGIN_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNOME_TYPE_SETTINGS_PLUGIN_INFO, GnomeSettingsPluginInfoClass)) typedef struct GnomeSettingsPluginInfoPrivate GnomeSettingsPluginInfoPrivate; typedef struct { GObject parent; GnomeSettingsPluginInfoPrivate *priv; } GnomeSettingsPluginInfo; typedef struct { GObjectClass parent_class; void (* activated) (GnomeSettingsPluginInfo *info); void (* deactivated) (GnomeSettingsPluginInfo *info); } GnomeSettingsPluginInfoClass; GType gnome_settings_plugin_info_get_type (void) G_GNUC_CONST; GnomeSettingsPluginInfo *gnome_settings_plugin_info_new_from_file (const char *filename); void gnome_settings_plugin_info_set_settings_prefix (GnomeSettingsPluginInfo *info, const char *settings_prefix); gboolean gnome_settings_plugin_info_activate (GnomeSettingsPluginInfo *info); gboolean gnome_settings_plugin_info_deactivate (GnomeSettingsPluginInfo *info); gboolean gnome_settings_plugin_info_is_active (GnomeSettingsPluginInfo *info); gboolean gnome_settings_plugin_info_get_enabled (GnomeSettingsPluginInfo *info); gboolean gnome_settings_plugin_info_is_available (GnomeSettingsPluginInfo *info); const char *gnome_settings_plugin_info_get_name (GnomeSettingsPluginInfo *info); const char *gnome_settings_plugin_info_get_description (GnomeSettingsPluginInfo *info); const char **gnome_settings_plugin_info_get_authors (GnomeSettingsPluginInfo *info); const char *gnome_settings_plugin_info_get_website (GnomeSettingsPluginInfo *info); const char *gnome_settings_plugin_info_get_copyright (GnomeSettingsPluginInfo *info); const char *gnome_settings_plugin_info_get_location (GnomeSettingsPluginInfo *info); int gnome_settings_plugin_info_get_priority (GnomeSettingsPluginInfo *info); void gnome_settings_plugin_info_set_priority (GnomeSettingsPluginInfo *info, int priority); G_END_DECLS #endif /* __GNOME_SETTINGS_PLUGIN_INFO_H__ */ unity-settings-daemon/gnome-settings-daemon/gnome-settings-plugin.c0000664000000000000000000000334515172222611023030 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2002-2005 Paolo Maggi * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include "gnome-settings-plugin.h" G_DEFINE_TYPE (GnomeSettingsPlugin, gnome_settings_plugin, G_TYPE_OBJECT) static void dummy (GnomeSettingsPlugin *plugin) { /* Empty */ } static void gnome_settings_plugin_class_init (GnomeSettingsPluginClass *klass) { klass->activate = dummy; klass->deactivate = dummy; } static void gnome_settings_plugin_init (GnomeSettingsPlugin *plugin) { /* Empty */ } void gnome_settings_plugin_activate (GnomeSettingsPlugin *plugin) { g_return_if_fail (GNOME_IS_SETTINGS_PLUGIN (plugin)); GNOME_SETTINGS_PLUGIN_GET_CLASS (plugin)->activate (plugin); } void gnome_settings_plugin_deactivate (GnomeSettingsPlugin *plugin) { g_return_if_fail (GNOME_IS_SETTINGS_PLUGIN (plugin)); GNOME_SETTINGS_PLUGIN_GET_CLASS (plugin)->deactivate (plugin); } unity-settings-daemon/gnome-settings-daemon/gnome-settings-plugin.h0000664000000000000000000002311115172222611023026 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2002-2005 Paolo Maggi * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __GNOME_SETTINGS_PLUGIN_H__ #define __GNOME_SETTINGS_PLUGIN_H__ #include #include G_BEGIN_DECLS #define GNOME_TYPE_SETTINGS_PLUGIN (gnome_settings_plugin_get_type()) #define GNOME_SETTINGS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNOME_TYPE_SETTINGS_PLUGIN, GnomeSettingsPlugin)) #define GNOME_SETTINGS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNOME_TYPE_SETTINGS_PLUGIN, GnomeSettingsPluginClass)) #define GNOME_IS_SETTINGS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNOME_TYPE_SETTINGS_PLUGIN)) #define GNOME_IS_SETTINGS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_SETTINGS_PLUGIN)) #define GNOME_SETTINGS_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNOME_TYPE_SETTINGS_PLUGIN, GnomeSettingsPluginClass)) typedef struct { GObject parent; } GnomeSettingsPlugin; typedef struct { GObjectClass parent_class; /* Virtual public methods */ void (*activate) (GnomeSettingsPlugin *plugin); void (*deactivate) (GnomeSettingsPlugin *plugin); } GnomeSettingsPluginClass; GType gnome_settings_plugin_get_type (void) G_GNUC_CONST; void gnome_settings_plugin_activate (GnomeSettingsPlugin *plugin); void gnome_settings_plugin_deactivate (GnomeSettingsPlugin *plugin); #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" #define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" /* * Utility macro used to register plugins * * use: GNOME_SETTINGS_PLUGIN_REGISTER (PluginName, plugin_name) */ #define GNOME_SETTINGS_PLUGIN_REGISTER(PluginName, plugin_name) \ typedef struct { \ PluginName##Manager *manager; \ } PluginName##PluginPrivate; \ typedef struct { \ GnomeSettingsPlugin parent; \ PluginName##PluginPrivate *priv; \ } PluginName##Plugin; \ typedef struct { \ GnomeSettingsPluginClass parent_class; \ } PluginName##PluginClass; \ GType plugin_name##_plugin_get_type (void) G_GNUC_CONST; \ G_MODULE_EXPORT GType register_gnome_settings_plugin (GTypeModule *module); \ \ G_DEFINE_DYNAMIC_TYPE (PluginName##Plugin, \ plugin_name##_plugin, \ GNOME_TYPE_SETTINGS_PLUGIN) \ \ G_MODULE_EXPORT GType \ register_gnome_settings_plugin (GTypeModule *type_module) \ { \ plugin_name##_plugin_register_type (type_module); \ \ return plugin_name##_plugin_get_type(); \ } \ \ static void \ plugin_name##_plugin_class_finalize (PluginName##PluginClass * plugin_name##_class) \ { \ } \ \ static void \ plugin_name##_plugin_init (PluginName##Plugin *plugin) \ { \ plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE ((plugin), \ plugin_name##_plugin_get_type(), PluginName##PluginPrivate); \ g_debug (#PluginName " initializing"); \ plugin->priv->manager = plugin_name##_manager_new (); \ } \ \ static void \ plugin_name##_plugin_finalize (GObject *object) \ { \ PluginName##Plugin *plugin; \ g_return_if_fail (object != NULL); \ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (object, plugin_name##_plugin_get_type())); \ g_debug ("PluginName## finalizing"); \ plugin = G_TYPE_CHECK_INSTANCE_CAST ((object), plugin_name##_plugin_get_type(), PluginName##Plugin); \ g_return_if_fail (plugin->priv != NULL); \ if (plugin->priv->manager != NULL) \ g_object_unref (plugin->priv->manager); \ G_OBJECT_CLASS (plugin_name##_plugin_parent_class)->finalize (object); \ } \ \ static void \ impl_activate (GnomeSettingsPlugin *plugin) \ { \ GError *error = NULL; \ PluginName##Plugin *plugin_cast; \ g_debug ("Activating %s plugin", G_STRINGIFY(plugin_name)); \ plugin_cast = G_TYPE_CHECK_INSTANCE_CAST ((plugin), plugin_name##_plugin_get_type(), PluginName##Plugin); \ if (!plugin_name##_manager_start (plugin_cast->priv->manager, &error)) { \ g_warning ("Unable to start %s manager: %s", G_STRINGIFY(plugin_name), error->message); \ g_error_free (error); \ } \ } \ \ static void \ impl_deactivate (GnomeSettingsPlugin *plugin) \ { \ PluginName##Plugin *plugin_cast; \ plugin_cast = G_TYPE_CHECK_INSTANCE_CAST ((plugin), plugin_name##_plugin_get_type(), PluginName##Plugin); \ g_debug ("Deactivating %s plugin", G_STRINGIFY (plugin_name)); \ plugin_name##_manager_stop (plugin_cast->priv->manager); \ } \ \ static void \ plugin_name##_plugin_class_init (PluginName##PluginClass *klass) \ { \ GObjectClass *object_class = G_OBJECT_CLASS (klass); \ GnomeSettingsPluginClass *plugin_class = GNOME_SETTINGS_PLUGIN_CLASS (klass); \ \ object_class->finalize = plugin_name##_plugin_finalize; \ plugin_class->activate = impl_activate; \ plugin_class->deactivate = impl_deactivate; \ g_type_class_add_private (klass, sizeof (PluginName##PluginPrivate)); \ } G_END_DECLS #endif /* __GNOME_SETTINGS_PLUGIN_H__ */ unity-settings-daemon/gnome-settings-daemon/gnome-settings-profile.c0000664000000000000000000000367315172222611023176 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2005 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Authors: William Jon McCann * */ #include "config.h" #include #include #include #include #include #include #include #include #include "gnome-settings-profile.h" void _gnome_settings_profile_log (const char *func, const char *note, const char *format, ...) { va_list args; char *str; char *formatted; if (format == NULL) { formatted = g_strdup (""); } else { va_start (args, format); formatted = g_strdup_vprintf (format, args); va_end (args); } if (func != NULL) { str = g_strdup_printf ("MARK: %s %s: %s %s", g_get_prgname(), func, note ? note : "", formatted); } else { str = g_strdup_printf ("MARK: %s: %s %s", g_get_prgname(), note ? note : "", formatted); } g_free (formatted); g_access (str, F_OK); g_free (str); } unity-settings-daemon/gnome-settings-daemon/gnome-settings-profile.h0000664000000000000000000000420515172222611023173 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2005 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Authors: William Jon McCann * */ #ifndef __GNOME_SETTINGS_PROFILE_H #define __GNOME_SETTINGS_PROFILE_H #include G_BEGIN_DECLS #ifdef ENABLE_PROFILING #ifdef G_HAVE_ISO_VARARGS #define gnome_settings_profile_start(...) _gnome_settings_profile_log (G_STRFUNC, "start", __VA_ARGS__) #define gnome_settings_profile_end(...) _gnome_settings_profile_log (G_STRFUNC, "end", __VA_ARGS__) #define gnome_settings_profile_msg(...) _gnome_settings_profile_log (NULL, NULL, __VA_ARGS__) #elif defined(G_HAVE_GNUC_VARARGS) #define gnome_settings_profile_start(format...) _gnome_settings_profile_log (G_STRFUNC, "start", format) #define gnome_settings_profile_end(format...) _gnome_settings_profile_log (G_STRFUNC, "end", format) #define gnome_settings_profile_msg(format...) _gnome_settings_profile_log (NULL, NULL, format) #endif #else #define gnome_settings_profile_start(...) #define gnome_settings_profile_end(...) #define gnome_settings_profile_msg(...) #endif void _gnome_settings_profile_log (const char *func, const char *note, const char *format, ...) G_GNUC_PRINTF (3, 4); G_END_DECLS #endif /* __GNOME_SETTINGS_PROFILE_H */ unity-settings-daemon/gnome-settings-daemon/gsd-bg-crossfade.c0000664000000000000000000003540715172222611021707 0ustar /* gsd-bg-crossfade.h - fade window background between two surfaces * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * Author: Ray Strode */ #include #include #include #include #include #include #include #include #include #include #include #include "gsd-bg.h" #include "gsd-bg-crossfade.h" struct _GsdBGCrossfadePrivate { GdkWindow *window; int width; int height; cairo_surface_t *fading_surface; cairo_surface_t *end_surface; gdouble start_time; gdouble total_duration; guint timeout_id; guint is_first_frame : 1; }; enum { PROP_0, PROP_WIDTH, PROP_HEIGHT, }; enum { FINISHED, NUMBER_OF_SIGNALS }; static guint signals[NUMBER_OF_SIGNALS] = { 0 }; G_DEFINE_TYPE_WITH_PRIVATE (GsdBGCrossfade, gsd_bg_crossfade, G_TYPE_OBJECT) static void gsd_bg_crossfade_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GsdBGCrossfade *fade; g_assert (GSD_IS_BG_CROSSFADE (object)); fade = GSD_BG_CROSSFADE (object); switch (property_id) { case PROP_WIDTH: fade->priv->width = g_value_get_int (value); break; case PROP_HEIGHT: fade->priv->height = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gsd_bg_crossfade_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GsdBGCrossfade *fade; g_assert (GSD_IS_BG_CROSSFADE (object)); fade = GSD_BG_CROSSFADE (object); switch (property_id) { case PROP_WIDTH: g_value_set_int (value, fade->priv->width); break; case PROP_HEIGHT: g_value_set_int (value, fade->priv->height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gsd_bg_crossfade_finalize (GObject *object) { GsdBGCrossfade *fade; fade = GSD_BG_CROSSFADE (object); gsd_bg_crossfade_stop (fade); if (fade->priv->fading_surface != NULL) { cairo_surface_destroy (fade->priv->fading_surface); fade->priv->fading_surface = NULL; } if (fade->priv->end_surface != NULL) { g_object_unref (fade->priv->end_surface); fade->priv->end_surface = NULL; } } static void gsd_bg_crossfade_class_init (GsdBGCrossfadeClass *fade_class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (fade_class); gobject_class->get_property = gsd_bg_crossfade_get_property; gobject_class->set_property = gsd_bg_crossfade_set_property; gobject_class->finalize = gsd_bg_crossfade_finalize; /** * GsdBGCrossfade:width: * * When a crossfade is running, this is width of the fading * surface. */ g_object_class_install_property (gobject_class, PROP_WIDTH, g_param_spec_int ("width", "Window Width", "Width of window to fade", 0, G_MAXINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); /** * GsdBGCrossfade:height: * * When a crossfade is running, this is height of the fading * surface. */ g_object_class_install_property (gobject_class, PROP_HEIGHT, g_param_spec_int ("height", "Window Height", "Height of window to fade on", 0, G_MAXINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); /** * GsdBGCrossfade::finished: * @fade: the #GsdBGCrossfade that received the signal * @window: the #GdkWindow the crossfade happend on. * * When a crossfade finishes, @window will have a copy * of the end surface as its background, and this signal will * get emitted. */ signals[FINISHED] = g_signal_new ("finished", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); } static void gsd_bg_crossfade_init (GsdBGCrossfade *fade) { fade->priv = gsd_bg_crossfade_get_instance_private (fade); fade->priv->fading_surface = NULL; fade->priv->end_surface = NULL; fade->priv->timeout_id = 0; } /** * gsd_bg_crossfade_new: * @width: The width of the crossfading window * @height: The height of the crossfading window * * Creates a new object to manage crossfading a * window background between two #cairo_surface_ts. * * Return value: the new #GsdBGCrossfade **/ GsdBGCrossfade * gsd_bg_crossfade_new (int width, int height) { GObject *object; object = g_object_new (GSD_TYPE_BG_CROSSFADE, "width", width, "height", height, NULL); return (GsdBGCrossfade *) object; } static cairo_surface_t * tile_surface (cairo_surface_t *surface, int width, int height) { cairo_surface_t *copy; cairo_t *cr; if (surface == NULL) { copy = gdk_window_create_similar_surface (gdk_get_default_root_window (), CAIRO_CONTENT_COLOR, width, height); } else { copy = cairo_surface_create_similar (surface, cairo_surface_get_content (surface), width, height); } cr = cairo_create (copy); if (surface != NULL) { cairo_pattern_t *pattern; cairo_set_source_surface (cr, surface, 0.0, 0.0); pattern = cairo_get_source (cr); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); } else { GtkStyle *style; style = gtk_widget_get_default_style (); gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]); } cairo_paint (cr); if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (copy); copy = NULL; } cairo_destroy (cr); return copy; } /** * gsd_bg_crossfade_set_start_surface: * @fade: a #GsdBGCrossfade * @surface: The cairo surface to fade from * * Before initiating a crossfade with gsd_bg_crossfade_start() * a start and end surface have to be set. This function sets * the surface shown at the beginning of the crossfade effect. * * Return value: %TRUE if successful, or %FALSE if the surface * could not be copied. **/ gboolean gsd_bg_crossfade_set_start_surface (GsdBGCrossfade *fade, cairo_surface_t *surface) { g_return_val_if_fail (GSD_IS_BG_CROSSFADE (fade), FALSE); if (fade->priv->fading_surface != NULL) { cairo_surface_destroy (fade->priv->fading_surface); fade->priv->fading_surface = NULL; } fade->priv->fading_surface = tile_surface (surface, fade->priv->width, fade->priv->height); return fade->priv->fading_surface != NULL; } static gdouble get_current_time (void) { const double microseconds_per_second = (double) G_USEC_PER_SEC; double timestamp; GTimeVal now; g_get_current_time (&now); timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) / microseconds_per_second; return timestamp; } /** * gsd_bg_crossfade_set_end_surface: * @fade: a #GsdBGCrossfade * @surface: The cairo surface to fade to * * Before initiating a crossfade with gsd_bg_crossfade_start() * a start and end surface have to be set. This function sets * the surface shown at the end of the crossfade effect. * * Return value: %TRUE if successful, or %FALSE if the surface * could not be copied. **/ gboolean gsd_bg_crossfade_set_end_surface (GsdBGCrossfade *fade, cairo_surface_t *surface) { g_return_val_if_fail (GSD_IS_BG_CROSSFADE (fade), FALSE); if (fade->priv->end_surface != NULL) { cairo_surface_destroy (fade->priv->end_surface); fade->priv->end_surface = NULL; } fade->priv->end_surface = tile_surface (surface, fade->priv->width, fade->priv->height); /* Reset timer in case we're called while animating */ fade->priv->start_time = get_current_time (); return fade->priv->end_surface != NULL; } static gboolean animations_are_disabled (GsdBGCrossfade *fade) { GtkSettings *settings; GdkScreen *screen; gboolean are_enabled; g_assert (fade->priv->window != NULL); screen = gdk_window_get_screen (fade->priv->window); settings = gtk_settings_get_for_screen (screen); g_object_get (settings, "gtk-enable-animations", &are_enabled, NULL); return !are_enabled; } static void send_root_property_change_notification (GsdBGCrossfade *fade) { long zero_length_pixmap; /* We do a zero length append to force a change notification, * without changing the value */ XChangeProperty (GDK_WINDOW_XDISPLAY (fade->priv->window), GDK_WINDOW_XID (fade->priv->window), gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"), XA_PIXMAP, 32, PropModeAppend, (guchar *) &zero_length_pixmap, 0); } static void draw_background (GsdBGCrossfade *fade) { if (gdk_window_get_window_type (fade->priv->window) == GDK_WINDOW_ROOT) { XClearArea (GDK_WINDOW_XDISPLAY (fade->priv->window), GDK_WINDOW_XID (fade->priv->window), 0, 0, gdk_window_get_width (fade->priv->window), gdk_window_get_height (fade->priv->window), False); send_root_property_change_notification (fade); gdk_flush (); } else { gdk_window_invalidate_rect (fade->priv->window, NULL, FALSE); gdk_window_process_updates (fade->priv->window, FALSE); } } static gboolean on_tick (GsdBGCrossfade *fade) { gdouble now, percent_done; cairo_t *cr; cairo_status_t status; g_return_val_if_fail (GSD_IS_BG_CROSSFADE (fade), FALSE); now = get_current_time (); percent_done = (now - fade->priv->start_time) / fade->priv->total_duration; percent_done = CLAMP (percent_done, 0.0, 1.0); /* If it's taking a long time to get to the first frame, * then lengthen the duration, so the user will get to see * the effect. */ if (fade->priv->is_first_frame && percent_done > .33) { fade->priv->is_first_frame = FALSE; fade->priv->total_duration *= 1.5; return on_tick (fade); } if (fade->priv->fading_surface == NULL) { return FALSE; } if (animations_are_disabled (fade)) { return FALSE; } /* We accumulate the results in place for performance reasons. * * This means 1) The fade is exponential, not linear (looks good!) * 2) The rate of fade is not independent of frame rate. Slower machines * will get a slower fade (but never longer than .75 seconds), and * even the fastest machines will get *some* fade because the framerate * is capped. */ cr = cairo_create (fade->priv->fading_surface); cairo_set_source_surface (cr, fade->priv->end_surface, 0.0, 0.0); cairo_paint_with_alpha (cr, percent_done); status = cairo_status (cr); cairo_destroy (cr); if (status == CAIRO_STATUS_SUCCESS) { draw_background (fade); } return percent_done <= .99; } static void on_finished (GsdBGCrossfade *fade) { cairo_pattern_t *pattern; if (fade->priv->timeout_id == 0) return; g_assert (fade->priv->end_surface != NULL); pattern = cairo_pattern_create_for_surface (fade->priv->end_surface); gdk_window_set_background_pattern (fade->priv->window, pattern); cairo_pattern_destroy (pattern); draw_background (fade); cairo_surface_destroy (fade->priv->end_surface); fade->priv->end_surface = NULL; g_assert (fade->priv->fading_surface != NULL); cairo_surface_destroy (fade->priv->fading_surface); fade->priv->fading_surface = NULL; fade->priv->timeout_id = 0; g_signal_emit (fade, signals[FINISHED], 0, fade->priv->window); } /** * gsd_bg_crossfade_start: * @fade: a #GsdBGCrossfade * @window: The #GdkWindow to draw crossfade on * * This function initiates a quick crossfade between two surfaces on * the background of @window. Before initiating the crossfade both * gsd_bg_crossfade_start() and gsd_bg_crossfade_end() need to * be called. If animations are disabled, the crossfade is skipped, * and the window background is set immediately to the end surface. **/ void gsd_bg_crossfade_start (GsdBGCrossfade *fade, GdkWindow *window) { GSource *source; GMainContext *context; cairo_pattern_t *pattern; g_return_if_fail (GSD_IS_BG_CROSSFADE (fade)); g_return_if_fail (window != NULL); g_return_if_fail (fade->priv->fading_surface != NULL); g_return_if_fail (fade->priv->end_surface != NULL); g_return_if_fail (!gsd_bg_crossfade_is_started (fade)); g_return_if_fail (gdk_window_get_window_type (window) != GDK_WINDOW_FOREIGN); source = g_timeout_source_new (1000 / 60.0); g_source_set_callback (source, (GSourceFunc) on_tick, fade, (GDestroyNotify) on_finished); context = g_main_context_default (); fade->priv->timeout_id = g_source_attach (source, context); g_source_unref (source); fade->priv->window = window; pattern = cairo_pattern_create_for_surface (fade->priv->fading_surface); gdk_window_set_background_pattern (fade->priv->window, pattern); cairo_pattern_destroy (pattern); draw_background (fade); fade->priv->is_first_frame = TRUE; fade->priv->total_duration = .75; fade->priv->start_time = get_current_time (); } /** * gsd_bg_crossfade_is_started: * @fade: a #GsdBGCrossfade * * This function reveals whether or not @fade is currently * running on a window. See gsd_bg_crossfade_start() for * information on how to initiate a crossfade. * * Return value: %TRUE if fading, or %FALSE if not fading **/ gboolean gsd_bg_crossfade_is_started (GsdBGCrossfade *fade) { g_return_val_if_fail (GSD_IS_BG_CROSSFADE (fade), FALSE); return fade->priv->timeout_id != 0; } /** * gsd_bg_crossfade_stop: * @fade: a #GsdBGCrossfade * * This function stops any in progress crossfades that may be * happening. It's harmless to call this function if @fade is * already stopped. **/ void gsd_bg_crossfade_stop (GsdBGCrossfade *fade) { g_return_if_fail (GSD_IS_BG_CROSSFADE (fade)); if (!gsd_bg_crossfade_is_started (fade)) return; g_assert (fade->priv->timeout_id != 0); g_source_remove (fade->priv->timeout_id); fade->priv->timeout_id = 0; } unity-settings-daemon/gnome-settings-daemon/gsd-bg-crossfade.h0000664000000000000000000000550415172222611021707 0ustar /* gsd-bg-crossfade.h - fade window background between two surfaces Copyright 2008, Red Hat, Inc. This file is part of the Gnome Library. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Author: Ray Strode */ #ifndef __GSD_BG_CROSSFADE_H__ #define __GSD_BG_CROSSFADE_H__ #include G_BEGIN_DECLS #define GSD_TYPE_BG_CROSSFADE (gsd_bg_crossfade_get_type ()) #define GSD_BG_CROSSFADE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_BG_CROSSFADE, GsdBGCrossfade)) #define GSD_BG_CROSSFADE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_BG_CROSSFADE, GsdBGCrossfadeClass)) #define GSD_IS_BG_CROSSFADE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_BG_CROSSFADE)) #define GSD_IS_BG_CROSSFADE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_BG_CROSSFADE)) #define GSD_BG_CROSSFADE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_BG_CROSSFADE, GsdBGCrossfadeClass)) typedef struct _GsdBGCrossfadePrivate GsdBGCrossfadePrivate; typedef struct _GsdBGCrossfade GsdBGCrossfade; typedef struct _GsdBGCrossfadeClass GsdBGCrossfadeClass; struct _GsdBGCrossfade { GObject parent_object; GsdBGCrossfadePrivate *priv; }; struct _GsdBGCrossfadeClass { GObjectClass parent_class; void (* finished) (GsdBGCrossfade *fade, GdkWindow *window); }; G_DEFINE_AUTOPTR_CLEANUP_FUNC(GsdBGCrossfade, g_object_unref) GType gsd_bg_crossfade_get_type (void); GsdBGCrossfade *gsd_bg_crossfade_new (int width, int height); gboolean gsd_bg_crossfade_set_start_surface (GsdBGCrossfade *fade, cairo_surface_t *surface); gboolean gsd_bg_crossfade_set_end_surface (GsdBGCrossfade *fade, cairo_surface_t *surface); void gsd_bg_crossfade_start (GsdBGCrossfade *fade, GdkWindow *window); gboolean gsd_bg_crossfade_is_started (GsdBGCrossfade *fade); void gsd_bg_crossfade_stop (GsdBGCrossfade *fade); G_END_DECLS #endif unity-settings-daemon/gnome-settings-daemon/gsd-bg-slide-show.c0000664000000000000000000006165315172222611022016 0ustar /* gsd-bg-slide-show.h * * Copyright (C) 2008, 2013 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * */ #include #include #include #include #include #include "gsd-bg-slide-show.h" struct _GsdBGSlideShowPrivate { GFile *file; double start_time; double total_duration; GQueue *slides; gboolean has_multiple_sizes; /* used during parsing */ struct tm start_tm; GQueue *stack; }; typedef struct _Slide Slide; struct _Slide { double duration; /* in seconds */ gboolean fixed; GSList *file1; GSList *file2; /* NULL if fixed is TRUE */ }; typedef struct _FileSize FileSize; struct _FileSize { gint width; gint height; char *file; }; enum { PROP_0, PROP_FILE, PROP_START_TIME, PROP_TOTAL_DURATION, PROP_HAS_MULTIPLE_SIZES, }; G_DEFINE_TYPE_WITH_PRIVATE (GsdBGSlideShow, gsd_bg_slide_show, G_TYPE_OBJECT) static void gsd_bg_slide_show_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GsdBGSlideShow *self; g_assert (GSD_BG_IS_SLIDE_SHOW (object)); self = GSD_BG_SLIDE_SHOW (object); switch (property_id) { case PROP_FILE: self->priv->file = g_object_ref (g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gsd_bg_slide_show_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GsdBGSlideShow *self; g_assert (GSD_BG_IS_SLIDE_SHOW (object)); self = GSD_BG_SLIDE_SHOW (object); switch (property_id) { case PROP_FILE: g_value_set_object (value, self->priv->file); break; case PROP_START_TIME: g_value_set_int (value, self->priv->start_time); break; case PROP_TOTAL_DURATION: g_value_set_int (value, self->priv->total_duration); break; case PROP_HAS_MULTIPLE_SIZES: g_value_set_boolean (value, self->priv->has_multiple_sizes); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gsd_bg_slide_show_finalize (GObject *object) { GsdBGSlideShow *self; GList *list; GSList *slist; FileSize *size; self = GSD_BG_SLIDE_SHOW (object); for (list = self->priv->slides->head; list != NULL; list = list->next) { Slide *slide = list->data; for (slist = slide->file1; slist != NULL; slist = slist->next) { size = slist->data; g_free (size->file); g_free (size); } g_slist_free (slide->file1); for (slist = slide->file2; slist != NULL; slist = slist->next) { size = slist->data; g_free (size->file); g_free (size); } g_slist_free (slide->file2); g_free (slide); } g_queue_free (self->priv->slides); g_queue_free_full (self->priv->stack, g_free); g_object_unref (self->priv->file); } static void gsd_bg_slide_show_class_init (GsdBGSlideShowClass *self_class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (self_class); gobject_class->get_property = gsd_bg_slide_show_get_property; gobject_class->set_property = gsd_bg_slide_show_set_property; gobject_class->finalize = gsd_bg_slide_show_finalize; g_object_class_install_property (gobject_class, PROP_FILE, g_param_spec_object ("file", "File", "File", G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_START_TIME, g_param_spec_double ("start-time", "Start time", "start time", 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_TOTAL_DURATION, g_param_spec_double ("total-duration", "Start duration", "total duration", 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SIZES, g_param_spec_boolean ("has-multiple-sizes", "Has multiple sizes", "Has multiple sizes", FALSE, G_PARAM_READABLE)); } static void gsd_bg_slide_show_init (GsdBGSlideShow *self) { self->priv = gsd_bg_slide_show_get_instance_private (self); self->priv->stack = g_queue_new (); self->priv->slides = g_queue_new (); } /** * gsd_bg_slide_show_new: * @filename: The filename of the slide show * * Creates a new object to manage a slide show. * window background between two #cairo_surface_ts. * * Return value: the new #GsdBGSlideShow **/ GsdBGSlideShow * gsd_bg_slide_show_new (const char *filename) { GFile *file; GsdBGSlideShow *self; file = g_file_new_for_path (filename); self = GSD_BG_SLIDE_SHOW (g_object_new (GSD_BG_TYPE_SLIDE_SHOW, "file", file, NULL)); g_object_unref (file); return self; } static void threadsafe_localtime (time_t time, struct tm *tm) { struct tm *res; G_LOCK_DEFINE_STATIC (localtime_mutex); G_LOCK (localtime_mutex); res = localtime (&time); if (tm) { *tm = *res; } G_UNLOCK (localtime_mutex); } static gboolean stack_is (GsdBGSlideShow *self, const char *s1, ...); /* Parser for fading background */ static void handle_start_element (GMarkupParseContext *context, const gchar *name, const gchar **attr_names, const gchar **attr_values, gpointer user_data, GError **err) { GsdBGSlideShow *self = user_data; gint i; if (strcmp (name, "static") == 0 || strcmp (name, "transition") == 0) { Slide *slide = g_new0 (Slide, 1); if (strcmp (name, "static") == 0) slide->fixed = TRUE; g_queue_push_tail (self->priv->slides, slide); } else if (strcmp (name, "size") == 0) { Slide *slide = self->priv->slides->tail->data; FileSize *size = g_new0 (FileSize, 1); for (i = 0; attr_names[i]; i++) { if (strcmp (attr_names[i], "width") == 0) size->width = atoi (attr_values[i]); else if (strcmp (attr_names[i], "height") == 0) size->height = atoi (attr_values[i]); } if (self->priv->stack->tail && (strcmp (self->priv->stack->tail->data, "file") == 0 || strcmp (self->priv->stack->tail->data, "from") == 0)) { slide->file1 = g_slist_prepend (slide->file1, size); } else if (self->priv->stack->tail && strcmp (self->priv->stack->tail->data, "to") == 0) { slide->file2 = g_slist_prepend (slide->file2, size); } } g_queue_push_tail (self->priv->stack, g_strdup (name)); } static void handle_end_element (GMarkupParseContext *context, const gchar *name, gpointer user_data, GError **err) { GsdBGSlideShow *self = user_data; g_free (g_queue_pop_tail (self->priv->stack)); } static gboolean stack_is (GsdBGSlideShow *self, const char *s1, ...) { GList *stack = NULL; const char *s; GList *l1, *l2; va_list args; stack = g_list_prepend (stack, (gpointer)s1); va_start (args, s1); s = va_arg (args, const char *); while (s) { stack = g_list_prepend (stack, (gpointer)s); s = va_arg (args, const char *); } l1 = stack; l2 = self->priv->stack->head; while (l1 && l2) { if (strcmp (l1->data, l2->data) != 0) { g_list_free (stack); return FALSE; } l1 = l1->next; l2 = l2->next; } g_list_free (stack); return (!l1 && !l2); } static int parse_int (const char *text) { return strtol (text, NULL, 0); } static void handle_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **err) { GsdBGSlideShow *self = user_data; Slide *slide = self->priv->slides->tail? self->priv->slides->tail->data : NULL; FileSize *fs; gint i; if (stack_is (self, "year", "starttime", "background", NULL)) { self->priv->start_tm.tm_year = parse_int (text) - 1900; } else if (stack_is (self, "month", "starttime", "background", NULL)) { self->priv->start_tm.tm_mon = parse_int (text) - 1; } else if (stack_is (self, "day", "starttime", "background", NULL)) { self->priv->start_tm.tm_mday = parse_int (text); } else if (stack_is (self, "hour", "starttime", "background", NULL)) { self->priv->start_tm.tm_hour = parse_int (text) - 1; } else if (stack_is (self, "minute", "starttime", "background", NULL)) { self->priv->start_tm.tm_min = parse_int (text); } else if (stack_is (self, "second", "starttime", "background", NULL)) { self->priv->start_tm.tm_sec = parse_int (text); } else if (stack_is (self, "duration", "static", "background", NULL) || stack_is (self, "duration", "transition", "background", NULL)) { slide->duration = g_strtod (text, NULL); self->priv->total_duration += slide->duration; } else if (stack_is (self, "file", "static", "background", NULL) || stack_is (self, "from", "transition", "background", NULL)) { for (i = 0; text[i]; i++) { if (!g_ascii_isspace (text[i])) break; } if (text[i] == 0) return; fs = g_new (FileSize, 1); fs->width = -1; fs->height = -1; fs->file = g_strdup (text); slide->file1 = g_slist_prepend (slide->file1, fs); if (slide->file1->next != NULL) self->priv->has_multiple_sizes = TRUE; } else if (stack_is (self, "size", "file", "static", "background", NULL) || stack_is (self, "size", "from", "transition", "background", NULL)) { fs = slide->file1->data; fs->file = g_strdup (text); if (slide->file1->next != NULL) self->priv->has_multiple_sizes = TRUE; } else if (stack_is (self, "to", "transition", "background", NULL)) { for (i = 0; text[i]; i++) { if (!g_ascii_isspace (text[i])) break; } if (text[i] == 0) return; fs = g_new (FileSize, 1); fs->width = -1; fs->height = -1; fs->file = g_strdup (text); slide->file2 = g_slist_prepend (slide->file2, fs); if (slide->file2->next != NULL) self->priv->has_multiple_sizes = TRUE; } else if (stack_is (self, "size", "to", "transition", "background", NULL)) { fs = slide->file2->data; fs->file = g_strdup (text); if (slide->file2->next != NULL) self->priv->has_multiple_sizes = TRUE; } } /* * Find the FileSize that best matches the given size. * Do two passes; the first pass only considers FileSizes * that are larger than the given size. * We are looking for the image that best matches the aspect ratio. * When two images have the same aspect ratio, prefer the one whose * width is closer to the given width. */ static const char * find_best_size (GSList *sizes, gint width, gint height) { GSList *s; gdouble a, d, distance; FileSize *best = NULL; gint pass; a = width/(gdouble)height; distance = 10000.0; for (pass = 0; pass < 2; pass++) { for (s = sizes; s; s = s->next) { FileSize *size = s->data; if (pass == 0 && (size->width < width || size->height < height)) continue; d = fabs (a - size->width/(gdouble)size->height); if (d < distance) { distance = d; best = size; } else if (d == distance) { if (abs (size->width - width) < abs (best->width - width)) { best = size; } } } if (best) break; } return best->file; } static double now (void) { GTimeVal tv; g_get_current_time (&tv); return (double)tv.tv_sec + (tv.tv_usec / 1000000.0); } /** * gsd_bg_slide_show_get_current_slide: * @self: a #GsdBGSlideShow * @width: monitor width * @height: monitor height * @progress: (out) (allow-none): slide progress * @duration: (out) (allow-none): slide duration * @is_fixed: (out) (allow-none): if slide is fixed * @file1: (out) (allow-none) (transfer none): first file in slide * @file2: (out) (allow-none) (transfer none): second file in slide * * Returns the current slides progress. **/ void gsd_bg_slide_show_get_current_slide (GsdBGSlideShow *self, int width, int height, gdouble *progress, double *duration, gboolean *is_fixed, const char **file1, const char **file2) { double delta = fmod (now() - self->priv->start_time, self->priv->total_duration); GList *list; double elapsed; int i; if (delta < 0) delta += self->priv->total_duration; elapsed = 0; i = 0; for (list = self->priv->slides->head; list != NULL; list = list->next) { Slide *slide = list->data; if (elapsed + slide->duration > delta) { if (progress) *progress = (delta - elapsed) / (double)slide->duration; if (duration) *duration = slide->duration; if (is_fixed) *is_fixed = slide->fixed; if (file1) *file1 = find_best_size (slide->file1, width, height); if (file2 && slide->file2) *file2 = find_best_size (slide->file2, width, height); return; } i++; elapsed += slide->duration; } /* this should never happen since we have slides and we should always * find a current slide for the elapsed time since beginning -- we're * looping with fmod() */ g_assert_not_reached (); } /** * gsd_bg_slide_show_get_slide: * @self: a #GsdBGSlideShow * @frame_number: frame number * @width: monitor width * @height: monitor height * @progress: (out) (allow-none): slide progress * @duration: (out) (allow-none): slide duration * @is_fixed: (out) (allow-none): if slide is fixed * @file1: (out) (allow-none) (transfer none): first file in slide * @file2: (out) (allow-none) (transfer none): second file in slide * * Retrieves slide by frame number * * Return value: %TRUE if successful **/ gboolean gsd_bg_slide_show_get_slide (GsdBGSlideShow *self, int frame_number, int width, int height, double *progress, double *duration, gboolean *is_fixed, const char **file1, const char **file2) { double delta = fmod (now() - self->priv->start_time, self->priv->total_duration); GList *l; int i, skipped; gboolean found; double elapsed; Slide *slide; if (delta < 0) delta += self->priv->total_duration; elapsed = 0; i = 0; skipped = 0; found = FALSE; for (l = self->priv->slides->head; l; l = l->next) { slide = l->data; if (!slide->fixed) { elapsed += slide->duration; skipped++; continue; } if (i == frame_number) { found = TRUE; break; } i++; elapsed += slide->duration; } if (!found) return FALSE; if (progress) { if (elapsed + slide->duration > delta) { *progress = (delta - elapsed) / (double)slide->duration; } else { *progress = 0.0; } } if (duration) *duration = slide->duration; if (is_fixed) *is_fixed = slide->fixed; if (file1) *file1 = find_best_size (slide->file1, width, height); if (file2 && slide->file2) *file2 = find_best_size (slide->file2, width, height); return TRUE; } static gboolean parse_file_contents (GsdBGSlideShow *self, const char *contents, gsize len, GError **error) { GMarkupParser parser = { handle_start_element, handle_end_element, handle_text, NULL, /* passthrough */ NULL, /* error */ }; GMarkupParseContext *context = NULL; time_t t; gboolean failed = FALSE; threadsafe_localtime ((time_t)0, &self->priv->start_tm); context = g_markup_parse_context_new (&parser, 0, self, NULL); if (!g_markup_parse_context_parse (context, contents, len, error)) { failed = TRUE; } if (!failed && !g_markup_parse_context_end_parse (context, error)) { failed = TRUE; } g_markup_parse_context_free (context); if (!failed) { guint queue_length; t = mktime (&self->priv->start_tm); self->priv->start_time = (double)t; queue_length = g_queue_get_length (self->priv->slides); /* no slides, that's not a slideshow */ if (queue_length == 0) { g_set_error_literal (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "file is not a slide show since it has no slides"); failed = TRUE; /* one slide, there's no transition */ } else if (queue_length == 1) { Slide *slide = self->priv->slides->head->data; slide->duration = self->priv->total_duration = G_MAXUINT; } } return !failed; } /** * gsd_bg_slide_show_load: * @self: a #GsdBGSlideShow * @error: a #GError * * Tries to load the slide show. * * Return value: %TRUE if successful **/ gboolean gsd_bg_slide_show_load (GsdBGSlideShow *self, GError **error) { char *contents; gsize length; gboolean parsed; if (!g_file_load_contents (self->priv->file, NULL, &contents, &length, NULL, NULL)) { return FALSE; } parsed = parse_file_contents (self, contents, length, error); g_free (contents); return parsed; } static void on_file_loaded (GFile *file, GAsyncResult *result, GTask *task) { gboolean loaded; char *contents; gsize length; GError *error = NULL; loaded = g_file_load_contents_finish (file, result, &contents, &length, NULL, &error); if (!loaded) { g_task_return_error (task, error); g_object_unref (task); return; } if (!parse_file_contents (g_task_get_source_object (task), contents, length, &error)) { g_task_return_error (task, error); g_object_unref (task); g_free (contents); return; } g_free (contents); g_task_return_boolean (task, TRUE); g_object_unref (task); } /** * gsd_bg_slide_show_load_async: * @self: a #GsdBGSlideShow * @cancellable: a #GCancellable * @callback: the callback * @user_data: user data * * Tries to load the slide show asynchronously. **/ void gsd_bg_slide_show_load_async (GsdBGSlideShow *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; task = g_task_new (self, cancellable, callback, user_data); g_file_load_contents_async (self->priv->file, cancellable, (GAsyncReadyCallback) on_file_loaded, task); } /** * gsd_bg_slide_show_get_start_time: * @self: a #GsdBGSlideShow * * gets the start time of the slide show * * Return value: a timestamp **/ double gsd_bg_slide_show_get_start_time (GsdBGSlideShow *self) { return self->priv->start_time; } /** * gsd_bg_slide_show_get_total_duration: * @self: a #GsdBGSlideShow * * gets the total duration of the slide show * * Return value: a timestamp **/ double gsd_bg_slide_show_get_total_duration (GsdBGSlideShow *self) { return self->priv->total_duration; } /** * gsd_bg_slide_show_get_has_multiple_sizes: * @self: a #GsdBGSlideShow * * gets whether or not the slide show has multiple sizes for different monitors * * Return value: %TRUE if multiple sizes **/ gboolean gsd_bg_slide_show_get_has_multiple_sizes (GsdBGSlideShow *self) { return self->priv->has_multiple_sizes; } /** * gsd_bg_slide_show_get_num_slides: * @self: a #GsdBGSlideShow * * Returns number of slides in slide show **/ int gsd_bg_slide_show_get_num_slides (GsdBGSlideShow *self) { return g_queue_get_length (self->priv->slides); } unity-settings-daemon/gnome-settings-daemon/gsd-bg-slide-show.h0000664000000000000000000001033615172222611022013 0ustar /* gsd-bg-slide_show.h - fade window background between two surfaces Copyright 2008, Red Hat, Inc. This file is part of the Gnome Library. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Author: Ray Strode */ #ifndef __GSD_BG_SLIDE_SHOW_H__ #define __GSD_BG_SLIDE_SHOW_H__ #include G_BEGIN_DECLS #define GSD_BG_TYPE_SLIDE_SHOW (gsd_bg_slide_show_get_type ()) #define GSD_BG_SLIDE_SHOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_BG_TYPE_SLIDE_SHOW, GsdBGSlideShow)) #define GSD_BG_SLIDE_SHOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_BG_TYPE_SLIDE_SHOW, GsdBGSlideShowClass)) #define GSD_BG_IS_SLIDE_SHOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_BG_TYPE_SLIDE_SHOW)) #define GSD_BG_IS_SLIDE_SHOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_BG_TYPE_SLIDE_SHOW)) #define GSD_BG_SLIDE_SHOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_BG_TYPE_SLIDE_SHOW, GsdBGSlideShowClass)) typedef struct _GsdBGSlideShowPrivate GsdBGSlideShowPrivate; typedef struct _GsdBGSlideShow GsdBGSlideShow; typedef struct _GsdBGSlideShowClass GsdBGSlideShowClass; struct _GsdBGSlideShow { GObject parent_object; GsdBGSlideShowPrivate *priv; }; struct _GsdBGSlideShowClass { GObjectClass parent_class; }; G_DEFINE_AUTOPTR_CLEANUP_FUNC(GsdBGSlideShow, g_object_unref) GType gsd_bg_slide_show_get_type (void); GsdBGSlideShow *gsd_bg_slide_show_new (const char *filename); gboolean gsd_bg_slide_show_load (GsdBGSlideShow *self, GError **error); void gsd_bg_slide_show_load_async (GsdBGSlideShow *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean gsd_bg_slide_show_get_slide (GsdBGSlideShow *self, int frame_number, int width, int height, gdouble *progress, double *duration, gboolean *is_fixed, const char **file1, const char **file2); void gsd_bg_slide_show_get_current_slide (GsdBGSlideShow *self, int width, int height, gdouble *progress, double *duration, gboolean *is_fixed, const char **file1, const char **file2); double gsd_bg_slide_show_get_start_time (GsdBGSlideShow *self); double gsd_bg_slide_show_get_total_duration (GsdBGSlideShow *self); gboolean gsd_bg_slide_show_get_has_multiple_sizes (GsdBGSlideShow *self); int gsd_bg_slide_show_get_num_slides (GsdBGSlideShow *self); G_END_DECLS #endif unity-settings-daemon/gnome-settings-daemon/gsd-bg.c0000664000000000000000000022273115172222611017736 0ustar /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- gnomebg.c: Object for the desktop background. Copyright (C) 2000 Eazel, Inc. Copyright (C) 2007-2008 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Derived from eel-background.c and eel-gdk-pixbuf-extensions.c by Darin Adler and Ramiro Estrugo Author: Soren Sandmann */ #include #include #include #include #include #include #include #include #include #include #include #include "gsd-bg.h" #include "gsd-bg-slide-show.h" #include "gsd-bg-crossfade.h" #define BG_KEY_DRAW_BACKGROUND "draw-background" #define BG_KEY_PRIMARY_COLOR "primary-color" #define BG_KEY_SECONDARY_COLOR "secondary-color" #define BG_KEY_COLOR_TYPE "color-shading-type" #define BG_KEY_PICTURE_PLACEMENT "picture-options" #define BG_KEY_PICTURE_OPACITY "picture-opacity" #define BG_KEY_PICTURE_URI "picture-uri" /* We keep the large pixbufs around if the next update in the slideshow is less than 60 seconds away */ #define KEEP_EXPENSIVE_CACHE_SECS 60 #define QUAD_MAX_LEVEL_OF_RECURSION 16 #define QUAD_MIN_LEVEL_OF_RECURSION 2 /* We're weighting the left side of the screen higher than the right because the launcher and dash are on that side of the screen. */ #define QUAD_CORNER_WEIGHT_NW 3 #define QUAD_CORNER_WEIGHT_NE 1 #define QUAD_CORNER_WEIGHT_SE 1 #define QUAD_CORNER_WEIGHT_SW 3 #define QUAD_CORNER_WEIGHT_CENTER 2 #define QUAD_CORNER_WEIGHT_TOTAL (QUAD_CORNER_WEIGHT_NW + QUAD_CORNER_WEIGHT_NE + QUAD_CORNER_WEIGHT_SE + QUAD_CORNER_WEIGHT_SW + QUAD_CORNER_WEIGHT_CENTER) /* This is the size of the GdkRGB dither matrix, in order to avoid * bad dithering when tiling the gradient */ #define GRADIENT_PIXMAP_TILE_SIZE 128 #define THUMBNAIL_SIZE 256 typedef struct FileCacheEntry FileCacheEntry; #define CACHE_SIZE 4 /* * Implementation of the GsdBG class */ struct _GsdBG { GObject parent_instance; char * filename; GDesktopBackgroundStyle placement; GDesktopBackgroundShading color_type; GdkRGBA primary; GdkRGBA secondary; gboolean is_enabled; GFileMonitor * file_monitor; guint changed_id; guint transitioned_id; guint blow_caches_id; /* Cached information, only access through cache accessor functions */ GsdBGSlideShow * slideshow; time_t file_mtime; GdkPixbuf * pixbuf_cache; int timeout_id; GList * file_cache; }; struct _GsdBGClass { GObjectClass parent_class; }; enum { CHANGED, TRANSITIONED, N_SIGNALS }; static const cairo_user_data_key_t average_color_key; static guint signals[N_SIGNALS] = { 0 }; G_DEFINE_TYPE (GsdBG, gsd_bg, G_TYPE_OBJECT) static cairo_surface_t *make_root_pixmap (GdkScreen *screen, gint width, gint height); /* Pixbuf utils */ static void pixbuf_average_value (GdkPixbuf *pixbuf, GdkRGBA *result); static GdkPixbuf *pixbuf_scale_to_fit (GdkPixbuf *src, int max_width, int max_height); static GdkPixbuf *pixbuf_scale_to_min (GdkPixbuf *src, int min_width, int min_height); static void pixbuf_draw_gradient (GdkPixbuf *pixbuf, gboolean horizontal, GdkRGBA *c1, GdkRGBA *c2, GdkRectangle *rect); static void pixbuf_tile (GdkPixbuf *src, GdkPixbuf *dest); static void pixbuf_blend (GdkPixbuf *src, GdkPixbuf *dest, int src_x, int src_y, int width, int height, int dest_x, int dest_y, double alpha); /* Thumbnail utilities */ static GdkPixbuf *create_thumbnail_for_filename (GnomeDesktopThumbnailFactory *factory, const char *filename); static gboolean get_thumb_annotations (GdkPixbuf *thumb, int *orig_width, int *orig_height); /* Cache */ static GdkPixbuf *get_pixbuf_for_size (GsdBG *bg, gint num_monitor, int width, int height); static void clear_cache (GsdBG *bg); static gboolean is_different (GsdBG *bg, const char *filename); static time_t get_mtime (const char *filename); static GdkPixbuf *create_img_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, GdkScreen *screen, int dest_width, int dest_height, int frame_num); static GsdBGSlideShow * get_as_slideshow (GsdBG *bg, const char *filename); static GsdBGSlideShow *read_slideshow_file (const char *filename, GError **err); static void color_from_string (const char *string, GdkRGBA *colorp) { /* If all else fails use black */ gdk_rgba_parse (colorp, "black"); if (!string) return; gdk_rgba_parse (colorp, string); } static char * color_to_string (const GdkRGBA *color) { return g_strdup_printf ("#%02x%02x%02x", (int) (0.5 + color->red * 255), (int) (0.5 + color->green * 255), (int) (0.5 + color->blue * 255)); } static gboolean do_changed (GsdBG *bg) { gboolean ignore_pending_change; bg->changed_id = 0; ignore_pending_change = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (bg), "ignore-pending-change")); if (!ignore_pending_change) { g_signal_emit (G_OBJECT (bg), signals[CHANGED], 0); } return FALSE; } static void queue_changed (GsdBG *bg) { if (bg->changed_id > 0) { g_source_remove (bg->changed_id); } /* We unset this here to allow apps to set it if they don't want to get the change event. This is used by nautilus when it gets the pixmap from the bg (due to a reason other than the changed event). Because if there is no other change after this time the pending changed event will just uselessly cause us to recreate the pixmap. */ g_object_set_data (G_OBJECT (bg), "ignore-pending-change", GINT_TO_POINTER (FALSE)); bg->changed_id = g_timeout_add_full (G_PRIORITY_LOW, 100, (GSourceFunc)do_changed, bg, NULL); } static gboolean do_transitioned (GsdBG *bg) { bg->transitioned_id = 0; if (bg->pixbuf_cache) { g_object_unref (bg->pixbuf_cache); bg->pixbuf_cache = NULL; } g_signal_emit (G_OBJECT (bg), signals[TRANSITIONED], 0); return FALSE; } static void queue_transitioned (GsdBG *bg) { if (bg->transitioned_id > 0) { g_source_remove (bg->transitioned_id); } bg->transitioned_id = g_timeout_add_full (G_PRIORITY_LOW, 100, (GSourceFunc)do_transitioned, bg, NULL); } static gboolean bg_gsettings_mapping (GVariant *value, gpointer *result, gpointer user_data) { const gchar *bg_key_value; char *filename = NULL; /* The final fallback if nothing matches is with a NULL value. */ if (value == NULL) { *result = NULL; return TRUE; } bg_key_value = g_variant_get_string (value, NULL); if (bg_key_value && *bg_key_value != '\0') { filename = g_filename_from_uri (bg_key_value, NULL, NULL); if (filename != NULL && g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE) { g_free (filename); return FALSE; } if (filename != NULL) { *result = filename; return TRUE; } } return FALSE; } void gsd_bg_load_from_preferences (GsdBG *bg, GSettings *settings) { char *tmp; char *filename; GDesktopBackgroundShading ctype; GdkRGBA c1, c2; GDesktopBackgroundStyle placement; GSettings *background_settings; g_return_if_fail (GSD_IS_BG (bg)); g_return_if_fail (G_IS_SETTINGS (settings)); background_settings = g_settings_new ("com.canonical.unity.desktop.background"); bg->is_enabled = g_settings_get_boolean (background_settings, BG_KEY_DRAW_BACKGROUND); g_object_unref (background_settings); /* Filename */ filename = g_settings_get_mapped (settings, BG_KEY_PICTURE_URI, bg_gsettings_mapping, NULL); /* Colors */ tmp = g_settings_get_string (settings, BG_KEY_PRIMARY_COLOR); color_from_string (tmp, &c1); g_free (tmp); tmp = g_settings_get_string (settings, BG_KEY_SECONDARY_COLOR); color_from_string (tmp, &c2); g_free (tmp); /* Color type */ ctype = g_settings_get_enum (settings, BG_KEY_COLOR_TYPE); /* Placement */ placement = g_settings_get_enum (settings, BG_KEY_PICTURE_PLACEMENT); gsd_bg_set_rgba (bg, ctype, &c1, &c2); gsd_bg_set_placement (bg, placement); gsd_bg_set_filename (bg, filename); g_free (filename); } void gsd_bg_save_to_preferences (GsdBG *bg, GSettings *settings) { gchar *primary; gchar *secondary; gchar *uri; GSettings *background_settings; g_return_if_fail (GSD_IS_BG (bg)); g_return_if_fail (G_IS_SETTINGS (settings)); primary = color_to_string (&bg->primary); secondary = color_to_string (&bg->secondary); g_settings_delay (settings); uri = NULL; if (bg->filename != NULL) uri = g_filename_to_uri (bg->filename, NULL, NULL); if (uri == NULL) uri = g_strdup (""); background_settings = g_settings_new ("com.canonical.unity.desktop.background"); g_settings_set_boolean (background_settings, BG_KEY_DRAW_BACKGROUND, bg->is_enabled); g_object_unref (background_settings); g_settings_set_string (settings, BG_KEY_PICTURE_URI, uri); g_settings_set_string (settings, BG_KEY_PRIMARY_COLOR, primary); g_settings_set_string (settings, BG_KEY_SECONDARY_COLOR, secondary); g_settings_set_enum (settings, BG_KEY_COLOR_TYPE, bg->color_type); g_settings_set_enum (settings, BG_KEY_PICTURE_PLACEMENT, bg->placement); /* Apply changes atomically. */ g_settings_apply (settings); g_free (primary); g_free (secondary); g_free (uri); } static void gsd_bg_init (GsdBG *bg) { } static void gsd_bg_dispose (GObject *object) { GsdBG *bg = GSD_BG (object); if (bg->file_monitor) { g_object_unref (bg->file_monitor); bg->file_monitor = NULL; } clear_cache (bg); G_OBJECT_CLASS (gsd_bg_parent_class)->dispose (object); } static void gsd_bg_finalize (GObject *object) { GsdBG *bg = GSD_BG (object); if (bg->changed_id != 0) { g_source_remove (bg->changed_id); bg->changed_id = 0; } if (bg->transitioned_id != 0) { g_source_remove (bg->transitioned_id); bg->transitioned_id = 0; } if (bg->blow_caches_id != 0) { g_source_remove (bg->blow_caches_id); bg->blow_caches_id = 0; } g_free (bg->filename); bg->filename = NULL; G_OBJECT_CLASS (gsd_bg_parent_class)->finalize (object); } static void gsd_bg_class_init (GsdBGClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = gsd_bg_dispose; object_class->finalize = gsd_bg_finalize; signals[CHANGED] = g_signal_new ("changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[TRANSITIONED] = g_signal_new ("transitioned", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } GsdBG * gsd_bg_new (void) { return g_object_new (GSD_TYPE_BG, NULL); } void gsd_bg_set_rgba (GsdBG *bg, GDesktopBackgroundShading type, GdkRGBA *primary, GdkRGBA *secondary) { g_return_if_fail (bg != NULL); g_return_if_fail (primary != NULL); if (bg->color_type != type || !gdk_rgba_equal (&bg->primary, primary) || (secondary && !gdk_rgba_equal (&bg->secondary, secondary))) { bg->color_type = type; bg->primary = *primary; if (secondary) { bg->secondary = *secondary; } queue_changed (bg); } } void gsd_bg_set_placement (GsdBG *bg, GDesktopBackgroundStyle placement) { g_return_if_fail (bg != NULL); if (bg->placement != placement) { bg->placement = placement; queue_changed (bg); } } GDesktopBackgroundStyle gsd_bg_get_placement (GsdBG *bg) { g_return_val_if_fail (bg != NULL, -1); return bg->placement; } void gsd_bg_get_rgba (GsdBG *bg, GDesktopBackgroundShading *type, GdkRGBA *primary, GdkRGBA *secondary) { g_return_if_fail (bg != NULL); if (type) *type = bg->color_type; if (primary) *primary = bg->primary; if (secondary) *secondary = bg->secondary; } void gsd_bg_set_draw_background (GsdBG *bg, gboolean draw_background) { g_return_if_fail (bg != NULL); if (bg->is_enabled != draw_background) { bg->is_enabled = draw_background; queue_changed (bg); } } gboolean gsd_bg_get_draw_background (GsdBG *bg) { g_return_val_if_fail (bg != NULL, FALSE); return bg->is_enabled; } const gchar * gsd_bg_get_filename (GsdBG *bg) { g_return_val_if_fail (bg != NULL, NULL); return bg->filename; } static inline gchar * get_wallpaper_cache_dir (void) { return g_build_filename (g_get_user_cache_dir(), "wallpaper", NULL); } static inline gchar * get_wallpaper_cache_prefix_name (gint num_monitor, GDesktopBackgroundStyle placement, gint width, gint height) { return g_strdup_printf ("%i_%i_%i_%i", num_monitor, (gint) placement, width, height); } static char * get_wallpaper_cache_filename (const char *filename, gint num_monitor, GDesktopBackgroundStyle placement, gint width, gint height) { gchar *cache_filename; gchar *cache_prefix_name; gchar *md5_filename; gchar *cache_basename; gchar *cache_dir; md5_filename = g_compute_checksum_for_data (G_CHECKSUM_MD5, (const guchar *) filename, strlen (filename)); cache_prefix_name = get_wallpaper_cache_prefix_name (num_monitor, placement, width, height); cache_basename = g_strdup_printf ("%s_%s", cache_prefix_name, md5_filename); cache_dir = get_wallpaper_cache_dir (); cache_filename = g_build_filename (cache_dir, cache_basename, NULL); g_free (cache_prefix_name); g_free (md5_filename); g_free (cache_basename); g_free (cache_dir); return cache_filename; } static void cleanup_cache_for_monitor (gchar *cache_dir, gint num_monitor) { GDir *g_cache_dir; gchar *monitor_prefix; const gchar *file; g_cache_dir = g_dir_open (cache_dir, 0, NULL); monitor_prefix = g_strdup_printf ("%i_", num_monitor); file = g_dir_read_name (g_cache_dir); while (file != NULL) { gchar *path; path = g_build_filename (cache_dir, file, NULL); /* purge files with same monitor id */ if (g_str_has_prefix (file, monitor_prefix) && g_file_test (path, G_FILE_TEST_IS_REGULAR)) g_unlink (path); g_free (path); file = g_dir_read_name (g_cache_dir); } g_free (monitor_prefix); g_dir_close (g_cache_dir); } static gboolean cache_file_is_valid (const char *filename, const char *cache_filename) { time_t mtime; time_t cache_mtime; if (!g_file_test (cache_filename, G_FILE_TEST_IS_REGULAR)) return FALSE; mtime = get_mtime (filename); cache_mtime = get_mtime (cache_filename); return (mtime < cache_mtime); } static void refresh_cache_file (GsdBG *bg, GdkPixbuf *new_pixbuf, gint num_monitor, gint width, gint height) { gchar *cache_filename; gchar *cache_dir; GdkPixbufFormat *format; gchar *format_name; if ((num_monitor == -1) || (width <= 300) || (height <= 300)) return; cache_filename = get_wallpaper_cache_filename (bg->filename, num_monitor, bg->placement, width, height); cache_dir = get_wallpaper_cache_dir (); /* Only refresh scaled file on disk if useful (and don't cache slideshow) */ if (!cache_file_is_valid (bg->filename, cache_filename)) { format = gdk_pixbuf_get_file_info (bg->filename, NULL, NULL); if (format != NULL) { if (!g_file_test (cache_dir, G_FILE_TEST_IS_DIR)) { g_mkdir_with_parents (cache_dir, 0700); } else { cleanup_cache_for_monitor (cache_dir, num_monitor); } format_name = gdk_pixbuf_format_get_name (format); if (strcmp (format_name, "jpeg") == 0) gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, "quality", "100", NULL); else gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, NULL); g_free (format_name); } } g_free (cache_filename); g_free (cache_dir); } static void file_changed (GFileMonitor *file_monitor, GFile *child, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { GsdBG *bg = GSD_BG (user_data); clear_cache (bg); queue_changed (bg); } void gsd_bg_set_filename (GsdBG *bg, const char *filename) { g_return_if_fail (bg != NULL); if (is_different (bg, filename)) { g_free (bg->filename); bg->filename = g_strdup (filename); bg->file_mtime = get_mtime (bg->filename); if (bg->file_monitor) { g_object_unref (bg->file_monitor); bg->file_monitor = NULL; } if (bg->filename) { GFile *f = g_file_new_for_path (bg->filename); bg->file_monitor = g_file_monitor_file (f, 0, NULL, NULL); g_signal_connect (bg->file_monitor, "changed", G_CALLBACK (file_changed), bg); g_object_unref (f); } clear_cache (bg); queue_changed (bg); } } static void draw_color_area (GsdBG *bg, GdkPixbuf *dest, GdkRectangle *rect) { guint32 pixel; GdkRectangle extent; extent.x = 0; extent.y = 0; extent.width = gdk_pixbuf_get_width (dest); extent.height = gdk_pixbuf_get_height (dest); gdk_rectangle_intersect (rect, &extent, rect); switch (bg->color_type) { case G_DESKTOP_BACKGROUND_SHADING_SOLID: /* not really a big deal to ignore the area of interest */ pixel = ((int) (0.5 + bg->primary.red * 255) << 24) | ((int) (0.5 + bg->primary.green * 255) << 16) | ((int) (0.5 + bg->primary.blue * 255) << 8) | (0xff); gdk_pixbuf_fill (dest, pixel); break; case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL: pixbuf_draw_gradient (dest, TRUE, &(bg->primary), &(bg->secondary), rect); break; case G_DESKTOP_BACKGROUND_SHADING_VERTICAL: pixbuf_draw_gradient (dest, FALSE, &(bg->primary), &(bg->secondary), rect); break; default: break; } } static void draw_color (GsdBG *bg, GdkPixbuf *dest) { GdkRectangle rect; rect.x = 0; rect.y = 0; rect.width = gdk_pixbuf_get_width (dest); rect.height = gdk_pixbuf_get_height (dest); draw_color_area (bg, dest, &rect); } static void draw_color_each_monitor (GsdBG *bg, GdkPixbuf *dest, GdkScreen *screen, gint scale) { GdkRectangle rect; gint num_monitors; int monitor; num_monitors = gdk_screen_get_n_monitors (screen); for (monitor = 0; monitor < num_monitors; monitor++) { gdk_screen_get_monitor_geometry (screen, monitor, &rect); rect.x *= scale; rect.y *= scale; rect.width *= scale; rect.height *= scale; draw_color_area (bg, dest, &rect); } } static GdkPixbuf * pixbuf_clip_to_fit (GdkPixbuf *src, int max_width, int max_height) { int src_width, src_height; int w, h; int src_x, src_y; GdkPixbuf *pixbuf; src_width = gdk_pixbuf_get_width (src); src_height = gdk_pixbuf_get_height (src); if (src_width < max_width && src_height < max_height) return g_object_ref (src); w = MIN(src_width, max_width); h = MIN(src_height, max_height); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, gdk_pixbuf_get_has_alpha (src), 8, w, h); src_x = (src_width - w) / 2; src_y = (src_height - h) / 2; gdk_pixbuf_copy_area (src, src_x, src_y, w, h, pixbuf, 0, 0); return pixbuf; } static GdkPixbuf * get_scaled_pixbuf (GDesktopBackgroundStyle placement, GdkPixbuf *pixbuf, int width, int height, int *x, int *y, int *w, int *h) { GdkPixbuf *new; #if 0 g_print ("original_width: %d %d\n", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); #endif switch (placement) { case G_DESKTOP_BACKGROUND_STYLE_SPANNED: new = pixbuf_scale_to_fit (pixbuf, width, height); break; case G_DESKTOP_BACKGROUND_STYLE_ZOOM: new = pixbuf_scale_to_min (pixbuf, width, height); break; case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: new = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR); break; case G_DESKTOP_BACKGROUND_STYLE_SCALED: new = pixbuf_scale_to_fit (pixbuf, width, height); break; case G_DESKTOP_BACKGROUND_STYLE_NONE: /* This shouldn’t be true, but if it is, assert and * fall through, in case assertions are disabled. */ g_assert_not_reached (); case G_DESKTOP_BACKGROUND_STYLE_CENTERED: case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: default: new = pixbuf_clip_to_fit (pixbuf, width, height); break; } *w = gdk_pixbuf_get_width (new); *h = gdk_pixbuf_get_height (new); *x = (width - *w) / 2; *y = (height - *h) / 2; return new; } static void draw_image_area (GsdBG *bg, gint num_monitor, GdkPixbuf *pixbuf, GdkPixbuf *dest, GdkRectangle *area) { int dest_width = area->width; int dest_height = area->height; int x, y, w, h; GdkPixbuf *scaled; if (!pixbuf) return; scaled = get_scaled_pixbuf (bg->placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h); switch (bg->placement) { case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: pixbuf_tile (scaled, dest); break; case G_DESKTOP_BACKGROUND_STYLE_ZOOM: case G_DESKTOP_BACKGROUND_STYLE_CENTERED: case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: case G_DESKTOP_BACKGROUND_STYLE_SCALED: pixbuf_blend (scaled, dest, 0, 0, w, h, x + area->x, y + area->y, 1.0); break; case G_DESKTOP_BACKGROUND_STYLE_SPANNED: pixbuf_blend (scaled, dest, 0, 0, w, h, x, y, 1.0); break; case G_DESKTOP_BACKGROUND_STYLE_NONE: default: g_assert_not_reached (); break; } refresh_cache_file (bg, scaled, num_monitor, dest_width, dest_height); g_object_unref (scaled); } static void draw_image_for_thumb (GsdBG *bg, GdkPixbuf *pixbuf, GdkPixbuf *dest) { GdkRectangle rect; rect.x = 0; rect.y = 0; rect.width = gdk_pixbuf_get_width (dest); rect.height = gdk_pixbuf_get_height (dest); draw_image_area (bg, -1, pixbuf, dest, &rect); } static void draw_once (GsdBG *bg, GdkPixbuf *dest) { GdkRectangle rect; GdkPixbuf *pixbuf; gint num_monitor; /* we just draw on the whole screen */ num_monitor = 0; rect.x = 0; rect.y = 0; rect.width = gdk_pixbuf_get_width (dest); rect.height = gdk_pixbuf_get_height (dest); pixbuf = get_pixbuf_for_size (bg, num_monitor, rect.width, rect.height); if (pixbuf) { GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); if (rotated != NULL) { g_object_unref (pixbuf); pixbuf = rotated; } draw_image_area (bg, num_monitor, pixbuf, dest, &rect); g_object_unref (pixbuf); } } static void draw_each_monitor (GsdBG *bg, GdkPixbuf *dest, GdkScreen *screen, gint scale) { GdkRectangle rect; gint num_monitors; int monitor; num_monitors = gdk_screen_get_n_monitors (screen); for (monitor = 0; monitor < num_monitors; monitor++) { GdkPixbuf *pixbuf; gdk_screen_get_monitor_geometry (screen, monitor, &rect); rect.x *= scale; rect.y *= scale; rect.width *= scale; rect.height *= scale; pixbuf = get_pixbuf_for_size (bg, monitor, rect.width, rect.height); if (pixbuf) { draw_image_area (bg, monitor, pixbuf, dest, &rect); g_object_unref (pixbuf); } } } void gsd_bg_draw (GsdBG *bg, GdkPixbuf *dest, GdkScreen *screen, gboolean is_root) { if (!bg) return; if (is_root && (bg->placement != G_DESKTOP_BACKGROUND_STYLE_SPANNED)) { draw_color_each_monitor (bg, dest, screen, 1); if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { draw_each_monitor (bg, dest, screen, 1); } } else { draw_color (bg, dest); if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { draw_once (bg, dest); } } } static void gsd_bg_draw_at_scale (GsdBG *bg, GdkPixbuf *dest, gint scale, GdkScreen *screen, gboolean is_root) { if (is_root && (bg->placement != G_DESKTOP_BACKGROUND_STYLE_SPANNED)) { draw_color_each_monitor (bg, dest, screen, scale); if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { draw_each_monitor (bg, dest, screen, scale); } } else { draw_color (bg, dest); if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { draw_once (bg, dest); } } } gboolean gsd_bg_has_multiple_sizes (GsdBG *bg) { GsdBGSlideShow *show; gboolean ret; g_return_val_if_fail (bg != NULL, FALSE); ret = FALSE; show = get_as_slideshow (bg, bg->filename); if (show) { ret = gsd_bg_slide_show_get_has_multiple_sizes (show); g_object_unref (show); } return ret; } static void gsd_bg_get_pixmap_size (GsdBG *bg, int width, int height, int *pixmap_width, int *pixmap_height) { int dummy; if (!pixmap_width) pixmap_width = &dummy; if (!pixmap_height) pixmap_height = &dummy; *pixmap_width = width; *pixmap_height = height; if (!bg->filename) { switch (bg->color_type) { case G_DESKTOP_BACKGROUND_SHADING_SOLID: *pixmap_width = 1; *pixmap_height = 1; break; case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL: case G_DESKTOP_BACKGROUND_SHADING_VERTICAL: default: break; } return; } } /** * gsd_bg_create_surface: * @bg: GsdBG * @window: * @width: * @height: * @root: * * Create a surface that can be set as background for @window. If @is_root is * TRUE, the surface created will be created by a temporary X server connection * so that if someone calls XKillClient on it, it won't affect the application * who created it. * * Returns: %NULL on error (e.g. out of X connections) **/ cairo_surface_t * gsd_bg_create_surface (GsdBG *bg, GdkWindow *window, int width, int height, gboolean root) { gint scale; int pm_width, pm_height; cairo_surface_t *surface; GdkRGBA average; cairo_t *cr; g_return_val_if_fail (bg != NULL, NULL); g_return_val_if_fail (window != NULL, NULL); scale = gdk_window_get_scale_factor (window); if (bg->pixbuf_cache && gdk_pixbuf_get_width (bg->pixbuf_cache) != width && gdk_pixbuf_get_height (bg->pixbuf_cache) != height) { g_object_unref (bg->pixbuf_cache); bg->pixbuf_cache = NULL; } /* has the side effect of loading and caching pixbuf only when in tile mode */ gsd_bg_get_pixmap_size (bg, width, height, &pm_width, &pm_height); if (root) { surface = make_root_pixmap (gdk_window_get_screen (window), scale * pm_width, scale * pm_height); cairo_surface_set_device_scale (surface, scale, scale); } else { surface = gdk_window_create_similar_surface (window, CAIRO_CONTENT_COLOR, pm_width, pm_height); } if (surface == NULL) return NULL; cr = cairo_create (surface); if (!bg->filename && bg->color_type == G_DESKTOP_BACKGROUND_SHADING_SOLID) { gdk_cairo_set_source_rgba (cr, &(bg->primary)); average = bg->primary; } else { GdkPixbuf *pixbuf; cairo_surface_t *pixbuf_surface; pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, scale * width, scale * height); gsd_bg_draw_at_scale (bg, pixbuf, scale, gdk_window_get_screen (window), root); pixbuf_average_value (pixbuf, &average); pixbuf_surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, window); cairo_set_source_surface (cr, pixbuf_surface, 0, 0); cairo_surface_destroy (pixbuf_surface); g_object_unref (pixbuf); } cairo_paint (cr); cairo_destroy (cr); cairo_surface_set_user_data (surface, &average_color_key, gdk_rgba_copy (&average), (cairo_destroy_func_t) gdk_rgba_free); return surface; } /* determine if a background is darker or lighter than average, to help * clients know what colors to draw on top with */ gboolean gsd_bg_is_dark (GsdBG *bg, int width, int height) { GdkRGBA color; gdouble intensity; GdkPixbuf *pixbuf; g_return_val_if_fail (bg != NULL, FALSE); if (bg->color_type == G_DESKTOP_BACKGROUND_SHADING_SOLID) { color = bg->primary; } else { color.red = (bg->primary.red + bg->secondary.red) / 2; color.green = (bg->primary.green + bg->secondary.green) / 2; color.blue = (bg->primary.blue + bg->secondary.blue) / 2; } pixbuf = get_pixbuf_for_size (bg, -1, width, height); if (pixbuf) { GdkRGBA average; pixbuf_average_value (pixbuf, &average); color.red = color.red * (1.0 - average.alpha) + average.red * average.alpha; color.green = color.green * (1.0 - average.alpha) + average.green * average.alpha; color.blue = color.blue * (1.0 - average.alpha) + average.blue * average.alpha; g_object_unref (pixbuf); } intensity = color.red * 77 + color.green * 150 + color.blue * 28; return intensity < 160; /* biased slightly to be dark */ } /* * Create a persistent pixmap. We create a separate display * and set the closedown mode on it to RetainPermanent. */ static cairo_surface_t * make_root_pixmap (GdkScreen *screen, gint width, gint height) { Display *display; const char *display_name; Pixmap result; cairo_surface_t *surface; int screen_num; int depth; screen_num = gdk_screen_get_number (screen); gdk_flush (); display_name = gdk_display_get_name (gdk_screen_get_display (screen)); display = XOpenDisplay (display_name); if (display == NULL) { g_warning ("Unable to open display '%s' when setting " "background pixmap\n", (display_name) ? display_name : "NULL"); return NULL; } /* Desktop background pixmap should be created from * dummy X client since most applications will try to * kill it with XKillClient later when changing pixmap */ XSetCloseDownMode (display, RetainPermanent); depth = DefaultDepth (display, screen_num); result = XCreatePixmap (display, RootWindow (display, screen_num), width, height, depth); XCloseDisplay (display); surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen), result, GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)), width, height); return surface; } static gboolean get_original_size (const char *filename, int *orig_width, int *orig_height) { gboolean result; if (gdk_pixbuf_get_file_info (filename, orig_width, orig_height)) result = TRUE; else result = FALSE; return result; } static const char * get_filename_for_size (GsdBG *bg, gint best_width, gint best_height) { GsdBGSlideShow *show; const char *file = NULL; if (!bg->filename) return NULL; show = get_as_slideshow (bg, bg->filename); if (!show) { return bg->filename; } gsd_bg_slide_show_get_current_slide (show, best_width, best_height, NULL, NULL, NULL, &file, NULL); g_object_unref (show); return file; } gboolean gsd_bg_get_image_size (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, int best_width, int best_height, int *width, int *height) { GdkPixbuf *thumb; gboolean result = FALSE; const gchar *filename; g_return_val_if_fail (bg != NULL, FALSE); g_return_val_if_fail (factory != NULL, FALSE); if (!bg->filename) return FALSE; filename = get_filename_for_size (bg, best_width, best_height); thumb = create_thumbnail_for_filename (factory, filename); if (thumb) { if (get_thumb_annotations (thumb, width, height)) result = TRUE; g_object_unref (thumb); } if (!result) { if (get_original_size (filename, width, height)) result = TRUE; } return result; } static double fit_factor (int from_width, int from_height, int to_width, int to_height) { return MIN (to_width / (double) from_width, to_height / (double) from_height); } /** * gsd_bg_create_thumbnail: * * Returns: (transfer full): a #GdkPixbuf showing the background as a thumbnail */ GdkPixbuf * gsd_bg_create_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, GdkScreen *screen, int dest_width, int dest_height) { GdkPixbuf *result; GdkPixbuf *thumb; g_return_val_if_fail (bg != NULL, NULL); result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height); draw_color (bg, result); if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, -1); if (thumb) { draw_image_for_thumb (bg, thumb, result); g_object_unref (thumb); } } return result; } /** * gsd_bg_get_surface_from_root: * @screen: a #GdkScreen * * This function queries the _XROOTPMAP_ID property from * the root window associated with @screen to determine * the current root window background pixmap and returns * a copy of it. If the _XROOTPMAP_ID is not set, then * a black surface is returned. * * Return value: a #cairo_surface_t if successful or %NULL **/ cairo_surface_t * gsd_bg_get_surface_from_root (GdkScreen *screen) { int result; gint format; gulong nitems; gulong bytes_after; gpointer data; Atom type; Display *display; int screen_num; cairo_surface_t *surface; cairo_surface_t *source_pixmap; int width, height; cairo_t *cr; display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen)); screen_num = gdk_screen_get_number (screen); result = XGetWindowProperty (display, RootWindow (display, screen_num), gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"), 0L, 1L, False, XA_PIXMAP, &type, &format, &nitems, &bytes_after, (guchar **) &data); surface = NULL; source_pixmap = NULL; if (result != Success || type != XA_PIXMAP || format != 32 || nitems != 1) { XFree (data); data = NULL; } if (data != NULL) { Pixmap xpixmap = *(Pixmap *) data; Window root_return; int x_ret, y_ret; unsigned int w_ret, h_ret, bw_ret, depth_ret; gdk_error_trap_push (); if (XGetGeometry (GDK_SCREEN_XDISPLAY (screen), xpixmap, &root_return, &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret)) { source_pixmap = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen), xpixmap, GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)), w_ret, h_ret); } gdk_error_trap_pop_ignored (); } width = gdk_screen_get_width (screen); height = gdk_screen_get_height (screen); if (source_pixmap) { surface = cairo_surface_create_similar (source_pixmap, CAIRO_CONTENT_COLOR, width, height); cr = cairo_create (surface); cairo_set_source_surface (cr, source_pixmap, 0, 0); cairo_paint (cr); if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (surface); surface = NULL; } cairo_destroy (cr); } if (surface == NULL) { surface = gdk_window_create_similar_surface (gdk_screen_get_root_window (screen), CAIRO_CONTENT_COLOR, width, height); } if (source_pixmap != NULL) cairo_surface_destroy (source_pixmap); if (data != NULL) XFree (data); return surface; } static void gsd_bg_set_root_pixmap_id (GdkScreen *screen, cairo_surface_t *surface) { int result; gint format; gulong nitems; gulong bytes_after; gpointer data_esetroot; Pixmap pixmap_id; Atom type; Display *display; int screen_num; GdkRGBA *average; screen_num = gdk_screen_get_number (screen); data_esetroot = NULL; display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen)); result = XGetWindowProperty (display, RootWindow (display, screen_num), gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"), 0L, 1L, False, XA_PIXMAP, &type, &format, &nitems, &bytes_after, (guchar **) &data_esetroot); if (data_esetroot != NULL) { if (result == Success && type == XA_PIXMAP && format == 32 && nitems == 1) { gdk_error_trap_push (); XKillClient (display, *(Pixmap *)data_esetroot); gdk_error_trap_pop_ignored (); } XFree (data_esetroot); } pixmap_id = cairo_xlib_surface_get_drawable (surface); XChangeProperty (display, RootWindow (display, screen_num), gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"), XA_PIXMAP, 32, PropModeReplace, (guchar *) &pixmap_id, 1); XChangeProperty (display, RootWindow (display, screen_num), gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"), XA_PIXMAP, 32, PropModeReplace, (guchar *) &pixmap_id, 1); average = cairo_surface_get_user_data (surface, &average_color_key); if (average != NULL) { gchar *string; string = gdk_rgba_to_string (average); /* X encodes string lists as one big string with a nul * terminator after each item in the list. That's why * the strlen has to be given; scanning for nul would * only find the first item. * * For now, we only want to set a single string. * Fortunately, since this is C, it comes with its own * nul and we can just give strlen + 1 for the size of * our "list". */ XChangeProperty (display, RootWindow (display, screen_num), gdk_x11_get_xatom_by_name ("_GNOME_BACKGROUND_REPRESENTATIVE_COLORS"), XA_STRING, 8, PropModeReplace, (guchar *) string, strlen (string) + 1); g_free (string); } else { /* Could happen if we didn't create the surface... */ XDeleteProperty (display, RootWindow (display, screen_num), gdk_x11_get_xatom_by_name ("_GNOME_BACKGROUND_REPRESENTATIVE_COLORS")); } } /** * gsd_bg_set_surface_as_root: * @screen: the #GdkScreen to change root background on * @surface: the #cairo_surface_t to set root background from. * Must be an xlib surface backing a pixmap. * * Set the root pixmap, and properties pointing to it. We * do this atomically with a server grab to make sure that * we won't leak the pixmap if somebody else it setting * it at the same time. (This assumes that they follow the * same conventions we do). @surface should come from a call * to gsd_bg_create_surface(). **/ void gsd_bg_set_surface_as_root (GdkScreen *screen, cairo_surface_t *surface) { Display *display; int screen_num; g_return_if_fail (screen != NULL); g_return_if_fail (surface != NULL); g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB); screen_num = gdk_screen_get_number (screen); display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen)); gdk_x11_display_grab (gdk_screen_get_display (screen)); gsd_bg_set_root_pixmap_id (screen, surface); XSetWindowBackgroundPixmap (display, RootWindow (display, screen_num), cairo_xlib_surface_get_drawable (surface)); XClearWindow (display, RootWindow (display, screen_num)); gdk_display_flush (gdk_screen_get_display (screen)); gdk_x11_display_ungrab (gdk_screen_get_display (screen)); } /** * gsd_bg_set_surface_as_root_with_crossfade: * @screen: the #GdkScreen to change root background on * @surface: the cairo xlib surface to set root background from * * Set the root pixmap, and properties pointing to it. * This function differs from gsd_bg_set_surface_as_root() * in that it adds a subtle crossfade animation from the * current root pixmap to the new one. * * Return value: (transfer full): a #GsdBGCrossfade object **/ GsdBGCrossfade * gsd_bg_set_surface_as_root_with_crossfade (GdkScreen *screen, cairo_surface_t *surface) { GdkDisplay *display; GdkWindow *root_window; cairo_surface_t *old_surface; int width, height; GsdBGCrossfade *fade; g_return_val_if_fail (screen != NULL, NULL); g_return_val_if_fail (surface != NULL, NULL); root_window = gdk_screen_get_root_window (screen); width = gdk_screen_get_width (screen); height = gdk_screen_get_height (screen); fade = gsd_bg_crossfade_new (width, height); display = gdk_screen_get_display (screen); gdk_x11_display_grab (display); old_surface = gsd_bg_get_surface_from_root (screen); gsd_bg_set_root_pixmap_id (screen, surface); gsd_bg_crossfade_set_start_surface (fade, old_surface); cairo_surface_destroy (old_surface); gsd_bg_crossfade_set_end_surface (fade, surface); gdk_display_flush (display); gdk_x11_display_ungrab (display); gsd_bg_crossfade_start (fade, root_window); return fade; } /* Implementation of the pixbuf cache */ struct _SlideShow { gint ref_count; double start_time; double total_duration; GQueue *slides; gboolean has_multiple_sizes; /* used during parsing */ struct tm start_tm; GQueue *stack; }; static GdkPixbuf * blend (GdkPixbuf *p1, GdkPixbuf *p2, double alpha) { GdkPixbuf *result = gdk_pixbuf_copy (p1); GdkPixbuf *tmp; if (gdk_pixbuf_get_width (p2) != gdk_pixbuf_get_width (p1) || gdk_pixbuf_get_height (p2) != gdk_pixbuf_get_height (p1)) { tmp = gdk_pixbuf_scale_simple (p2, gdk_pixbuf_get_width (p1), gdk_pixbuf_get_height (p1), GDK_INTERP_BILINEAR); } else { tmp = g_object_ref (p2); } pixbuf_blend (tmp, result, 0, 0, -1, -1, 0, 0, alpha); g_object_unref (tmp); return result; } typedef enum { PIXBUF, SLIDESHOW, THUMBNAIL } FileType; struct FileCacheEntry { FileType type; char *filename; union { GdkPixbuf *pixbuf; GsdBGSlideShow *slideshow; GdkPixbuf *thumbnail; } u; }; static void file_cache_entry_delete (FileCacheEntry *ent) { g_free (ent->filename); switch (ent->type) { case PIXBUF: g_object_unref (ent->u.pixbuf); break; case SLIDESHOW: g_object_unref (ent->u.slideshow); break; case THUMBNAIL: g_object_unref (ent->u.thumbnail); break; default: break; } g_free (ent); } static void bound_cache (GsdBG *bg) { while (g_list_length (bg->file_cache) >= CACHE_SIZE) { GList *last_link = g_list_last (bg->file_cache); FileCacheEntry *ent = last_link->data; file_cache_entry_delete (ent); bg->file_cache = g_list_delete_link (bg->file_cache, last_link); } } static const FileCacheEntry * file_cache_lookup (GsdBG *bg, FileType type, const char *filename) { GList *list; for (list = bg->file_cache; list != NULL; list = list->next) { FileCacheEntry *ent = list->data; if (ent && ent->type == type && strcmp (ent->filename, filename) == 0) { return ent; } } return NULL; } static FileCacheEntry * file_cache_entry_new (GsdBG *bg, FileType type, const char *filename) { FileCacheEntry *ent = g_new0 (FileCacheEntry, 1); g_assert (!file_cache_lookup (bg, type, filename)); ent->type = type; ent->filename = g_strdup (filename); bg->file_cache = g_list_prepend (bg->file_cache, ent); bound_cache (bg); return ent; } static void file_cache_add_pixbuf (GsdBG *bg, const char *filename, GdkPixbuf *pixbuf) { FileCacheEntry *ent = file_cache_entry_new (bg, PIXBUF, filename); ent->u.pixbuf = g_object_ref (pixbuf); } static void file_cache_add_thumbnail (GsdBG *bg, const char *filename, GdkPixbuf *pixbuf) { FileCacheEntry *ent = file_cache_entry_new (bg, THUMBNAIL, filename); ent->u.thumbnail = g_object_ref (pixbuf); } static void file_cache_add_slide_show (GsdBG *bg, const char *filename, GsdBGSlideShow *show) { FileCacheEntry *ent = file_cache_entry_new (bg, SLIDESHOW, filename); ent->u.slideshow = g_object_ref (show); } static GdkPixbuf * load_from_cache_file (GsdBG *bg, const char *filename, gint num_monitor, gint best_width, gint best_height) { GdkPixbuf *pixbuf = NULL; gchar *cache_filename; cache_filename = get_wallpaper_cache_filename (filename, num_monitor, bg->placement, best_width, best_height); if (cache_file_is_valid (filename, cache_filename)) pixbuf = gdk_pixbuf_new_from_file (cache_filename, NULL); g_free (cache_filename); return pixbuf; } static GdkPixbuf * get_as_pixbuf_for_size (GsdBG *bg, const char *filename, gint num_monitor, gint best_width, gint best_height) { const FileCacheEntry *ent; if ((ent = file_cache_lookup (bg, PIXBUF, filename))) { return g_object_ref (ent->u.pixbuf); } else { GdkPixbufFormat *format; GdkPixbuf *pixbuf; gchar *tmp; pixbuf = NULL; /* Try to hit local cache first if relevant */ if (num_monitor != -1) pixbuf = load_from_cache_file (bg, filename, num_monitor, best_width, best_height); if (!pixbuf) { /* If scalable choose maximum size */ format = gdk_pixbuf_get_file_info (filename, NULL, NULL); if (format != NULL) { tmp = gdk_pixbuf_format_get_name (format); } else { tmp = NULL; } if (tmp != NULL && strcmp (tmp, "svg") == 0 && (best_width > 0 && best_height > 0) && (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED || bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED || bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM)) pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL); else pixbuf = gdk_pixbuf_new_from_file (filename, NULL); g_free (tmp); } if (pixbuf) file_cache_add_pixbuf (bg, filename, pixbuf); return pixbuf; } } static GsdBGSlideShow * get_as_slideshow (GsdBG *bg, const char *filename) { const FileCacheEntry *ent; if ((ent = file_cache_lookup (bg, SLIDESHOW, filename))) { return g_object_ref (ent->u.slideshow); } else { GsdBGSlideShow *show = read_slideshow_file (filename, NULL); if (show) file_cache_add_slide_show (bg, filename, show); return show; } } static GdkPixbuf * get_as_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, const char *filename) { const FileCacheEntry *ent; if ((ent = file_cache_lookup (bg, THUMBNAIL, filename))) { return g_object_ref (ent->u.thumbnail); } else { GdkPixbuf *thumb = create_thumbnail_for_filename (factory, filename); if (thumb) file_cache_add_thumbnail (bg, filename, thumb); return thumb; } } static gboolean blow_expensive_caches (gpointer data) { GsdBG *bg = data; GList *list, *next; bg->blow_caches_id = 0; for (list = bg->file_cache; list != NULL; list = next) { FileCacheEntry *ent = list->data; next = list->next; if (ent->type == PIXBUF) { file_cache_entry_delete (ent); bg->file_cache = g_list_delete_link (bg->file_cache, list); } } if (bg->pixbuf_cache) { g_object_unref (bg->pixbuf_cache); bg->pixbuf_cache = NULL; } return FALSE; } static void blow_expensive_caches_in_idle (GsdBG *bg) { if (bg->blow_caches_id == 0) { bg->blow_caches_id = g_idle_add (blow_expensive_caches, bg); } } static gboolean on_timeout (gpointer data) { GsdBG *bg = data; bg->timeout_id = 0; queue_transitioned (bg); return FALSE; } static double get_slide_timeout (gboolean is_fixed, gdouble duration) { double timeout; if (is_fixed) { timeout = duration; } else { /* Maybe the number of steps should be configurable? */ /* In the worst case we will do a fade from 0 to 256, which mean * we will never use more than 255 steps, however in most cases * the first and last value are similar and users can't percieve * changes in pixel values as small as 1/255th. So, lets not waste * CPU cycles on transitioning to often. * * 64 steps is enough for each step to be just detectable in a 16bit * color mode in the worst case, so we'll use this as an approximation * of whats detectable. */ timeout = duration / 64.0; } return timeout; } static void ensure_timeout (GsdBG *bg, gdouble timeout) { if (!bg->timeout_id) { /* G_MAXUINT means "only one slide" */ if (timeout < G_MAXUINT) { bg->timeout_id = g_timeout_add_full ( G_PRIORITY_LOW, timeout * 1000, on_timeout, bg, NULL); } } } static time_t get_mtime (const char *filename) { GFile *file; GFileInfo *info; time_t mtime; mtime = (time_t)-1; if (filename) { file = g_file_new_for_path (filename); info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (info) { mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); g_object_unref (info); } g_object_unref (file); } return mtime; } static GdkPixbuf * scale_thumbnail (GDesktopBackgroundStyle placement, const char *filename, GdkPixbuf *thumb, GdkScreen *screen, int dest_width, int dest_height) { int o_width; int o_height; if (placement != G_DESKTOP_BACKGROUND_STYLE_WALLPAPER && placement != G_DESKTOP_BACKGROUND_STYLE_CENTERED) { /* In this case, the pixbuf will be scaled to fit the screen anyway, * so just return the pixbuf here */ return g_object_ref (thumb); } if (get_thumb_annotations (thumb, &o_width, &o_height) || (filename && get_original_size (filename, &o_width, &o_height))) { int scr_height = gdk_screen_get_height (screen); int scr_width = gdk_screen_get_width (screen); int thumb_width = gdk_pixbuf_get_width (thumb); int thumb_height = gdk_pixbuf_get_height (thumb); double screen_to_dest = fit_factor (scr_width, scr_height, dest_width, dest_height); double thumb_to_orig = fit_factor (thumb_width, thumb_height, o_width, o_height); double f = thumb_to_orig * screen_to_dest; int new_width, new_height; new_width = floor (thumb_width * f + 0.5); new_height = floor (thumb_height * f + 0.5); if (placement == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER) { /* Heuristic to make sure tiles don't become so small that * they turn into a blur. * * This is strictly speaking incorrect, but the resulting * thumbnail gives a much better idea what the background * will actually look like. */ if ((new_width < 32 || new_height < 32) && (new_width < o_width / 4 || new_height < o_height / 4)) { new_width = o_width / 4; new_height = o_height / 4; } } thumb = gdk_pixbuf_scale_simple (thumb, new_width, new_height, GDK_INTERP_BILINEAR); } else g_object_ref (thumb); return thumb; } /* frame_num determines which slide to thumbnail. * -1 means 'current slide'. */ static GdkPixbuf * create_img_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, GdkScreen *screen, int dest_width, int dest_height, int frame_num) { if (bg->filename) { GdkPixbuf *thumb; thumb = get_as_thumbnail (bg, factory, bg->filename); if (thumb) { GdkPixbuf *result; result = scale_thumbnail (bg->placement, bg->filename, thumb, screen, dest_width, dest_height); g_object_unref (thumb); return result; } else { GsdBGSlideShow *show = get_as_slideshow (bg, bg->filename); if (show) { double alpha; double duration; gboolean is_fixed; const char *file1; const char *file2; GdkPixbuf *tmp; if (frame_num == -1) gsd_bg_slide_show_get_current_slide (show, dest_width, dest_height, &alpha, &duration, &is_fixed, &file1, &file2); else gsd_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, &alpha, &duration, &is_fixed, &file1, &file2); if (is_fixed) { tmp = get_as_thumbnail (bg, factory, file1); if (tmp) { thumb = scale_thumbnail (bg->placement, file1, tmp, screen, dest_width, dest_height); g_object_unref (tmp); } } else { GdkPixbuf *p1, *p2; p1 = get_as_thumbnail (bg, factory, file1); p2 = get_as_thumbnail (bg, factory, file2); if (p1 && p2) { GdkPixbuf *thumb1, *thumb2; thumb1 = scale_thumbnail (bg->placement, file1, p1, screen, dest_width, dest_height); thumb2 = scale_thumbnail (bg->placement, file2, p2, screen, dest_width, dest_height); thumb = blend (thumb1, thumb2, alpha); g_object_unref (thumb1); g_object_unref (thumb2); } if (p1) g_object_unref (p1); if (p2) g_object_unref (p2); } ensure_timeout (bg, (guint)get_slide_timeout (is_fixed, duration)); g_object_unref (show); } } return thumb; } return NULL; } static GdkPixbuf * get_pixbuf_for_size (GsdBG *bg, gint num_monitor, gint best_width, gint best_height) { guint time_until_next_change; gboolean hit_cache = FALSE; /* only hit the cache if the aspect ratio matches */ if (bg->pixbuf_cache) { int width, height; width = gdk_pixbuf_get_width (bg->pixbuf_cache); height = gdk_pixbuf_get_height (bg->pixbuf_cache); hit_cache = 0.2 > fabs ((best_width / (double)best_height) - (width / (double)height)); if (!hit_cache) { g_object_unref (bg->pixbuf_cache); bg->pixbuf_cache = NULL; } } if (!hit_cache && bg->filename) { bg->file_mtime = get_mtime (bg->filename); bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, num_monitor, best_width, best_height); time_until_next_change = G_MAXUINT; if (!bg->pixbuf_cache) { GsdBGSlideShow *show = get_as_slideshow (bg, bg->filename); if (show) { double alpha; double duration; gboolean is_fixed; const char *file1; const char *file2; g_object_ref (show); gsd_bg_slide_show_get_current_slide (show, best_width, best_height, &alpha, &duration, &is_fixed, &file1, &file2); time_until_next_change = (guint)get_slide_timeout (is_fixed, duration); if (is_fixed) { bg->pixbuf_cache = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width, best_height); } else { GdkPixbuf *p1, *p2; p1 = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width, best_height); p2 = get_as_pixbuf_for_size (bg, file2, num_monitor, best_width, best_height); if (p1 && p2) { bg->pixbuf_cache = blend (p1, p2, alpha); } if (p1) g_object_unref (p1); if (p2) g_object_unref (p2); } ensure_timeout (bg, time_until_next_change); g_object_unref (show); } } /* If the next slideshow step is a long time away then we blow away the expensive stuff (large pixbufs) from the cache */ if (time_until_next_change > KEEP_EXPENSIVE_CACHE_SECS) blow_expensive_caches_in_idle (bg); } if (bg->pixbuf_cache) g_object_ref (bg->pixbuf_cache); return bg->pixbuf_cache; } static gboolean is_different (GsdBG *bg, const char *filename) { if (!filename && bg->filename) { return TRUE; } else if (filename && !bg->filename) { return TRUE; } else if (!filename && !bg->filename) { return FALSE; } else { time_t mtime = get_mtime (filename); if (mtime != bg->file_mtime) return TRUE; if (strcmp (filename, bg->filename) != 0) return TRUE; return FALSE; } } static void clear_cache (GsdBG *bg) { GList *list; if (bg->file_cache) { for (list = bg->file_cache; list != NULL; list = list->next) { FileCacheEntry *ent = list->data; file_cache_entry_delete (ent); } g_list_free (bg->file_cache); bg->file_cache = NULL; } if (bg->pixbuf_cache) { g_object_unref (bg->pixbuf_cache); bg->pixbuf_cache = NULL; } if (bg->timeout_id) { g_source_remove (bg->timeout_id); bg->timeout_id = 0; } } /* Pixbuf utilities */ G_INLINE_FUNC GdkRGBA get_pixbuf_sample (guchar *pixels, gint rowstride, gint channels, gint x, gint y) { GdkRGBA sample; gdouble dd = 0xFF; guchar *p = pixels + ((y * rowstride) + (x * channels)); sample.red = *p++ / dd; sample.green = *p++ / dd; sample.blue = *p++ / dd; sample.alpha = 1.0f; return sample; } G_INLINE_FUNC gboolean is_color_different (const GdkRGBA color_a, const GdkRGBA color_b) { GdkRGBA diff; diff.red = color_a.red - color_b.red; diff.green = color_a.green - color_b.green; diff.blue = color_a.blue - color_b.blue; diff.alpha = 1.0f; if (fabs (diff.red) > 0.15 || fabs (diff.green) > 0.15 || fabs (diff.blue) > 0.15) return TRUE; return FALSE; } static GdkRGBA get_quad_average (gint x, gint y, gint width, gint height, gint level_of_recursion, guchar *pixels, gint rowstride, gint channels) { // samples four corners // c1-----c2 // | | // c3-----c4 GdkRGBA average; GdkRGBA corner1 = get_pixbuf_sample (pixels, rowstride, channels, x , y ); GdkRGBA corner2 = get_pixbuf_sample (pixels, rowstride, channels, x + width, y ); GdkRGBA corner3 = get_pixbuf_sample (pixels, rowstride, channels, x , y + height); GdkRGBA corner4 = get_pixbuf_sample (pixels, rowstride, channels, x + width, y + height); GdkRGBA centre = get_pixbuf_sample (pixels, rowstride, channels, x + (width / 2), y + (height / 2)); /* If we're over the max we want to just take the average and be happy with that value */ if (level_of_recursion < QUAD_MAX_LEVEL_OF_RECURSION) { /* Otherwise we want to look at each value and check it's distance from the center color and take the average if they're far apart. */ /* corner 1 */ if (level_of_recursion < QUAD_MIN_LEVEL_OF_RECURSION || is_color_different(corner1, centre)) { corner1 = get_quad_average (x, y, width/2, height/2, level_of_recursion + 1, pixels, rowstride, channels); } /* corner 2 */ if (level_of_recursion < QUAD_MIN_LEVEL_OF_RECURSION || is_color_different(corner2, centre)) { corner2 = get_quad_average (x + width/2, y, width/2, height/2, level_of_recursion + 1, pixels, rowstride, channels); } /* corner 3 */ if (level_of_recursion < QUAD_MIN_LEVEL_OF_RECURSION || is_color_different(corner3, centre)) { corner3 = get_quad_average (x, y + height/2, width/2, height/2, level_of_recursion + 1, pixels, rowstride, channels); } /* corner 4 */ if (level_of_recursion < QUAD_MIN_LEVEL_OF_RECURSION || is_color_different(corner4, centre)) { corner4 = get_quad_average (x + width/2, y + height/2, width/2, height/2, level_of_recursion + 1, pixels, rowstride, channels); } } average.red = ((corner1.red * QUAD_CORNER_WEIGHT_NW) + (corner3.red * QUAD_CORNER_WEIGHT_SW) + (centre.red * QUAD_CORNER_WEIGHT_CENTER) + (corner2.red * QUAD_CORNER_WEIGHT_NE) + (corner4.red * QUAD_CORNER_WEIGHT_SE)) / QUAD_CORNER_WEIGHT_TOTAL; average.green = ((corner1.green * QUAD_CORNER_WEIGHT_NW) + (corner3.green * QUAD_CORNER_WEIGHT_SW) + (centre.green * QUAD_CORNER_WEIGHT_CENTER) + (corner2.green * QUAD_CORNER_WEIGHT_NE) + (corner4.green * QUAD_CORNER_WEIGHT_SE)) / QUAD_CORNER_WEIGHT_TOTAL; average.blue = ((corner1.blue * QUAD_CORNER_WEIGHT_NW) + (corner3.blue * QUAD_CORNER_WEIGHT_SW) + (centre.blue * QUAD_CORNER_WEIGHT_CENTER) + (corner2.blue * QUAD_CORNER_WEIGHT_NE) + (corner4.blue * QUAD_CORNER_WEIGHT_SE)) / QUAD_CORNER_WEIGHT_TOTAL; average.alpha = 1.0f; return average; } static void pixbuf_average_value (GdkPixbuf *pixbuf, GdkRGBA *result) { GdkRGBA average; average = get_quad_average (0, 0, gdk_pixbuf_get_width (pixbuf) - 1, gdk_pixbuf_get_height (pixbuf) - 1, 1, gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_rowstride (pixbuf), gdk_pixbuf_get_n_channels (pixbuf)); result->red = average.red; result->green = average.green; result->blue = average.blue; result->alpha = average.alpha; #if 0 guint64 a_total, r_total, g_total, b_total; guint row, column; int row_stride; const guchar *pixels, *p; int r, g, b, a; guint64 dividend; guint width, height; gdouble dd; width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); row_stride = gdk_pixbuf_get_rowstride (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); /* iterate through the pixbuf, counting up each component */ a_total = 0; r_total = 0; g_total = 0; b_total = 0; if (gdk_pixbuf_get_has_alpha (pixbuf)) { for (row = 0; row < height; row++) { p = pixels + (row * row_stride); for (column = 0; column < width / 2; column++) { r = *p++; g = *p++; b = *p++; a = *p++; a_total += a; r_total += r * a; g_total += g * a; b_total += b * a; } } dividend = height * width * 0xFF; a_total *= 0xFF; } else { for (row = 0; row < height; row++) { p = pixels + (row * row_stride); for (column = 0; column < width / 2; column++) { r = *p++; g = *p++; b = *p++; r_total += r; g_total += g; b_total += b; } } dividend = height * width; a_total = dividend * 0xFF; } dd = dividend * 0xFF; result->alpha = a_total / dd; result->red = r_total / dd; result->green = g_total / dd; result->blue = b_total / dd; #endif } static GdkPixbuf * pixbuf_scale_to_fit (GdkPixbuf *src, int max_width, int max_height) { double factor; int src_width, src_height; int new_width, new_height; src_width = gdk_pixbuf_get_width (src); src_height = gdk_pixbuf_get_height (src); factor = MIN (max_width / (double) src_width, max_height / (double) src_height); new_width = floor (src_width * factor + 0.5); new_height = floor (src_height * factor + 0.5); return gdk_pixbuf_scale_simple (src, new_width, new_height, GDK_INTERP_BILINEAR); } static GdkPixbuf * pixbuf_scale_to_min (GdkPixbuf *src, int min_width, int min_height) { double factor; int src_width, src_height; int new_width, new_height; GdkPixbuf *dest; src_width = gdk_pixbuf_get_width (src); src_height = gdk_pixbuf_get_height (src); factor = MAX (min_width / (double) src_width, min_height / (double) src_height); new_width = floor (src_width * factor + 0.5); new_height = floor (src_height * factor + 0.5); dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, gdk_pixbuf_get_has_alpha (src), 8, min_width, min_height); if (!dest) return NULL; /* crop the result */ gdk_pixbuf_scale (src, dest, 0, 0, min_width, min_height, (new_width - min_width) / -2, (new_height - min_height) / -2, factor, factor, GDK_INTERP_BILINEAR); return dest; } static guchar * create_gradient (const GdkRGBA *primary, const GdkRGBA *secondary, int n_pixels) { guchar *result = g_malloc (n_pixels * 3); int i; for (i = 0; i < n_pixels; ++i) { double ratio = (i + 0.5) / n_pixels; result[3 * i + 0] = (int) (0.5 + (primary->red * (1 - ratio) + secondary->red * ratio) * 255); result[3 * i + 1] = (int) (0.5 + (primary->green * (1 - ratio) + secondary->green * ratio) * 255); result[3 * i + 2] = (int) (0.5 + (primary->blue * (1 - ratio) + secondary->blue * ratio) * 255); } return result; } static void pixbuf_draw_gradient (GdkPixbuf *pixbuf, gboolean horizontal, GdkRGBA *primary, GdkRGBA *secondary, GdkRectangle *rect) { int width; int height; int rowstride; guchar *dst; int n_channels = 3; rowstride = gdk_pixbuf_get_rowstride (pixbuf); width = rect->width; height = rect->height; dst = gdk_pixbuf_get_pixels (pixbuf) + rect->x * n_channels + rowstride * rect->y; if (horizontal) { guchar *gradient = create_gradient (primary, secondary, width); int copy_bytes_per_row = width * n_channels; int i; for (i = 0; i < height; i++) { guchar *d; d = dst + rowstride * i; memcpy (d, gradient, copy_bytes_per_row); } g_free (gradient); } else { guchar *gb, *gradient; int i; gradient = create_gradient (primary, secondary, height); for (i = 0; i < height; i++) { int j; guchar *d; d = dst + rowstride * i; gb = gradient + n_channels * i; for (j = width; j > 0; j--) { int k; for (k = 0; k < n_channels; k++) { *(d++) = gb[k]; } } } g_free (gradient); } } static void pixbuf_blend (GdkPixbuf *src, GdkPixbuf *dest, int src_x, int src_y, int src_width, int src_height, int dest_x, int dest_y, double alpha) { int dest_width = gdk_pixbuf_get_width (dest); int dest_height = gdk_pixbuf_get_height (dest); int offset_x = dest_x - src_x; int offset_y = dest_y - src_y; if (src_width < 0) src_width = gdk_pixbuf_get_width (src); if (src_height < 0) src_height = gdk_pixbuf_get_height (src); if (dest_x < 0) dest_x = 0; if (dest_y < 0) dest_y = 0; if (dest_x + src_width > dest_width) { src_width = dest_width - dest_x; } if (dest_y + src_height > dest_height) { src_height = dest_height - dest_y; } gdk_pixbuf_composite (src, dest, dest_x, dest_y, src_width, src_height, offset_x, offset_y, 1, 1, GDK_INTERP_NEAREST, alpha * 0xFF + 0.5); } static void pixbuf_tile (GdkPixbuf *src, GdkPixbuf *dest) { int x, y; int tile_width, tile_height; int dest_width = gdk_pixbuf_get_width (dest); int dest_height = gdk_pixbuf_get_height (dest); tile_width = gdk_pixbuf_get_width (src); tile_height = gdk_pixbuf_get_height (src); for (y = 0; y < dest_height; y += tile_height) { for (x = 0; x < dest_width; x += tile_width) { pixbuf_blend (src, dest, 0, 0, tile_width, tile_height, x, y, 1.0); } } } static GsdBGSlideShow * read_slideshow_file (const char *filename, GError **err) { GsdBGSlideShow *show; show = gsd_bg_slide_show_new (filename); if (!gsd_bg_slide_show_load (show, err)) { g_object_unref (show); return NULL; } return show; } /* Thumbnail utilities */ static GdkPixbuf * create_thumbnail_for_filename (GnomeDesktopThumbnailFactory *factory, const char *filename) { char *thumb; time_t mtime; GdkPixbuf *orig, *result = NULL; char *uri; GTask *task; GError *error = NULL; mtime = get_mtime (filename); if (mtime == (time_t)-1) return NULL; uri = g_filename_to_uri (filename, NULL, NULL); if (uri == NULL) return NULL; thumb = gnome_desktop_thumbnail_factory_lookup (factory, uri, mtime); if (thumb) { result = gdk_pixbuf_new_from_file (thumb, NULL); g_free (thumb); } else { orig = gdk_pixbuf_new_from_file (filename, NULL); if (orig) { int orig_width, orig_height; GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (orig); if (rotated != NULL) { g_object_unref (orig); orig = rotated; } orig_width = gdk_pixbuf_get_width (orig); orig_height = gdk_pixbuf_get_height (orig); result = pixbuf_scale_to_fit (orig, THUMBNAIL_SIZE, THUMBNAIL_SIZE); g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-height", g_strdup_printf ("%d", orig_height), g_free); g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-width", g_strdup_printf ("%d", orig_width), g_free); g_object_unref (orig); #if defined(GNOME_DESKTOP_PLATFORM_VERSION) && GNOME_DESKTOP_PLATFORM_VERSION >= 43 gnome_desktop_thumbnail_factory_save_thumbnail (factory, result, uri, mtime, NULL, &error); if (error) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Thumbnailing failed: %s", error->message); g_error_free (error); } } else { gnome_desktop_thumbnail_factory_create_failed_thumbnail (factory, uri, mtime, NULL, &error); if (error) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Thumbnailing failed: %s", error->message); g_error_free (error); } #else gnome_desktop_thumbnail_factory_save_thumbnail (factory, result, uri, mtime); } else { gnome_desktop_thumbnail_factory_create_failed_thumbnail (factory, uri, mtime); #endif } } g_free (uri); return result; } static gboolean get_thumb_annotations (GdkPixbuf *thumb, int *orig_width, int *orig_height) { char *end; const char *wstr, *hstr; wstr = gdk_pixbuf_get_option (thumb, "tEXt::Thumb::Image::Width"); hstr = gdk_pixbuf_get_option (thumb, "tEXt::Thumb::Image::Height"); if (hstr && wstr) { *orig_width = strtol (wstr, &end, 10); if (*end != 0) return FALSE; *orig_height = strtol (hstr, &end, 10); if (*end != 0) return FALSE; return TRUE; } return FALSE; } /* * Returns whether the background is a slideshow. */ gboolean gsd_bg_changes_with_time (GsdBG *bg) { GsdBGSlideShow *show; gboolean ret = FALSE; g_return_val_if_fail (bg != NULL, FALSE); if (!bg->filename) return FALSE; show = get_as_slideshow (bg, bg->filename); if (show) { ret = gsd_bg_slide_show_get_num_slides (show) > 1; g_object_unref (show); } return ret; } /** * gsd_bg_create_frame_thumbnail: * * Creates a thumbnail for a certain frame, where 'frame' is somewhat * vaguely defined as 'suitable point to show while single-stepping * through the slideshow'. * * Returns: (transfer full): the newly created thumbnail or * or NULL if frame_num is out of bounds. */ GdkPixbuf * gsd_bg_create_frame_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, GdkScreen *screen, int dest_width, int dest_height, int frame_num) { GsdBGSlideShow *show; GdkPixbuf *result; GdkPixbuf *thumb; int skipped; gboolean is_fixed; g_return_val_if_fail (bg != NULL, FALSE); show = get_as_slideshow (bg, bg->filename); if (!show) return NULL; if (frame_num < 0 || frame_num >= gsd_bg_slide_show_get_num_slides (show)) return NULL; gsd_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, NULL, NULL, &is_fixed, NULL, NULL); skipped = 0; while (!is_fixed) { skipped++; gsd_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, NULL, NULL, &is_fixed, NULL, NULL); } result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height); draw_color (bg, result); if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, frame_num + skipped); if (thumb) { draw_image_for_thumb (bg, thumb, result); g_object_unref (thumb); } } return result; } unity-settings-daemon/gnome-settings-daemon/gsd-bg.h0000664000000000000000000001243415172222611017740 0ustar /* gsd-bg.h - Copyright 2007, Red Hat, Inc. This file is part of the Gnome Library. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Author: Soren Sandmann */ #ifndef __GSD_BG_H__ #define __GSD_BG_H__ #define GNOME_DESKTOP_USE_UNSTABLE_API #include #include #include #include #include #include "gsd-bg-crossfade.h" G_BEGIN_DECLS #define GSD_TYPE_BG (gsd_bg_get_type ()) #define GSD_BG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_BG, GsdBG)) #define GSD_BG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_BG, GsdBGClass)) #define GSD_IS_BG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_BG)) #define GSD_IS_BG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_BG)) #define GSD_BG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_BG, GsdBGClass)) typedef struct _GsdBG GsdBG; typedef struct _GsdBGClass GsdBGClass; G_DEFINE_AUTOPTR_CLEANUP_FUNC(GsdBG, g_object_unref) GType gsd_bg_get_type (void); GsdBG * gsd_bg_new (void); void gsd_bg_load_from_preferences (GsdBG *bg, GSettings *settings); void gsd_bg_save_to_preferences (GsdBG *bg, GSettings *settings); /* Setters */ void gsd_bg_set_filename (GsdBG *bg, const char *filename); void gsd_bg_set_placement (GsdBG *bg, GDesktopBackgroundStyle placement); void gsd_bg_set_rgba (GsdBG *bg, GDesktopBackgroundShading type, GdkRGBA *primary, GdkRGBA *secondary); void gsd_bg_set_draw_background (GsdBG *bg, gboolean draw_background); /* Getters */ GDesktopBackgroundStyle gsd_bg_get_placement (GsdBG *bg); gboolean gsd_bg_get_draw_background (GsdBG *bg); void gsd_bg_get_rgba (GsdBG *bg, GDesktopBackgroundShading *type, GdkRGBA *primary, GdkRGBA *secondary); const gchar * gsd_bg_get_filename (GsdBG *bg); /* Drawing and thumbnailing */ void gsd_bg_draw (GsdBG *bg, GdkPixbuf *dest, GdkScreen *screen, gboolean is_root); cairo_surface_t *gsd_bg_create_surface (GsdBG *bg, GdkWindow *window, int width, int height, gboolean root); gboolean gsd_bg_get_image_size (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, int best_width, int best_height, int *width, int *height); GdkPixbuf * gsd_bg_create_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, GdkScreen *screen, int dest_width, int dest_height); gboolean gsd_bg_is_dark (GsdBG *bg, int dest_width, int dest_height); gboolean gsd_bg_has_multiple_sizes (GsdBG *bg); gboolean gsd_bg_changes_with_time (GsdBG *bg); GdkPixbuf * gsd_bg_create_frame_thumbnail (GsdBG *bg, GnomeDesktopThumbnailFactory *factory, GdkScreen *screen, int dest_width, int dest_height, int frame_num); /* Set a surface as root - not a GsdBG method. At some point * if we decide to stabilize the API then we may want to make * these object methods, drop gsd_bg_create_surface, etc. */ void gsd_bg_set_surface_as_root (GdkScreen *screen, cairo_surface_t *surface); GsdBGCrossfade *gsd_bg_set_surface_as_root_with_crossfade (GdkScreen *screen, cairo_surface_t *surface); cairo_surface_t *gsd_bg_get_surface_from_root (GdkScreen *screen); G_END_DECLS #endif unity-settings-daemon/gnome-settings-daemon/gsd-idle-monitor-private.h0000664000000000000000000000204515172222611023417 0ustar /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright 2013 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and * from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c */ #include #include void gsd_idle_monitor_handle_xevent_all (XEvent *xevent); void gsd_idle_monitor_init_dbus (gboolean replace); unity-settings-daemon/gnome-settings-daemon/gsd-idle-monitor.c0000664000000000000000000006577315172222611021763 0ustar /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright 2013 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and * from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c */ /** * SECTION:idle-monitor * @title: GsdIdleMonitor * @short_description: Mutter idle counter (similar to X's IDLETIME) */ #include "config.h" #include #include #include #include #include #include "gsd-idle-monitor.h" #include "gsd-idle-monitor-private.h" #include "meta-dbus-idle-monitor.h" G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer)); struct _GsdIdleMonitor { GObject parent_instance; GHashTable *watches; GHashTable *alarms; int device_id; /* X11 implementation */ Display *display; int sync_event_base; XSyncCounter counter; XSyncAlarm user_active_alarm; }; struct _GsdIdleMonitorClass { GObjectClass parent_class; }; typedef struct { GsdIdleMonitor *monitor; guint id; GsdIdleMonitorWatchFunc callback; gpointer user_data; GDestroyNotify notify; guint64 timeout_msec; /* x11 */ XSyncAlarm xalarm; int idle_source_id; } GsdIdleMonitorWatch; typedef struct { /* X11 implementation */ Display *display; int sync_event_base; int sync_error_base; unsigned int have_xsync : 1; }GsdXSync; static GsdXSync *xsync; enum { PROP_0, PROP_DEVICE_ID, PROP_LAST, }; static GParamSpec *obj_props[PROP_LAST]; G_DEFINE_TYPE (GsdIdleMonitor, gsd_idle_monitor, G_TYPE_OBJECT) static GsdIdleMonitor *device_monitors[256]; static int device_id_max; static gint64 _xsyncvalue_to_int64 (XSyncValue value) { return ((guint64) XSyncValueHigh32 (value)) << 32 | (guint64) XSyncValueLow32 (value); } #define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32) static void fire_watch (GsdIdleMonitorWatch *watch) { GsdIdleMonitor *monitor; guint id; gboolean is_user_active_watch; monitor = watch->monitor; g_object_ref (monitor); if (watch->idle_source_id) { g_source_remove (watch->idle_source_id); watch->idle_source_id = 0; } id = watch->id; is_user_active_watch = (watch->timeout_msec == 0); if (watch->callback) watch->callback (monitor, id, watch->user_data); if (is_user_active_watch) gsd_idle_monitor_remove_watch (monitor, id); g_object_unref (monitor); } static XSyncAlarm _xsync_alarm_set (GsdIdleMonitor *monitor, XSyncTestType test_type, guint64 interval, gboolean want_events) { XSyncAlarmAttributes attr; XSyncValue delta; guint flags; flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | XSyncCAValue | XSyncCADelta | XSyncCAEvents; XSyncIntToValue (&delta, 0); attr.trigger.counter = monitor->counter; attr.trigger.value_type = XSyncAbsolute; attr.delta = delta; attr.events = want_events; GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value); attr.trigger.test_type = test_type; return XSyncCreateAlarm (monitor->display, flags, &attr); } static void ensure_alarm_rescheduled (Display *dpy, XSyncAlarm alarm) { XSyncAlarmAttributes attr; /* Some versions of Xorg have an issue where alarms aren't * always rescheduled. Calling XSyncChangeAlarm, even * without any attributes, will reschedule the alarm. */ XSyncChangeAlarm (dpy, alarm, 0, &attr); } static void set_alarm_enabled (Display *dpy, XSyncAlarm alarm, gboolean enabled) { XSyncAlarmAttributes attr; attr.events = enabled; XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr); } static void check_x11_watch (gpointer data, gpointer user_data) { GsdIdleMonitorWatch *watch = data; XSyncAlarm alarm = (XSyncAlarm) user_data; if (watch->xalarm != alarm) return; fire_watch (watch); } static void gsd_idle_monitor_handle_xevent (GsdIdleMonitor *monitor, XSyncAlarmNotifyEvent *alarm_event) { XSyncAlarm alarm; GList *watches; gboolean has_alarm; if (alarm_event->state != XSyncAlarmActive) return; alarm = alarm_event->alarm; has_alarm = FALSE; if (alarm == monitor->user_active_alarm) { set_alarm_enabled (monitor->display, alarm, FALSE); has_alarm = TRUE; } else if (g_hash_table_contains (monitor->alarms, (gpointer) alarm)) { ensure_alarm_rescheduled (monitor->display, alarm); has_alarm = TRUE; } if (has_alarm) { watches = g_hash_table_get_values (monitor->watches); g_list_foreach (watches, check_x11_watch, (gpointer) alarm); g_list_free (watches); } } void gsd_idle_monitor_handle_xevent_all (XEvent *xevent) { int i; for (i = 0; i <= device_id_max; i++) if (device_monitors[i]) gsd_idle_monitor_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent); } static char * counter_name_for_device (int device_id) { if (device_id > 0) return g_strdup_printf ("DEVICEIDLETIME %d", device_id); return g_strdup ("IDLETIME"); } static XSyncCounter find_idletime_counter (GsdIdleMonitor *monitor) { int i; int ncounters; XSyncSystemCounter *counters; XSyncCounter counter = None; char *counter_name; counter_name = counter_name_for_device (monitor->device_id); counters = XSyncListSystemCounters (monitor->display, &ncounters); for (i = 0; i < ncounters; i++) { if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0) { counter = counters[i].counter; break; } } XSyncFreeSystemCounterList (counters); g_free (counter_name); return counter; } static guint32 get_next_watch_serial (void) { static guint32 serial = 0; g_atomic_int_inc (&serial); return serial; } static void idle_monitor_watch_free (GsdIdleMonitorWatch *watch) { GsdIdleMonitor *monitor; if (watch == NULL) return; monitor = watch->monitor; g_object_ref (monitor); if (watch->idle_source_id) { g_source_remove (watch->idle_source_id); watch->idle_source_id = 0; } if (watch->notify != NULL) watch->notify (watch->user_data); if (watch->xalarm != monitor->user_active_alarm && watch->xalarm != None) { XSyncDestroyAlarm (monitor->display, watch->xalarm); g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm); } g_object_unref (monitor); g_slice_free (GsdIdleMonitorWatch, watch); } static GdkFilterReturn xevent_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data) { XEvent *ev; ev = xevent; if (ev->xany.type == xsync->sync_event_base + XSyncAlarmNotify) { gsd_idle_monitor_handle_xevent_all (ev); } return GDK_FILTER_CONTINUE; } static void init_xsync (GsdIdleMonitor *monitor) { monitor->counter = find_idletime_counter (monitor); /* IDLETIME counter not found? */ if (monitor->counter == None) { g_warning ("IDLETIME counter not found\n"); return; } monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE); } static void gsd_idle_monitor_dispose (GObject *object) { GsdIdleMonitor *monitor; monitor = gsd_idle_monitor (object); g_clear_pointer (&monitor->watches, g_hash_table_destroy); g_clear_pointer (&monitor->alarms, g_hash_table_destroy); if (monitor->user_active_alarm != None) { XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm); monitor->user_active_alarm = None; } /* The device in device_monitors is cleared when the device is * removed. Ensure that the object is not deleted before that. */ g_assert_null (device_monitors[monitor->device_id]); G_OBJECT_CLASS (gsd_idle_monitor_parent_class)->dispose (object); } static void gsd_idle_monitor_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GsdIdleMonitor *monitor = gsd_idle_monitor (object); switch (prop_id) { case PROP_DEVICE_ID: g_value_set_int (value, monitor->device_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gsd_idle_monitor_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GsdIdleMonitor *monitor = gsd_idle_monitor (object); switch (prop_id) { case PROP_DEVICE_ID: monitor->device_id = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gsd_idle_monitor_constructed (GObject *object) { GsdIdleMonitor *monitor = gsd_idle_monitor (object); monitor->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); init_xsync (monitor); } static void gsd_idle_monitor_class_init (GsdIdleMonitorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = gsd_idle_monitor_dispose; object_class->constructed = gsd_idle_monitor_constructed; object_class->get_property = gsd_idle_monitor_get_property; object_class->set_property = gsd_idle_monitor_set_property; /** * GsdIdleMonitor:device_id: * * The device to listen to idletime on. */ obj_props[PROP_DEVICE_ID] = g_param_spec_int ("device-id", "Device ID", "The device to listen to idletime on", 0, 255, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]); } static void gsd_idle_monitor_init (GsdIdleMonitor *monitor) { monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)idle_monitor_watch_free); monitor->alarms = g_hash_table_new (NULL, NULL); } static void ensure_device_monitor (int device_id) { if (device_monitors[device_id]) return; device_monitors[device_id] = g_object_new (GSD_TYPE_IDLE_MONITOR, "device-id", device_id, NULL); device_id_max = MAX (device_id_max, device_id); } /** * gsd_idle_monitor_get_core: * * Returns: (transfer none): the #GsdIdleMonitor that tracks the server-global * idletime for all devices. To track device-specific idletime, * use gsd_idle_monitor_get_for_device(). */ GsdIdleMonitor * gsd_idle_monitor_get_core (void) { ensure_device_monitor (0); return device_monitors[0]; } /** * gsd_idle_monitor_get_for_device: * @device_id: the device to get the idle time for. * * Returns: (transfer none): a new #GsdIdleMonitor that tracks the * device-specific idletime for @device. To track server-global idletime * for all devices, use gsd_idle_monitor_get_core(). */ GsdIdleMonitor * gsd_idle_monitor_get_for_device (int device_id) { g_return_val_if_fail (device_id > 0 && device_id < 256, NULL); ensure_device_monitor (device_id); return device_monitors[device_id]; } static gboolean fire_watch_idle (gpointer data) { GsdIdleMonitorWatch *watch = data; watch->idle_source_id = 0; fire_watch (watch); return FALSE; } static GsdIdleMonitorWatch * make_watch (GsdIdleMonitor *monitor, guint64 timeout_msec, GsdIdleMonitorWatchFunc callback, gpointer user_data, GDestroyNotify notify) { GsdIdleMonitorWatch *watch; watch = g_slice_new0 (GsdIdleMonitorWatch); watch->monitor = monitor; watch->id = get_next_watch_serial (); watch->callback = callback; watch->user_data = user_data; watch->notify = notify; watch->timeout_msec = timeout_msec; if (timeout_msec != 0) { watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE); g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm); if (gsd_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec) watch->idle_source_id = g_idle_add (fire_watch_idle, watch); } else if (monitor->user_active_alarm != None) { watch->xalarm = monitor->user_active_alarm; set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE); } g_hash_table_insert (monitor->watches, GUINT_TO_POINTER (watch->id), watch); return watch; } /** * gsd_idle_monitor_add_idle_watch: * @monitor: A #GsdIdleMonitor * @interval_msec: The idletime interval, in milliseconds * @callback: (allow-none): The callback to call when the user has * accumulated @interval_msec milliseconds of idle time. * @user_data: (allow-none): The user data to pass to the callback * @notify: A #GDestroyNotify * * Returns: a watch id * * Adds a watch for a specific idle time. The callback will be called * when the user has accumulated @interval_msec milliseconds of idle time. * This function will return an ID that can either be passed to * gsd_idle_monitor_remove_watch(), or can be used to tell idle time * watches apart if you have more than one. * * Also note that this function will only care about positive transitions * (user's idle time exceeding a certain time). If you want to know about * when the user has become active, use * gsd_idle_monitor_add_user_active_watch(). */ guint gsd_idle_monitor_add_idle_watch (GsdIdleMonitor *monitor, guint64 interval_msec, GsdIdleMonitorWatchFunc callback, gpointer user_data, GDestroyNotify notify) { GsdIdleMonitorWatch *watch; g_return_val_if_fail (GSD_IS_IDLE_MONITOR (monitor), 0); g_return_val_if_fail (interval_msec > 0, 0); watch = make_watch (monitor, interval_msec, callback, user_data, notify); return watch->id; } /** * gsd_idle_monitor_add_user_active_watch: * @monitor: A #GsdIdleMonitor * @callback: (allow-none): The callback to call when the user is * active again. * @user_data: (allow-none): The user data to pass to the callback * @notify: A #GDestroyNotify * * Returns: a watch id * * Add a one-time watch to know when the user is active again. * Note that this watch is one-time and will de-activate after the * function is called, for efficiency purposes. It's most convenient * to call this when an idle watch, as added by * gsd_idle_monitor_add_idle_watch(), has triggered. */ guint gsd_idle_monitor_add_user_active_watch (GsdIdleMonitor *monitor, GsdIdleMonitorWatchFunc callback, gpointer user_data, GDestroyNotify notify) { GsdIdleMonitorWatch *watch; g_return_val_if_fail (GSD_IS_IDLE_MONITOR (monitor), 0); watch = make_watch (monitor, 0, callback, user_data, notify); return watch->id; } /** * gsd_idle_monitor_remove_watch: * @monitor: A #GsdIdleMonitor * @id: A watch ID * * Removes an idle time watcher, previously added by * gsd_idle_monitor_add_idle_watch() or * gsd_idle_monitor_add_user_active_watch(). */ void gsd_idle_monitor_remove_watch (GsdIdleMonitor *monitor, guint id) { g_return_if_fail (GSD_IS_IDLE_MONITOR (monitor)); g_object_ref (monitor); g_hash_table_remove (monitor->watches, GUINT_TO_POINTER (id)); g_object_unref (monitor); } /** * gsd_idle_monitor_get_idletime: * @monitor: A #GsdIdleMonitor * * Returns: The current idle time, in milliseconds, or -1 for not supported */ gint64 gsd_idle_monitor_get_idletime (GsdIdleMonitor *monitor) { XSyncValue value; g_return_val_if_fail (GSD_IS_IDLE_MONITOR (monitor), -1); if (monitor->counter == None) return -1; if (!XSyncQueryCounter (monitor->display, monitor->counter, &value)) return -1; return _xsyncvalue_to_int64 (value); } static gboolean handle_get_idletime (MetaDBusIdleMonitor *skeleton, GDBusMethodInvocation *invocation, GsdIdleMonitor *monitor) { guint64 idletime; idletime = gsd_idle_monitor_get_idletime (monitor); meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime); return TRUE; } typedef struct { MetaDBusIdleMonitor *dbus_monitor; GsdIdleMonitor *monitor; char *dbus_name; guint watch_id; guint name_watcher_id; } DBusWatch; static void destroy_dbus_watch (gpointer data) { DBusWatch *watch = data; g_object_unref (watch->dbus_monitor); g_object_unref (watch->monitor); g_free (watch->dbus_name); g_bus_unwatch_name (watch->name_watcher_id); g_slice_free (DBusWatch, watch); } static void dbus_idle_callback (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data) { DBusWatch *watch = user_data; GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor); g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton), watch->dbus_name, g_dbus_interface_skeleton_get_object_path (skeleton), "org.gnome.Mutter.IdleMonitor", "WatchFired", g_variant_new ("(u)", watch_id), NULL); } static void name_vanished_callback (GDBusConnection *connection, const char *name, gpointer user_data) { DBusWatch *watch = user_data; gsd_idle_monitor_remove_watch (watch->monitor, watch->watch_id); if (xsync) g_slice_free(GsdXSync, xsync); } static DBusWatch * make_dbus_watch (MetaDBusIdleMonitor *skeleton, GDBusMethodInvocation *invocation, GsdIdleMonitor *monitor) { DBusWatch *watch; watch = g_slice_new (DBusWatch); watch->dbus_monitor = g_object_ref (skeleton); watch->monitor = g_object_ref (monitor); watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation)); watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation), watch->dbus_name, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, /* appeared */ name_vanished_callback, watch, NULL); return watch; } static gboolean handle_add_idle_watch (MetaDBusIdleMonitor *skeleton, GDBusMethodInvocation *invocation, guint64 interval, GsdIdleMonitor *monitor) { DBusWatch *watch; watch = make_dbus_watch (skeleton, invocation, monitor); watch->watch_id = gsd_idle_monitor_add_idle_watch (monitor, interval, dbus_idle_callback, watch, destroy_dbus_watch); meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id); return TRUE; } static gboolean handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton, GDBusMethodInvocation *invocation, GsdIdleMonitor *monitor) { DBusWatch *watch; watch = make_dbus_watch (skeleton, invocation, monitor); watch->watch_id = gsd_idle_monitor_add_user_active_watch (monitor, dbus_idle_callback, watch, destroy_dbus_watch); meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id); return TRUE; } static gboolean handle_remove_watch (MetaDBusIdleMonitor *skeleton, GDBusMethodInvocation *invocation, guint id, GsdIdleMonitor *monitor) { gsd_idle_monitor_remove_watch (monitor, id); meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation); return TRUE; } static void create_monitor_skeleton (GDBusObjectManagerServer *manager, GsdIdleMonitor *monitor, const char *path) { MetaDBusIdleMonitor *skeleton; MetaDBusObjectSkeleton *object; skeleton = meta_dbus_idle_monitor_skeleton_new (); g_signal_connect_object (skeleton, "handle-add-idle-watch", G_CALLBACK (handle_add_idle_watch), monitor, 0); g_signal_connect_object (skeleton, "handle-add-user-active-watch", G_CALLBACK (handle_add_user_active_watch), monitor, 0); g_signal_connect_object (skeleton, "handle-remove-watch", G_CALLBACK (handle_remove_watch), monitor, 0); g_signal_connect_object (skeleton, "handle-get-idletime", G_CALLBACK (handle_get_idletime), monitor, 0); object = meta_dbus_object_skeleton_new (path); meta_dbus_object_skeleton_set_idle_monitor (object, skeleton); g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object)); g_object_unref (skeleton); g_object_unref (object); } static void on_device_added (GdkDeviceManager *device_manager, GdkDevice *device, GDBusObjectManagerServer *manager) { GsdIdleMonitor *monitor; int device_id; char *path; device_id = gdk_x11_device_get_id (device); monitor = gsd_idle_monitor_get_for_device (device_id); g_object_ref(monitor); path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id); create_monitor_skeleton (manager, monitor, path); g_free (path); } static void on_device_removed (GdkDeviceManager *device_manager, GdkDevice *device, GDBusObjectManagerServer *manager) { int device_id; char *path; device_id = gdk_x11_device_get_id (device); path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id); g_dbus_object_manager_server_unexport (manager, path); g_free (path); g_clear_object (&device_monitors[device_id]); if (device_id == device_id_max) device_id_max--; } static void on_bus_acquired (GDBusConnection *connection, const char *name, gpointer user_data) { GDBusObjectManagerServer *manager; GdkDeviceManager *device_manager; GsdIdleMonitor *monitor; GList *devices, *iter; char *path; manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor"); /* We never clear the core monitor, as that's supposed to cumulate idle times from all devices */ monitor = gsd_idle_monitor_get_core (); path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core"); create_monitor_skeleton (manager, monitor, path); g_free (path); device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); g_object_ref (device_manager); devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER); devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE)); devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING)); for (iter = devices; iter; iter = iter->next) on_device_added (device_manager, iter->data, manager); g_list_free (devices); g_signal_connect_object (device_manager, "device-added", G_CALLBACK (on_device_added), manager, 0); g_signal_connect_object (device_manager, "device-removed", G_CALLBACK (on_device_removed), manager, 0); g_dbus_object_manager_server_set_connection (manager, connection); gdk_window_add_filter (NULL, xevent_filter, NULL); } static void on_name_acquired (GDBusConnection *connection, const char *name, gpointer user_data) { g_debug ("Acquired name %s\n", name); } static void on_name_lost (GDBusConnection *connection, const char *name, gpointer user_data) { g_warning ("Lost or failed to acquire name %s\n", name); gdk_window_remove_filter (NULL, xevent_filter, NULL); } static void init_xsync_global (void) { int major, minor; xsync->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); xsync->have_xsync = FALSE; xsync->sync_error_base = 0; xsync->sync_event_base = 0; /* I don't think we really have to fill these in */ major = SYNC_MAJOR_VERSION; minor = SYNC_MINOR_VERSION; if (!XSyncQueryExtension (xsync->display, &xsync->sync_event_base, &xsync->sync_error_base) || !XSyncInitialize (xsync->display, &major, &minor)) { xsync->sync_error_base = 0; xsync->sync_event_base = 0; } else { xsync->have_xsync = TRUE; XSyncSetPriority (xsync->display, None, 10); } } void gsd_idle_monitor_init_dbus (gboolean replace) { static int dbus_name_id; if (dbus_name_id > 0) return; xsync = g_slice_new0 (GsdXSync); init_xsync_global(); dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION, "org.gnome.Mutter.IdleMonitor", G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | (replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0), on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL); } unity-settings-daemon/gnome-settings-daemon/gsd-idle-monitor.h0000664000000000000000000000533015172222611021747 0ustar /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright 2013 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef gsd_idle_monitor_H #define gsd_idle_monitor_H #include #define GSD_TYPE_IDLE_MONITOR (gsd_idle_monitor_get_type ()) #define gsd_idle_monitor(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_IDLE_MONITOR, GsdIdleMonitor)) #define gsd_idle_monitor_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_IDLE_MONITOR, GsdIdleMonitorClass)) #define GSD_IS_IDLE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_IDLE_MONITOR)) #define GSD_IS_IDLE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_IDLE_MONITOR)) #define gsd_idle_monitor_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_IDLE_MONITOR, GsdIdleMonitorClass)) typedef struct _GsdIdleMonitor GsdIdleMonitor; typedef struct _GsdIdleMonitorClass GsdIdleMonitorClass; GType gsd_idle_monitor_get_type (void); typedef void (*GsdIdleMonitorWatchFunc) (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data); GsdIdleMonitor *gsd_idle_monitor_get_core (void); GsdIdleMonitor *gsd_idle_monitor_get_for_device (int device_id); guint gsd_idle_monitor_add_idle_watch (GsdIdleMonitor *monitor, guint64 interval_msec, GsdIdleMonitorWatchFunc callback, gpointer user_data, GDestroyNotify notify); guint gsd_idle_monitor_add_user_active_watch (GsdIdleMonitor *monitor, GsdIdleMonitorWatchFunc callback, gpointer user_data, GDestroyNotify notify); void gsd_idle_monitor_remove_watch (GsdIdleMonitor *monitor, guint id); gint64 gsd_idle_monitor_get_idletime (GsdIdleMonitor *monitor); #endif unity-settings-daemon/gnome-settings-daemon/gsd-pnp-ids.c0000664000000000000000000002322015172222611020710 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include "gsd-pnp-ids.h" static void gsd_pnp_ids_finalize (GObject *object); #define GSD_PNP_IDS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_PNP_IDS, GsdPnpIdsPrivate)) struct _GsdPnpIdsPrivate { gchar *table_data; GHashTable *pnp_table; }; static gpointer gsd_pnp_ids_object = NULL; G_DEFINE_TYPE (GsdPnpIds, gsd_pnp_ids, G_TYPE_OBJECT) typedef struct Vendor Vendor; struct Vendor { const char vendor_id[4]; const char vendor_name[28]; }; /* This list of vendor codes derived from lshw * * http://ezix.org/project/wiki/HardwareLiSter * * Note: we now prefer to use data coming from hwdata (and shipped with * gnome-desktop). See * http://git.fedorahosted.org/git/?p=hwdata.git;a=blob_plain;f=pnp.ids;hb=HEAD * All contributions to the list of vendors should go there. */ static const struct Vendor vendors[] = { { "AIC", "AG Neovo" }, { "ACR", "Acer" }, { "DEL", "DELL" }, { "SAM", "SAMSUNG" }, { "SNY", "SONY" }, { "SEC", "Epson" }, { "WAC", "Wacom" }, { "NEC", "NEC" }, { "CMO", "CMO" }, /* Chi Mei */ { "BNQ", "BenQ" }, { "ABP", "Advansys" }, { "ACC", "Accton" }, { "ACE", "Accton" }, { "ADP", "Adaptec" }, { "ADV", "AMD" }, { "AIR", "AIR" }, { "AMI", "AMI" }, { "ASU", "ASUS" }, { "ATI", "ATI" }, { "ATK", "Allied Telesyn" }, { "AZT", "Aztech" }, { "BAN", "Banya" }, { "BRI", "Boca Research" }, { "BUS", "Buslogic" }, { "CCI", "Cache Computers Inc." }, { "CHA", "Chase" }, { "CMD", "CMD Technology, Inc." }, { "COG", "Cogent" }, { "CPQ", "Compaq" }, { "CRS", "Crescendo" }, { "CSC", "Crystal" }, { "CSI", "CSI" }, { "CTL", "Creative Labs" }, { "DBI", "Digi" }, { "DEC", "Digital Equipment" }, { "DBK", "Databook" }, { "EGL", "Eagle Technology" }, { "ELS", "ELSA" }, { "ESS", "ESS" }, { "FAR", "Farallon" }, { "FDC", "Future Domain" }, { "HWP", "Hewlett-Packard" }, { "IBM", "IBM" }, { "INT", "Intel" }, { "ISA", "Iomega" }, { "LEN", "Lenovo" }, { "MDG", "Madge" }, { "MDY", "Microdyne" }, { "MET", "Metheus" }, { "MIC", "Micronics" }, { "MLX", "Mylex" }, { "NVL", "Novell" }, { "OLC", "Olicom" }, { "PRO", "Proteon" }, { "RII", "Racal" }, { "RTL", "Realtek" }, { "SCM", "SCM" }, { "SKD", "SysKonnect" }, { "SGI", "SGI" }, { "SMC", "SMC" }, { "SNI", "Siemens Nixdorf" }, { "STL", "Stallion Technologies" }, { "SUN", "Sun" }, { "SUP", "SupraExpress" }, { "SVE", "SVEC" }, { "TCC", "Thomas-Conrad" }, { "TCI", "Tulip" }, { "TCM", "3Com" }, { "TCO", "Thomas-Conrad" }, { "TEC", "Tecmar" }, { "TRU", "Truevision" }, { "TOS", "Toshiba" }, { "TYN", "Tyan" }, { "UBI", "Ungermann-Bass" }, { "USC", "UltraStor" }, { "VDM", "Vadem" }, { "VMI", "Vermont" }, { "WDC", "Western Digital" }, { "ZDS", "Zeos" }, /* From http://faydoc.tripod.com/structures/01/0136.htm */ { "ACT", "Targa" }, { "ADI", "ADI" }, { "AOC", "AOC Intl" }, { "API", "Acer America" }, { "APP", "Apple Computer" }, { "ART", "ArtMedia" }, { "AST", "AST Research" }, { "CPL", "Compal" }, { "CTX", "Chuntex Electronic Co." }, { "DPC", "Delta Electronics" }, { "DWE", "Daewoo" }, { "ECS", "ELITEGROUP" }, { "EIZ", "EIZO" }, { "FCM", "Funai" }, { "GSM", "LG Electronics" }, { "GWY", "Gateway 2000" }, { "HEI", "Hyundai" }, { "HIT", "Hitachi" }, { "HSL", "Hansol" }, { "HTC", "Hitachi" }, { "ICL", "Fujitsu ICL" }, { "IVM", "Idek Iiyama" }, { "KFC", "KFC Computek" }, { "LKM", "ADLAS" }, { "LNK", "LINK Tech" }, { "LTN", "Lite-On" }, { "MAG", "MAG InnoVision" }, { "MAX", "Maxdata" }, { "MEI", "Panasonic" }, { "MEL", "Mitsubishi" }, { "MIR", "miro" }, { "MTC", "MITAC" }, { "NAN", "NANAO" }, { "NEC", "NEC Tech" }, { "NOK", "Nokia" }, { "OQI", "OPTIQUEST" }, { "PBN", "Packard Bell" }, { "PGS", "Princeton" }, { "PHL", "Philips" }, { "REL", "Relisys" }, { "SDI", "Samtron" }, { "SMI", "Smile" }, { "SPT", "Sceptre" }, { "SRC", "Shamrock Technology" }, { "STP", "Sceptre" }, { "TAT", "Tatung" }, { "TRL", "Royal Information Company" }, { "TSB", "Toshiba, Inc." }, { "UNM", "Unisys" }, { "VSC", "ViewSonic" }, { "WTC", "Wen Tech" }, { "ZCM", "Zenith Data Systems" }, { "???", "Unknown" }, }; static gboolean gsd_pnp_ids_load (GsdPnpIds *pnp_ids, GError **error) { gchar *retval = NULL; GsdPnpIdsPrivate *priv = pnp_ids->priv; guint i; /* load the contents */ g_debug ("loading: %s", PNP_IDS); if (g_file_get_contents (PNP_IDS, &priv->table_data, NULL, error) == FALSE) return FALSE; /* parse into lines */ retval = priv->table_data; for (i = 0; priv->table_data[i] != '\0'; i++) { /* ignore */ if (priv->table_data[i] != '\n') continue; /* convert newline to NULL */ priv->table_data[i] = '\0'; /* the ID to text is a fixed offset */ if (retval[0] && retval[1] && retval[2] && retval[3] == '\t' && retval[4]) { retval[3] = '\0'; g_hash_table_insert (priv->pnp_table, retval, retval+4); retval = &priv->table_data[i+1]; } } g_debug ("Added %i items to the vendor hashtable", i); return TRUE; } static const char * find_vendor (const char *pnp_id) { guint i; for (i = 0; i < G_N_ELEMENTS (vendors); i++) { if (g_strcmp0 (vendors[i].vendor_id, pnp_id) == 0) return vendors[i].vendor_name; } return NULL; } /** * gsd_pnp_ids_get_pnp_id: * @pnp_ids: a #GsdPnpIds object * @pnp_id: the PNP ID to look for * * Find the full manufacturer name for the given PNP ID. * * Returns: (transfer full): a new string representing the manufacturer name, * or %NULL when not found. */ gchar * gsd_pnp_ids_get_pnp_id (GsdPnpIds *pnp_ids, const gchar *pnp_id) { GsdPnpIdsPrivate *priv = pnp_ids->priv; const char *found; GError *error = NULL; guint size; g_return_val_if_fail (GSD_IS_PNP_IDS (pnp_ids), NULL); g_return_val_if_fail (pnp_id != NULL, NULL); /* if table is empty, try to load it */ size = g_hash_table_size (priv->pnp_table); if (size == 0) { if (gsd_pnp_ids_load (pnp_ids, &error) == FALSE) { g_warning ("Failed to load PNP ids: %s", error->message); g_error_free (error); return NULL; } } /* look this up in the table */ found = g_hash_table_lookup (priv->pnp_table, pnp_id); if (found == NULL) { found = find_vendor (pnp_id); if (found == NULL) return NULL; } return g_strdup (found); } static void gsd_pnp_ids_class_init (GsdPnpIdsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_pnp_ids_finalize; g_type_class_add_private (klass, sizeof (GsdPnpIdsPrivate)); } static void gsd_pnp_ids_init (GsdPnpIds *pnp_ids) { pnp_ids->priv = GSD_PNP_IDS_GET_PRIVATE (pnp_ids); /* we don't keep malloc'd data in the hash; instead we read it * out into priv->table_data and then link to it in the hash */ pnp_ids->priv->pnp_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); } static void gsd_pnp_ids_finalize (GObject *object) { GsdPnpIds *pnp_ids = GSD_PNP_IDS (object); GsdPnpIdsPrivate *priv = pnp_ids->priv; g_free (priv->table_data); g_hash_table_unref (priv->pnp_table); G_OBJECT_CLASS (gsd_pnp_ids_parent_class)->finalize (object); } /** * gsd_pnp_ids_new: * * Returns a reference to a #GsdPnpIds object, or creates * a new one if none have been created. * * Returns: (transfer full): a #GsdPnpIds object. */ GsdPnpIds * gsd_pnp_ids_new (void) { if (gsd_pnp_ids_object != NULL) { g_object_ref (gsd_pnp_ids_object); } else { gsd_pnp_ids_object = g_object_new (GSD_TYPE_PNP_IDS, NULL); g_object_add_weak_pointer (gsd_pnp_ids_object, &gsd_pnp_ids_object); } return GSD_PNP_IDS (gsd_pnp_ids_object); } unity-settings-daemon/gnome-settings-daemon/gsd-pnp-ids.h0000664000000000000000000000430315172222611020716 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2010 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GSD_PNP_IDS_H #define __GSD_PNP_IDS_H #include G_BEGIN_DECLS #define GSD_TYPE_PNP_IDS (gsd_pnp_ids_get_type ()) #define GSD_PNP_IDS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_PNP_IDS, GsdPnpIds)) #define GSD_PNP_IDS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_PNP_IDS, GsdPnpIdsClass)) #define GSD_IS_PNP_IDS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_PNP_IDS)) #define GSD_IS_PNP_IDS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_PNP_IDS)) #define GSD_PNP_IDS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_PNP_IDS, GsdPnpIdsClass)) #define GSD_PNP_IDS_ERROR (gsd_pnp_ids_error_quark ()) typedef struct _GsdPnpIdsPrivate GsdPnpIdsPrivate; typedef struct _GsdPnpIds GsdPnpIds; typedef struct _GsdPnpIdsClass GsdPnpIdsClass; struct _GsdPnpIds { GObject parent; GsdPnpIdsPrivate *priv; }; struct _GsdPnpIdsClass { GObjectClass parent_class; }; GType gsd_pnp_ids_get_type (void); GsdPnpIds *gsd_pnp_ids_new (void); gchar *gsd_pnp_ids_get_pnp_id (GsdPnpIds *pnp_ids, const gchar *pnp_id); G_END_DECLS #endif /* __GSD_PNP_IDS_H */ unity-settings-daemon/gnome-settings-daemon/gsd-rr-config.c0000664000000000000000000015034015172222611021230 0ustar /* gnome-rr-config.c * -*- c-basic-offset: 4 -*- * * Copyright 2007, 2008, Red Hat, Inc. * Copyright 2010 Giovanni Campagna * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Author: Soren Sandmann */ #include #include #include #include #include #include #include #include #include #include #include #include "gsd-rr-config.h" #include "edid.h" #include "gsd-rr-private.h" #define CONFIG_INTENDED_BASENAME "unity-monitors.xml" #define CONFIG_BACKUP_BASENAME "unity-monitors.xml.backup" /* Look for DPI_FALLBACK in: * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c * for the reasoning */ #define DPI_FALLBACK 96.0 /* In version 0 of the config file format, we had several * toplevel elements and no explicit version number. So, the filed looked * like * * * ... * * * ... * * * Since version 1 of the config file, the file has a toplevel * element to group all the configurations. That element has a "version" * attribute which is an integer. So, the file looks like this: * * * * ... * * * ... * * */ /* A helper wrapper around the GMarkup parser stuff */ static gboolean parse_file_gmarkup (const gchar *file, const GMarkupParser *parser, gpointer data, GError **err); typedef struct CrtcAssignment CrtcAssignment; static gboolean crtc_assignment_apply (CrtcAssignment *assign, guint32 timestamp, GError **error); static CrtcAssignment *crtc_assignment_new (GsdRRScreen *screen, GsdRROutputInfo **outputs, GError **error); static void crtc_assignment_free (CrtcAssignment *assign); enum { PROP_0, PROP_SCREEN, PROP_LAST }; G_DEFINE_TYPE (GsdRRConfig, gsd_rr_config, G_TYPE_OBJECT) typedef struct Parser Parser; /* Parser for monitor configurations */ struct Parser { int config_file_version; GsdRROutputInfo * output; GsdRRConfig * configuration; GPtrArray * outputs; GPtrArray * configurations; GQueue * stack; }; static int parse_int (const char *text) { return strtol (text, NULL, 0); } static guint parse_uint (const char *text) { return strtoul (text, NULL, 0); } static gboolean stack_is (Parser *parser, const char *s1, ...) { GList *stack = NULL; const char *s; GList *l1, *l2; va_list args; stack = g_list_prepend (stack, (gpointer)s1); va_start (args, s1); s = va_arg (args, const char *); while (s) { stack = g_list_prepend (stack, (gpointer)s); s = va_arg (args, const char *); } l1 = stack; l2 = parser->stack->head; while (l1 && l2) { if (strcmp (l1->data, l2->data) != 0) { g_list_free (stack); return FALSE; } l1 = l1->next; l2 = l2->next; } g_list_free (stack); return (!l1 && !l2); } static void handle_start_element (GMarkupParseContext *context, const gchar *name, const gchar **attr_names, const gchar **attr_values, gpointer user_data, GError **err) { Parser *parser = user_data; if (strcmp (name, "output") == 0) { int i; g_assert (parser->output == NULL); parser->output = g_object_new (GSD_TYPE_RR_OUTPUT_INFO, NULL); parser->output->priv->rotation = 0; for (i = 0; attr_names[i] != NULL; ++i) { if (strcmp (attr_names[i], "name") == 0) { parser->output->priv->name = g_strdup (attr_values[i]); break; } } if (!parser->output->priv->name) { /* This really shouldn't happen, but it's better to make * something up than to crash later. */ g_warning ("Malformed monitor configuration file"); parser->output->priv->name = g_strdup ("default"); } parser->output->priv->connected = FALSE; parser->output->priv->on = FALSE; parser->output->priv->primary = FALSE; } else if (strcmp (name, "configuration") == 0) { g_assert (parser->configuration == NULL); parser->configuration = g_object_new (GSD_TYPE_RR_CONFIG, NULL); parser->configuration->priv->clone = FALSE; parser->configuration->priv->outputs = NULL; } else if (strcmp (name, "monitors") == 0) { int i; for (i = 0; attr_names[i] != NULL; i++) { if (strcmp (attr_names[i], "version") == 0) { parser->config_file_version = parse_int (attr_values[i]); break; } } } g_queue_push_tail (parser->stack, g_strdup (name)); } static void handle_end_element (GMarkupParseContext *context, const gchar *name, gpointer user_data, GError **err) { Parser *parser = user_data; if (strcmp (name, "output") == 0) { /* If no rotation properties were set, just use GSD_RR_ROTATION_0 */ if (parser->output->priv->rotation == 0) parser->output->priv->rotation = GSD_RR_ROTATION_0; g_ptr_array_add (parser->outputs, parser->output); parser->output = NULL; } else if (strcmp (name, "configuration") == 0) { g_ptr_array_add (parser->outputs, NULL); parser->configuration->priv->outputs = (GsdRROutputInfo **)g_ptr_array_free (parser->outputs, FALSE); parser->outputs = g_ptr_array_new (); g_ptr_array_add (parser->configurations, parser->configuration); parser->configuration = NULL; } g_free (g_queue_pop_tail (parser->stack)); } #define TOPLEVEL_ELEMENT (parser->config_file_version > 0 ? "monitors" : NULL) static void handle_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **err) { Parser *parser = user_data; if (stack_is (parser, "vendor", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->connected = TRUE; strncpy ((gchar*) parser->output->priv->vendor, text, 3); parser->output->priv->vendor[3] = 0; } else if (stack_is (parser, "clone", "configuration", TOPLEVEL_ELEMENT, NULL)) { if (strcmp (text, "yes") == 0) parser->configuration->priv->clone = TRUE; } else if (stack_is (parser, "product", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->connected = TRUE; parser->output->priv->product = parse_int (text); } else if (stack_is (parser, "serial", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->connected = TRUE; parser->output->priv->serial = parse_uint (text); } else if (stack_is (parser, "width", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->on = TRUE; parser->output->priv->width = parse_int (text); } else if (stack_is (parser, "x", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->on = TRUE; parser->output->priv->x = parse_int (text); } else if (stack_is (parser, "y", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->on = TRUE; parser->output->priv->y = parse_int (text); } else if (stack_is (parser, "height", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->on = TRUE; parser->output->priv->height = parse_int (text); } else if (stack_is (parser, "rate", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { parser->output->priv->on = TRUE; parser->output->priv->rate = parse_int (text); } else if (stack_is (parser, "rotation", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { if (strcmp (text, "normal") == 0) { parser->output->priv->rotation |= GSD_RR_ROTATION_0; } else if (strcmp (text, "left") == 0) { parser->output->priv->rotation |= GSD_RR_ROTATION_90; } else if (strcmp (text, "upside_down") == 0) { parser->output->priv->rotation |= GSD_RR_ROTATION_180; } else if (strcmp (text, "right") == 0) { parser->output->priv->rotation |= GSD_RR_ROTATION_270; } } else if (stack_is (parser, "reflect_x", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { if (strcmp (text, "yes") == 0) { parser->output->priv->rotation |= GSD_RR_REFLECT_X; } } else if (stack_is (parser, "reflect_y", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { if (strcmp (text, "yes") == 0) { parser->output->priv->rotation |= GSD_RR_REFLECT_Y; } } else if (stack_is (parser, "primary", "output", "configuration", TOPLEVEL_ELEMENT, NULL)) { if (strcmp (text, "yes") == 0) { parser->output->priv->primary = TRUE; } } else { /* Ignore other properties so we can expand the format in the future */ } } static void parser_free (Parser *parser) { int i; GList *list; g_assert (parser != NULL); if (parser->output) g_object_unref (parser->output); if (parser->configuration) g_object_unref (parser->configuration); for (i = 0; i < parser->outputs->len; ++i) { GsdRROutputInfo *output = parser->outputs->pdata[i]; g_object_unref (output); } g_ptr_array_free (parser->outputs, TRUE); for (i = 0; i < parser->configurations->len; ++i) { GsdRRConfig *config = parser->configurations->pdata[i]; g_object_unref (config); } g_ptr_array_free (parser->configurations, TRUE); for (list = parser->stack->head; list; list = list->next) g_free (list->data); g_queue_free (parser->stack); g_free (parser); } static GsdRRConfig ** configurations_read_from_file (const gchar *filename, GError **error) { Parser *parser = g_new0 (Parser, 1); GsdRRConfig **result; GMarkupParser callbacks = { handle_start_element, handle_end_element, handle_text, NULL, /* passthrough */ NULL, /* error */ }; parser->config_file_version = 0; parser->configurations = g_ptr_array_new (); parser->outputs = g_ptr_array_new (); parser->stack = g_queue_new (); if (!parse_file_gmarkup (filename, &callbacks, parser, error)) { result = NULL; g_assert (parser->outputs); goto out; } g_assert (parser->outputs); g_ptr_array_add (parser->configurations, NULL); result = (GsdRRConfig **)g_ptr_array_free (parser->configurations, FALSE); parser->configurations = g_ptr_array_new (); g_assert (parser->outputs); out: parser_free (parser); return result; } static void gsd_rr_config_init (GsdRRConfig *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GSD_TYPE_RR_CONFIG, GsdRRConfigPrivate); self->priv->clone = FALSE; self->priv->screen = NULL; self->priv->outputs = NULL; } static void gsd_rr_config_set_property (GObject *gobject, guint property_id, const GValue *value, GParamSpec *property) { GsdRRConfig *self = GSD_RR_CONFIG (gobject); switch (property_id) { case PROP_SCREEN: self->priv->screen = g_value_dup_object (value); return; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property); } } static void gsd_rr_config_finalize (GObject *gobject) { GsdRRConfig *self = GSD_RR_CONFIG (gobject); if (self->priv->screen) g_object_unref (self->priv->screen); if (self->priv->outputs) { int i; for (i = 0; self->priv->outputs[i] != NULL; i++) { GsdRROutputInfo *output = self->priv->outputs[i]; g_object_unref (output); } g_free (self->priv->outputs); } G_OBJECT_CLASS (gsd_rr_config_parent_class)->finalize (gobject); } gboolean gsd_rr_config_load_current (GsdRRConfig *config, GError **error) { GPtrArray *a; GsdRROutput **rr_outputs; int i; int clone_width = -1; int clone_height = -1; int last_x; g_return_val_if_fail (GSD_IS_RR_CONFIG (config), FALSE); a = g_ptr_array_new (); rr_outputs = gsd_rr_screen_list_outputs (config->priv->screen); config->priv->clone = FALSE; for (i = 0; rr_outputs[i] != NULL; ++i) { GsdRROutput *rr_output = rr_outputs[i]; GsdRROutputInfo *output = g_object_new (GSD_TYPE_RR_OUTPUT_INFO, NULL); GsdRRMode *mode = NULL; const guint8 *edid_data = gsd_rr_output_get_edid_data (rr_output, NULL); GsdRRCrtc *crtc; output->priv->name = g_strdup (gsd_rr_output_get_name (rr_output)); output->priv->connected = gsd_rr_output_is_connected (rr_output); output->priv->display_name = g_strdup (gsd_rr_output_get_display_name (rr_output)); if (!output->priv->connected) { output->priv->x = -1; output->priv->y = -1; output->priv->width = -1; output->priv->height = -1; output->priv->rate = -1; output->priv->rotation = GSD_RR_ROTATION_0; } else { MonitorInfo *info = NULL; if (edid_data) info = decode_edid (edid_data); if (info) { memcpy (output->priv->vendor, info->manufacturer_code, sizeof (output->priv->vendor)); output->priv->product = info->product_code; output->priv->serial = info->serial_number; output->priv->aspect = info->aspect_ratio; } else { strcpy (output->priv->vendor, "???"); output->priv->product = 0; output->priv->serial = 0; } g_free (info); crtc = gsd_rr_output_get_crtc (rr_output); mode = crtc? gsd_rr_crtc_get_current_mode (crtc) : NULL; if (crtc && mode) { output->priv->on = TRUE; gsd_rr_crtc_get_position (crtc, &output->priv->x, &output->priv->y); output->priv->width = gsd_rr_mode_get_width (mode); output->priv->height = gsd_rr_mode_get_height (mode); output->priv->rate = gsd_rr_mode_get_freq (mode); output->priv->rotation = gsd_rr_crtc_get_current_rotation (crtc); if (output->priv->x == 0 && output->priv->y == 0) { if (clone_width == -1) { clone_width = output->priv->width; clone_height = output->priv->height; } else if (clone_width == output->priv->width && clone_height == output->priv->height) { config->priv->clone = TRUE; } } } else { output->priv->on = FALSE; config->priv->clone = FALSE; } /* Get preferred size for the monitor */ mode = gsd_rr_output_get_preferred_mode (rr_output); if (!mode) { GsdRRMode **modes = gsd_rr_output_list_modes (rr_output); /* FIXME: we should pick the "best" mode here, where best is * sorted wrt * * - closest aspect ratio * - mode area * - refresh rate * - We may want to extend randrwrap so that get_preferred * returns that - although that could also depend on * the crtc. */ if (modes[0]) mode = modes[0]; } if (mode) { output->priv->pref_width = gsd_rr_mode_get_width (mode); output->priv->pref_height = gsd_rr_mode_get_height (mode); } else { /* Pick some random numbers. This should basically never happen */ output->priv->pref_width = 1024; output->priv->pref_height = 768; } } output->priv->primary = gsd_rr_output_get_is_primary (rr_output); g_ptr_array_add (a, output); } g_ptr_array_add (a, NULL); config->priv->outputs = (GsdRROutputInfo **)g_ptr_array_free (a, FALSE); /* Walk the outputs computing the right-most edge of all * lit-up displays */ last_x = 0; for (i = 0; config->priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *output = config->priv->outputs[i]; if (output->priv->on) { last_x = MAX (last_x, output->priv->x + output->priv->width); } } /* Now position all off displays to the right of the * on displays */ for (i = 0; config->priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *output = config->priv->outputs[i]; if (output->priv->connected && !output->priv->on) { output->priv->x = last_x; last_x = output->priv->x + output->priv->width; } } g_assert (gsd_rr_config_match (config, config)); return TRUE; } gboolean gsd_rr_config_load_filename (GsdRRConfig *result, const char *filename, GError **error) { GsdRRConfig *current; GsdRRConfig **configs; gboolean found = FALSE; g_return_val_if_fail (GSD_IS_RR_CONFIG (result), FALSE); g_return_val_if_fail (filename != NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); current = gsd_rr_config_new_current (result->priv->screen, error); configs = configurations_read_from_file (filename, error); if (configs) { int i; for (i = 0; configs[i] != NULL; ++i) { if (gsd_rr_config_match (configs[i], current)) { int j; GPtrArray *array; result->priv->clone = configs[i]->priv->clone; array = g_ptr_array_new (); for (j = 0; configs[i]->priv->outputs[j] != NULL; j++) { g_object_ref (configs[i]->priv->outputs[j]); g_ptr_array_add (array, configs[i]->priv->outputs[j]); } g_ptr_array_add (array, NULL); result->priv->outputs = (GsdRROutputInfo **) g_ptr_array_free (array, FALSE); found = TRUE; break; } g_object_unref (configs[i]); } g_free (configs); if (!found) g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_NO_MATCHING_CONFIG, _("none of the saved display configurations matched the active configuration")); } g_object_unref (current); return found; } static void gsd_rr_config_class_init (GsdRRConfigClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GsdRROutputInfoPrivate)); gobject_class->set_property = gsd_rr_config_set_property; gobject_class->finalize = gsd_rr_config_finalize; g_object_class_install_property (gobject_class, PROP_SCREEN, g_param_spec_object ("screen", "Screen", "The GsdRRScreen this config applies to", GSD_TYPE_RR_SCREEN, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } GsdRRConfig * gsd_rr_config_new_current (GsdRRScreen *screen, GError **error) { GsdRRConfig *self = g_object_new (GSD_TYPE_RR_CONFIG, "screen", screen, NULL); if (gsd_rr_config_load_current (self, error)) return self; else { g_object_unref (self); return NULL; } } GsdRRConfig * gsd_rr_config_new_stored (GsdRRScreen *screen, GError **error) { GsdRRConfig *self = g_object_new (GSD_TYPE_RR_CONFIG, "screen", screen, NULL); char *filename; gboolean success; filename = gsd_rr_config_get_intended_filename (); success = gsd_rr_config_load_filename (self, filename, error); g_free (filename); if (success) return self; else { g_object_unref (self); return NULL; } } static gboolean parse_file_gmarkup (const gchar *filename, const GMarkupParser *parser, gpointer data, GError **err) { GMarkupParseContext *context = NULL; gchar *contents = NULL; gboolean result = TRUE; gsize len; if (!g_file_get_contents (filename, &contents, &len, err)) { result = FALSE; goto out; } context = g_markup_parse_context_new (parser, 0, data, NULL); if (!g_markup_parse_context_parse (context, contents, len, err)) { result = FALSE; goto out; } if (!g_markup_parse_context_end_parse (context, err)) { result = FALSE; goto out; } out: if (contents) g_free (contents); if (context) g_markup_parse_context_free (context); return result; } static gboolean output_match (GsdRROutputInfo *output1, GsdRROutputInfo *output2) { g_assert (GSD_IS_RR_OUTPUT_INFO (output1)); g_assert (GSD_IS_RR_OUTPUT_INFO (output2)); if (strcmp (output1->priv->name, output2->priv->name) != 0) return FALSE; if (strcmp (output1->priv->vendor, output2->priv->vendor) != 0) return FALSE; if (output1->priv->product != output2->priv->product) return FALSE; if (output1->priv->serial != output2->priv->serial) return FALSE; if (output1->priv->connected != output2->priv->connected) return FALSE; return TRUE; } static gboolean output_equal (GsdRROutputInfo *output1, GsdRROutputInfo *output2) { g_assert (GSD_IS_RR_OUTPUT_INFO (output1)); g_assert (GSD_IS_RR_OUTPUT_INFO (output2)); if (!output_match (output1, output2)) return FALSE; if (output1->priv->on != output2->priv->on) return FALSE; if (output1->priv->on) { if (output1->priv->width != output2->priv->width) return FALSE; if (output1->priv->height != output2->priv->height) return FALSE; if (output1->priv->rate != output2->priv->rate) return FALSE; if (output1->priv->x != output2->priv->x) return FALSE; if (output1->priv->y != output2->priv->y) return FALSE; if (output1->priv->rotation != output2->priv->rotation) return FALSE; } return TRUE; } static GsdRROutputInfo * find_output (GsdRRConfig *config, const char *name) { int i; for (i = 0; config->priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *output = config->priv->outputs[i]; if (strcmp (name, output->priv->name) == 0) return output; } return NULL; } /* Match means "these configurations apply to the same hardware * setups" */ gboolean gsd_rr_config_match (GsdRRConfig *c1, GsdRRConfig *c2) { int i; g_return_val_if_fail (GSD_IS_RR_CONFIG (c1), FALSE); g_return_val_if_fail (GSD_IS_RR_CONFIG (c2), FALSE); for (i = 0; c1->priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *output1 = c1->priv->outputs[i]; GsdRROutputInfo *output2; output2 = find_output (c2, output1->priv->name); if (!output2 || !output_match (output1, output2)) return FALSE; } return TRUE; } /* Equal means "the configurations will result in the same * modes being set on the outputs" */ gboolean gsd_rr_config_equal (GsdRRConfig *c1, GsdRRConfig *c2) { int i; g_return_val_if_fail (GSD_IS_RR_CONFIG (c1), FALSE); g_return_val_if_fail (GSD_IS_RR_CONFIG (c2), FALSE); for (i = 0; c1->priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *output1 = c1->priv->outputs[i]; GsdRROutputInfo *output2; output2 = find_output (c2, output1->priv->name); if (!output2 || !output_equal (output1, output2)) return FALSE; } return TRUE; } static GsdRROutputInfo ** make_outputs (GsdRRConfig *config) { GPtrArray *outputs; GsdRROutputInfo *first_on; int i; outputs = g_ptr_array_new (); first_on = NULL; for (i = 0; config->priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *old = config->priv->outputs[i]; GsdRROutputInfo *new = g_object_new (GSD_TYPE_RR_OUTPUT_INFO, NULL); *(new->priv) = *(old->priv); if (old->priv->name) new->priv->name = g_strdup (old->priv->name); if (old->priv->display_name) new->priv->display_name = g_strdup (old->priv->display_name); if (old->priv->on && !first_on) first_on = old; if (config->priv->clone && new->priv->on) { g_assert (first_on); new->priv->width = first_on->priv->width; new->priv->height = first_on->priv->height; new->priv->rotation = first_on->priv->rotation; new->priv->x = 0; new->priv->y = 0; } g_ptr_array_add (outputs, new); } g_ptr_array_add (outputs, NULL); return (GsdRROutputInfo **)g_ptr_array_free (outputs, FALSE); } gboolean gsd_rr_config_applicable (GsdRRConfig *configuration, GsdRRScreen *screen, GError **error) { GsdRROutputInfo **outputs; CrtcAssignment *assign; gboolean result; int i; g_return_val_if_fail (GSD_IS_RR_CONFIG (configuration), FALSE); g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); outputs = make_outputs (configuration); assign = crtc_assignment_new (screen, outputs, error); if (assign) { result = TRUE; crtc_assignment_free (assign); } else { result = FALSE; } for (i = 0; outputs[i] != NULL; i++) { g_object_unref (outputs[i]); } return result; } /* Database management */ static void ensure_config_directory (void) { g_mkdir_with_parents (g_get_user_config_dir (), 0700); } char * gsd_rr_config_get_backup_filename (void) { ensure_config_directory (); return g_build_filename (g_get_user_config_dir (), CONFIG_BACKUP_BASENAME, NULL); } char * gsd_rr_config_get_intended_filename (void) { ensure_config_directory (); return g_build_filename (g_get_user_config_dir (), CONFIG_INTENDED_BASENAME, NULL); } static const char * get_rotation_name (GsdRRRotation r) { if (r & GSD_RR_ROTATION_0) return "normal"; if (r & GSD_RR_ROTATION_90) return "left"; if (r & GSD_RR_ROTATION_180) return "upside_down"; if (r & GSD_RR_ROTATION_270) return "right"; return "normal"; } static const char * yes_no (int x) { return x? "yes" : "no"; } static const char * get_reflect_x (GsdRRRotation r) { return yes_no (r & GSD_RR_REFLECT_X); } static const char * get_reflect_y (GsdRRRotation r) { return yes_no (r & GSD_RR_REFLECT_Y); } static void emit_configuration (GsdRRConfig *config, GString *string) { int j; g_string_append_printf (string, " \n"); g_string_append_printf (string, " %s\n", yes_no (config->priv->clone)); for (j = 0; config->priv->outputs[j] != NULL; ++j) { GsdRROutputInfo *output = config->priv->outputs[j]; g_string_append_printf ( string, " \n", output->priv->name); if (output->priv->connected && *output->priv->vendor != '\0') { g_string_append_printf ( string, " %s\n", output->priv->vendor); g_string_append_printf ( string, " 0x%04x\n", output->priv->product); g_string_append_printf ( string, " 0x%08x\n", output->priv->serial); } /* An unconnected output which is on does not make sense */ if (output->priv->connected && output->priv->on) { g_string_append_printf ( string, " %d\n", output->priv->width); g_string_append_printf ( string, " %d\n", output->priv->height); g_string_append_printf ( string, " %d\n", output->priv->rate); g_string_append_printf ( string, " %d\n", output->priv->x); g_string_append_printf ( string, " %d\n", output->priv->y); g_string_append_printf ( string, " %s\n", get_rotation_name (output->priv->rotation)); g_string_append_printf ( string, " %s\n", get_reflect_x (output->priv->rotation)); g_string_append_printf ( string, " %s\n", get_reflect_y (output->priv->rotation)); g_string_append_printf ( string, " %s\n", yes_no (output->priv->primary)); } g_string_append_printf (string, " \n"); } g_string_append_printf (string, " \n"); } void gsd_rr_config_sanitize (GsdRRConfig *config) { int i; int x_offset, y_offset; gboolean found; /* Offset everything by the top/left-most coordinate to * make sure the configuration starts at (0, 0) */ x_offset = y_offset = G_MAXINT; for (i = 0; config->priv->outputs[i]; ++i) { GsdRROutputInfo *output = config->priv->outputs[i]; if (output->priv->on) { x_offset = MIN (x_offset, output->priv->x); y_offset = MIN (y_offset, output->priv->y); } } for (i = 0; config->priv->outputs[i]; ++i) { GsdRROutputInfo *output = config->priv->outputs[i]; if (output->priv->on) { output->priv->x -= x_offset; output->priv->y -= y_offset; } } /* Only one primary, please */ found = FALSE; for (i = 0; config->priv->outputs[i]; ++i) { if (config->priv->outputs[i]->priv->primary) { if (found) { config->priv->outputs[i]->priv->primary = FALSE; } else { found = TRUE; } } } } gboolean gsd_rr_config_ensure_primary (GsdRRConfig *configuration) { int i; GsdRROutputInfo *laptop; GsdRROutputInfo *top_left; gboolean found; GsdRRConfigPrivate *priv; g_return_val_if_fail (GSD_IS_RR_CONFIG (configuration), FALSE); laptop = NULL; top_left = NULL; found = FALSE; priv = configuration->priv; for (i = 0; priv->outputs[i] != NULL; ++i) { GsdRROutputInfo *info = priv->outputs[i]; if (!info->priv->on) { info->priv->primary = FALSE; continue; } /* ensure only one */ if (info->priv->primary) { if (found) { info->priv->primary = FALSE; } else { found = TRUE; } } if (top_left == NULL || (info->priv->x < top_left->priv->x && info->priv->y < top_left->priv->y)) { top_left = info; } if (laptop == NULL && _gsd_rr_output_name_is_laptop (info->priv->name)) { /* shame we can't find the connector type as with gsd_rr_output_is_laptop */ laptop = info; } } if (!found) { if (laptop != NULL) { laptop->priv->primary = TRUE; } else if (top_left != NULL) { /* Note: top_left can be NULL if all outputs are off */ top_left->priv->primary = TRUE; } } return !found; } gboolean gsd_rr_config_save (GsdRRConfig *configuration, GError **error) { GsdRRConfig **configurations; GString *output; int i; gchar *intended_filename; gchar *backup_filename; gboolean result; g_return_val_if_fail (GSD_IS_RR_CONFIG (configuration), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); output = g_string_new (""); backup_filename = gsd_rr_config_get_backup_filename (); intended_filename = gsd_rr_config_get_intended_filename (); configurations = configurations_read_from_file (intended_filename, NULL); /* NULL-GError */ g_string_append_printf (output, "\n"); if (configurations) { for (i = 0; configurations[i] != NULL; ++i) { if (!gsd_rr_config_match (configurations[i], configuration)) emit_configuration (configurations[i], output); g_object_unref (configurations[i]); } g_free (configurations); } emit_configuration (configuration, output); g_string_append_printf (output, "\n"); /* backup the file first */ rename (intended_filename, backup_filename); /* no error checking because the intended file may not even exist */ result = g_file_set_contents (intended_filename, output->str, -1, error); if (!result) rename (backup_filename, intended_filename); /* no error checking because the backup may not even exist */ g_free (backup_filename); g_free (intended_filename); return result; } gboolean gsd_rr_config_apply_with_time (GsdRRConfig *config, GsdRRScreen *screen, guint32 timestamp, GError **error) { CrtcAssignment *assignment; GsdRROutputInfo **outputs; gboolean result = FALSE; int i; g_return_val_if_fail (GSD_IS_RR_CONFIG (config), FALSE); g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), FALSE); outputs = make_outputs (config); assignment = crtc_assignment_new (screen, outputs, error); for (i = 0; outputs[i] != NULL; i++) g_object_unref (outputs[i]); g_free (outputs); if (assignment) { if (crtc_assignment_apply (assignment, timestamp, error)) result = TRUE; crtc_assignment_free (assignment); gdk_flush (); } return result; } /* gsd_rr_config_apply_from_filename_with_time: * @screen: A #GsdRRScreen * @filename: Path of the file to look in for stored RANDR configurations. * @timestamp: X server timestamp from the event that causes the screen configuration to change (a user's button press, for example) * @error: Location to store error, or %NULL * * Loads the file in @filename and looks for suitable matching RANDR * configurations in the file; if one is found, that configuration will be * applied to the current set of RANDR outputs. * * Typically, @filename is the result of gsd_rr_config_get_intended_filename() or * gsd_rr_config_get_backup_filename(). * * Returns: TRUE if the RANDR configuration was loaded and applied from * the specified file, or FALSE otherwise: * * If the file in question is loaded successfully but the configuration cannot * be applied, the @error will have a domain of #GSD_RR_ERROR. Note that an * error code of #GSD_RR_ERROR_NO_MATCHING_CONFIG is not a real error; it * simply means that there were no stored configurations that match the current * set of RANDR outputs. * * If the file in question cannot be loaded, the @error will have a domain of * #G_FILE_ERROR. Note that an error code of G_FILE_ERROR_NOENT is not really * an error, either; it means that there was no stored configuration file and so * nothing is changed. */ gboolean gsd_rr_config_apply_from_filename_with_time (GsdRRScreen *screen, const char *filename, guint32 timestamp, GError **error) { GsdRRConfig *stored; g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), FALSE); g_return_val_if_fail (filename != NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); stored = g_object_new (GSD_TYPE_RR_CONFIG, "screen", screen, NULL); if (gsd_rr_config_load_filename (stored, filename, error)) { gboolean result; gsd_rr_config_ensure_primary (stored); result = gsd_rr_config_apply_with_time (stored, screen, timestamp, error); g_object_unref (stored); return result; } else { g_object_unref (stored); return FALSE; } } /** * gsd_rr_config_get_outputs: * * Returns: (array zero-terminated=1) (element-type GnomeDesktop.RROutputInfo) (transfer none): the output configuration for this #GsdRRConfig */ GsdRROutputInfo ** gsd_rr_config_get_outputs (GsdRRConfig *self) { g_return_val_if_fail (GSD_IS_RR_CONFIG (self), NULL); return self->priv->outputs; } /** * gsd_rr_config_get_clone: * * Returns: whether at least two outputs are at (0, 0) offset and they * have the same width/height. Those outputs are of course connected and on * (i.e. they have a CRTC assigned). */ gboolean gsd_rr_config_get_clone (GsdRRConfig *self) { g_return_val_if_fail (GSD_IS_RR_CONFIG (self), FALSE); return self->priv->clone; } void gsd_rr_config_set_clone (GsdRRConfig *self, gboolean clone) { g_return_if_fail (GSD_IS_RR_CONFIG (self)); self->priv->clone = clone; } /* * CRTC assignment */ typedef struct CrtcInfo CrtcInfo; struct CrtcInfo { GsdRRMode *mode; int x; int y; GsdRRRotation rotation; GPtrArray *outputs; }; struct CrtcAssignment { GsdRRScreen *screen; GHashTable *info; GsdRROutput *primary; }; static gboolean can_clone (CrtcInfo *info, GsdRROutput *output) { int i; for (i = 0; i < info->outputs->len; ++i) { GsdRROutput *clone = info->outputs->pdata[i]; if (!gsd_rr_output_can_clone (clone, output)) return FALSE; } return TRUE; } static gboolean crtc_assignment_assign (CrtcAssignment *assign, GsdRRCrtc *crtc, GsdRRMode *mode, int x, int y, GsdRRRotation rotation, gboolean primary, GsdRROutput *output, GError **error) { CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); guint32 crtc_id; const char *output_name; crtc_id = gsd_rr_crtc_get_id (crtc); output_name = gsd_rr_output_get_name (output); if (!gsd_rr_crtc_can_drive_output (crtc, output)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("CRTC %d cannot drive output %s"), crtc_id, output_name); return FALSE; } if (!gsd_rr_output_supports_mode (output, mode)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("output %s does not support mode %dx%d@%dHz"), output_name, gsd_rr_mode_get_width (mode), gsd_rr_mode_get_height (mode), gsd_rr_mode_get_freq (mode)); return FALSE; } if (!gsd_rr_crtc_supports_rotation (crtc, rotation)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("CRTC %d does not support rotation=%s"), crtc_id, get_rotation_name (rotation)); return FALSE; } if (info) { if (!(info->mode == mode && info->x == x && info->y == y && info->rotation == rotation)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("output %s does not have the same parameters as another cloned output:\n" "existing mode = %d, new mode = %d\n" "existing coordinates = (%d, %d), new coordinates = (%d, %d)\n" "existing rotation = %s, new rotation = %s"), output_name, gsd_rr_mode_get_id (info->mode), gsd_rr_mode_get_id (mode), info->x, info->y, x, y, get_rotation_name (info->rotation), get_rotation_name (rotation)); return FALSE; } if (!can_clone (info, output)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("cannot clone to output %s"), output_name); return FALSE; } g_ptr_array_add (info->outputs, output); if (primary && !assign->primary) { assign->primary = output; } return TRUE; } else { CrtcInfo *info = g_new0 (CrtcInfo, 1); info->mode = mode; info->x = x; info->y = y; info->rotation = rotation; info->outputs = g_ptr_array_new (); g_ptr_array_add (info->outputs, output); g_hash_table_insert (assign->info, crtc, info); if (primary && !assign->primary) { assign->primary = output; } return TRUE; } } static void crtc_assignment_unassign (CrtcAssignment *assign, GsdRRCrtc *crtc, GsdRROutput *output) { CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); if (info) { g_ptr_array_remove (info->outputs, output); if (assign->primary == output) { assign->primary = NULL; } if (info->outputs->len == 0) g_hash_table_remove (assign->info, crtc); } } static void crtc_assignment_free (CrtcAssignment *assign) { g_hash_table_destroy (assign->info); g_free (assign); } typedef struct { guint32 timestamp; gboolean has_error; GError **error; } ConfigureCrtcState; static void configure_crtc (gpointer key, gpointer value, gpointer data) { GsdRRCrtc *crtc = key; CrtcInfo *info = value; ConfigureCrtcState *state = data; if (state->has_error) return; if (!gsd_rr_crtc_set_config_with_time (crtc, state->timestamp, info->x, info->y, info->mode, info->rotation, (GsdRROutput **)info->outputs->pdata, info->outputs->len, state->error)) state->has_error = TRUE; } static gboolean mode_is_rotated (CrtcInfo *info) { if ((info->rotation & GSD_RR_ROTATION_270) || (info->rotation & GSD_RR_ROTATION_90)) { return TRUE; } return FALSE; } static gboolean crtc_is_rotated (GsdRRCrtc *crtc) { GsdRRRotation r = gsd_rr_crtc_get_current_rotation (crtc); if ((r & GSD_RR_ROTATION_270) || (r & GSD_RR_ROTATION_90)) { return TRUE; } return FALSE; } static void accumulate_error (GString *accumulated_error, GError *error) { g_string_append_printf (accumulated_error, " %s\n", error->message); g_error_free (error); } /* Check whether the given set of settings can be used * at the same time -- ie. whether there is an assignment * of CRTC's to outputs. * * Brute force - the number of objects involved is small * enough that it doesn't matter. */ static gboolean real_assign_crtcs (GsdRRScreen *screen, GsdRROutputInfo **outputs, CrtcAssignment *assignment, GError **error) { GsdRRCrtc **crtcs = gsd_rr_screen_list_crtcs (screen); GsdRROutputInfo *output; int i; gboolean tried_mode; GError *my_error; GString *accumulated_error; gboolean success; output = *outputs; if (!output) return TRUE; /* It is always allowed for an output to be turned off */ if (!output->priv->on) { return real_assign_crtcs (screen, outputs + 1, assignment, error); } success = FALSE; tried_mode = FALSE; accumulated_error = g_string_new (NULL); for (i = 0; crtcs[i] != NULL; ++i) { GsdRRCrtc *crtc = crtcs[i]; int crtc_id = gsd_rr_crtc_get_id (crtc); int pass; g_string_append_printf (accumulated_error, _("Trying modes for CRTC %d\n"), crtc_id); /* Make two passes, one where frequencies must match, then * one where they don't have to */ for (pass = 0; pass < 2; ++pass) { GsdRROutput *gsd_rr_output = gsd_rr_screen_get_output_by_name (screen, output->priv->name); GsdRRMode **modes = gsd_rr_output_list_modes (gsd_rr_output); int j; for (j = 0; modes[j] != NULL; ++j) { GsdRRMode *mode = modes[j]; int mode_width; int mode_height; int mode_freq; mode_width = gsd_rr_mode_get_width (mode); mode_height = gsd_rr_mode_get_height (mode); mode_freq = gsd_rr_mode_get_freq (mode); g_string_append_printf (accumulated_error, _("CRTC %d: trying mode %dx%d@%dHz with output at %dx%d@%dHz (pass %d)\n"), crtc_id, mode_width, mode_height, mode_freq, output->priv->width, output->priv->height, output->priv->rate, pass); if (mode_width == output->priv->width && mode_height == output->priv->height && (pass == 1 || mode_freq == output->priv->rate)) { tried_mode = TRUE; my_error = NULL; if (crtc_assignment_assign ( assignment, crtc, modes[j], output->priv->x, output->priv->y, output->priv->rotation, output->priv->primary, gsd_rr_output, &my_error)) { my_error = NULL; if (real_assign_crtcs (screen, outputs + 1, assignment, &my_error)) { success = TRUE; goto out; } else accumulate_error (accumulated_error, my_error); crtc_assignment_unassign (assignment, crtc, gsd_rr_output); } else accumulate_error (accumulated_error, my_error); } } } } out: if (success) g_string_free (accumulated_error, TRUE); else { char *str; str = g_string_free (accumulated_error, FALSE); if (tried_mode) g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("could not assign CRTCs to outputs:\n%s"), str); else g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_CRTC_ASSIGNMENT, _("none of the selected modes were compatible with the possible modes:\n%s"), str); g_free (str); } return success; } static void crtc_info_free (CrtcInfo *info) { g_ptr_array_free (info->outputs, TRUE); g_free (info); } static void get_required_virtual_size (CrtcAssignment *assign, int *width, int *height) { GList *active_crtcs = g_hash_table_get_keys (assign->info); GList *list; int d; if (!width) width = &d; if (!height) height = &d; /* Compute size of the screen */ *width = *height = 1; for (list = active_crtcs; list != NULL; list = list->next) { GsdRRCrtc *crtc = list->data; CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); int w, h; w = gsd_rr_mode_get_width (info->mode); h = gsd_rr_mode_get_height (info->mode); if (mode_is_rotated (info)) { int tmp = h; h = w; w = tmp; } *width = MAX (*width, info->x + w); *height = MAX (*height, info->y + h); } g_list_free (active_crtcs); } static gboolean unity_running (void) { const gchar *desktop_environment = g_getenv ("DESKTOP_SESSION"); return !g_strcmp0 (desktop_environment, "ubuntu"); } static gint _max_texture_size_cache = -1; static gint get_max_texture_size (GsdRRScreen *screen) { if (_max_texture_size_cache != -1) { return _max_texture_size_cache; } else { /* * Spawn a second process to check the GL texture limits * We do this across a process boundary to ensure that crashes * in the GL driver (which are unfortunately common) don't take * down the app. */ int pipe_fd[2]; pid_t canary_pid; char * const canary_argv[] = { LIBEXECDIR "/check_gl_texture_size", NULL }; char *canary_env[2]; char display_env[80]; snprintf (display_env, sizeof (display_env), "DISPLAY=%s", DisplayString (screen->priv->xdisplay)); canary_env[0] = display_env; canary_env[1] = NULL; if (pipe (pipe_fd) == -1) { _max_texture_size_cache = 0; return 0; } canary_pid = fork (); if (canary_pid == -1) { _max_texture_size_cache = 0; return 0; } if (canary_pid == 0) { close (pipe_fd[0]); dup2 (pipe_fd[1], 1); close (pipe_fd[1]); execve (canary_argv[0], canary_argv, canary_env); } else { char buffer[10]; gint max_texture_size; int child_status; int num_char; struct timespec fifty_msec = {0, 50000000}; int wait_count = 0; close (pipe_fd[1]); /* Empirical testing suggests this check takes < 150msec on my * crappy Atom netbook with slow rotating HDD. A 500msec timeout * should be generous while not being *too* long if it triggers. * * Do a sleep/poll dance because we're a library and there's no * guarantee that waiting on SIGCHLD won't stomp over a client's * set up. */ while (waitpid (canary_pid, &child_status, WNOHANG) == 0 && wait_count < 10) { g_debug ("Waiting for GL_MAX_TEXTURE_SIZE helper..."); nanosleep (&fifty_msec, NULL); wait_count++; } if (WIFEXITED (child_status) && WEXITSTATUS (child_status) == EXIT_SUCCESS) { if ((num_char = read (pipe_fd[0], buffer, sizeof(buffer) - 1)) <= 0) { g_warning ("Failed to read GL_MAX_TEXTURE_SIZE from helper."); max_texture_size = 0; } else { buffer[num_char] = '\0'; sscanf (buffer, "%u", &max_texture_size); /* * Sanity check the numbers. No hardware I know of has a * GL_MAX_TEXTURE_SIZE smaller than 1024. */ if (max_texture_size < 1024) max_texture_size = 0; } } else { if (wait_count == 10) { g_warning ("Timed out waiting for GL_MAX_TEXTURE_SIZE helper"); /* Ensure we don't leave processes sitting around. Who knows what they're doing? */ kill (canary_pid, SIGTERM); waitpid (canary_pid, &child_status, 0); } else { g_warning ("GL_MAX_TEXTURE_SIZE helper quit unexpectedly"); } max_texture_size = 0; } close (pipe_fd[0]); g_debug ("Found GL_MAX_TEXTURE_SIZE of %u", max_texture_size); _max_texture_size_cache = max_texture_size; return _max_texture_size_cache; } } } static CrtcAssignment * crtc_assignment_new (GsdRRScreen *screen, GsdRROutputInfo **outputs, GError **error) { CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1); assignment->info = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free); if (real_assign_crtcs (screen, outputs, assignment, error)) { int width, height; int min_width, max_width, min_height, max_height; int max_texture_size; get_required_virtual_size (assignment, &width, &height); gsd_rr_screen_get_ranges ( screen, &min_width, &max_width, &min_height, &max_height); if (width < min_width || width > max_width || height < min_height || height > max_height) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_BOUNDS_ERROR, /* Translators: the "requested", "minimum", and * "maximum" words here are not keywords; please * translate them as usual. */ _("required virtual size does not fit available size: " "requested=(%d, %d), minimum=(%d, %d), maximum=(%d, %d)"), width, height, min_width, min_height, max_width, max_height); goto fail; } /* Hack: * This should either be solved by * (a) Allowing the compositor to veto RandR changes * (b) Fixing the compositor * * Nethier of these are feasible at this point, so just fix Unity. */ if (unity_running ()) { max_texture_size = get_max_texture_size (screen); if (max_texture_size > 0 && (width > max_texture_size || height > max_texture_size)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_BOUNDS_ERROR, _("Requested size (%d, %d) exceeds 3D hardware limit (%d, %d).\n" "You must either rearrange the displays so that they fit within a (%d, %d) square."), width, height, max_texture_size, max_texture_size, max_texture_size, max_texture_size); goto fail; } } assignment->screen = screen; return assignment; } fail: crtc_assignment_free (assignment); return NULL; } static gboolean crtc_assignment_apply (CrtcAssignment *assign, guint32 timestamp, GError **error) { GsdRRCrtc **all_crtcs = gsd_rr_screen_list_crtcs (assign->screen); int width, height; int i; int min_width, max_width, min_height, max_height; int width_mm, height_mm; gboolean success = TRUE; /* Compute size of the screen */ get_required_virtual_size (assign, &width, &height); gsd_rr_screen_get_ranges ( assign->screen, &min_width, &max_width, &min_height, &max_height); /* We should never get here if the dimensions don't fit in the virtual size, * but just in case we do, fix it up. */ width = MAX (min_width, width); width = MIN (max_width, width); height = MAX (min_height, height); height = MIN (max_height, height); /* FMQ: do we need to check the sizes instead of clamping them? */ /* Grab the server while we fiddle with the CRTCs and the screen, so that * apps that listen for RANDR notifications will only receive the final * status. */ gdk_x11_display_grab (gdk_screen_get_display (assign->screen->priv->gdk_screen)); /* Turn off all crtcs that are currently displaying outside the new screen, * or are not used in the new setup */ for (i = 0; all_crtcs[i] != NULL; ++i) { GsdRRCrtc *crtc = all_crtcs[i]; GsdRRMode *mode = gsd_rr_crtc_get_current_mode (crtc); int x, y; if (mode) { int w, h; gsd_rr_crtc_get_position (crtc, &x, &y); w = gsd_rr_mode_get_width (mode); h = gsd_rr_mode_get_height (mode); if (crtc_is_rotated (crtc)) { int tmp = h; h = w; w = tmp; } if (x + w > width || y + h > height || !g_hash_table_lookup (assign->info, crtc)) { if (!gsd_rr_crtc_set_config_with_time (crtc, timestamp, 0, 0, NULL, GSD_RR_ROTATION_0, NULL, 0, error)) { success = FALSE; break; } } } } /* The 'physical size' of an X screen is meaningless if that screen * can consist of many monitors. So just pick a size that make the * dpi 96. * * Firefox and Evince apparently believe what X tells them. */ width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5; height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5; if (success) { ConfigureCrtcState state; gsd_rr_screen_set_size (assign->screen, width, height, width_mm, height_mm); state.timestamp = timestamp; state.has_error = FALSE; state.error = error; g_hash_table_foreach (assign->info, configure_crtc, &state); success = !state.has_error; } gsd_rr_screen_set_primary_output (assign->screen, assign->primary); gdk_x11_display_ungrab (gdk_screen_get_display (assign->screen->priv->gdk_screen)); return success; } unity-settings-daemon/gnome-settings-daemon/gsd-rr-config.h0000664000000000000000000001446215172222611021241 0ustar /* gnome-rr-config.h * -*- c-basic-offset: 4 -*- * * Copyright 2007, 2008, Red Hat, Inc. * Copyright 2010 Giovanni Campagna * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Author: Soren Sandmann */ #ifndef GSD_RR_CONFIG_H #define GSD_RR_CONFIG_H #include #include #include "gsd-rr.h" typedef struct _GsdRROutputInfo GsdRROutputInfo; typedef struct _GsdRROutputInfoClass GsdRROutputInfoClass; typedef struct _GsdRROutputInfoPrivate GsdRROutputInfoPrivate; struct _GsdRROutputInfo { GObject parent; /*< private >*/ GsdRROutputInfoPrivate *priv; }; struct _GsdRROutputInfoClass { GObjectClass parent_class; }; #define GSD_TYPE_RR_OUTPUT_INFO (gsd_rr_output_info_get_type()) #define GSD_RR_OUTPUT_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_RR_OUTPUT_INFO, GsdRROutputInfo)) #define GSD_IS_RR_OUTPUT_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_RR_OUTPUT_INFO)) #define GSD_RR_OUTPUT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_RR_OUTPUT_INFO, GsdRROutputInfoClass)) #define GSD_IS_RR_OUTPUT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_RR_OUTPUT_INFO)) #define GSD_RR_OUTPUT_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_RR_OUTPUT_INFO, GsdRROutputInfoClass)) GType gsd_rr_output_info_get_type (void); char *gsd_rr_output_info_get_name (GsdRROutputInfo *self); gboolean gsd_rr_output_info_is_active (GsdRROutputInfo *self); void gsd_rr_output_info_set_active (GsdRROutputInfo *self, gboolean active); void gsd_rr_output_info_get_geometry (GsdRROutputInfo *self, int *x, int *y, int *width, int *height); void gsd_rr_output_info_set_geometry (GsdRROutputInfo *self, int x, int y, int width, int height); int gsd_rr_output_info_get_refresh_rate (GsdRROutputInfo *self); void gsd_rr_output_info_set_refresh_rate (GsdRROutputInfo *self, int rate); GsdRRRotation gsd_rr_output_info_get_rotation (GsdRROutputInfo *self); void gsd_rr_output_info_set_rotation (GsdRROutputInfo *self, GsdRRRotation rotation); gboolean gsd_rr_output_info_is_connected (GsdRROutputInfo *self); void gsd_rr_output_info_get_vendor (GsdRROutputInfo *self, gchar* vendor); guint gsd_rr_output_info_get_product (GsdRROutputInfo *self); guint gsd_rr_output_info_get_serial (GsdRROutputInfo *self); double gsd_rr_output_info_get_aspect_ratio (GsdRROutputInfo *self); char *gsd_rr_output_info_get_display_name (GsdRROutputInfo *self); gboolean gsd_rr_output_info_get_primary (GsdRROutputInfo *self); void gsd_rr_output_info_set_primary (GsdRROutputInfo *self, gboolean primary); int gsd_rr_output_info_get_preferred_width (GsdRROutputInfo *self); int gsd_rr_output_info_get_preferred_height (GsdRROutputInfo *self); typedef struct _GsdRRConfig GsdRRConfig; typedef struct _GsdRRConfigClass GsdRRConfigClass; typedef struct _GsdRRConfigPrivate GsdRRConfigPrivate; struct _GsdRRConfig { GObject parent; /*< private >*/ GsdRRConfigPrivate *priv; }; struct _GsdRRConfigClass { GObjectClass parent_class; }; #define GSD_TYPE_RR_CONFIG (gsd_rr_config_get_type()) #define GSD_RR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_RR_CONFIG, GsdRRConfig)) #define GSD_IS_RR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_RR_CONFIG)) #define GSD_RR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_RR_CONFIG, GsdRRConfigClass)) #define GSD_IS_RR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_RR_CONFIG)) #define GSD_RR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_RR_CONFIG, GsdRRConfigClass)) GType gsd_rr_config_get_type (void); GsdRRConfig *gsd_rr_config_new_current (GsdRRScreen *screen, GError **error); GsdRRConfig *gsd_rr_config_new_stored (GsdRRScreen *screen, GError **error); gboolean gsd_rr_config_load_current (GsdRRConfig *self, GError **error); gboolean gsd_rr_config_load_filename (GsdRRConfig *self, const gchar *filename, GError **error); gboolean gsd_rr_config_match (GsdRRConfig *config1, GsdRRConfig *config2); gboolean gsd_rr_config_equal (GsdRRConfig *config1, GsdRRConfig *config2); gboolean gsd_rr_config_save (GsdRRConfig *configuration, GError **error); void gsd_rr_config_sanitize (GsdRRConfig *configuration); gboolean gsd_rr_config_ensure_primary (GsdRRConfig *configuration); gboolean gsd_rr_config_apply_with_time (GsdRRConfig *configuration, GsdRRScreen *screen, guint32 timestamp, GError **error); gboolean gsd_rr_config_apply_from_filename_with_time (GsdRRScreen *screen, const char *filename, guint32 timestamp, GError **error); gboolean gsd_rr_config_applicable (GsdRRConfig *configuration, GsdRRScreen *screen, GError **error); gboolean gsd_rr_config_get_clone (GsdRRConfig *configuration); void gsd_rr_config_set_clone (GsdRRConfig *configuration, gboolean clone); GsdRROutputInfo **gsd_rr_config_get_outputs (GsdRRConfig *configuration); char *gsd_rr_config_get_backup_filename (void); char *gsd_rr_config_get_intended_filename (void); #endif unity-settings-daemon/gnome-settings-daemon/gsd-rr-output-info.c0000664000000000000000000001417715172222611022263 0ustar /* gnome-rr-output-info.c * -*- c-basic-offset: 4 -*- * * Copyright 2010 Giovanni Campagna * * This file is part of the Gnome Desktop Library. * * The Gnome Desktop Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Desktop Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include "gsd-rr-config.h" #include "edid.h" #include "gsd-rr-private.h" G_DEFINE_TYPE (GsdRROutputInfo, gsd_rr_output_info, G_TYPE_OBJECT) static void gsd_rr_output_info_init (GsdRROutputInfo *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GSD_TYPE_RR_OUTPUT_INFO, GsdRROutputInfoPrivate); self->priv->name = NULL; self->priv->on = FALSE; self->priv->display_name = NULL; } static void gsd_rr_output_info_finalize (GObject *gobject) { GsdRROutputInfo *self = GSD_RR_OUTPUT_INFO (gobject); g_free (self->priv->name); g_free (self->priv->display_name); G_OBJECT_CLASS (gsd_rr_output_info_parent_class)->finalize (gobject); } static void gsd_rr_output_info_class_init (GsdRROutputInfoClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GsdRROutputInfoPrivate)); gobject_class->finalize = gsd_rr_output_info_finalize; } /** * gsd_rr_output_info_get_name: * * Returns: (transfer none): the output name */ char *gsd_rr_output_info_get_name (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), NULL); return self->priv->name; } /** * gsd_rr_output_info_is_active: * * Returns: whether there is a CRTC assigned to this output (i.e. a signal is being sent to it) */ gboolean gsd_rr_output_info_is_active (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), FALSE); return self->priv->on; } void gsd_rr_output_info_set_active (GsdRROutputInfo *self, gboolean active) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); self->priv->on = active; } /** * gsd_rr_output_info_get_geometry: * @self: a #GsdRROutputInfo * @x: (out) (allow-none): * @y: (out) (allow-none): * @width: (out) (allow-none): * @height: (out) (allow-none): */ void gsd_rr_output_info_get_geometry (GsdRROutputInfo *self, int *x, int *y, int *width, int *height) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); if (x) *x = self->priv->x; if (y) *y = self->priv->y; if (width) *width = self->priv->width; if (height) *height = self->priv->height; } void gsd_rr_output_info_set_geometry (GsdRROutputInfo *self, int x, int y, int width, int height) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); self->priv->x = x; self->priv->y = y; self->priv->width = width; self->priv->height = height; } int gsd_rr_output_info_get_refresh_rate (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), 0); return self->priv->rate; } void gsd_rr_output_info_set_refresh_rate (GsdRROutputInfo *self, int rate) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); self->priv->rate = rate; } GsdRRRotation gsd_rr_output_info_get_rotation (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), GSD_RR_ROTATION_0); return self->priv->rotation; } void gsd_rr_output_info_set_rotation (GsdRROutputInfo *self, GsdRRRotation rotation) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); self->priv->rotation = rotation; } /** * gsd_rr_output_info_is_connected: * * Returns: whether the output is physically connected to a monitor */ gboolean gsd_rr_output_info_is_connected (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), FALSE); return self->priv->connected; } /** * gsd_rr_output_info_get_vendor: * @self: a #GsdRROutputInfo * @vendor: (out caller-allocates) (array fixed-size=4): */ void gsd_rr_output_info_get_vendor (GsdRROutputInfo *self, gchar* vendor) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); g_return_if_fail (vendor != NULL); vendor[0] = self->priv->vendor[0]; vendor[1] = self->priv->vendor[1]; vendor[2] = self->priv->vendor[2]; vendor[3] = self->priv->vendor[3]; } guint gsd_rr_output_info_get_product (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), 0); return self->priv->product; } guint gsd_rr_output_info_get_serial (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), 0); return self->priv->serial; } double gsd_rr_output_info_get_aspect_ratio (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), 0); return self->priv->aspect; } /** * gsd_rr_output_info_get_display_name: * * Returns: (transfer none): the display name of this output */ char *gsd_rr_output_info_get_display_name (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), NULL); return self->priv->display_name; } gboolean gsd_rr_output_info_get_primary (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), FALSE); return self->priv->primary; } void gsd_rr_output_info_set_primary (GsdRROutputInfo *self, gboolean primary) { g_return_if_fail (GSD_IS_RR_OUTPUT_INFO (self)); self->priv->primary = primary; } int gsd_rr_output_info_get_preferred_width (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), 0); return self->priv->pref_width; } int gsd_rr_output_info_get_preferred_height (GsdRROutputInfo *self) { g_return_val_if_fail (GSD_IS_RR_OUTPUT_INFO (self), 0); return self->priv->pref_height; } unity-settings-daemon/gnome-settings-daemon/gsd-rr-private.h0000664000000000000000000000260415172222611021441 0ustar #ifndef GSD_RR_PRIVATE_H #define GSD_RR_PRIVATE_H #include #include typedef struct ScreenInfo ScreenInfo; struct ScreenInfo { int min_width; int max_width; int min_height; int max_height; XRRScreenResources *resources; GsdRROutput ** outputs; GsdRRCrtc ** crtcs; GsdRRMode ** modes; GsdRRScreen * screen; GsdRRMode ** clone_modes; RROutput primary; }; struct GsdRRScreenPrivate { GdkScreen * gdk_screen; GdkWindow * gdk_root; Display * xdisplay; Screen * xscreen; Window xroot; ScreenInfo * info; int randr_event_base; int rr_major_version; int rr_minor_version; Atom connector_type_atom; gboolean dpms_capable; }; struct _GsdRROutputInfoPrivate { char * name; gboolean on; int width; int height; int rate; int x; int y; GsdRRRotation rotation; gboolean connected; gchar vendor[4]; guint product; guint serial; double aspect; int pref_width; int pref_height; char * display_name; gboolean primary; }; struct _GsdRRConfigPrivate { gboolean clone; GsdRRScreen *screen; GsdRROutputInfo **outputs; }; gboolean _gsd_rr_output_name_is_laptop (const char *name); #endif unity-settings-daemon/gnome-settings-daemon/gsd-rr.c0000664000000000000000000020434415172222611017771 0ustar /* gnome-rr.c * * Copyright 2007, 2008, Red Hat, Inc. * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Author: Soren Sandmann */ #include #include #include #include #include #include #include #include #include #undef GNOME_DISABLE_DEPRECATED #include "gsd-rr.h" #include "gsd-rr-config.h" #include "edid.h" #include "gsd-rr-private.h" #define DISPLAY(o) ((o)->info->screen->priv->xdisplay) #define SERVERS_RANDR_IS_AT_LEAST_1_3(priv) (priv->rr_major_version > 1 || (priv->rr_major_version == 1 && priv->rr_minor_version >= 3)) enum { SCREEN_PROP_0, SCREEN_PROP_GDK_SCREEN, SCREEN_PROP_LAST, }; enum { SCREEN_CHANGED, SCREEN_OUTPUT_CONNECTED, SCREEN_OUTPUT_DISCONNECTED, SCREEN_SIGNAL_LAST, }; gint screen_signals[SCREEN_SIGNAL_LAST]; struct GsdRROutput { ScreenInfo * info; RROutput id; char * name; char * display_name; GsdRRCrtc * current_crtc; gboolean connected; gulong width_mm; gulong height_mm; GsdRRCrtc ** possible_crtcs; GsdRROutput ** clones; GsdRRMode ** modes; int n_preferred; guint8 * edid_data; gsize edid_size; char * connector_type; gint backlight_min; gint backlight_max; }; struct GsdRROutputWrap { RROutput id; }; struct GsdRRCrtc { ScreenInfo * info; RRCrtc id; GsdRRMode * current_mode; GsdRROutput ** current_outputs; GsdRROutput ** possible_outputs; int x; int y; GsdRRRotation current_rotation; GsdRRRotation rotations; int gamma_size; }; struct GsdRRMode { ScreenInfo * info; RRMode id; char * name; int width; int height; int freq; /* in mHz */ }; /* GsdRRCrtc */ static GsdRRCrtc * crtc_new (ScreenInfo *info, RRCrtc id); static GsdRRCrtc * crtc_copy (const GsdRRCrtc *from); static void crtc_free (GsdRRCrtc *crtc); static gboolean crtc_initialize (GsdRRCrtc *crtc, XRRScreenResources *res, GError **error); /* GsdRROutput */ static GsdRROutput *output_new (ScreenInfo *info, RROutput id); static gboolean output_initialize (GsdRROutput *output, XRRScreenResources *res, GError **error); static gboolean output_initialize_clones (GsdRROutput *output, XRRScreenResources *res, GError **error); static GsdRROutput *output_copy (const GsdRROutput *from); static void output_free (GsdRROutput *output); /* GsdRRMode */ static GsdRRMode * mode_new (ScreenInfo *info, RRMode id); static void mode_initialize (GsdRRMode *mode, XRRModeInfo *info); static GsdRRMode * mode_copy (const GsdRRMode *from); static void mode_free (GsdRRMode *mode); static void gsd_rr_screen_finalize (GObject*); static void gsd_rr_screen_set_property (GObject*, guint, const GValue*, GParamSpec*); static void gsd_rr_screen_get_property (GObject*, guint, GValue*, GParamSpec*); static gboolean gsd_rr_screen_initable_init (GInitable*, GCancellable*, GError**); static void gsd_rr_screen_initable_iface_init (GInitableIface *iface); G_DEFINE_TYPE_WITH_CODE (GsdRRScreen, gsd_rr_screen, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gsd_rr_screen_initable_iface_init)) G_DEFINE_BOXED_TYPE (GsdRRCrtc, gsd_rr_crtc, crtc_copy, crtc_free) G_DEFINE_BOXED_TYPE (GsdRROutput, gsd_rr_output, output_copy, output_free) G_DEFINE_BOXED_TYPE (GsdRRMode, gsd_rr_mode, mode_copy, mode_free) /* Errors */ /** * gsd_rr_error_quark: * * Returns the #GQuark that will be used for #GError values returned by the * GsdRR API. * * Return value: a #GQuark used to identify errors coming from the GsdRR API. */ GQuark gsd_rr_error_quark (void) { return g_quark_from_static_string ("gsd-rr-error-quark"); } /* Screen */ static GsdRROutput * gsd_rr_output_by_id (ScreenInfo *info, RROutput id) { GsdRROutput **output; g_assert (info != NULL); for (output = info->outputs; *output; ++output) { if ((*output)->id == id) return *output; } return NULL; } static GsdRRCrtc * crtc_by_id (ScreenInfo *info, RRCrtc id) { GsdRRCrtc **crtc; if (!info) return NULL; for (crtc = info->crtcs; *crtc; ++crtc) { if ((*crtc)->id == id) return *crtc; } return NULL; } static GsdRRMode * mode_by_id (ScreenInfo *info, RRMode id) { GsdRRMode **mode; g_assert (info != NULL); for (mode = info->modes; *mode; ++mode) { if ((*mode)->id == id) return *mode; } return NULL; } static void screen_info_free (ScreenInfo *info) { GsdRROutput **output; GsdRRCrtc **crtc; GsdRRMode **mode; g_assert (info != NULL); if (info->resources) { XRRFreeScreenResources (info->resources); info->resources = NULL; } if (info->outputs) { for (output = info->outputs; *output; ++output) output_free (*output); g_free (info->outputs); } if (info->crtcs) { for (crtc = info->crtcs; *crtc; ++crtc) crtc_free (*crtc); g_free (info->crtcs); } if (info->modes) { for (mode = info->modes; *mode; ++mode) mode_free (*mode); g_free (info->modes); } if (info->clone_modes) { /* The modes themselves were freed above */ g_free (info->clone_modes); } g_free (info); } static gboolean has_similar_mode (GsdRROutput *output, GsdRRMode *mode) { int i; GsdRRMode **modes = gsd_rr_output_list_modes (output); int width = gsd_rr_mode_get_width (mode); int height = gsd_rr_mode_get_height (mode); for (i = 0; modes[i] != NULL; ++i) { GsdRRMode *m = modes[i]; if (gsd_rr_mode_get_width (m) == width && gsd_rr_mode_get_height (m) == height) { return TRUE; } } return FALSE; } static void gather_clone_modes (ScreenInfo *info) { int i; GPtrArray *result = g_ptr_array_new (); for (i = 0; info->outputs[i] != NULL; ++i) { int j; GsdRROutput *output1, *output2; output1 = info->outputs[i]; if (!output1->connected) continue; for (j = 0; output1->modes[j] != NULL; ++j) { GsdRRMode *mode = output1->modes[j]; gboolean valid; int k; valid = TRUE; for (k = 0; info->outputs[k] != NULL; ++k) { output2 = info->outputs[k]; if (!output2->connected) continue; if (!has_similar_mode (output2, mode)) { valid = FALSE; break; } } if (valid) g_ptr_array_add (result, mode); } } g_ptr_array_add (result, NULL); info->clone_modes = (GsdRRMode **)g_ptr_array_free (result, FALSE); } static gboolean fill_screen_info_from_resources (ScreenInfo *info, XRRScreenResources *resources, GError **error) { int i; GPtrArray *a; GsdRRCrtc **crtc; GsdRROutput **output; info->resources = resources; /* We create all the structures before initializing them, so * that they can refer to each other. */ a = g_ptr_array_new (); for (i = 0; i < resources->ncrtc; ++i) { GsdRRCrtc *crtc = crtc_new (info, resources->crtcs[i]); g_ptr_array_add (a, crtc); } g_ptr_array_add (a, NULL); info->crtcs = (GsdRRCrtc **)g_ptr_array_free (a, FALSE); a = g_ptr_array_new (); for (i = 0; i < resources->nmode; ++i) { GsdRRMode *mode = mode_new (info, resources->modes[i].id); g_ptr_array_add (a, mode); } g_ptr_array_add (a, NULL); info->modes = (GsdRRMode **)g_ptr_array_free (a, FALSE); /* We create and partially initialize the outputs in one pass to make it * easier to filter out ones that don't have any valid modes or CRTCs */ a = g_ptr_array_new (); for (i = 0; i < resources->noutput; ++i) { GsdRROutput *output = output_new (info, resources->outputs[i]); if (!output_initialize (output, resources, error)) { output_free(output); g_ptr_array_foreach (a, (GFunc) output_free, NULL); g_ptr_array_free (a, FALSE); return FALSE; } if (!output->possible_crtcs[0] || !output->modes[0]) { output_free(output); continue; } g_ptr_array_add (a, output); } g_ptr_array_add (a, NULL); info->outputs = (GsdRROutput **)g_ptr_array_free (a, FALSE); /* Initialize everything else */ for (crtc = info->crtcs; *crtc; ++crtc) { if (!crtc_initialize (*crtc, resources, error)) return FALSE; } for (output = info->outputs; *output; ++output) { if (!output_initialize_clones (*output, resources, error)) return FALSE; } for (i = 0; i < resources->nmode; ++i) { GsdRRMode *mode = mode_by_id (info, resources->modes[i].id); mode_initialize (mode, &(resources->modes[i])); } gather_clone_modes (info); return TRUE; } static gboolean fill_out_screen_info (Display *xdisplay, Window xroot, ScreenInfo *info, gboolean needs_reprobe, GError **error) { XRRScreenResources *resources; GsdRRScreenPrivate *priv; g_assert (xdisplay != NULL); g_assert (info != NULL); priv = info->screen->priv; /* First update the screen resources */ if (needs_reprobe) resources = XRRGetScreenResources (xdisplay, xroot); else { /* XRRGetScreenResourcesCurrent is less expensive than * XRRGetScreenResources, however it is available only * in RandR 1.3 or higher */ if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv)) resources = XRRGetScreenResourcesCurrent (xdisplay, xroot); else resources = XRRGetScreenResources (xdisplay, xroot); } if (resources) { if (!fill_screen_info_from_resources (info, resources, error)) return FALSE; } else { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, /* Translators: a CRTC is a CRT Controller (this is X terminology). */ _("could not get the screen resources (CRTCs, outputs, modes)")); return FALSE; } /* Then update the screen size range. We do this after XRRGetScreenResources() so that * the X server will already have an updated view of the outputs. */ if (needs_reprobe) { gboolean success; gdk_error_trap_push (); success = XRRGetScreenSizeRange (xdisplay, xroot, &(info->min_width), &(info->min_height), &(info->max_width), &(info->max_height)); gdk_flush (); if (gdk_error_trap_pop ()) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, _("unhandled X error while getting the range of screen sizes")); return FALSE; } if (!success) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, _("could not get the range of screen sizes")); return FALSE; } } else { gsd_rr_screen_get_ranges (info->screen, &(info->min_width), &(info->max_width), &(info->min_height), &(info->max_height)); } info->primary = None; if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv)) { gdk_error_trap_push (); info->primary = XRRGetOutputPrimary (xdisplay, xroot); gdk_error_trap_pop_ignored (); } /* can the screen do DPMS? */ gdk_error_trap_push (); priv->dpms_capable = DPMSCapable (priv->xdisplay); gdk_error_trap_pop_ignored (); return TRUE; } static ScreenInfo * screen_info_new (GsdRRScreen *screen, gboolean needs_reprobe, GError **error) { ScreenInfo *info = g_new0 (ScreenInfo, 1); GsdRRScreenPrivate *priv; g_assert (screen != NULL); priv = screen->priv; info->outputs = NULL; info->crtcs = NULL; info->modes = NULL; info->screen = screen; if (fill_out_screen_info (priv->xdisplay, priv->xroot, info, needs_reprobe, error)) { return info; } else { screen_info_free (info); return NULL; } } static GsdRROutput * find_output_by_id (GsdRROutput **haystack, guint32 id) { guint i; for (i = 0; haystack[i] != NULL; i++) { if (gsd_rr_output_get_id (haystack[i]) == id) return haystack[i]; } return NULL; } static void diff_outputs_and_emit_signals (ScreenInfo *old, ScreenInfo *new) { guint i; guint32 id_old, id_new; GsdRROutput *output_old; GsdRROutput *output_new; /* have any outputs been removed or disconnected */ for (i = 0; old->outputs[i] != NULL; i++) { id_old = gsd_rr_output_get_id (old->outputs[i]); output_new = find_output_by_id (new->outputs, id_old); if (output_new == NULL) { /* output removed (and disconnected) */ if (gsd_rr_output_is_connected (old->outputs[i])) { g_signal_emit (G_OBJECT (new->screen), screen_signals[SCREEN_OUTPUT_DISCONNECTED], 0, old->outputs[i]); } continue; } if (gsd_rr_output_is_connected (old->outputs[i]) && !gsd_rr_output_is_connected (output_new)) { /* output disconnected */ g_signal_emit (G_OBJECT (new->screen), screen_signals[SCREEN_OUTPUT_DISCONNECTED], 0, old->outputs[i]); } } /* have any outputs been created or connected */ for (i = 0; new->outputs[i] != NULL; i++) { id_new = gsd_rr_output_get_id (new->outputs[i]); output_old = find_output_by_id (old->outputs, id_new); if (output_old == NULL) { /* output created */ if (gsd_rr_output_is_connected (new->outputs[i])) { g_signal_emit (G_OBJECT (new->screen), screen_signals[SCREEN_OUTPUT_CONNECTED], 0, new->outputs[i]); } continue; } if (!gsd_rr_output_is_connected (output_old) && gsd_rr_output_is_connected (new->outputs[i])) { /* output connected */ g_signal_emit (G_OBJECT (new->screen), screen_signals[SCREEN_OUTPUT_CONNECTED], 0, new->outputs[i]); } } } static gboolean screen_update (GsdRRScreen *screen, gboolean force_callback, gboolean needs_reprobe, GError **error) { ScreenInfo *info; gboolean changed = FALSE; g_assert (screen != NULL); info = screen_info_new (screen, needs_reprobe, error); if (!info) return FALSE; if (info->resources->configTimestamp != screen->priv->info->resources->configTimestamp) changed = TRUE; /* work out if any outputs have changed connected state */ diff_outputs_and_emit_signals (screen->priv->info, info); screen_info_free (screen->priv->info); screen->priv->info = info; if (changed || force_callback) g_signal_emit (G_OBJECT (screen), screen_signals[SCREEN_CHANGED], 0); return changed; } static GdkFilterReturn screen_on_event (GdkXEvent *xevent, GdkEvent *event, gpointer data) { GsdRRScreen *screen = data; GsdRRScreenPrivate *priv = screen->priv; XEvent *e = xevent; int event_num; if (!e) return GDK_FILTER_CONTINUE; event_num = e->type - priv->randr_event_base; if (event_num == RRScreenChangeNotify) { /* We don't reprobe the hardware; we just fetch the X server's latest * state. The server already knows the new state of the outputs; that's * why it sent us an event! */ screen_update (screen, TRUE, FALSE, NULL); /* NULL-GError */ #if 0 /* Enable this code to get a dialog showing the RANDR timestamps, for debugging purposes */ { GtkWidget *dialog; XRRScreenChangeNotifyEvent *rr_event; static int dialog_num; rr_event = (XRRScreenChangeNotifyEvent *) e; dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "RRScreenChangeNotify timestamps (%d):\n" "event change: %u\n" "event config: %u\n" "event serial: %lu\n" "----------------------" "screen change: %u\n" "screen config: %u\n", dialog_num++, (guint32) rr_event->timestamp, (guint32) rr_event->config_timestamp, rr_event->serial, (guint32) priv->info->resources->timestamp, (guint32) priv->info->resources->configTimestamp); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_widget_show (dialog); } #endif } #if 0 /* WHY THIS CODE IS DISABLED: * * Note that in gsd_rr_screen_new(), we only select for * RRScreenChangeNotifyMask. We used to select for other values in * RR*NotifyMask, but we weren't really doing anything useful with those * events. We only care about "the screens changed in some way or another" * for now. * * If we ever run into a situtation that could benefit from processing more * detailed events, we can enable this code again. * * Note that the X server sends RRScreenChangeNotify in conjunction with the * more detailed events from RANDR 1.2 - see xserver/randr/randr.c:TellChanged(). */ else if (event_num == RRNotify) { /* Other RandR events */ XRRNotifyEvent *event = (XRRNotifyEvent *)e; /* Here we can distinguish between RRNotify events supported * since RandR 1.2 such as RRNotify_OutputProperty. For now, we * don't have anything special to do for particular subevent types, so * we leave this as an empty switch(). */ switch (event->subtype) { default: break; } /* No need to reprobe hardware here */ screen_update (screen, TRUE, FALSE, NULL); /* NULL-GError */ } #endif /* Pass the event on to GTK+ */ return GDK_FILTER_CONTINUE; } static gboolean gsd_rr_screen_initable_init (GInitable *initable, GCancellable *canc, GError **error) { GsdRRScreen *self = GSD_RR_SCREEN (initable); GsdRRScreenPrivate *priv = self->priv; Display *dpy = GDK_SCREEN_XDISPLAY (self->priv->gdk_screen); int event_base; int ignore; priv->connector_type_atom = XInternAtom (dpy, "ConnectorType", FALSE); if (XRRQueryExtension (dpy, &event_base, &ignore)) { priv->randr_event_base = event_base; XRRQueryVersion (dpy, &priv->rr_major_version, &priv->rr_minor_version); if (priv->rr_major_version < 1 || (priv->rr_major_version == 1 && priv->rr_minor_version < 2)) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_NO_RANDR_EXTENSION, "RANDR extension is too old (must be at least 1.2)"); return FALSE; } priv->info = screen_info_new (self, TRUE, error); if (!priv->info) { return FALSE; } XRRSelectInput (priv->xdisplay, priv->xroot, RRScreenChangeNotifyMask); gdk_x11_register_standard_event_type (gdk_screen_get_display (priv->gdk_screen), event_base, RRNotify + 1); gdk_window_add_filter (priv->gdk_root, screen_on_event, self); return TRUE; } else { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_NO_RANDR_EXTENSION, _("RANDR extension is not present")); return FALSE; } } void gsd_rr_screen_initable_iface_init (GInitableIface *iface) { iface->init = gsd_rr_screen_initable_init; } void gsd_rr_screen_finalize (GObject *gobject) { GsdRRScreen *screen = GSD_RR_SCREEN (gobject); gdk_window_remove_filter (screen->priv->gdk_root, screen_on_event, screen); if (screen->priv->info) screen_info_free (screen->priv->info); G_OBJECT_CLASS (gsd_rr_screen_parent_class)->finalize (gobject); } void gsd_rr_screen_set_property (GObject *gobject, guint property_id, const GValue *value, GParamSpec *property) { GsdRRScreen *self = GSD_RR_SCREEN (gobject); GsdRRScreenPrivate *priv = self->priv; switch (property_id) { case SCREEN_PROP_GDK_SCREEN: priv->gdk_screen = g_value_get_object (value); priv->gdk_root = gdk_screen_get_root_window (priv->gdk_screen); priv->xroot = gdk_x11_window_get_xid (priv->gdk_root); priv->xdisplay = GDK_SCREEN_XDISPLAY (priv->gdk_screen); priv->xscreen = gdk_x11_screen_get_xscreen (priv->gdk_screen); return; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property); return; } } void gsd_rr_screen_get_property (GObject *gobject, guint property_id, GValue *value, GParamSpec *property) { GsdRRScreen *self = GSD_RR_SCREEN (gobject); GsdRRScreenPrivate *priv = self->priv; switch (property_id) { case SCREEN_PROP_GDK_SCREEN: g_value_set_object (value, priv->gdk_screen); return; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property); return; } } void gsd_rr_screen_class_init (GsdRRScreenClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GsdRRScreenPrivate)); bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); gobject_class->set_property = gsd_rr_screen_set_property; gobject_class->get_property = gsd_rr_screen_get_property; gobject_class->finalize = gsd_rr_screen_finalize; g_object_class_install_property( gobject_class, SCREEN_PROP_GDK_SCREEN, g_param_spec_object ( "gdk-screen", "GDK Screen", "The GDK Screen represented by this GsdRRScreen", GDK_TYPE_SCREEN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS) ); screen_signals[SCREEN_CHANGED] = g_signal_new("changed", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GsdRRScreenClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * GsdRRScreen::output-connected: * @screen: the #GsdRRScreen that emitted the signal * @output: the #GsdRROutput that was connected * * This signal is emitted when a display device is connected to a * port, or a port is hotplugged with an active output. The latter * can happen if a laptop is docked, and the dock provides a new * active output. * * The @output value is not a #GObject. The returned @output value can * only assume to be valid during the emission of the signal (i.e. within * your signal handler only), as it may change later when the @screen * is modified due to an event from the X server, or due to another * place in the application modifying the @screen and the @output. * Therefore, deal with changes to the @output right in your signal * handler, instead of keeping the @output reference for an async or * idle function. **/ screen_signals[SCREEN_OUTPUT_CONNECTED] = g_signal_new("output-connected", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GsdRRScreenClass, output_connected), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * GsdRRScreen::output-disconnected: * @screen: the #GsdRRScreen that emitted the signal * @output: the #GsdRROutput that was disconnected * * This signal is emitted when a display device is disconnected from * a port, or a port output is hot-unplugged. The latter can happen * if a laptop is undocked, and the dock provided the output. * * The @output value is not a #GObject. The returned @output value can * only assume to be valid during the emission of the signal (i.e. within * your signal handler only), as it may change later when the @screen * is modified due to an event from the X server, or due to another * place in the application modifying the @screen and the @output. * Therefore, deal with changes to the @output right in your signal * handler, instead of keeping the @output reference for an async or * idle function. **/ screen_signals[SCREEN_OUTPUT_DISCONNECTED] = g_signal_new("output-disconnected", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GsdRRScreenClass, output_disconnected), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } void gsd_rr_screen_init (GsdRRScreen *self) { GsdRRScreenPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GSD_TYPE_RR_SCREEN, GsdRRScreenPrivate); self->priv = priv; priv->gdk_screen = NULL; priv->gdk_root = NULL; priv->xdisplay = NULL; priv->xroot = None; priv->xscreen = NULL; priv->info = NULL; priv->rr_major_version = 0; priv->rr_minor_version = 0; } /* Weak reference callback set in gsd_rr_screen_new(); we remove the GObject data from the GdkScreen. */ static void rr_screen_weak_notify_cb (gpointer data, GObject *where_the_object_was) { GdkScreen *screen = GDK_SCREEN (data); g_object_set_data (G_OBJECT (screen), "GsdRRScreen", NULL); } /** * gsd_rr_screen_new: * @screen: the #GdkScreen on which to operate * @error: will be set if XRandR is not supported * * Creates a unique #GsdRRScreen instance for the specified @screen. * * Returns: a unique #GsdRRScreen instance, specific to the @screen, or NULL * if this could not be created, for instance if the driver does not support * Xrandr 1.2. Each #GdkScreen thus has a single instance of #GsdRRScreen. */ GsdRRScreen * gsd_rr_screen_new (GdkScreen *screen, GError **error) { GsdRRScreen *rr_screen; g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); rr_screen = g_object_get_data (G_OBJECT (screen), "GsdRRScreen"); if (rr_screen) g_object_ref (rr_screen); else { rr_screen = g_initable_new (GSD_TYPE_RR_SCREEN, NULL, error, "gdk-screen", screen, NULL); if (rr_screen) { g_object_set_data (G_OBJECT (screen), "GsdRRScreen", rr_screen); g_object_weak_ref (G_OBJECT (rr_screen), rr_screen_weak_notify_cb, screen); } } return rr_screen; } void gsd_rr_screen_set_size (GsdRRScreen *screen, int width, int height, int mm_width, int mm_height) { g_return_if_fail (GSD_IS_RR_SCREEN (screen)); gdk_error_trap_push (); XRRSetScreenSize (screen->priv->xdisplay, screen->priv->xroot, width, height, mm_width, mm_height); gdk_error_trap_pop_ignored (); } /** * gsd_rr_screen_get_ranges: * @screen: a #GsdRRScreen * @min_width: (out): the minimum width * @max_width: (out): the maximum width * @min_height: (out): the minimum height * @max_height: (out): the maximum height * * Get the ranges of the screen */ void gsd_rr_screen_get_ranges (GsdRRScreen *screen, int *min_width, int *max_width, int *min_height, int *max_height) { GsdRRScreenPrivate *priv; g_return_if_fail (GSD_IS_RR_SCREEN (screen)); priv = screen->priv; if (min_width) *min_width = priv->info->min_width; if (max_width) *max_width = priv->info->max_width; if (min_height) *min_height = priv->info->min_height; if (max_height) *max_height = priv->info->max_height; } /** * gsd_rr_screen_get_timestamps: * @screen: a #GsdRRScreen * @change_timestamp_ret: (out): Location in which to store the timestamp at which the RANDR configuration was last changed * @config_timestamp_ret: (out): Location in which to store the timestamp at which the RANDR configuration was last obtained * * Queries the two timestamps that the X RANDR extension maintains. The X * server will prevent change requests for stale configurations, those whose * timestamp is not equal to that of the latest request for configuration. The * X server will also prevent change requests that have an older timestamp to * the latest change request. */ void gsd_rr_screen_get_timestamps (GsdRRScreen *screen, guint32 *change_timestamp_ret, guint32 *config_timestamp_ret) { GsdRRScreenPrivate *priv; g_return_if_fail (GSD_IS_RR_SCREEN (screen)); priv = screen->priv; if (change_timestamp_ret) *change_timestamp_ret = priv->info->resources->timestamp; if (config_timestamp_ret) *config_timestamp_ret = priv->info->resources->configTimestamp; } static gboolean force_timestamp_update (GsdRRScreen *screen) { GsdRRScreenPrivate *priv = screen->priv; GsdRRCrtc *crtc; XRRCrtcInfo *current_info; Status status; gboolean timestamp_updated; timestamp_updated = FALSE; crtc = priv->info->crtcs[0]; if (crtc == NULL) goto out; current_info = XRRGetCrtcInfo (priv->xdisplay, priv->info->resources, crtc->id); if (current_info == NULL) goto out; gdk_error_trap_push (); status = XRRSetCrtcConfig (priv->xdisplay, priv->info->resources, crtc->id, current_info->timestamp, current_info->x, current_info->y, current_info->mode, current_info->rotation, current_info->outputs, current_info->noutput); XRRFreeCrtcInfo (current_info); gdk_flush (); if (gdk_error_trap_pop ()) goto out; if (status == RRSetConfigSuccess) timestamp_updated = TRUE; out: return timestamp_updated; } /** * gsd_rr_screen_refresh: * @screen: a #GsdRRScreen * @error: location to store error, or %NULL * * Refreshes the screen configuration, and calls the screen's callback if it * exists and if the screen's configuration changed. * * Return value: TRUE if the screen's configuration changed; otherwise, the * function returns FALSE and a NULL error if the configuration didn't change, * or FALSE and a non-NULL error if there was an error while refreshing the * configuration. */ gboolean gsd_rr_screen_refresh (GsdRRScreen *screen, GError **error) { gboolean refreshed; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); gdk_x11_display_grab (gdk_screen_get_display (screen->priv->gdk_screen)); refreshed = screen_update (screen, FALSE, TRUE, error); force_timestamp_update (screen); /* this is to keep other clients from thinking that the X server re-detected things by itself - bgo#621046 */ gdk_x11_display_ungrab (gdk_screen_get_display (screen->priv->gdk_screen)); return refreshed; } /** * gsd_rr_screen_get_dpms_mode: * @mode: (out): The current #GsdRRDpmsMode of this screen **/ gboolean gsd_rr_screen_get_dpms_mode (GsdRRScreen *screen, GsdRRDpmsMode *mode, GError **error) { BOOL enabled = FALSE; CARD16 state; gboolean ret = FALSE; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (mode != NULL, FALSE); if (!screen->priv->dpms_capable) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_NO_DPMS_EXTENSION, "Display is not DPMS capable"); goto out; } if (!DPMSInfo (screen->priv->xdisplay, &state, &enabled)) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, "Unable to get DPMS state"); goto out; } /* DPMS not enabled is a valid mode */ if (!enabled) { *mode = GSD_RR_DPMS_DISABLED; ret = TRUE; goto out; } switch (state) { case DPMSModeOn: *mode = GSD_RR_DPMS_ON; break; case DPMSModeStandby: *mode = GSD_RR_DPMS_STANDBY; break; case DPMSModeSuspend: *mode = GSD_RR_DPMS_SUSPEND; break; case DPMSModeOff: *mode = GSD_RR_DPMS_OFF; break; default: g_assert_not_reached (); break; } ret = TRUE; out: return ret; } /** * gsd_rr_screen_clear_dpms_timeouts: **/ static gboolean gsd_rr_screen_clear_dpms_timeouts (GsdRRScreen *screen, GError **error) { gdk_error_trap_push (); /* DPMSSetTimeouts() return value is often a lie, so ignore it */ DPMSSetTimeouts (screen->priv->xdisplay, 0, 0, 0); if (gdk_error_trap_pop ()) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, "Could not set DPMS timeouts"); return FALSE; } return TRUE; } /** * gsd_rr_screen_set_dpms_mode: * * This method also disables the DPMS timeouts. **/ gboolean gsd_rr_screen_set_dpms_mode (GsdRRScreen *screen, GsdRRDpmsMode mode, GError **error) { CARD16 state = 0; gboolean ret; GsdRRDpmsMode current_mode; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* set, if the new mode is different */ ret = gsd_rr_screen_get_dpms_mode (screen, ¤t_mode, error); if (!ret) goto out; if (current_mode == mode) { ret = gsd_rr_screen_clear_dpms_timeouts (screen, error); goto out; } switch (mode) { case GSD_RR_DPMS_ON: state = DPMSModeOn; break; case GSD_RR_DPMS_STANDBY: state = DPMSModeStandby; break; case GSD_RR_DPMS_SUSPEND: state = DPMSModeSuspend; break; case GSD_RR_DPMS_OFF: state = DPMSModeOff; break; default: g_assert_not_reached (); break; } gdk_error_trap_push (); /* DPMSForceLevel() return value is often a lie, so ignore it */ DPMSForceLevel (screen->priv->xdisplay, state); XSync (screen->priv->xdisplay, False); if (gdk_error_trap_pop ()) { ret = FALSE; g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, "Could not change DPMS mode"); goto out; } ret = gsd_rr_screen_clear_dpms_timeouts (screen, error); if (!ret) goto out; out: return ret; } /** * gsd_rr_screen_list_modes: * * List available XRandR modes * * Returns: (array zero-terminated=1) (transfer none): */ GsdRRMode ** gsd_rr_screen_list_modes (GsdRRScreen *screen) { g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); return screen->priv->info->modes; } /** * gsd_rr_screen_list_clone_modes: * * List available XRandR clone modes * * Returns: (array zero-terminated=1) (transfer none): */ GsdRRMode ** gsd_rr_screen_list_clone_modes (GsdRRScreen *screen) { g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); return screen->priv->info->clone_modes; } /** * gsd_rr_screen_list_crtcs: * * List all CRTCs * * Returns: (array zero-terminated=1) (transfer none): */ GsdRRCrtc ** gsd_rr_screen_list_crtcs (GsdRRScreen *screen) { g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); return screen->priv->info->crtcs; } /** * gsd_rr_screen_list_outputs: * * List all outputs * * Returns: (array zero-terminated=1) (transfer none): */ GsdRROutput ** gsd_rr_screen_list_outputs (GsdRRScreen *screen) { g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); return screen->priv->info->outputs; } /** * gsd_rr_screen_get_crtc_by_id: * * Returns: (transfer none): the CRTC identified by @id */ GsdRRCrtc * gsd_rr_screen_get_crtc_by_id (GsdRRScreen *screen, guint32 id) { GsdRRCrtc **crtcs; int i; g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); crtcs = screen->priv->info->crtcs; for (i = 0; crtcs[i] != NULL; ++i) { if (crtcs[i]->id == id) return crtcs[i]; } return NULL; } /** * gsd_rr_screen_get_output_by_id: * * Returns: (transfer none): the output identified by @id */ GsdRROutput * gsd_rr_screen_get_output_by_id (GsdRRScreen *screen, guint32 id) { GsdRROutput **outputs; int i; g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); outputs = screen->priv->info->outputs; for (i = 0; outputs[i] != NULL; ++i) { if (outputs[i]->id == id) return outputs[i]; } return NULL; } /* GsdRROutput */ static GsdRROutput * output_new (ScreenInfo *info, RROutput id) { GsdRROutput *output = g_slice_new0 (GsdRROutput); output->id = id; output->info = info; return output; } static guint8 * get_property (Display *dpy, RROutput output, Atom atom, gsize *len) { unsigned char *prop; int actual_format; unsigned long nitems, bytes_after; Atom actual_type; guint8 *result; XRRGetOutputProperty (dpy, output, atom, 0, 100, False, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); if (actual_type == XA_INTEGER && actual_format == 8) { result = g_memdup (prop, nitems); if (len) *len = nitems; } else { result = NULL; } XFree (prop); return result; } static guint8 * read_edid_data (GsdRROutput *output, gsize *len) { Atom edid_atom; guint8 *result; edid_atom = XInternAtom (DISPLAY (output), "EDID", FALSE); result = get_property (DISPLAY (output), output->id, edid_atom, len); if (!result) { edid_atom = XInternAtom (DISPLAY (output), "EDID_DATA", FALSE); result = get_property (DISPLAY (output), output->id, edid_atom, len); } if (!result) { edid_atom = XInternAtom (DISPLAY (output), "XFree86_DDC_EDID1_RAWDATA", FALSE); result = get_property (DISPLAY (output), output->id, edid_atom, len); } if (result) { if (*len % 128 == 0) return result; else g_free (result); } return NULL; } static char * get_connector_type_string (GsdRROutput *output) { char *result; unsigned char *prop; int actual_format; unsigned long nitems, bytes_after; Atom actual_type; Atom connector_type; char *connector_type_str; result = NULL; if (XRRGetOutputProperty (DISPLAY (output), output->id, output->info->screen->priv->connector_type_atom, 0, 100, False, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop) != Success) return NULL; if (!(actual_type == XA_ATOM && actual_format == 32 && nitems == 1)) goto out; connector_type = *((Atom *) prop); connector_type_str = XGetAtomName (DISPLAY (output), connector_type); if (connector_type_str) { result = g_strdup (connector_type_str); /* so the caller can g_free() it */ XFree (connector_type_str); } out: XFree (prop); return result; } static void update_brightness_limits (GsdRROutput *output) { gint rc; Atom atom; XRRPropertyInfo *info; gdk_error_trap_push (); atom = XInternAtom (DISPLAY (output), "Backlight", FALSE); info = XRRQueryOutputProperty (DISPLAY (output), output->id, atom); rc = gdk_error_trap_pop (); if (rc != Success) { if (rc != BadName) g_warning ("could not get output property for %s, rc: %i", output->name, rc); goto out; } if (info == NULL) { g_warning ("could not get output property for %s", output->name); goto out; } if (!info->range || info->num_values != 2) { g_debug ("backlight %s was not range", output->name); goto out; } output->backlight_min = info->values[0]; output->backlight_max = info->values[1]; /* If the interface has more than 99 possible values, it's * likely that 0 turns the backlight off so we let 1 be * set in that case. */ if (output->backlight_max > 99 && output->backlight_min == 0) output->backlight_min = 1; out: if (info != NULL) { XFree (info); } } static gboolean output_initialize (GsdRROutput *output, XRRScreenResources *res, GError **error) { XRROutputInfo *info = XRRGetOutputInfo ( DISPLAY (output), res, output->id); GPtrArray *a; int i; #if 0 g_print ("Output %lx Timestamp: %u\n", output->id, (guint32)info->timestamp); #endif if (!info || !output->info) { /* FIXME: see the comment in crtc_initialize() */ /* Translators: here, an "output" is a video output */ g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, _("could not get information about output %d"), (int) output->id); return FALSE; } output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */ output->display_name = NULL; /* set first time the getter is used */ output->current_crtc = crtc_by_id (output->info, info->crtc); output->width_mm = info->mm_width; output->height_mm = info->mm_height; output->connected = (info->connection == RR_Connected); output->connector_type = get_connector_type_string (output); /* Possible crtcs */ a = g_ptr_array_new (); for (i = 0; i < info->ncrtc; ++i) { GsdRRCrtc *crtc = crtc_by_id (output->info, info->crtcs[i]); if (crtc) g_ptr_array_add (a, crtc); } g_ptr_array_add (a, NULL); output->possible_crtcs = (GsdRRCrtc **)g_ptr_array_free (a, FALSE); /* Modes */ a = g_ptr_array_new (); for (i = 0; i < info->nmode; ++i) { GsdRRMode *mode = mode_by_id (output->info, info->modes[i]); if (mode) g_ptr_array_add (a, mode); } g_ptr_array_add (a, NULL); output->modes = (GsdRRMode **)g_ptr_array_free (a, FALSE); output->n_preferred = info->npreferred; /* Edid data */ output->edid_data = read_edid_data (output, &output->edid_size); /* brightness data */ if (output->connected) update_brightness_limits (output); XRRFreeOutputInfo (info); return TRUE; } static gboolean output_initialize_clones (GsdRROutput *output, XRRScreenResources *res, GError **error) { XRROutputInfo *info = XRRGetOutputInfo (DISPLAY (output), res, output->id); GPtrArray *a; int i; if (!info || !output->info) { /* FIXME: see the comment in crtc_initialize() */ /* Translators: here, an "output" is a video output */ g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, _("could not get information about output %d"), (int) output->id); return FALSE; } a = g_ptr_array_new (); for (i = 0; i < info->nclone; ++i) { GsdRROutput *gsd_rr_output = gsd_rr_output_by_id (output->info, info->clones[i]); if (gsd_rr_output) g_ptr_array_add (a, gsd_rr_output); } g_ptr_array_add (a, NULL); output->clones = (GsdRROutput **)g_ptr_array_free (a, FALSE); XRRFreeOutputInfo (info); return TRUE; } static GsdRROutput* output_copy (const GsdRROutput *from) { GPtrArray *array; GsdRRCrtc **p_crtc; GsdRROutput **p_output; GsdRRMode **p_mode; GsdRROutput *output = g_slice_new0 (GsdRROutput); output->id = from->id; output->info = from->info; output->name = g_strdup (from->name); output->current_crtc = from->current_crtc; output->width_mm = from->width_mm; output->height_mm = from->height_mm; output->connected = from->connected; output->n_preferred = from->n_preferred; output->connector_type = g_strdup (from->connector_type); output->backlight_min = -1; output->backlight_max = -1; array = g_ptr_array_new (); for (p_crtc = from->possible_crtcs; *p_crtc != NULL; p_crtc++) { g_ptr_array_add (array, *p_crtc); } output->possible_crtcs = (GsdRRCrtc**) g_ptr_array_free (array, FALSE); array = g_ptr_array_new (); for (p_output = from->clones; *p_output != NULL; p_output++) { g_ptr_array_add (array, *p_output); } output->clones = (GsdRROutput**) g_ptr_array_free (array, FALSE); array = g_ptr_array_new (); for (p_mode = from->modes; *p_mode != NULL; p_mode++) { g_ptr_array_add (array, *p_mode); } output->modes = (GsdRRMode**) g_ptr_array_free (array, FALSE); output->edid_size = from->edid_size; output->edid_data = g_memdup (from->edid_data, from->edid_size); return output; } static void output_free (GsdRROutput *output) { g_free (output->clones); g_free (output->modes); g_free (output->possible_crtcs); g_free (output->edid_data); g_free (output->name); g_free (output->display_name); g_free (output->connector_type); g_slice_free (GsdRROutput, output); } guint32 gsd_rr_output_get_id (GsdRROutput *output) { g_assert(output != NULL); return output->id; } const guint8 * gsd_rr_output_get_edid_data (GsdRROutput *output, gsize *size) { g_return_val_if_fail (output != NULL, NULL); if (size) *size = output->edid_size; return output->edid_data; } /** * gsd_rr_output_get_ids_from_edid: * @output: a #GsdRROutput * @vendor: (out) (allow-none): * @product: (out) (allow-none): * @serial: (out) (allow-none): */ gboolean gsd_rr_output_get_ids_from_edid (GsdRROutput *output, char **vendor, int *product, int *serial) { MonitorInfo *info; g_return_val_if_fail (output != NULL, FALSE); if (!output->edid_data) return FALSE; info = decode_edid (output->edid_data); if (!info) return FALSE; if (vendor) *vendor = g_memdup (info->manufacturer_code, 4); if (product) *product = info->product_code; if (serial) *serial = info->serial_number; g_free (info); return TRUE; } static void ensure_display_name (GsdRROutput *output) { if (output->display_name != NULL) return; if (gsd_rr_output_is_laptop (output)) output->display_name = g_strdup (_("Built-in Display")); if (output->display_name == NULL && output->edid_data != NULL) { MonitorInfo *info; info = decode_edid (output->edid_data); if (info != NULL) output->display_name = make_display_name (info); g_free (info); } if (output->display_name == NULL) { char *inches; inches = make_display_size_string (output->width_mm, output->height_mm); if (inches != NULL) { /* Translators: %s is the size of the monitor in inches */ output->display_name = g_strdup_printf (_("%s Display"), inches); } g_free (inches); } /* last chance on the stairway */ if (output->display_name == NULL) { output->display_name = g_strdup (_("Unknown Display")); } } const char * gsd_rr_output_get_display_name (GsdRROutput *output) { g_return_val_if_fail (output != NULL, NULL); ensure_display_name (output); return output->display_name; } /** * gsd_rr_output_get_backlight_min: * * Returns: The mimimum backlight value, or -1 if not supported */ gint gsd_rr_output_get_backlight_min (GsdRROutput *output) { g_return_val_if_fail (output != NULL, -1); return output->backlight_min; } /** * gsd_rr_output_get_backlight_max: * * Returns: The maximum backlight value, or -1 if not supported */ gint gsd_rr_output_get_backlight_max (GsdRROutput *output) { g_return_val_if_fail (output != NULL, -1); return output->backlight_max; } /** * gsd_rr_output_get_backlight: * * Returns: The currently set backlight brightness */ gint gsd_rr_output_get_backlight (GsdRROutput *output, GError **error) { guint now = -1; unsigned long nitems; unsigned long bytes_after; guint *prop; Atom atom; Atom actual_type; int actual_format; gint retval; g_return_val_if_fail (output != NULL, -1); gdk_error_trap_push (); atom = XInternAtom (DISPLAY (output), "Backlight", FALSE); retval = XRRGetOutputProperty (DISPLAY (output), output->id, atom, 0, 4, False, False, None, &actual_type, &actual_format, &nitems, &bytes_after, ((unsigned char **)&prop)); gdk_flush (); if (gdk_error_trap_pop ()) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, "unhandled X error while getting the range of backlight values"); goto out; } if (retval != Success) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, "could not get the range of backlight values"); goto out; } if (actual_type == XA_INTEGER && nitems == 1 && actual_format == 32) { memcpy (&now, prop, sizeof (guint)); } else { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, "failed to get correct property type, got %lu,%i", nitems, actual_format); } out: XFree (prop); return now; } /** * gsd_rr_output_set_backlight: * @value: the absolute value which is min >= this <= max * * Returns: %TRUE for success */ gboolean gsd_rr_output_set_backlight (GsdRROutput *output, gint value, GError **error) { gboolean ret = FALSE; Atom atom; g_return_val_if_fail (output != NULL, FALSE); /* check this is sane */ if (value < output->backlight_min || value > output->backlight_max) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_BOUNDS_ERROR, "out of brightness range: %i, has to be %i -> %i", value, output->backlight_max, output->backlight_min); goto out; } /* don't abort on error */ gdk_error_trap_push (); atom = XInternAtom (DISPLAY (output), "Backlight", FALSE); XRRChangeOutputProperty (DISPLAY (output), output->id, atom, XA_INTEGER, 32, PropModeReplace, (unsigned char *) &value, 1); if (gdk_error_trap_pop ()) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, "unhandled X error while setting the backlight values"); goto out; } /* we assume this succeeded as there's no return value */ ret = TRUE; out: return ret; } /** * gsd_rr_screen_get_output_by_name: * * Returns: (transfer none): the output identified by @name */ GsdRROutput * gsd_rr_screen_get_output_by_name (GsdRRScreen *screen, const char *name) { int i; g_return_val_if_fail (GSD_IS_RR_SCREEN (screen), NULL); g_return_val_if_fail (screen->priv->info != NULL, NULL); for (i = 0; screen->priv->info->outputs[i] != NULL; ++i) { GsdRROutput *output = screen->priv->info->outputs[i]; if (strcmp (output->name, name) == 0) return output; } return NULL; } GsdRRCrtc * gsd_rr_output_get_crtc (GsdRROutput *output) { g_return_val_if_fail (output != NULL, NULL); return output->current_crtc; } /* Returns NULL if the ConnectorType property is not available */ const char * gsd_rr_output_get_connector_type (GsdRROutput *output) { g_return_val_if_fail (output != NULL, NULL); return output->connector_type; } gboolean _gsd_rr_output_name_is_laptop (const char *name) { if (!name) return FALSE; if (strstr (name, "lvds") || /* Most drivers use an "LVDS" prefix... */ strstr (name, "LVDS") || strstr (name, "Lvds") || strstr (name, "LCD") || /* ... but fglrx uses "LCD" in some versions. Shoot me now, kthxbye. */ strstr (name, "eDP") || /* eDP is for internal laptop panel connections */ strstr (name, "default")) /* Finally, NVidia and all others that don't bother to do RANDR properly */ return TRUE; return FALSE; } gboolean gsd_rr_output_is_laptop (GsdRROutput *output) { g_return_val_if_fail (output != NULL, FALSE); if (!output->connected) return FALSE; /* The ConnectorType property is present in RANDR 1.3 and greater */ if (g_strcmp0 (output->connector_type, GSD_RR_CONNECTOR_TYPE_PANEL) == 0) return TRUE; /* Older versions of RANDR - this is a best guess, as @#$% RANDR doesn't have standard output names, * so drivers can use whatever they like. */ if (_gsd_rr_output_name_is_laptop (output->name)) return TRUE; return FALSE; } GsdRRMode * gsd_rr_output_get_current_mode (GsdRROutput *output) { GsdRRCrtc *crtc; g_return_val_if_fail (output != NULL, NULL); if ((crtc = gsd_rr_output_get_crtc (output))) return gsd_rr_crtc_get_current_mode (crtc); return NULL; } /** * gsd_rr_output_get_position: * @output: a #GsdRROutput * @x: (out) (allow-none): * @y: (out) (allow-none): */ void gsd_rr_output_get_position (GsdRROutput *output, int *x, int *y) { GsdRRCrtc *crtc; g_return_if_fail (output != NULL); if ((crtc = gsd_rr_output_get_crtc (output))) gsd_rr_crtc_get_position (crtc, x, y); } const char * gsd_rr_output_get_name (GsdRROutput *output) { g_assert (output != NULL); return output->name; } int gsd_rr_output_get_width_mm (GsdRROutput *output) { g_assert (output != NULL); return output->width_mm; } int gsd_rr_output_get_height_mm (GsdRROutput *output) { g_assert (output != NULL); return output->height_mm; } GsdRRMode * gsd_rr_output_get_preferred_mode (GsdRROutput *output) { g_return_val_if_fail (output != NULL, NULL); if (output->n_preferred) return output->modes[0]; return NULL; } GsdRRMode ** gsd_rr_output_list_modes (GsdRROutput *output) { g_return_val_if_fail (output != NULL, NULL); return output->modes; } gboolean gsd_rr_output_is_connected (GsdRROutput *output) { g_return_val_if_fail (output != NULL, FALSE); return output->connected; } gboolean gsd_rr_output_supports_mode (GsdRROutput *output, GsdRRMode *mode) { int i; g_return_val_if_fail (output != NULL, FALSE); g_return_val_if_fail (mode != NULL, FALSE); for (i = 0; output->modes[i] != NULL; ++i) { if (output->modes[i] == mode) return TRUE; } return FALSE; } gboolean gsd_rr_output_can_clone (GsdRROutput *output, GsdRROutput *clone) { int i; g_return_val_if_fail (output != NULL, FALSE); g_return_val_if_fail (clone != NULL, FALSE); for (i = 0; output->clones[i] != NULL; ++i) { if (output->clones[i] == clone) return TRUE; } return FALSE; } gboolean gsd_rr_output_get_is_primary (GsdRROutput *output) { return output->info->primary == output->id; } void gsd_rr_screen_set_primary_output (GsdRRScreen *screen, GsdRROutput *output) { GsdRRScreenPrivate *priv; RROutput id; g_return_if_fail (GSD_IS_RR_SCREEN (screen)); priv = screen->priv; if (output) id = output->id; else id = None; if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv)) { gdk_error_trap_push (); XRRSetOutputPrimary (priv->xdisplay, priv->xroot, id); gdk_error_trap_pop_ignored (); } } /* GsdRRCrtc */ typedef struct { Rotation xrot; GsdRRRotation rot; } RotationMap; static const RotationMap rotation_map[] = { { RR_Rotate_0, GSD_RR_ROTATION_0 }, { RR_Rotate_90, GSD_RR_ROTATION_90 }, { RR_Rotate_180, GSD_RR_ROTATION_180 }, { RR_Rotate_270, GSD_RR_ROTATION_270 }, { RR_Reflect_X, GSD_RR_REFLECT_X }, { RR_Reflect_Y, GSD_RR_REFLECT_Y }, }; static GsdRRRotation gsd_rr_rotation_from_xrotation (Rotation r) { int i; GsdRRRotation result = 0; for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i) { if (r & rotation_map[i].xrot) result |= rotation_map[i].rot; } return result; } static Rotation xrotation_from_rotation (GsdRRRotation r) { int i; Rotation result = 0; for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i) { if (r & rotation_map[i].rot) result |= rotation_map[i].xrot; } return result; } gboolean gsd_rr_crtc_set_config_with_time (GsdRRCrtc *crtc, guint32 timestamp, int x, int y, GsdRRMode *mode, GsdRRRotation rotation, GsdRROutput **outputs, int n_outputs, GError **error) { ScreenInfo *info; GArray *output_ids; Status status; gboolean result; int i; g_return_val_if_fail (crtc != NULL, FALSE); g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); info = crtc->info; if (mode) { if (x + mode->width > info->max_width || y + mode->height > info->max_height) { g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_BOUNDS_ERROR, /* Translators: the "position", "size", and "maximum" * words here are not keywords; please translate them * as usual. A CRTC is a CRT Controller (this is X terminology) */ _("requested position/size for CRTC %d is outside the allowed limit: " "position=(%d, %d), size=(%d, %d), maximum=(%d, %d)"), (int) crtc->id, x, y, mode->width, mode->height, info->max_width, info->max_height); return FALSE; } } output_ids = g_array_new (FALSE, FALSE, sizeof (RROutput)); if (outputs) { for (i = 0; i < n_outputs; ++i) g_array_append_val (output_ids, outputs[i]->id); } gdk_error_trap_push (); status = XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id, timestamp, x, y, mode ? mode->id : None, xrotation_from_rotation (rotation), (RROutput *)output_ids->data, output_ids->len); g_array_free (output_ids, TRUE); if (gdk_error_trap_pop () || status != RRSetConfigSuccess) { /* Translators: CRTC is a CRT Controller (this is X terminology). * It is *very* unlikely that you'll ever get this error, so it is * only listed for completeness. */ g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, _("could not set the configuration for CRTC %d"), (int) crtc->id); return FALSE; } else { result = TRUE; } return result; } GsdRRMode * gsd_rr_crtc_get_current_mode (GsdRRCrtc *crtc) { g_return_val_if_fail (crtc != NULL, NULL); return crtc->current_mode; } guint32 gsd_rr_crtc_get_id (GsdRRCrtc *crtc) { g_return_val_if_fail (crtc != NULL, 0); return crtc->id; } gboolean gsd_rr_crtc_can_drive_output (GsdRRCrtc *crtc, GsdRROutput *output) { int i; g_return_val_if_fail (crtc != NULL, FALSE); g_return_val_if_fail (output != NULL, FALSE); for (i = 0; crtc->possible_outputs[i] != NULL; ++i) { if (crtc->possible_outputs[i] == output) return TRUE; } return FALSE; } /* FIXME: merge with get_mode()? */ /** * gsd_rr_crtc_get_position: * @crtc: a #GsdRRCrtc * @x: (out) (allow-none): * @y: (out) (allow-none): */ void gsd_rr_crtc_get_position (GsdRRCrtc *crtc, int *x, int *y) { g_return_if_fail (crtc != NULL); if (x) *x = crtc->x; if (y) *y = crtc->y; } /* FIXME: merge with get_mode()? */ GsdRRRotation gsd_rr_crtc_get_current_rotation (GsdRRCrtc *crtc) { g_assert(crtc != NULL); return crtc->current_rotation; } GsdRRRotation gsd_rr_crtc_get_rotations (GsdRRCrtc *crtc) { g_assert(crtc != NULL); return crtc->rotations; } gboolean gsd_rr_crtc_supports_rotation (GsdRRCrtc * crtc, GsdRRRotation rotation) { g_return_val_if_fail (crtc != NULL, FALSE); return (crtc->rotations & rotation); } static GsdRRCrtc * crtc_new (ScreenInfo *info, RROutput id) { GsdRRCrtc *crtc = g_slice_new0 (GsdRRCrtc); crtc->id = id; crtc->info = info; return crtc; } static GsdRRCrtc * crtc_copy (const GsdRRCrtc *from) { GsdRROutput **p_output; GPtrArray *array; GsdRRCrtc *to = g_slice_new0 (GsdRRCrtc); to->info = from->info; to->id = from->id; to->current_mode = from->current_mode; to->x = from->x; to->y = from->y; to->current_rotation = from->current_rotation; to->rotations = from->rotations; to->gamma_size = from->gamma_size; array = g_ptr_array_new (); for (p_output = from->current_outputs; *p_output != NULL; p_output++) { g_ptr_array_add (array, *p_output); } to->current_outputs = (GsdRROutput**) g_ptr_array_free (array, FALSE); array = g_ptr_array_new (); for (p_output = from->possible_outputs; *p_output != NULL; p_output++) { g_ptr_array_add (array, *p_output); } to->possible_outputs = (GsdRROutput**) g_ptr_array_free (array, FALSE); return to; } static gboolean crtc_initialize (GsdRRCrtc *crtc, XRRScreenResources *res, GError **error) { XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id); GPtrArray *a; int i; #if 0 g_print ("CRTC %lx Timestamp: %u\n", crtc->id, (guint32)info->timestamp); #endif if (!info) { /* FIXME: We need to reaquire the screen resources */ /* FIXME: can we actually catch BadRRCrtc, and does it make sense to emit that? */ /* Translators: CRTC is a CRT Controller (this is X terminology). * It is *very* unlikely that you'll ever get this error, so it is * only listed for completeness. */ g_set_error (error, GSD_RR_ERROR, GSD_RR_ERROR_RANDR_ERROR, _("could not get information about CRTC %d"), (int) crtc->id); return FALSE; } /* GsdRRMode */ crtc->current_mode = mode_by_id (crtc->info, info->mode); crtc->x = info->x; crtc->y = info->y; /* Current outputs */ a = g_ptr_array_new (); for (i = 0; i < info->noutput; ++i) { GsdRROutput *output = gsd_rr_output_by_id (crtc->info, info->outputs[i]); if (output) g_ptr_array_add (a, output); } g_ptr_array_add (a, NULL); crtc->current_outputs = (GsdRROutput **)g_ptr_array_free (a, FALSE); /* Possible outputs */ a = g_ptr_array_new (); for (i = 0; i < info->npossible; ++i) { GsdRROutput *output = gsd_rr_output_by_id (crtc->info, info->possible[i]); if (output) g_ptr_array_add (a, output); } g_ptr_array_add (a, NULL); crtc->possible_outputs = (GsdRROutput **)g_ptr_array_free (a, FALSE); /* Rotations */ crtc->current_rotation = gsd_rr_rotation_from_xrotation (info->rotation); crtc->rotations = gsd_rr_rotation_from_xrotation (info->rotations); XRRFreeCrtcInfo (info); /* get an store gamma size */ crtc->gamma_size = XRRGetCrtcGammaSize (DISPLAY (crtc), crtc->id); return TRUE; } static void crtc_free (GsdRRCrtc *crtc) { g_free (crtc->current_outputs); g_free (crtc->possible_outputs); g_slice_free (GsdRRCrtc, crtc); } /* GsdRRMode */ static GsdRRMode * mode_new (ScreenInfo *info, RRMode id) { GsdRRMode *mode = g_slice_new0 (GsdRRMode); mode->id = id; mode->info = info; return mode; } guint32 gsd_rr_mode_get_id (GsdRRMode *mode) { g_return_val_if_fail (mode != NULL, 0); return mode->id; } guint gsd_rr_mode_get_width (GsdRRMode *mode) { g_return_val_if_fail (mode != NULL, 0); return mode->width; } int gsd_rr_mode_get_freq (GsdRRMode *mode) { g_return_val_if_fail (mode != NULL, 0); return (mode->freq) / 1000; } guint gsd_rr_mode_get_height (GsdRRMode *mode) { g_return_val_if_fail (mode != NULL, 0); return mode->height; } static void mode_initialize (GsdRRMode *mode, XRRModeInfo *info) { g_assert (mode != NULL); g_assert (info != NULL); mode->name = g_strdup (info->name); mode->width = info->width; mode->height = info->height; mode->freq = ((info->dotClock / (double)info->hTotal) / info->vTotal + 0.5) * 1000; } static GsdRRMode * mode_copy (const GsdRRMode *from) { GsdRRMode *to = g_slice_new0 (GsdRRMode); to->id = from->id; to->info = from->info; to->name = g_strdup (from->name); to->width = from->width; to->height = from->height; to->freq = from->freq; return to; } static void mode_free (GsdRRMode *mode) { g_free (mode->name); g_slice_free (GsdRRMode, mode); } void gsd_rr_crtc_set_gamma (GsdRRCrtc *crtc, int size, unsigned short *red, unsigned short *green, unsigned short *blue) { int copy_size; XRRCrtcGamma *gamma; g_return_if_fail (crtc != NULL); g_return_if_fail (red != NULL); g_return_if_fail (green != NULL); g_return_if_fail (blue != NULL); if (size != crtc->gamma_size) return; gamma = XRRAllocGamma (crtc->gamma_size); copy_size = crtc->gamma_size * sizeof (unsigned short); memcpy (gamma->red, red, copy_size); memcpy (gamma->green, green, copy_size); memcpy (gamma->blue, blue, copy_size); XRRSetCrtcGamma (DISPLAY (crtc), crtc->id, gamma); XRRFreeGamma (gamma); } gboolean gsd_rr_crtc_get_gamma (GsdRRCrtc *crtc, int *size, unsigned short **red, unsigned short **green, unsigned short **blue) { int copy_size; unsigned short *r, *g, *b; XRRCrtcGamma *gamma; g_return_val_if_fail (crtc != NULL, FALSE); gamma = XRRGetCrtcGamma (DISPLAY (crtc), crtc->id); if (!gamma) return FALSE; copy_size = crtc->gamma_size * sizeof (unsigned short); if (red) { r = g_new0 (unsigned short, crtc->gamma_size); memcpy (r, gamma->red, copy_size); *red = r; } if (green) { g = g_new0 (unsigned short, crtc->gamma_size); memcpy (g, gamma->green, copy_size); *green = g; } if (blue) { b = g_new0 (unsigned short, crtc->gamma_size); memcpy (b, gamma->blue, copy_size); *blue = b; } XRRFreeGamma (gamma); if (size) *size = crtc->gamma_size; return TRUE; } unity-settings-daemon/gnome-settings-daemon/gsd-rr.h0000664000000000000000000002454615172222611020002 0ustar /* gnome-rr.h * * Copyright 2007, 2008, Red Hat, Inc. * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Author: Soren Sandmann */ #ifndef GSD_RR_H #define GSD_RR_H #include #include typedef struct GsdRRScreenPrivate GsdRRScreenPrivate; typedef struct GsdRROutput GsdRROutput; typedef struct GsdRRCrtc GsdRRCrtc; typedef struct GsdRRMode GsdRRMode; typedef struct { GObject parent; GsdRRScreenPrivate* priv; } GsdRRScreen; typedef struct { GObjectClass parent_class; void (*changed) (GsdRRScreen *screen); void (*output_connected) (GsdRRScreen *screen, GsdRROutput *output); void (*output_disconnected) (GsdRRScreen *screen, GsdRROutput *output); } GsdRRScreenClass; typedef enum { GSD_RR_ROTATION_NEXT = 0, GSD_RR_ROTATION_0 = (1 << 0), GSD_RR_ROTATION_90 = (1 << 1), GSD_RR_ROTATION_180 = (1 << 2), GSD_RR_ROTATION_270 = (1 << 3), GSD_RR_REFLECT_X = (1 << 4), GSD_RR_REFLECT_Y = (1 << 5) } GsdRRRotation; typedef enum { GSD_RR_DPMS_ON, GSD_RR_DPMS_STANDBY, GSD_RR_DPMS_SUSPEND, GSD_RR_DPMS_OFF, GSD_RR_DPMS_DISABLED, GSD_RR_DPMS_UNKNOWN } GsdRRDpmsMode; /* Error codes */ #define GSD_RR_ERROR (gsd_rr_error_quark ()) GQuark gsd_rr_error_quark (void); typedef enum { GSD_RR_ERROR_UNKNOWN, /* generic "fail" */ GSD_RR_ERROR_NO_RANDR_EXTENSION, /* RANDR extension is not present */ GSD_RR_ERROR_RANDR_ERROR, /* generic/undescribed error from the underlying XRR API */ GSD_RR_ERROR_BOUNDS_ERROR, /* requested bounds of a CRTC are outside the maximum size */ GSD_RR_ERROR_CRTC_ASSIGNMENT, /* could not assign CRTCs to outputs */ GSD_RR_ERROR_NO_MATCHING_CONFIG, /* none of the saved configurations matched the current configuration */ GSD_RR_ERROR_NO_DPMS_EXTENSION, /* DPMS extension is not present */ } GsdRRError; #define GSD_RR_CONNECTOR_TYPE_PANEL "Panel" /* This is a laptop's built-in LCD */ #define GSD_TYPE_RR_SCREEN (gsd_rr_screen_get_type()) #define GSD_RR_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_RR_SCREEN, GsdRRScreen)) #define GSD_IS_RR_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_RR_SCREEN)) #define GSD_RR_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_RR_SCREEN, GsdRRScreenClass)) #define GSD_IS_RR_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_RR_SCREEN)) #define GSD_RR_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_RR_SCREEN, GsdRRScreenClass)) #define GSD_TYPE_RR_OUTPUT (gsd_rr_output_get_type()) #define GSD_TYPE_RR_CRTC (gsd_rr_crtc_get_type()) #define GSD_TYPE_RR_MODE (gsd_rr_mode_get_type()) GType gsd_rr_screen_get_type (void); GType gsd_rr_output_get_type (void); GType gsd_rr_crtc_get_type (void); GType gsd_rr_mode_get_type (void); /* GsdRRScreen */ GsdRRScreen * gsd_rr_screen_new (GdkScreen *screen, GError **error); GsdRROutput **gsd_rr_screen_list_outputs (GsdRRScreen *screen); GsdRRCrtc ** gsd_rr_screen_list_crtcs (GsdRRScreen *screen); GsdRRMode ** gsd_rr_screen_list_modes (GsdRRScreen *screen); GsdRRMode ** gsd_rr_screen_list_clone_modes (GsdRRScreen *screen); void gsd_rr_screen_set_size (GsdRRScreen *screen, int width, int height, int mm_width, int mm_height); GsdRRCrtc * gsd_rr_screen_get_crtc_by_id (GsdRRScreen *screen, guint32 id); gboolean gsd_rr_screen_refresh (GsdRRScreen *screen, GError **error); GsdRROutput * gsd_rr_screen_get_output_by_id (GsdRRScreen *screen, guint32 id); GsdRROutput * gsd_rr_screen_get_output_by_name (GsdRRScreen *screen, const char *name); void gsd_rr_screen_get_ranges (GsdRRScreen *screen, int *min_width, int *max_width, int *min_height, int *max_height); void gsd_rr_screen_get_timestamps (GsdRRScreen *screen, guint32 *change_timestamp_ret, guint32 *config_timestamp_ret); void gsd_rr_screen_set_primary_output (GsdRRScreen *screen, GsdRROutput *output); GsdRRMode **gsd_rr_screen_create_clone_modes (GsdRRScreen *screen); gboolean gsd_rr_screen_get_dpms_mode (GsdRRScreen *screen, GsdRRDpmsMode *mode, GError **error); gboolean gsd_rr_screen_set_dpms_mode (GsdRRScreen *screen, GsdRRDpmsMode mode, GError **error); /* GsdRROutput */ guint32 gsd_rr_output_get_id (GsdRROutput *output); const char * gsd_rr_output_get_name (GsdRROutput *output); const char * gsd_rr_output_get_display_name (GsdRROutput *output); gboolean gsd_rr_output_is_connected (GsdRROutput *output); int gsd_rr_output_get_size_inches (GsdRROutput *output); int gsd_rr_output_get_width_mm (GsdRROutput *outout); int gsd_rr_output_get_height_mm (GsdRROutput *output); const guint8 * gsd_rr_output_get_edid_data (GsdRROutput *output, gsize *size); gboolean gsd_rr_output_get_ids_from_edid (GsdRROutput *output, char **vendor, int *product, int *serial); gint gsd_rr_output_get_backlight_min (GsdRROutput *output); gint gsd_rr_output_get_backlight_max (GsdRROutput *output); gint gsd_rr_output_get_backlight (GsdRROutput *output, GError **error); gboolean gsd_rr_output_set_backlight (GsdRROutput *output, gint value, GError **error); GsdRRCrtc ** gsd_rr_output_get_possible_crtcs (GsdRROutput *output); GsdRRMode * gsd_rr_output_get_current_mode (GsdRROutput *output); GsdRRCrtc * gsd_rr_output_get_crtc (GsdRROutput *output); const char * gsd_rr_output_get_connector_type (GsdRROutput *output); gboolean gsd_rr_output_is_laptop (GsdRROutput *output); void gsd_rr_output_get_position (GsdRROutput *output, int *x, int *y); gboolean gsd_rr_output_can_clone (GsdRROutput *output, GsdRROutput *clone); GsdRRMode ** gsd_rr_output_list_modes (GsdRROutput *output); GsdRRMode * gsd_rr_output_get_preferred_mode (GsdRROutput *output); gboolean gsd_rr_output_supports_mode (GsdRROutput *output, GsdRRMode *mode); gboolean gsd_rr_output_get_is_primary (GsdRROutput *output); /* GsdRRMode */ guint32 gsd_rr_mode_get_id (GsdRRMode *mode); guint gsd_rr_mode_get_width (GsdRRMode *mode); guint gsd_rr_mode_get_height (GsdRRMode *mode); int gsd_rr_mode_get_freq (GsdRRMode *mode); /* GsdRRCrtc */ guint32 gsd_rr_crtc_get_id (GsdRRCrtc *crtc); gboolean gsd_rr_crtc_set_config_with_time (GsdRRCrtc *crtc, guint32 timestamp, int x, int y, GsdRRMode *mode, GsdRRRotation rotation, GsdRROutput **outputs, int n_outputs, GError **error); gboolean gsd_rr_crtc_can_drive_output (GsdRRCrtc *crtc, GsdRROutput *output); GsdRRMode * gsd_rr_crtc_get_current_mode (GsdRRCrtc *crtc); void gsd_rr_crtc_get_position (GsdRRCrtc *crtc, int *x, int *y); GsdRRRotation gsd_rr_crtc_get_current_rotation (GsdRRCrtc *crtc); GsdRRRotation gsd_rr_crtc_get_rotations (GsdRRCrtc *crtc); gboolean gsd_rr_crtc_supports_rotation (GsdRRCrtc *crtc, GsdRRRotation rotation); gboolean gsd_rr_crtc_get_gamma (GsdRRCrtc *crtc, int *size, unsigned short **red, unsigned short **green, unsigned short **blue); void gsd_rr_crtc_set_gamma (GsdRRCrtc *crtc, int size, unsigned short *red, unsigned short *green, unsigned short *blue); #endif /* GSD_RR_H */ unity-settings-daemon/gnome-settings-daemon/idle-monitor.xml0000664000000000000000000000167615172222611021556 0ustar unity-settings-daemon/gnome-settings-daemon/main.c0000664000000000000000000003532515172222611017520 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-manager.h" #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #include "gnome-settings-bus.h" #include "gsd-idle-monitor-private.h" #define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager" #define GNOME_SESSION_CLIENT_PRIVATE_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate" static gboolean replace = FALSE; static gboolean debug = FALSE; static gboolean do_timed_exit = FALSE; static int term_signal_pipe_fds[2]; static guint name_id = 0; static GnomeSettingsManager *manager = NULL; static GOptionEntry entries[] = { {"debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, N_("Replace existing daemon"), NULL }, { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time (for debugging)"), NULL }, {NULL} }; static gboolean timed_exit_cb (void) { g_debug ("Doing timed exit"); gtk_main_quit (); return FALSE; } static void stop_manager (GnomeSettingsManager *manager) { gnome_settings_manager_stop (manager); gtk_main_quit (); } static void on_session_over (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, gpointer user_data) { if (g_strcmp0 (signal_name, "SessionOver") == 0) { g_debug ("Got a SessionOver signal - stopping"); stop_manager (manager); } } static void respond_to_end_session (GDBusProxy *proxy) { /* we must answer with "EndSessionResponse" */ g_dbus_proxy_call (proxy, "EndSessionResponse", g_variant_new ("(bs)", TRUE, ""), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); } static void client_proxy_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, gpointer user_data) { if (g_strcmp0 (signal_name, "QueryEndSession") == 0) { g_debug ("Got QueryEndSession signal"); respond_to_end_session (proxy); } else if (g_strcmp0 (signal_name, "EndSession") == 0) { g_debug ("Got EndSession signal"); respond_to_end_session (proxy); } else if (g_strcmp0 (signal_name, "Stop") == 0) { g_debug ("Got Stop signal"); stop_manager (manager); } } static void got_client_proxy (GObject *object, GAsyncResult *res, gpointer user_data) { GDBusProxy *client_proxy; GError *error = NULL; client_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (error != NULL) { g_debug ("Unable to get the session client proxy: %s", error->message); g_error_free (error); return; } g_signal_connect (client_proxy, "g-signal", G_CALLBACK (client_proxy_signal_cb), manager); } static void start_settings_manager (void) { gboolean res; GError *error; gnome_settings_profile_start ("gnome_settings_manager_new"); manager = gnome_settings_manager_new (); gnome_settings_profile_end ("gnome_settings_manager_new"); if (manager == NULL) { g_warning ("Unable to register object"); gtk_main_quit (); } error = NULL; res = gnome_settings_manager_start (manager, &error); if (! res) { g_warning ("Unable to start: %s", error->message); g_error_free (error); gtk_main_quit (); } } static void on_client_registered (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *variant; GError *error = NULL; gchar *object_path = NULL; variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (error != NULL) { g_warning ("Unable to register client: %s", error->message); g_error_free (error); } else { g_variant_get (variant, "(o)", &object_path); g_debug ("Registered client at path %s", object_path); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, 0, NULL, GNOME_SESSION_DBUS_NAME, object_path, GNOME_SESSION_CLIENT_PRIVATE_DBUS_INTERFACE, NULL, got_client_proxy, manager); g_free (object_path); g_variant_unref (variant); } } static void session_env_done (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *result; GError *error = NULL; result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_debug ("Failed to set the environment: %s", error->message); g_error_free (error); return; } g_variant_unref (result); } static void set_session_env (GDBusProxy *proxy, const gchar *name, const gchar *value) { g_dbus_proxy_call (proxy, "Setenv", g_variant_new ("(ss)", name, value), G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback) session_env_done, NULL); } static void set_locale (GDBusProxy *proxy) { GSettings *locale_settings; gchar *region; /* Set locale environment */ locale_settings = g_settings_new ("org.gnome.system.locale"); region = g_settings_get_string (locale_settings, "region"); if (region[0]) { /* Only set the locale settings if the user has ever customized them */ set_session_env (proxy, "LC_TIME", region); set_session_env (proxy, "LC_NUMERIC", region); set_session_env (proxy, "LC_MONETARY", region); set_session_env (proxy, "LC_MEASUREMENT", region); set_session_env (proxy, "LC_PAPER", region); } g_free (region); g_object_unref (locale_settings); } #ifdef HAVE_IBUS static gboolean is_program_in_path (const char *binary) { char *path; path = g_find_program_in_path (binary); if (path == NULL) return FALSE; g_free (path); return TRUE; } static gboolean keyboard_plugin_is_enabled (void) { GSettings *settings; gboolean enabled; settings = g_settings_new ("com.canonical.unity.settings-daemon.plugins.keyboard"); enabled = g_settings_get_boolean (settings, "active"); g_object_unref (settings); return enabled; } static void set_legacy_ibus_env_vars (GDBusProxy *proxy) { if (is_program_in_path ("ibus-daemon") && keyboard_plugin_is_enabled ()) { set_session_env (proxy, "QT_IM_MODULE", "ibus"); set_session_env (proxy, "XMODIFIERS", "@im=ibus"); } } #endif static void register_with_gnome_session (GDBusProxy *proxy) { const char *startup_id; g_signal_connect (G_OBJECT (proxy), "g-signal", G_CALLBACK (on_session_over), NULL); startup_id = g_getenv ("DESKTOP_AUTOSTART_ID"); g_dbus_proxy_call (proxy, "RegisterClient", g_variant_new ("(ss)", "gnome-settings-daemon", startup_id ? startup_id : ""), G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback) on_client_registered, manager); } static gboolean on_term_signal_pipe_closed (GIOChannel *source, GIOCondition condition, gpointer data) { term_signal_pipe_fds[0] = -1; g_debug ("Received SIGTERM - shutting down"); /* Got SIGTERM, time to clean up and get out */ gtk_main_quit (); return FALSE; } static void on_term_signal (int signal) { /* Wake up main loop to tell it to shutdown */ close (term_signal_pipe_fds[1]); term_signal_pipe_fds[1] = -1; } static void watch_for_term_signal (GnomeSettingsManager *manager) { GIOChannel *channel; if (-1 == pipe (term_signal_pipe_fds) || -1 == fcntl (term_signal_pipe_fds[0], F_SETFD, FD_CLOEXEC) || -1 == fcntl (term_signal_pipe_fds[1], F_SETFD, FD_CLOEXEC)) { g_error ("Could not create pipe: %s", g_strerror (errno)); exit (EXIT_FAILURE); } channel = g_io_channel_unix_new (term_signal_pipe_fds[0]); g_io_channel_set_encoding (channel, NULL, NULL); g_io_channel_set_buffered (channel, FALSE); g_io_add_watch (channel, G_IO_HUP, on_term_signal_pipe_closed, manager); g_io_channel_unref (channel); signal (SIGTERM, on_term_signal); } static void name_acquired_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { GDBusProxy *proxy; proxy = G_DBUS_PROXY (gnome_settings_bus_get_session_proxy ()); #ifdef HAVE_IBUS set_legacy_ibus_env_vars (proxy); #endif start_settings_manager (); register_with_gnome_session (proxy); watch_for_term_signal (manager); } static void name_lost_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { /* Name was already taken, or the bus went away */ g_warning ("Name taken or bus went away - shutting down"); if (manager != NULL) stop_manager (manager); gtk_main_quit (); } static void bus_register (void) { GBusNameOwnerFlags flags; flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; if (replace) flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; name_id = g_bus_own_name (G_BUS_TYPE_SESSION, GSD_DBUS_NAME, flags, NULL, (GBusNameAcquiredCallback) name_acquired_handler, (GBusNameLostCallback) name_lost_handler, NULL, NULL); } static void gsd_log_default_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data) { /* filter out DEBUG messages if debug isn't set */ if ((log_level & G_LOG_LEVEL_MASK) == G_LOG_LEVEL_DEBUG && ! debug) { return; } g_log_default_handler (log_domain, log_level, message, unused_data); } static void parse_args (int *argc, char ***argv) { GError *error; GOptionContext *context; gnome_settings_profile_start (NULL); context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); g_option_context_add_group (context, gtk_get_option_group (FALSE)); error = NULL; if (!g_option_context_parse (context, argc, argv, &error)) { if (error != NULL) { g_warning ("%s", error->message); g_error_free (error); } else { g_warning ("Unable to initialize GTK+"); } exit (EXIT_FAILURE); } g_option_context_free (context); gnome_settings_profile_end (NULL); if (debug) g_setenv ("G_MESSAGES_DEBUG", "all", FALSE); } int main (int argc, char *argv[]) { gnome_settings_profile_start (NULL); bindtextdomain (GETTEXT_PACKAGE, GNOME_SETTINGS_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); setlocale (LC_ALL, ""); parse_args (&argc, &argv); gnome_settings_profile_start ("opening gtk display"); if (! gtk_init_check (NULL, NULL)) { g_warning ("Unable to initialize GTK+"); exit (EXIT_FAILURE); } gnome_settings_profile_end ("opening gtk display"); g_log_set_default_handler (gsd_log_default_handler, NULL); notify_init ("gnome-settings-daemon"); bus_register (); if (do_timed_exit) { g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, NULL); } gsd_idle_monitor_init_dbus (replace); gtk_main (); g_debug ("Shutting down"); if (name_id > 0) { g_bus_unown_name (name_id); name_id = 0; } if (manager != NULL) { g_object_unref (manager); } g_debug ("SettingsDaemon finished"); gnome_settings_profile_end (NULL); return 0; } unity-settings-daemon/gnome-settings-daemon/org.gnome.ScreenSaver.xml0000664000000000000000000000335515172222611023262 0ustar unity-settings-daemon/gnome-settings-daemon/org.gnome.SessionManager.xml0000664000000000000000000003735015172222611023762 0ustar The variable name The value Adds the variable name to the application launch environment with the specified value. May only be used during the Session Manager initialization phase. The locale category The value Reads the current state of the specific locale category. The error message Whether the error should be treated as fatal May be used by applications launched during the Session Manager initialization phase to indicate there was a problem. The application identifier Client startup identifier The object path of the newly registered client Register the caller as a Session Management client. The object path of the client Unregister the specified client from Session Management. The application identifier The toplevel X window identifier The reason for the inhibit Flags that specify what should be inhibited The cookie Proactively indicates that the calling application is performing an action that should not be interrupted and sets a reason to be displayed to the user when an interruption is about to take placea. Applications should invoke this method when they begin an operation that should not be interrupted, such as creating a CD or DVD. The types of actions that may be blocked are specified by the flags parameter. When the application completes the operation it should call Uninhibit() or disconnect from the session bus. Applications should not expect that they will always be able to block the action. In most cases, users will be given the option to force the action to take place. Reasons should be short and to the point. The flags parameter must include at least one of the following: 1 Inhibit logging out 2 Inhibit user switching 4 Inhibit suspending the session or computer 8 Inhibit the session being marked as idle 16 Inhibit auto-mounting removable media for the session Values for flags may be bitwise or'ed together. The returned cookie is used to uniquely identify this request. It should be used as an argument to Uninhibit() in order to remove the request. The cookie Cancel a previous call to Inhibit() identified by the cookie. Flags that spefify what should be inhibited Returns TRUE if any of the operations in the bitfield flags are inhibited Determine if operation(s) specified by the flags are currently inhibited. Flags are same as those accepted by the Inhibit() method. an array of client IDs This gets a list of all the Clients that are currently known to the session manager. Each Client ID is an D-Bus object path for the object that implements the Client interface. org.gnome.SessionManager.Client an array of inhibitor IDs This gets a list of all the Inhibitors that are currently known to the session manager. Each Inhibitor ID is an D-Bus object path for the object that implements the Inhibitor interface. org.gnome.SessionManager.Inhibitor The autostart condition string True if condition is handled, false otherwise Allows the caller to determine whether the session manager is handling changes to the specified autostart condition. Request a shutdown dialog. Request a reboot dialog. True if shutdown is available to the user, false otherwise Allows the caller to determine whether or not it's okay to show a shutdown option in the UI The type of logout that is being requested Request a logout dialog Allowed values for the mode parameter are: 0 Normal. 1 No confirmation inferface should be shown. 2 Forcefully logout. No confirmation will be shown and any inhibitors will be ignored. Values for flags may be bitwise or'ed together. True if the session has entered the Running phase, false otherwise Allows the caller to determine whether the session manager has entered the Running phase, in case the client missed the SessionRunning signal. The object path for the added client Emitted when a client has been added to the session manager. The object path for the removed client Emitted when a client has been removed from the session manager. The object path for the added inhibitor Emitted when an inhibitor has been added to the session manager. The object path for the removed inhibitor Emitted when an inhibitor has been removed from the session manager. Indicates the session has entered the Running phase. Indicates the session is about to end. The name of the session that has been loaded. If true, the session is currently in the foreground and available for user input. A bitmask of flags to indicate which actions are inhibited. See the Inhibit() function's description for a list of possible values. unity-settings-daemon/gnome-settings-daemon/unity-settings-daemon-localeexec.in0000775000000000000000000000064415172222611025330 0ustar #!/bin/sh SETTING=$(gsettings get org.gnome.system.locale region) REGION=${SETTING#\'} REGION=${REGION%\'} if [ -n "$REGION" ]; then export LC_TIME=$REGION export LC_NUMERIC=$REGION export LC_MONETARY=$REGION export LC_MEASUREMENT=$REGION export LC_PAPER=$REGION fi if [ -x @prefix@/bin/ibus-daemon ]; then export QT_IM_MODULE=ibus export XMODIFIERS=@im=ibus fi exec @libexecdir@/unity-settings-daemon unity-settings-daemon/gnome-settings-daemon.doap0000664000000000000000000000321415172222611017265 0ustar GNOME Settings Daemon GNOME Settings Daemon Rui Matos rtcm Bastien Nocera hadess Richard Hughes rhughes Olivier Fourdan ofourdan unity-settings-daemon/man/0000775000000000000000000000000015172222611012767 5ustar unity-settings-daemon/man/Makefile.am0000664000000000000000000000103715172222611015024 0ustar XSLTPROC_FLAGS = \ --nonet \ --stringparam man.output.quietly 1 \ --stringparam funcsynopsis.style ansi \ --stringparam man.th.extra1.suppress 1 \ --stringparam man.authors.section.enabled 0 \ --stringparam man.copyright.section.enabled 0 .xml.1: $(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< man_MANS = \ unity-settings-daemon.1 xml_files = $(man_MANS:.1=.xml) EXTRA_DIST = $(xml_files) DISTCLEANFILES = $(man_MANS) unity-settings-daemon/man/unity-settings-daemon.xml0000664000000000000000000001403515172222611017763 0ustar unity-settings-daemon Unity Maintainer Bastien Nocera hadess@hadess.net unity-settings-daemon 1 User Commands unity-settings-daemon Unity settings daemon unity-settings-daemon OPTION Description unity-settings-daemon provides many session-wide services and functions that require a long-running process. Among the services implemented by unity-settings-daemon are an XSettings manager, which provides theming, font and other settings to GTK+ applications, and a clipboard manager, which preserves clipboard contents when an application exits. Many user interface elements of unity and unity-control-center rely on unity-settings-daemon for their functionality. The internal architecture of unity-settings-daemon consists of a number of plugins, which provide functionality such as printer notifications, software update monitoring, background changing, etc. For debugging purposes, these plugins can be individually disabled by changing the gsettings key org.gnome.settings-daemon.plugins.plugin-name.active, where plugin-name is the name of the plugin. To see a list of all plugins, use the command gsettings list-children org.gnome.settings-daemon.plugins unity-settings-daemon takes the name org.gnome.SettingsDaemon on the session bus to ensure that only one instance is running. Some plugins export objects under this name to make their functionality available to other applications. The interfaces of these objects should generally be considered private and unstable. unity-settings-daemon is a required component of the Unity desktop, i.e. it is listed in the RequiredComponents field of /usr/share/gnome-session/sessions/gnome.session. It is started in the initialization phase of the session, and gnome-session will restart it if it crashes. Options , Prints a short help text and exits. Enables debugging code. Exits after a timeout (30 seconds) for debugging. Files /usr/share/gnome-session/sessions/ubuntu.session Unity session definition file where unity-settings-daemon is listed as a required component. /etc/xdg/autostart/unity-settings-daemon.desktop Autostart file for unity-settings-daemon, where its autostart phase is set. See Also unity1, unity-control-center1, gnome-session1 unity-settings-daemon/plugins/0000775000000000000000000000000015172222611013675 5ustar unity-settings-daemon/plugins/Makefile.am0000664000000000000000000000151015172222611015726 0ustar NULL = enabled_plugins = \ a11y-keyboard \ a11y-settings \ automount \ background \ clipboard \ color \ cursor \ dummy \ power \ housekeeping \ keyboard \ media-keys \ mouse \ remote-display \ screensaver-proxy \ sharing \ sound \ xrandr \ xsettings \ $(NULL) disabled_plugins = $(NULL) if HAVE_PACKAGEKIT enabled_plugins += updates else disabled_plugins += updates endif if SMARTCARD_SUPPORT enabled_plugins += smartcard else disabled_plugins += smartcard endif if HAVE_GUDEV enabled_plugins += orientation else disabled_plugins += orientation endif if HAVE_WACOM enabled_plugins += wacom else disabled_plugins += wacom endif if BUILD_RFKILL enabled_plugins += rfkill else disabled_plugins += rfkill endif SUBDIRS = common $(enabled_plugins) DIST_SUBDIRS = $(SUBDIRS) $(disabled_plugins) unity-settings-daemon/plugins/a11y-keyboard/0000775000000000000000000000000015172222611016246 5ustar unity-settings-daemon/plugins/a11y-keyboard/Makefile.am0000664000000000000000000000335315172222611020306 0ustar NULL = plugin_name = a11y-keyboard libexec_PROGRAMS = usd-test-a11y-keyboard usd_test_a11y_keyboard_SOURCES = \ gsd-a11y-keyboard-manager.h \ gsd-a11y-keyboard-manager.c \ test-a11y-keyboard.c usd_test_a11y_keyboard_CFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ $(PLUGIN_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_a11y_keyboard_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(LIBNOTIFY_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = \ liba11y-keyboard.la \ $(NULL) liba11y_keyboard_la_SOURCES = \ gsd-a11y-keyboard-plugin.c \ gsd-a11y-keyboard-manager.h \ gsd-a11y-keyboard-manager.c \ $(NULL) liba11y_keyboard_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DGTKBUILDERDIR=\""$(gtkbuilderdir)"\" \ $(AM_CPPFLAGS) liba11y_keyboard_la_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(AM_CFLAGS) liba11y_keyboard_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) \ $(NULL) liba11y_keyboard_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(XF86MISC_LIBS) \ $(LIBNOTIFY_LIBS) \ $(NULL) plugin_in_files = \ a11y-keyboard.gnome-settings-plugin.in \ $(NULL) plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) \ $(gtkbuilder_DATA) \ $(NULL) CLEANFILES = \ $(plugin_DATA) \ $(NULL) DISTCLEANFILES = \ $(plugin_DATA) \ $(NULL) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/a11y-keyboard/a11y-keyboard.gnome-settings-plugin.in0000664000000000000000000000031715172222611025406 0ustar [GNOME Settings Plugin] Module=a11y-keyboard IAge=0 Priority=7 _Name=Accessibility Keyboard _Description=Accessibility keyboard plugin Authors=Jody Goldberg Copyright=Copyright © 2001 Ximian, Inc. Website= unity-settings-daemon/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c0000664000000000000000000010142115172222611023145 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright © 2001 Ximian, Inc. * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-profile.h" #include "gsd-a11y-keyboard-manager.h" #define KEYBOARD_A11Y_SCHEMA "org.gnome.desktop.a11y.keyboard" #define NOTIFICATION_TIMEOUT 30 #define GSD_A11Y_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManagerPrivate)) struct GsdA11yKeyboardManagerPrivate { guint start_idle_id; int xkbEventBase; GdkDeviceManager *device_manager; guint device_added_id; gboolean stickykeys_shortcut_val; gboolean slowkeys_shortcut_val; XkbDescRec *desc; GSettings *settings; NotifyNotification *notification; }; #define DEFAULT_XKB_SET_CONTROLS_MASK XkbSlowKeysMask | \ XkbBounceKeysMask | \ XkbStickyKeysMask | \ XkbMouseKeysMask | \ XkbMouseKeysAccelMask | \ XkbAccessXKeysMask | \ XkbAccessXTimeoutMask | \ XkbAccessXFeedbackMask | \ XkbControlsEnabledMask static void gsd_a11y_keyboard_manager_class_init (GsdA11yKeyboardManagerClass *klass); static void gsd_a11y_keyboard_manager_init (GsdA11yKeyboardManager *a11y_keyboard_manager); static void gsd_a11y_keyboard_manager_finalize (GObject *object); static void set_server_from_gsettings (GsdA11yKeyboardManager *manager); G_DEFINE_TYPE (GsdA11yKeyboardManager, gsd_a11y_keyboard_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void device_added_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdA11yKeyboardManager *manager) { if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) set_server_from_gsettings (manager); } static void set_devicepresence_handler (GsdA11yKeyboardManager *manager) { GdkDeviceManager *device_manager; device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); if (device_manager == NULL) return; manager->priv->device_manager = device_manager; manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", G_CALLBACK (device_added_cb), manager); } static gboolean xkb_enabled (GsdA11yKeyboardManager *manager) { int opcode, errorBase, major, minor; if (!XkbQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &opcode, &manager->priv->xkbEventBase, &errorBase, &major, &minor)) return FALSE; if (!XkbUseExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor)) return FALSE; return TRUE; } static XkbDescRec * get_xkb_desc_rec (GsdA11yKeyboardManager *manager) { XkbDescRec *desc; Status status = Success; gdk_error_trap_push (); desc = XkbGetMap (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbAllMapComponentsMask, XkbUseCoreKbd); if (desc != NULL) { desc->ctrls = NULL; status = XkbGetControls (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbAllControlsMask, desc); } gdk_error_trap_pop_ignored (); g_return_val_if_fail (desc != NULL, NULL); g_return_val_if_fail (desc->ctrls != NULL, NULL); g_return_val_if_fail (status == Success, NULL); return desc; } static int get_int (GSettings *settings, char const *key) { int res = g_settings_get_int (settings, key); if (res <= 0) { res = 1; } return res; } static gboolean set_int (GSettings *settings, char const *key, int val) { int prev_val; prev_val = g_settings_get_int (settings, key); g_settings_set_int (settings, key, val); if (val != prev_val) { g_debug ("%s changed", key); } return val != prev_val; } static gboolean set_bool (GSettings *settings, char const *key, int val) { gboolean bval = (val != 0); gboolean prev_val; prev_val = g_settings_get_boolean (settings, key); g_settings_set_boolean (settings, key, bval ? TRUE : FALSE); if (bval != prev_val) { g_debug ("%s changed", key); return TRUE; } return (bval != prev_val); } static unsigned long set_clear (gboolean flag, unsigned long value, unsigned long mask) { if (flag) { return value | mask; } return value & ~mask; } static gboolean set_ctrl_from_gsettings (XkbDescRec *desc, GSettings *settings, char const *key, unsigned long mask) { gboolean result = g_settings_get_boolean (settings, key); desc->ctrls->enabled_ctrls = set_clear (result, desc->ctrls->enabled_ctrls, mask); return result; } static void set_server_from_gsettings (GsdA11yKeyboardManager *manager) { XkbDescRec *desc; gboolean enable_accessX; GSettings *settings; gnome_settings_profile_start (NULL); desc = get_xkb_desc_rec (manager); if (!desc) { return; } settings = manager->priv->settings; /* general */ enable_accessX = g_settings_get_boolean (settings, "enable"); desc->ctrls->enabled_ctrls = set_clear (enable_accessX, desc->ctrls->enabled_ctrls, XkbAccessXKeysMask); if (set_ctrl_from_gsettings (desc, settings, "timeout-enable", XkbAccessXTimeoutMask)) { desc->ctrls->ax_timeout = get_int (settings, "disable-timeout"); /* disable only the master flag via the server we will disable * the rest on the rebound without affecting GSettings state * don't change the option flags at all. */ desc->ctrls->axt_ctrls_mask = XkbAccessXKeysMask | XkbAccessXFeedbackMask; desc->ctrls->axt_ctrls_values = 0; desc->ctrls->axt_opts_mask = 0; } desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "feature-state-change-beep"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask); /* bounce keys */ if (set_ctrl_from_gsettings (desc, settings, "bouncekeys-enable", XkbBounceKeysMask)) { desc->ctrls->debounce_delay = get_int (settings, "bouncekeys-delay"); desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "bouncekeys-beep-reject"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_BKRejectFBMask); } /* mouse keys */ if (set_ctrl_from_gsettings (desc, settings, "mousekeys-enable", XkbMouseKeysMask | XkbMouseKeysAccelMask)) { desc->ctrls->mk_interval = 100; /* msec between mousekey events */ desc->ctrls->mk_curve = 50; /* We store pixels / sec, XKB wants pixels / event */ desc->ctrls->mk_max_speed = get_int (settings, "mousekeys-max-speed") / (1000 / desc->ctrls->mk_interval); if (desc->ctrls->mk_max_speed <= 0) desc->ctrls->mk_max_speed = 1; desc->ctrls->mk_time_to_max = get_int (settings, /* events before max */ "mousekeys-accel-time") / desc->ctrls->mk_interval; if (desc->ctrls->mk_time_to_max <= 0) desc->ctrls->mk_time_to_max = 1; desc->ctrls->mk_delay = get_int (settings, /* ms before 1st event */ "mousekeys-init-delay"); } /* slow keys */ if (set_ctrl_from_gsettings (desc, settings, "slowkeys-enable", XkbSlowKeysMask)) { desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "slowkeys-beep-press"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKPressFBMask); desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "slowkeys-beep-accept"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKAcceptFBMask); desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "slowkeys-beep-reject"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKRejectFBMask); desc->ctrls->slow_keys_delay = get_int (settings, "slowkeys-delay"); /* anything larger than 500 seems to loose all keyboard input */ if (desc->ctrls->slow_keys_delay > 500) desc->ctrls->slow_keys_delay = 500; } /* sticky keys */ if (set_ctrl_from_gsettings (desc, settings, "stickykeys-enable", XkbStickyKeysMask)) { desc->ctrls->ax_options |= XkbAX_LatchToLockMask; desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "stickykeys-two-key-off"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_TwoKeysMask); desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "stickykeys-modifier-beep"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_StickyKeysFBMask); } /* toggle keys */ desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "togglekeys-enable"), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_IndicatorFBMask); /* g_debug ("CHANGE to : 0x%x", desc->ctrls->enabled_ctrls); g_debug ("CHANGE to : 0x%x (2)", desc->ctrls->ax_options); */ gdk_error_trap_push (); XkbSetControls (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), DEFAULT_XKB_SET_CONTROLS_MASK, desc); XkbFreeKeyboard (desc, XkbAllComponentsMask, True); XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); gdk_error_trap_pop_ignored (); gnome_settings_profile_end (NULL); } static void ax_response_callback (GsdA11yKeyboardManager *manager, const char *action, guint revert_controls_mask, gboolean enabled) { if (g_strcmp0 (action, "reject") == 0) { /* we're reverting, so we invert sense of 'enabled' flag */ g_debug ("cancelling AccessX request"); if (revert_controls_mask == XkbStickyKeysMask) { g_settings_set_boolean (manager->priv->settings, "stickykeys-enable", !enabled); } else if (revert_controls_mask == XkbSlowKeysMask) { g_settings_set_boolean (manager->priv->settings, "slowkeys-enable", !enabled); } set_server_from_gsettings (manager); } } static void on_notification_closed (NotifyNotification *notification, GsdA11yKeyboardManager *manager) { g_object_unref (manager->priv->notification); manager->priv->notification = NULL; } static void on_slow_keys_action (NotifyNotification *notification, const char *action, GsdA11yKeyboardManager *manager) { g_assert (action != NULL); ax_response_callback (manager, action, XkbSlowKeysMask, manager->priv->slowkeys_shortcut_val); notify_notification_close (manager->priv->notification, NULL); } static void on_sticky_keys_action (NotifyNotification *notification, const char *action, GsdA11yKeyboardManager *manager) { g_assert (action != NULL); ax_response_callback (manager, action, XkbStickyKeysMask, manager->priv->stickykeys_shortcut_val); notify_notification_close (manager->priv->notification, NULL); } static gboolean ax_slowkeys_warning_post_bubble (GsdA11yKeyboardManager *manager, gboolean enabled) { gboolean res; const char *title; const char *message; GError *error; title = enabled ? _("Slow Keys Turned On") : _("Slow Keys Turned Off"); message = _("You just held down the Shift key for 8 seconds. This is the shortcut " "for the Slow Keys feature, which affects the way your keyboard works."); if (manager->priv->notification != NULL) { notify_notification_close (manager->priv->notification, NULL); } manager->priv->notification = notify_notification_new (title, message, "preferences-desktop-accessibility-symbolic"); notify_notification_set_app_name (manager->priv->notification, _("Universal Access")); notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000); notify_notification_set_hint (manager->priv->notification, "transient", g_variant_new_boolean (TRUE)); notify_notification_add_action (manager->priv->notification, "reject", enabled ? _("Turn Off") : _("Turn On"), (NotifyActionCallback) on_slow_keys_action, manager, NULL); notify_notification_add_action (manager->priv->notification, "accept", enabled ? _("Leave On") : _("Leave Off"), (NotifyActionCallback) on_slow_keys_action, manager, NULL); g_signal_connect (manager->priv->notification, "closed", G_CALLBACK (on_notification_closed), manager); error = NULL; res = notify_notification_show (manager->priv->notification, &error); if (! res) { g_warning ("GsdA11yKeyboardManager: unable to show notification: %s", error->message); g_error_free (error); notify_notification_close (manager->priv->notification, NULL); } return res; } static void ax_slowkeys_warning_post (GsdA11yKeyboardManager *manager, gboolean enabled) { manager->priv->slowkeys_shortcut_val = enabled; ax_slowkeys_warning_post_bubble (manager, enabled); } static gboolean ax_stickykeys_warning_post_bubble (GsdA11yKeyboardManager *manager, gboolean enabled) { gboolean res; const char *title; const char *message; GError *error; title = enabled ? _("Sticky Keys Turned On") : _("Sticky Keys Turned Off"); message = enabled ? _("You just pressed the Shift key 5 times in a row. This is the shortcut " "for the Sticky Keys feature, which affects the way your keyboard works.") : _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " "This turns off the Sticky Keys feature, which affects the way your keyboard works."); if (manager->priv->notification != NULL) { notify_notification_close (manager->priv->notification, NULL); } manager->priv->notification = notify_notification_new (title, message, "preferences-desktop-accessibility-symbolic"); notify_notification_set_app_name (manager->priv->notification, _("Universal Access")); notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000); notify_notification_set_hint (manager->priv->notification, "transient", g_variant_new_boolean (TRUE)); notify_notification_add_action (manager->priv->notification, "reject", enabled ? _("Turn Off") : _("Turn On"), (NotifyActionCallback) on_sticky_keys_action, manager, NULL); notify_notification_add_action (manager->priv->notification, "accept", enabled ? _("Leave On") : _("Leave Off"), (NotifyActionCallback) on_sticky_keys_action, manager, NULL); g_signal_connect (manager->priv->notification, "closed", G_CALLBACK (on_notification_closed), manager); error = NULL; res = notify_notification_show (manager->priv->notification, &error); if (! res) { g_warning ("GsdA11yKeyboardManager: unable to show notification: %s", error->message); g_error_free (error); notify_notification_close (manager->priv->notification, NULL); } return res; } static void ax_stickykeys_warning_post (GsdA11yKeyboardManager *manager, gboolean enabled) { manager->priv->stickykeys_shortcut_val = enabled; ax_stickykeys_warning_post_bubble (manager, enabled); } static void set_gsettings_from_server (GsdA11yKeyboardManager *manager) { XkbDescRec *desc; gboolean changed = FALSE; gboolean slowkeys_changed; gboolean stickykeys_changed; GSettings *settings; desc = get_xkb_desc_rec (manager); if (! desc) { return; } /* Create a new one, so that only those settings * are delayed */ settings = g_settings_new (KEYBOARD_A11Y_SCHEMA); g_settings_delay (settings); /* fprintf (stderr, "changed to : 0x%x\n", desc->ctrls->enabled_ctrls); fprintf (stderr, "changed to : 0x%x (2)\n", desc->ctrls->ax_options); */ changed |= set_bool (settings, "enable", desc->ctrls->enabled_ctrls & XkbAccessXKeysMask); changed |= set_bool (settings, "feature-state-change-beep", desc->ctrls->ax_options & (XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask)); changed |= set_bool (settings, "timeout-enable", desc->ctrls->enabled_ctrls & XkbAccessXTimeoutMask); changed |= set_int (settings, "disable-timeout", desc->ctrls->ax_timeout); changed |= set_bool (settings, "bouncekeys-enable", desc->ctrls->enabled_ctrls & XkbBounceKeysMask); changed |= set_int (settings, "bouncekeys-delay", desc->ctrls->debounce_delay); changed |= set_bool (settings, "bouncekeys-beep-reject", desc->ctrls->ax_options & XkbAX_BKRejectFBMask); changed |= set_bool (settings, "mousekeys-enable", desc->ctrls->enabled_ctrls & XkbMouseKeysMask); changed |= set_int (settings, "mousekeys-max-speed", desc->ctrls->mk_max_speed * (1000 / desc->ctrls->mk_interval)); /* NOTE : mk_time_to_max is measured in events not time */ changed |= set_int (settings, "mousekeys-accel-time", desc->ctrls->mk_time_to_max * desc->ctrls->mk_interval); changed |= set_int (settings, "mousekeys-init-delay", desc->ctrls->mk_delay); slowkeys_changed = set_bool (settings, "slowkeys-enable", desc->ctrls->enabled_ctrls & XkbSlowKeysMask); changed |= set_bool (settings, "slowkeys-beep-press", desc->ctrls->ax_options & XkbAX_SKPressFBMask); changed |= set_bool (settings, "slowkeys-beep-accept", desc->ctrls->ax_options & XkbAX_SKAcceptFBMask); changed |= set_bool (settings, "slowkeys-beep-reject", desc->ctrls->ax_options & XkbAX_SKRejectFBMask); changed |= set_int (settings, "slowkeys-delay", desc->ctrls->slow_keys_delay); stickykeys_changed = set_bool (settings, "stickykeys-enable", desc->ctrls->enabled_ctrls & XkbStickyKeysMask); changed |= set_bool (settings, "stickykeys-two-key-off", desc->ctrls->ax_options & XkbAX_TwoKeysMask); changed |= set_bool (settings, "stickykeys-modifier-beep", desc->ctrls->ax_options & XkbAX_StickyKeysFBMask); changed |= set_bool (settings, "togglekeys-enable", desc->ctrls->ax_options & XkbAX_IndicatorFBMask); if (!changed && stickykeys_changed ^ slowkeys_changed) { /* * sticky or slowkeys has changed, singly, without our intervention. * 99% chance this is due to a keyboard shortcut being used. * we need to detect via this hack until we get * XkbAXN_AXKWarning notifications working (probable XKB bug), * at which time we can directly intercept such shortcuts instead. * See cb_xkb_event_filter () below. */ /* sanity check: are keyboard shortcuts available? */ if (desc->ctrls->enabled_ctrls & XkbAccessXKeysMask) { if (slowkeys_changed) { ax_slowkeys_warning_post (manager, desc->ctrls->enabled_ctrls & XkbSlowKeysMask); } else { ax_stickykeys_warning_post (manager, desc->ctrls->enabled_ctrls & XkbStickyKeysMask); } } } XkbFreeKeyboard (desc, XkbAllComponentsMask, True); g_settings_apply (settings); g_object_unref (settings); } static GdkFilterReturn cb_xkb_event_filter (GdkXEvent *xevent, GdkEvent *ignored1, GsdA11yKeyboardManager *manager) { XEvent *xev = (XEvent *) xevent; XkbEvent *xkbEv = (XkbEvent *) xevent; /* 'event_type' is set to zero on notifying us of updates in * response to client requests (including our own) and non-zero * to notify us of key/mouse events causing changes (like * pressing shift 5 times to enable sticky keys). * * We only want to update GSettings when it's in response to an * explicit user input event, so require a non-zero event_type. */ if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) && xkbEv->any.xkb_type == XkbControlsNotify && xkbEv->ctrls.event_type != 0) { g_debug ("XKB state changed"); set_gsettings_from_server (manager); } else if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) && xkbEv->any.xkb_type == XkbAccessXNotify) { if (xkbEv->accessx.detail == XkbAXN_AXKWarning) { g_debug ("About to turn on an AccessX feature from the keyboard!"); /* * TODO: when XkbAXN_AXKWarnings start working, we need to * invoke ax_keys_warning_dialog_run here instead of in * set_gsettings_from_server(). */ } } return GDK_FILTER_CONTINUE; } static void keyboard_callback (GSettings *settings, const char *key, GsdA11yKeyboardManager *manager) { set_server_from_gsettings (manager); } static gboolean start_a11y_keyboard_idle_cb (GsdA11yKeyboardManager *manager) { guint event_mask; g_debug ("Starting a11y_keyboard manager"); gnome_settings_profile_start (NULL); if (!xkb_enabled (manager)) goto out; manager->priv->settings = g_settings_new (KEYBOARD_A11Y_SCHEMA); g_signal_connect (G_OBJECT (manager->priv->settings), "changed", G_CALLBACK (keyboard_callback), manager); set_devicepresence_handler (manager); /* Get the original configuration from the server */ manager->priv->desc = get_xkb_desc_rec (manager); event_mask = XkbControlsNotifyMask; event_mask |= XkbAccessXNotifyMask; /* make default when AXN_AXKWarning works */ /* be sure to init before starting to monitor the server */ set_server_from_gsettings (manager); XkbSelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbUseCoreKbd, event_mask, event_mask); gdk_window_add_filter (NULL, (GdkFilterFunc) cb_xkb_event_filter, manager); out: gnome_settings_profile_end (NULL); manager->priv->start_idle_id = 0; return FALSE; } gboolean gsd_a11y_keyboard_manager_start (GsdA11yKeyboardManager *manager, GError **error) { gnome_settings_profile_start (NULL); manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_a11y_keyboard_idle_cb, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_a11y_keyboard_manager_stop (GsdA11yKeyboardManager *manager) { GsdA11yKeyboardManagerPrivate *p = manager->priv; g_debug ("Stopping a11y_keyboard manager"); if (p->desc != NULL) { XkbDescRec *desc; desc = get_xkb_desc_rec (manager); if (desc != NULL) { if (p->desc->ctrls->enabled_ctrls != desc->ctrls->enabled_ctrls) { gdk_error_trap_push (); XkbSetControls (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), DEFAULT_XKB_SET_CONTROLS_MASK, p->desc); XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); gdk_error_trap_pop_ignored (); } XkbFreeKeyboard (desc, XkbAllComponentsMask, True); } XkbFreeKeyboard (p->desc, XkbAllComponentsMask, True); p->desc = NULL; } if (p->start_idle_id != 0) { g_source_remove (p->start_idle_id); p->start_idle_id = 0; } if (p->device_manager != NULL) { g_signal_handler_disconnect (p->device_manager, p->device_added_id); p->device_manager = NULL; } if (p->settings != NULL) { g_signal_handlers_disconnect_by_func (p->settings, keyboard_callback, manager); g_object_unref (p->settings); p->settings = NULL; } gdk_window_remove_filter (NULL, (GdkFilterFunc) cb_xkb_event_filter, manager); p->slowkeys_shortcut_val = FALSE; p->stickykeys_shortcut_val = FALSE; } static void gsd_a11y_keyboard_manager_class_init (GsdA11yKeyboardManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_a11y_keyboard_manager_finalize; g_type_class_add_private (klass, sizeof (GsdA11yKeyboardManagerPrivate)); } static void gsd_a11y_keyboard_manager_init (GsdA11yKeyboardManager *manager) { manager->priv = GSD_A11Y_KEYBOARD_MANAGER_GET_PRIVATE (manager); } static void gsd_a11y_keyboard_manager_finalize (GObject *object) { GsdA11yKeyboardManager *a11y_keyboard_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_A11Y_KEYBOARD_MANAGER (object)); a11y_keyboard_manager = GSD_A11Y_KEYBOARD_MANAGER (object); g_return_if_fail (a11y_keyboard_manager->priv != NULL); gsd_a11y_keyboard_manager_stop (a11y_keyboard_manager); G_OBJECT_CLASS (gsd_a11y_keyboard_manager_parent_class)->finalize (object); } GsdA11yKeyboardManager * gsd_a11y_keyboard_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_A11Y_KEYBOARD_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_A11Y_KEYBOARD_MANAGER (manager_object); } unity-settings-daemon/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.h0000664000000000000000000000474515172222611023165 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_A11Y_KEYBOARD_MANAGER_H #define __GSD_A11Y_KEYBOARD_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_A11Y_KEYBOARD_MANAGER (gsd_a11y_keyboard_manager_get_type ()) #define GSD_A11Y_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManager)) #define GSD_A11Y_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManagerClass)) #define GSD_IS_A11Y_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER)) #define GSD_IS_A11Y_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_A11Y_KEYBOARD_MANAGER)) #define GSD_A11Y_KEYBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_A11Y_KEYBOARD_MANAGER, GsdA11yKeyboardManagerClass)) typedef struct GsdA11yKeyboardManagerPrivate GsdA11yKeyboardManagerPrivate; typedef struct { GObject parent; GsdA11yKeyboardManagerPrivate *priv; } GsdA11yKeyboardManager; typedef struct { GObjectClass parent_class; } GsdA11yKeyboardManagerClass; GType gsd_a11y_keyboard_manager_get_type (void); GsdA11yKeyboardManager *gsd_a11y_keyboard_manager_new (void); gboolean gsd_a11y_keyboard_manager_start (GsdA11yKeyboardManager *manager, GError **error); void gsd_a11y_keyboard_manager_stop (GsdA11yKeyboardManager *manager); G_END_DECLS #endif /* __GSD_A11Y_KEYBOARD_MANAGER_H */ unity-settings-daemon/plugins/a11y-keyboard/gsd-a11y-keyboard-plugin.c0000664000000000000000000000204415172222611023032 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-a11y-keyboard-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdA11yKeyboard, gsd_a11y_keyboard) unity-settings-daemon/plugins/a11y-keyboard/test-a11y-keyboard.c0000664000000000000000000000035415172222611021742 0ustar #define NEW gsd_a11y_keyboard_manager_new #define START gsd_a11y_keyboard_manager_start #define STOP gsd_a11y_keyboard_manager_stop #define MANAGER GsdA11yKeyboardManager #include "gsd-a11y-keyboard-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/a11y-settings/0000775000000000000000000000000015172222611016306 5ustar unity-settings-daemon/plugins/a11y-settings/Makefile.am0000664000000000000000000000270315172222611020344 0ustar plugin_name = a11y-settings libexec_PROGRAMS = usd-test-a11y-settings usd_test_a11y_settings_SOURCES = \ gsd-a11y-settings-manager.h \ gsd-a11y-settings-manager.c \ test-a11y-settings.c usd_test_a11y_settings_CFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_a11y_settings_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = \ liba11y-settings.la liba11y_settings_la_SOURCES = \ gsd-a11y-settings-manager.c \ gsd-a11y-settings-manager.h \ gsd-a11y-settings-plugin.c liba11y_settings_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) liba11y_settings_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) liba11y_settings_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) liba11y_settings_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(NULL) plugin_in_files = \ a11y-settings.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/a11y-settings/a11y-settings.gnome-settings-plugin.in0000664000000000000000000000034415172222611025506 0ustar [GNOME Settings Plugin] Module=a11y-settings IAge=0 Priority=7 _Name=Accessibility settings _Description=Accessibility settings plugin Authors=Bastien Nocera Copyright=Copyright © 2011 Red Hat Inc. Website= unity-settings-daemon/plugins/a11y-settings/gsd-a11y-settings-manager.c0000664000000000000000000001541215172222611023251 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-profile.h" #include "gsd-a11y-settings-manager.h" #define GSD_A11Y_SETTINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_A11Y_SETTINGS_MANAGER, GsdA11ySettingsManagerPrivate)) struct GsdA11ySettingsManagerPrivate { GSettings *interface_settings; GSettings *a11y_apps_settings; }; enum { PROP_0, }; static void gsd_a11y_settings_manager_class_init (GsdA11ySettingsManagerClass *klass); static void gsd_a11y_settings_manager_init (GsdA11ySettingsManager *a11y_settings_manager); static void gsd_a11y_settings_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdA11ySettingsManager, gsd_a11y_settings_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void apps_settings_changed (GSettings *settings, const char *key, GsdA11ySettingsManager *manager) { gboolean screen_reader, keyboard; if (g_str_equal (key, "screen-reader-enabled") == FALSE && g_str_equal (key, "screen-keyboard-enabled") == FALSE) return; g_debug ("screen reader or OSK enablement changed"); screen_reader = g_settings_get_boolean (manager->priv->a11y_apps_settings, "screen-reader-enabled"); keyboard = g_settings_get_boolean (manager->priv->a11y_apps_settings, "screen-keyboard-enabled"); if (screen_reader || keyboard) { g_debug ("Enabling toolkit-accessibility, screen reader or OSK enabled"); g_settings_set_boolean (manager->priv->interface_settings, "toolkit-accessibility", TRUE); } else if (screen_reader == FALSE && keyboard == FALSE) { g_debug ("Disabling toolkit-accessibility, screen reader and OSK disabled"); g_settings_set_boolean (manager->priv->interface_settings, "toolkit-accessibility", FALSE); } } gboolean gsd_a11y_settings_manager_start (GsdA11ySettingsManager *manager, GError **error) { g_debug ("Starting a11y_settings manager"); gnome_settings_profile_start (NULL); manager->priv->interface_settings = g_settings_new ("org.gnome.desktop.interface"); manager->priv->a11y_apps_settings = g_settings_new ("org.gnome.desktop.a11y.applications"); g_signal_connect (G_OBJECT (manager->priv->a11y_apps_settings), "changed", G_CALLBACK (apps_settings_changed), manager); /* If any of the screen reader or on-screen keyboard are enabled, * make sure a11y is enabled for the toolkits. * We don't do the same thing for the reverse so it's possible to * enable AT-SPI for the toolkits without using an a11y app */ if (g_settings_get_boolean (manager->priv->a11y_apps_settings, "screen-keyboard-enabled") || g_settings_get_boolean (manager->priv->a11y_apps_settings, "screen-reader-enabled")) g_settings_set_boolean (manager->priv->interface_settings, "toolkit-accessibility", TRUE); gnome_settings_profile_end (NULL); return TRUE; } void gsd_a11y_settings_manager_stop (GsdA11ySettingsManager *manager) { if (manager->priv->interface_settings) { g_object_unref (manager->priv->interface_settings); manager->priv->interface_settings = NULL; } if (manager->priv->a11y_apps_settings) { g_object_unref (manager->priv->a11y_apps_settings); manager->priv->a11y_apps_settings = NULL; } g_debug ("Stopping a11y_settings manager"); } static GObject * gsd_a11y_settings_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdA11ySettingsManager *a11y_settings_manager; a11y_settings_manager = GSD_A11Y_SETTINGS_MANAGER (G_OBJECT_CLASS (gsd_a11y_settings_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (a11y_settings_manager); } static void gsd_a11y_settings_manager_dispose (GObject *object) { G_OBJECT_CLASS (gsd_a11y_settings_manager_parent_class)->dispose (object); } static void gsd_a11y_settings_manager_class_init (GsdA11ySettingsManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_a11y_settings_manager_constructor; object_class->dispose = gsd_a11y_settings_manager_dispose; object_class->finalize = gsd_a11y_settings_manager_finalize; g_type_class_add_private (klass, sizeof (GsdA11ySettingsManagerPrivate)); } static void gsd_a11y_settings_manager_init (GsdA11ySettingsManager *manager) { manager->priv = GSD_A11Y_SETTINGS_MANAGER_GET_PRIVATE (manager); } static void gsd_a11y_settings_manager_finalize (GObject *object) { GsdA11ySettingsManager *a11y_settings_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_A11Y_SETTINGS_MANAGER (object)); a11y_settings_manager = GSD_A11Y_SETTINGS_MANAGER (object); g_return_if_fail (a11y_settings_manager->priv != NULL); G_OBJECT_CLASS (gsd_a11y_settings_manager_parent_class)->finalize (object); } GsdA11ySettingsManager * gsd_a11y_settings_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_A11Y_SETTINGS_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_A11Y_SETTINGS_MANAGER (manager_object); } unity-settings-daemon/plugins/a11y-settings/gsd-a11y-settings-manager.h0000664000000000000000000000474115172222611023261 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_A11Y_SETTINGS_MANAGER_H #define __GSD_A11Y_SETTINGS_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_A11Y_SETTINGS_MANAGER (gsd_a11y_settings_manager_get_type ()) #define GSD_A11Y_SETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_A11Y_SETTINGS_MANAGER, GsdA11ySettingsManager)) #define GSD_A11Y_SETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_A11Y_SETTINGS_MANAGER, GsdA11ySettingsManagerClass)) #define GSD_IS_A11Y_SETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_A11Y_SETTINGS_MANAGER)) #define GSD_IS_A11Y_SETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_A11Y_SETTINGS_MANAGER)) #define GSD_A11Y_SETTINGS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_A11Y_SETTINGS_MANAGER, GsdA11ySettingsManagerClass)) typedef struct GsdA11ySettingsManagerPrivate GsdA11ySettingsManagerPrivate; typedef struct { GObject parent; GsdA11ySettingsManagerPrivate *priv; } GsdA11ySettingsManager; typedef struct { GObjectClass parent_class; } GsdA11ySettingsManagerClass; GType gsd_a11y_settings_manager_get_type (void); GsdA11ySettingsManager *gsd_a11y_settings_manager_new (void); gboolean gsd_a11y_settings_manager_start (GsdA11ySettingsManager *manager, GError **error); void gsd_a11y_settings_manager_stop (GsdA11ySettingsManager *manager); G_END_DECLS #endif /* __GSD_A11Y_SETTINGS_MANAGER_H */ unity-settings-daemon/plugins/a11y-settings/gsd-a11y-settings-plugin.c0000664000000000000000000000204415172222611023132 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-a11y-settings-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdA11ySettings, gsd_a11y_settings) unity-settings-daemon/plugins/a11y-settings/test-a11y-settings.c0000664000000000000000000000035415172222611022042 0ustar #define NEW gsd_a11y_settings_manager_new #define START gsd_a11y_settings_manager_start #define STOP gsd_a11y_settings_manager_stop #define MANAGER GsdA11ySettingsManager #include "gsd-a11y-settings-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/automount/0000775000000000000000000000000015172222611015730 5ustar unity-settings-daemon/plugins/automount/Makefile.am0000664000000000000000000000201515172222611017762 0ustar libexec_PROGRAMS = unity-fallback-mount-helper unity_fallback_mount_helper_SOURCES = \ gnome-fallback-mount-helper.c \ gsd-automount-manager.c \ gsd-automount-manager.h \ gsd-autorun.c \ gsd-autorun.h unity_fallback_mount_helper_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) unity_fallback_mount_helper_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AUTOMOUNT_CFLAGS) unity_fallback_mount_helper_LDADD = \ $(SETTINGS_PLUGIN_LIBS) \ $(AUTOMOUNT_LIBS) \ $(top_builddir)/gnome-settings-daemon/libgsd.la autostartdir = $(sysconfdir)/xdg/autostart autostart_in_files = unity-fallback-mount-helper.desktop.in autostart_in_in_files = unity-fallback-mount-helper.desktop.in.in autostart_DATA = $(autostart_in_files:.desktop.in=.desktop) $(autostart_in_files): $(autostart_in_in_files) @sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@ @INTLTOOL_DESKTOP_RULE@ EXTRA_DIST = $(autostart_in_in_files) CLEANFILES = $(autostart_DATA) $(autostart_in_files) unity-settings-daemon/plugins/automount/gnome-fallback-mount-helper.c0000664000000000000000000000351115172222611023353 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Tomas Bzatek */ #include "config.h" #include #include #include #include #include "gsd-automount-manager.h" int main (int argc, char **argv) { GMainLoop *loop; GsdAutomountManager *manager; GError *error = NULL; gtk_init (&argc, &argv); bindtextdomain (GETTEXT_PACKAGE, GNOME_SETTINGS_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); loop = g_main_loop_new (NULL, FALSE); manager = gsd_automount_manager_new (); gsd_automount_manager_start (manager, &error); if (error != NULL) { g_printerr ("Unable to start the mount manager: %s", error->message); g_error_free (error); _exit (1); } g_main_loop_run (loop); gsd_automount_manager_stop (manager); g_main_loop_unref (loop); return 0; } unity-settings-daemon/plugins/automount/gsd-automount-manager.c0000664000000000000000000005214415172222611022320 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Tomas Bzatek */ #include "config.h" #include #include #include #include #include #include "gnome-settings-profile.h" #include "gnome-settings-bus.h" #include "gsd-automount-manager.h" #include "gsd-autorun.h" #define GSD_AUTOMOUNT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_AUTOMOUNT_MANAGER, GsdAutomountManagerPrivate)) struct GsdAutomountManagerPrivate { GSettings *settings; GVolumeMonitor *volume_monitor; unsigned int automount_idle_id; GDBusProxy *session; gboolean session_is_active; gboolean screensaver_active; gboolean lockscreen_active; guint ss_watch_id; guint us_watch_id; GDBusProxy *ss_proxy; GDBusProxy *us_proxy; GList *volume_queue; }; static void gsd_automount_manager_class_init (GsdAutomountManagerClass *klass); static void gsd_automount_manager_init (GsdAutomountManager *gsd_automount_manager); G_DEFINE_TYPE (GsdAutomountManager, gsd_automount_manager, G_TYPE_OBJECT) static GtkDialog * show_error_dialog (const char *primary_text, const char *secondary_text) { GtkWidget *dialog; dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", ""); g_object_set (dialog, "text", primary_text, "secondary-text", secondary_text, NULL); gtk_widget_show (GTK_WIDGET (dialog)); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); return GTK_DIALOG (dialog); } static void startup_volume_mount_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { g_volume_mount_finish (G_VOLUME (source_object), res, NULL); } static void automount_all_volumes (GsdAutomountManager *manager) { GList *volumes, *l; GMount *mount; GVolume *volume; if (g_settings_get_boolean (manager->priv->settings, "automount")) { /* automount all mountable volumes at start-up */ volumes = g_volume_monitor_get_volumes (manager->priv->volume_monitor); for (l = volumes; l != NULL; l = l->next) { volume = l->data; if (!g_volume_should_automount (volume) || !g_volume_can_mount (volume)) { continue; } mount = g_volume_get_mount (volume); if (mount != NULL) { g_object_unref (mount); continue; } /* pass NULL as GMountOperation to avoid user interaction */ g_volume_mount (volume, 0, NULL, NULL, startup_volume_mount_cb, NULL); } g_list_free_full (volumes, g_object_unref); } } static gboolean automount_all_volumes_idle_cb (gpointer data) { GsdAutomountManager *manager = GSD_AUTOMOUNT_MANAGER (data); automount_all_volumes (manager); manager->priv->automount_idle_id = 0; return FALSE; } static void volume_mount_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GMountOperation *mount_op = user_data; GError *error; char *primary; char *name; error = NULL; gsd_allow_autorun_for_volume_finish (G_VOLUME (source_object)); if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) { if (error->code != G_IO_ERROR_FAILED_HANDLED) { name = g_volume_get_name (G_VOLUME (source_object)); primary = g_strdup_printf (_("Unable to mount %s"), name); g_free (name); show_error_dialog (primary, error->message); g_free (primary); } g_error_free (error); } g_object_unref (mount_op); } static void do_mount_volume (GVolume *volume) { GMountOperation *mount_op; mount_op = gtk_mount_operation_new (NULL); g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION); gsd_allow_autorun_for_volume (volume); g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, mount_op); } static void check_volume_queue (GsdAutomountManager *manager) { GList *l; GVolume *volume; if (manager->priv->screensaver_active || manager->priv->lockscreen_active) return; l = manager->priv->volume_queue; while (l != NULL) { volume = l->data; do_mount_volume (volume); manager->priv->volume_queue = g_list_remove (manager->priv->volume_queue, volume); g_object_unref (volume); l = l->next; } manager->priv->volume_queue = NULL; } static void clear_volume_queue (GsdAutomountManager *manager) { if (!manager->priv->volume_queue) return; g_list_free_full (manager->priv->volume_queue, g_object_unref); manager->priv->volume_queue = NULL; } static void check_screen_lock_and_mount (GsdAutomountManager *manager, GVolume *volume) { if (!manager->priv->session_is_active) return; if (manager->priv->screensaver_active || manager->priv->lockscreen_active) { /* queue the volume, to mount it after the screensaver state changed */ g_debug ("Queuing volume %p", volume); manager->priv->volume_queue = g_list_prepend (manager->priv->volume_queue, g_object_ref (volume)); } else { /* mount it immediately */ do_mount_volume (volume); } } static void volume_removed_callback (GVolumeMonitor *monitor, GVolume *volume, GsdAutomountManager *manager) { g_debug ("Volume %p removed, removing from the queue", volume); /* clear it from the queue, if present */ manager->priv->volume_queue = g_list_remove (manager->priv->volume_queue, volume); } static void volume_added_callback (GVolumeMonitor *monitor, GVolume *volume, GsdAutomountManager *manager) { if (g_settings_get_boolean (manager->priv->settings, "automount") && g_volume_should_automount (volume) && g_volume_can_mount (volume)) { check_screen_lock_and_mount (manager, volume); } else { /* Allow gsd_autorun() to run. When the mount is later * added programmatically (i.e. for a blank CD), * gsd_autorun() will be called by mount_added_callback(). */ gsd_allow_autorun_for_volume (volume); gsd_allow_autorun_for_volume_finish (volume); } } static void autorun_show_window (GMount *mount, gpointer user_data) { GFile *location; char *uri; GError *error; char *primary; char *name; location = g_mount_get_root (mount); uri = g_file_get_uri (location); error = NULL; /* use default folder handler */ if (! gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, &error)) { name = g_mount_get_name (mount); primary = g_strdup_printf (_("Unable to open a folder for %s"), name); g_free (name); show_error_dialog (primary, error->message); g_free (primary); g_error_free (error); } g_free (uri); g_object_unref (location); } static void mount_added_callback (GVolumeMonitor *monitor, GMount *mount, GsdAutomountManager *manager) { /* don't autorun if the session is not active */ if (!manager->priv->session_is_active) { return; } gsd_autorun (mount, manager->priv->settings, autorun_show_window, manager); } static void session_state_changed (GDBusProxy *session, GVariant *changed, char **invalidated, GsdAutomountManager *manager) { GsdAutomountManagerPrivate *p = manager->priv; GVariant *v; v = g_variant_lookup_value (changed, "SessionIsActive", G_VARIANT_TYPE_BOOLEAN); if (v) { gboolean active; active = g_variant_get_boolean (v); g_debug ("Received session is active change: now %s", active ? "active" : "inactive"); /* when doing the fast-user-switch into a new account, * ensure the new account is undimmed and with the backlight on */ if (active) p->session_is_active = TRUE; else p->session_is_active = FALSE; g_variant_unref (v); } if (!p->session_is_active) { if (p->volume_queue != NULL) { g_list_free_full (p->volume_queue, g_object_unref); p->volume_queue = NULL; } } } static gboolean is_session_active (GsdAutomountManager *manager) { GVariant *variant; gboolean is_session_active = FALSE; variant = g_dbus_proxy_get_cached_property (manager->priv->session, "SessionIsActive"); if (variant) { is_session_active = g_variant_get_boolean (variant); g_variant_unref (variant); } return is_session_active; } static void do_initialize_session (GsdAutomountManager *manager) { manager->priv->session = G_DBUS_PROXY (gnome_settings_bus_get_session_proxy ()); g_signal_connect (manager->priv->session, "g-properties-changed", G_CALLBACK (session_state_changed), manager); manager->priv->session_is_active = is_session_active (manager); } #define SCREENSAVER_NAME "org.gnome.ScreenSaver" static void screensaver_signal_callback (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { GsdAutomountManager *manager = user_data; if (g_strcmp0 (signal_name, "ActiveChanged") == 0) { g_variant_get (parameters, "(b)", &manager->priv->screensaver_active); g_debug ("Screensaver active changed to %d", manager->priv->screensaver_active); check_volume_queue (manager); } } static void screensaver_get_active_ready_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GsdAutomountManager *manager = user_data; GDBusProxy *proxy = manager->priv->ss_proxy; GVariant *result; GError *error = NULL; result = g_dbus_proxy_call_finish (proxy, res, &error); if (error != NULL) { g_warning ("Can't call GetActive() on the ScreenSaver object: %s", error->message); g_error_free (error); return; } g_variant_get (result, "(b)", &manager->priv->screensaver_active); g_variant_unref (result); g_debug ("Screensaver GetActive() returned %d", manager->priv->screensaver_active); } static void screensaver_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { GsdAutomountManager *manager = user_data; g_debug ("ScreenSaver name appeared"); manager->priv->ss_proxy = G_DBUS_PROXY (gnome_settings_bus_get_screen_saver_proxy ()); if (manager->priv->ss_proxy == NULL) { g_warning ("Can't get proxy for the ScreenSaver object"); return; } g_debug ("ScreenSaver proxy ready"); g_signal_connect (manager->priv->ss_proxy, "g-signal", G_CALLBACK (screensaver_signal_callback), manager); g_dbus_proxy_call (manager->priv->ss_proxy, "GetActive", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, screensaver_get_active_ready_cb, manager); } static void screensaver_vanished_callback (GDBusConnection *connection, const gchar *name, gpointer user_data) { GsdAutomountManager *manager = user_data; g_debug ("ScreenSaver name vanished"); manager->priv->screensaver_active = FALSE; g_clear_object (&manager->priv->ss_proxy); if (!manager->priv->ss_proxy && !manager->priv->us_proxy) { /* in this case force a clear of the volume queue, without * mounting them. */ clear_volume_queue (manager); } } static void do_initialize_screensaver (GsdAutomountManager *manager) { GsdAutomountManagerPrivate *p = manager->priv; p->ss_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, SCREENSAVER_NAME, G_BUS_NAME_WATCHER_FLAGS_NONE, screensaver_appeared_callback, screensaver_vanished_callback, manager, NULL); } #define UNITY_NAME "com.canonical.Unity" #define UNITY_SESSION_PATH "/com/canonical/Unity/Session" #define UNITY_SESSION_INTERFACE "com.canonical.Unity.Session" static void unity_session_signal_callback (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { GsdAutomountManager *manager = user_data; if (g_strcmp0 (signal_name, "Locked") == 0) { manager->priv->lockscreen_active = TRUE; check_volume_queue (manager); g_debug ("Unity.Session Locked"); } else if (g_strcmp0 (signal_name, "Unlocked") == 0) { manager->priv->lockscreen_active = FALSE; check_volume_queue (manager); g_debug ("Unity.Session Unlocked"); } } static void unity_session_is_locked_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GsdAutomountManager *manager = user_data; GDBusProxy *proxy = manager->priv->us_proxy; GVariant *result; GError *error = NULL; result = g_dbus_proxy_call_finish (proxy, res, &error); if (error != NULL) { g_warning ("Can't call IsLocked() on the Unity.Session object: %s", error->message); g_error_free (error); return; } g_variant_get (result, "(b)", &manager->priv->lockscreen_active); g_variant_unref (result); g_debug ("Unity Session IsLocked() returned %d", manager->priv->lockscreen_active); } static void unity_session_proxy_ready_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GsdAutomountManager *manager = user_data; GError *error = NULL; GDBusProxy *us_proxy; us_proxy = g_dbus_proxy_new_finish (res, &error); if (error != NULL) { g_warning ("Can't get proxy for the Unity Session object: %s", error->message); g_error_free (error); return; } g_debug ("Unity Session proxy ready"); manager->priv->us_proxy = us_proxy; g_signal_connect (us_proxy, "g-signal", G_CALLBACK (unity_session_signal_callback), manager); g_dbus_proxy_call (us_proxy, "IsLocked", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, unity_session_is_locked_cb, manager); } static void unity_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { GsdAutomountManager *manager = user_data; g_debug ("Unity name appeared"); manager->priv->lockscreen_active = FALSE; g_dbus_proxy_new (connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, name, UNITY_SESSION_PATH, UNITY_SESSION_INTERFACE, NULL, unity_session_proxy_ready_cb, manager); } static void unity_vanished_callback (GDBusConnection *connection, const gchar *name, gpointer user_data) { GsdAutomountManager *manager = user_data; g_debug ("Unity name vanished"); manager->priv->lockscreen_active = FALSE; g_clear_object (&manager->priv->us_proxy); if (!manager->priv->ss_proxy && !manager->priv->us_proxy) { /* in this case force a clear of the volume queue, without * mounting them. */ clear_volume_queue (manager); } } static void do_initialize_lockscreen (GsdAutomountManager *manager) { GsdAutomountManagerPrivate *p = manager->priv; p->us_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, UNITY_NAME, G_BUS_NAME_WATCHER_FLAGS_NONE, unity_appeared_callback, unity_vanished_callback, manager, NULL); } static void setup_automounter (GsdAutomountManager *manager) { do_initialize_session (manager); do_initialize_screensaver (manager); do_initialize_lockscreen (manager); manager->priv->volume_monitor = g_volume_monitor_get (); g_signal_connect_object (manager->priv->volume_monitor, "mount-added", G_CALLBACK (mount_added_callback), manager, 0); g_signal_connect_object (manager->priv->volume_monitor, "volume-added", G_CALLBACK (volume_added_callback), manager, 0); g_signal_connect_object (manager->priv->volume_monitor, "volume-removed", G_CALLBACK (volume_removed_callback), manager, 0); manager->priv->automount_idle_id = g_idle_add_full (G_PRIORITY_LOW, automount_all_volumes_idle_cb, manager, NULL); } gboolean gsd_automount_manager_start (GsdAutomountManager *manager, GError **error) { g_debug ("Starting automounting manager"); gnome_settings_profile_start (NULL); manager->priv->settings = g_settings_new ("org.gnome.desktop.media-handling"); setup_automounter (manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_automount_manager_stop (GsdAutomountManager *manager) { GsdAutomountManagerPrivate *p = manager->priv; g_debug ("Stopping automounting manager"); if (p->ss_proxy) { g_signal_handlers_disconnect_by_data (p->ss_proxy, manager); } g_clear_object (&p->session); g_clear_object (&p->volume_monitor); g_clear_object (&p->settings); g_clear_object (&p->ss_proxy); g_clear_object (&p->us_proxy); g_bus_unwatch_name (p->ss_watch_id); g_bus_unwatch_name (p->us_watch_id); if (p->volume_queue != NULL) { g_list_free_full (p->volume_queue, g_object_unref); p->volume_queue = NULL; } if (p->automount_idle_id != 0) { g_source_remove (p->automount_idle_id); p->automount_idle_id = 0; } } static void gsd_automount_manager_class_init (GsdAutomountManagerClass *klass) { g_type_class_add_private (klass, sizeof (GsdAutomountManagerPrivate)); } static void gsd_automount_manager_init (GsdAutomountManager *manager) { manager->priv = GSD_AUTOMOUNT_MANAGER_GET_PRIVATE (manager); } GsdAutomountManager * gsd_automount_manager_new (void) { return GSD_AUTOMOUNT_MANAGER (g_object_new (GSD_TYPE_AUTOMOUNT_MANAGER, NULL)); } unity-settings-daemon/plugins/automount/gsd-automount-manager.h0000664000000000000000000000461315172222611022323 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Tomas Bzatek */ #ifndef __GSD_AUTOMOUNT_MANAGER_H #define __GSD_AUTOMOUNT_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_AUTOMOUNT_MANAGER (gsd_automount_manager_get_type ()) #define GSD_AUTOMOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_AUTOMOUNT_MANAGER, GsdAutomountManager)) #define GSD_AUTOMOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_AUTOMOUNT_MANAGER, GsdAutomountManagerClass)) #define GSD_IS_AUTOMOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_AUTOMOUNT_MANAGER)) #define GSD_IS_AUTOMOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_AUTOMOUNT_MANAGER)) #define GSD_AUTOMOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_AUTOMOUNT_MANAGER, GsdAutomountManagerClass)) typedef struct GsdAutomountManagerPrivate GsdAutomountManagerPrivate; typedef struct { GObject parent; GsdAutomountManagerPrivate *priv; } GsdAutomountManager; typedef struct { GObjectClass parent_class; } GsdAutomountManagerClass; GType gsd_automount_manager_get_type (void); GsdAutomountManager * gsd_automount_manager_new (void); gboolean gsd_automount_manager_start (GsdAutomountManager *manager, GError **error); void gsd_automount_manager_stop (GsdAutomountManager *manager); G_END_DECLS #endif /* __GSD_AUTOMOUNT_MANAGER_H */ unity-settings-daemon/plugins/automount/gsd-autorun.c0000664000000000000000000007057215172222611020357 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ /* * gsd-automount.c: helpers for automounting hotplugged volumes * * Copyright (C) 2008, 2010 Red Hat, Inc. * * Nautilus is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: David Zeuthen * Cosimo Cecchi */ #include #include #include #include #include #include #include #include #include "gsd-autorun.h" static gboolean should_autorun_mount (GMount *mount); #define CUSTOM_ITEM_ASK "gsd-item-ask" #define CUSTOM_ITEM_DO_NOTHING "gsd-item-do-nothing" #define CUSTOM_ITEM_OPEN_FOLDER "gsd-item-open-folder" typedef struct { GtkWidget *dialog; GMount *mount; gboolean should_eject; gboolean selected_ignore; gboolean selected_open_folder; GAppInfo *selected_app; gboolean remember; char *x_content_type; GsdAutorunOpenWindow open_window_func; gpointer user_data; } AutorunDialogData; static int gsd_autorun_g_strv_find (char **strv, const char *find_me) { guint index; g_return_val_if_fail (find_me != NULL, -1); for (index = 0; strv[index] != NULL; ++index) { if (strcmp (strv[index], find_me) == 0) { return index; } } return -1; } #define ICON_SIZE_STANDARD 48 static gint get_icon_size_for_stock_size (GtkIconSize size) { gint w, h; if (gtk_icon_size_lookup (size, &w, &h)) { return MAX (w, h); } return ICON_SIZE_STANDARD; } static GdkPixbuf * render_icon (GIcon *icon, gint icon_size) { GdkPixbuf *pixbuf; GtkIconInfo *info; pixbuf = NULL; if (G_IS_THEMED_ICON (icon)) { gchar const * const *names; info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (), icon, icon_size, 0); if (info) { pixbuf = gtk_icon_info_load_icon (info, NULL); g_object_unref (info); } if (pixbuf == NULL) { names = g_themed_icon_get_names (G_THEMED_ICON (icon)); pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), *names, icon_size, 0, NULL); } } else if (G_IS_FILE_ICON (icon)) { GFile *icon_file; gchar *path; icon_file = g_file_icon_get_file (G_FILE_ICON (icon)); path = g_file_get_path (icon_file); pixbuf = gdk_pixbuf_new_from_file_at_size (path, icon_size, icon_size, NULL); g_free (path); g_object_unref (G_OBJECT (icon_file)); } return pixbuf; } static void gsd_autorun_get_preferences (const char *x_content_type, gboolean *pref_start_app, gboolean *pref_ignore, gboolean *pref_open_folder) { GSettings *settings; char **x_content_start_app; char **x_content_ignore; char **x_content_open_folder; g_return_if_fail (pref_start_app != NULL); g_return_if_fail (pref_ignore != NULL); g_return_if_fail (pref_open_folder != NULL); settings = g_settings_new ("org.gnome.desktop.media-handling"); *pref_start_app = FALSE; *pref_ignore = FALSE; *pref_open_folder = FALSE; x_content_start_app = g_settings_get_strv (settings, "autorun-x-content-start-app"); x_content_ignore = g_settings_get_strv (settings, "autorun-x-content-ignore"); x_content_open_folder = g_settings_get_strv (settings, "autorun-x-content-open-folder"); if (x_content_start_app != NULL) { *pref_start_app = gsd_autorun_g_strv_find (x_content_start_app, x_content_type) != -1; } if (x_content_ignore != NULL) { *pref_ignore = gsd_autorun_g_strv_find (x_content_ignore, x_content_type) != -1; } if (x_content_open_folder != NULL) { *pref_open_folder = gsd_autorun_g_strv_find (x_content_open_folder, x_content_type) != -1; } g_strfreev (x_content_ignore); g_strfreev (x_content_start_app); g_strfreev (x_content_open_folder); g_object_unref (settings); } static char ** remove_elem_from_str_array (char **v, const char *s) { GPtrArray *array; guint idx; array = g_ptr_array_new (); for (idx = 0; v[idx] != NULL; idx++) { if (g_strcmp0 (v[idx], s) == 0) { continue; } g_ptr_array_add (array, v[idx]); } g_ptr_array_add (array, NULL); g_free (v); return (char **) g_ptr_array_free (array, FALSE); } static char ** add_elem_to_str_array (char **v, const char *s) { GPtrArray *array; guint idx; array = g_ptr_array_new (); for (idx = 0; v[idx] != NULL; idx++) { g_ptr_array_add (array, v[idx]); } g_ptr_array_add (array, g_strdup (s)); g_ptr_array_add (array, NULL); g_free (v); return (char **) g_ptr_array_free (array, FALSE); } static void gsd_autorun_set_preferences (const char *x_content_type, gboolean pref_start_app, gboolean pref_ignore, gboolean pref_open_folder) { GSettings *settings; char **x_content_start_app; char **x_content_ignore; char **x_content_open_folder; g_assert (x_content_type != NULL); settings = g_settings_new ("org.gnome.desktop.media-handling"); x_content_start_app = g_settings_get_strv (settings, "autorun-x-content-start-app"); x_content_ignore = g_settings_get_strv (settings, "autorun-x-content-ignore"); x_content_open_folder = g_settings_get_strv (settings, "autorun-x-content-open-folder"); x_content_start_app = remove_elem_from_str_array (x_content_start_app, x_content_type); if (pref_start_app) { x_content_start_app = add_elem_to_str_array (x_content_start_app, x_content_type); } g_settings_set_strv (settings, "autorun-x-content-start-app", (const gchar * const*) x_content_start_app); x_content_ignore = remove_elem_from_str_array (x_content_ignore, x_content_type); if (pref_ignore) { x_content_ignore = add_elem_to_str_array (x_content_ignore, x_content_type); } g_settings_set_strv (settings, "autorun-x-content-ignore", (const gchar * const*) x_content_ignore); x_content_open_folder = remove_elem_from_str_array (x_content_open_folder, x_content_type); if (pref_open_folder) { x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type); } g_settings_set_strv (settings, "autorun-x-content-open-folder", (const gchar * const*) x_content_open_folder); g_strfreev (x_content_open_folder); g_strfreev (x_content_ignore); g_strfreev (x_content_start_app); g_object_unref (settings); } static void custom_item_activated_cb (GtkAppChooserButton *button, const gchar *item, gpointer user_data) { gchar *content_type; AutorunDialogData *data = user_data; content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (button)); if (g_strcmp0 (item, CUSTOM_ITEM_ASK) == 0) { gsd_autorun_set_preferences (content_type, FALSE, FALSE, FALSE); data->selected_open_folder = FALSE; data->selected_ignore = FALSE; } else if (g_strcmp0 (item, CUSTOM_ITEM_OPEN_FOLDER) == 0) { gsd_autorun_set_preferences (content_type, FALSE, FALSE, TRUE); data->selected_open_folder = TRUE; data->selected_ignore = FALSE; } else if (g_strcmp0 (item, CUSTOM_ITEM_DO_NOTHING) == 0) { gsd_autorun_set_preferences (content_type, FALSE, TRUE, FALSE); data->selected_open_folder = FALSE; data->selected_ignore = TRUE; } g_free (content_type); } static void combo_box_changed_cb (GtkComboBox *combo_box, gpointer user_data) { GAppInfo *info; AutorunDialogData *data = user_data; info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box)); if (info == NULL) return; g_clear_object (&data->selected_app); data->selected_app = info; } static void prepare_combo_box (GtkWidget *combo_box, AutorunDialogData *data) { GtkAppChooserButton *app_chooser = GTK_APP_CHOOSER_BUTTON (combo_box); GIcon *icon; gboolean pref_ask; gboolean pref_start_app; gboolean pref_ignore; gboolean pref_open_folder; GAppInfo *info; gchar *content_type; content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (app_chooser)); /* fetch preferences for this content type */ gsd_autorun_get_preferences (content_type, &pref_start_app, &pref_ignore, &pref_open_folder); pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder; info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box)); /* append the separator only if we have >= 1 apps in the chooser */ if (info != NULL) { gtk_app_chooser_button_append_separator (app_chooser); g_object_unref (info); } icon = g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION); gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_ASK, _("Ask what to do"), icon); g_object_unref (icon); icon = g_themed_icon_new (GTK_STOCK_CLOSE); gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING, _("Do Nothing"), icon); g_object_unref (icon); icon = g_themed_icon_new ("folder-open"); gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER, _("Open Folder"), icon); g_object_unref (icon); gtk_app_chooser_button_set_show_dialog_item (app_chooser, TRUE); if (pref_ask) { gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_ASK); } else if (pref_ignore) { gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING); } else if (pref_open_folder) { gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER); } g_signal_connect (app_chooser, "changed", G_CALLBACK (combo_box_changed_cb), data); g_signal_connect (app_chooser, "custom-item-activated", G_CALLBACK (custom_item_activated_cb), data); g_free (content_type); } static gboolean is_shift_pressed (void) { gboolean ret; XkbStateRec state; Bool status; ret = FALSE; gdk_error_trap_push (); status = XkbGetState (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbUseCoreKbd, &state); gdk_error_trap_pop_ignored (); if (status == Success) { ret = state.mods & ShiftMask; } return ret; } enum { AUTORUN_DIALOG_RESPONSE_EJECT = 0 }; static void gsd_autorun_launch_for_mount (GMount *mount, GAppInfo *app_info) { GFile *root; GdkAppLaunchContext *launch_context; GError *error; gboolean result; GList *list; gchar *uri_scheme; gchar *uri; root = g_mount_get_root (mount); list = g_list_append (NULL, root); launch_context = gdk_app_launch_context_new (); error = NULL; result = g_app_info_launch (app_info, list, G_APP_LAUNCH_CONTEXT (launch_context), &error); g_object_unref (launch_context); if (!result) { if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_SUPPORTED) { uri = g_file_get_uri (root); uri_scheme = g_uri_parse_scheme (uri); /* FIXME: Present user a dialog to choose another app when the last one failed to handle a file */ g_warning ("Cannot open location: %s\n", error->message); g_free (uri_scheme); g_free (uri); } else { g_warning ("Cannot open app: %s\n", error->message); } g_error_free (error); } g_list_free (list); g_object_unref (root); } static void autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data); static void autorun_dialog_destroy (AutorunDialogData *data) { g_signal_handlers_disconnect_by_func (G_OBJECT (data->mount), G_CALLBACK (autorun_dialog_mount_unmounted), data); gtk_widget_destroy (GTK_WIDGET (data->dialog)); if (data->selected_app != NULL) { g_object_unref (data->selected_app); } g_object_unref (data->mount); g_free (data->x_content_type); g_free (data); } static void autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data) { /* remove the dialog if the media is unmounted */ autorun_dialog_destroy (data); } static void unmount_mount_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error; char *primary; gboolean unmounted; gboolean should_eject; GtkWidget *dialog; should_eject = user_data != NULL; error = NULL; if (should_eject) { unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object), res, &error); } else { unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object), res, &error); } if (! unmounted) { if (error->code != G_IO_ERROR_FAILED_HANDLED) { if (should_eject) { primary = g_strdup_printf (_("Unable to eject %p"), source_object); } else { primary = g_strdup_printf (_("Unable to unmount %p"), source_object); } dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", primary); gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", error->message); gtk_widget_show (GTK_WIDGET (dialog)); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); g_free (primary); } } if (error != NULL) { g_error_free (error); } } static void do_unmount (GMount *mount, gboolean should_eject, GtkWindow *window) { GMountOperation *mount_op; mount_op = gtk_mount_operation_new (window); if (should_eject) { g_mount_eject_with_operation (mount, 0, mount_op, NULL, unmount_mount_callback, (gpointer) 1); } else { g_mount_unmount_with_operation (mount, 0, mount_op, NULL, unmount_mount_callback, (gpointer) 0); } g_object_unref (mount_op); } static void autorun_dialog_response (GtkDialog *dialog, gint response, AutorunDialogData *data) { switch (response) { case AUTORUN_DIALOG_RESPONSE_EJECT: do_unmount (data->mount, data->should_eject, GTK_WINDOW (dialog)); break; case GTK_RESPONSE_NONE: /* window was closed */ break; case GTK_RESPONSE_CANCEL: break; case GTK_RESPONSE_OK: /* do the selected action */ if (data->remember) { /* make sure we don't ask again */ gsd_autorun_set_preferences (data->x_content_type, TRUE, data->selected_ignore, data->selected_open_folder); if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) { g_app_info_set_as_default_for_type (data->selected_app, data->x_content_type, NULL); } } else { /* make sure we do ask again */ gsd_autorun_set_preferences (data->x_content_type, FALSE, FALSE, FALSE); } if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) { gsd_autorun_launch_for_mount (data->mount, data->selected_app); } else if (!data->selected_ignore && data->selected_open_folder) { if (data->open_window_func != NULL) data->open_window_func (data->mount, data->user_data); } break; } autorun_dialog_destroy (data); } static void autorun_always_toggled (GtkToggleButton *togglebutton, AutorunDialogData *data) { data->remember = gtk_toggle_button_get_active (togglebutton); } static gboolean combo_box_enter_ok (GtkWidget *togglebutton, GdkEventKey *event, GtkDialog *dialog) { if (event->keyval == GDK_KEY_KP_Enter || event->keyval == GDK_KEY_Return) { gtk_dialog_response (dialog, GTK_RESPONSE_OK); return TRUE; } return FALSE; } /* returns TRUE if a folder window should be opened */ static gboolean do_autorun_for_content_type (GMount *mount, const char *x_content_type, GsdAutorunOpenWindow open_window_func, gpointer user_data) { AutorunDialogData *data; GtkWidget *dialog; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *label; GtkWidget *combo_box; GtkWidget *always_check_button; GtkWidget *eject_button; GtkWidget *image; char *markup; char *content_description; char *mount_name; GIcon *icon; GdkPixbuf *pixbuf; int icon_size; gboolean user_forced_dialog; gboolean pref_ask; gboolean pref_start_app; gboolean pref_ignore; gboolean pref_open_folder; char *media_greeting; gboolean ret; ret = FALSE; mount_name = NULL; if (g_content_type_is_a (x_content_type, "x-content/win32-software")) { /* don't pop up the dialog anyway if the content type says * windows software. */ goto out; } user_forced_dialog = is_shift_pressed (); gsd_autorun_get_preferences (x_content_type, &pref_start_app, &pref_ignore, &pref_open_folder); pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder; if (user_forced_dialog) { goto show_dialog; } if (!pref_ask && !pref_ignore && !pref_open_folder) { GAppInfo *app_info; app_info = g_app_info_get_default_for_type (x_content_type, FALSE); if (app_info != NULL) { gsd_autorun_launch_for_mount (mount, app_info); } goto out; } if (pref_open_folder) { ret = TRUE; goto out; } if (pref_ignore) { goto out; } show_dialog: mount_name = g_mount_get_name (mount); dialog = gtk_dialog_new (); hbox = gtk_hbox_new (FALSE, 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 12); icon = g_mount_get_icon (mount); icon_size = get_icon_size_for_stock_size (GTK_ICON_SIZE_DIALOG); image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG); pixbuf = render_icon (icon, icon_size); gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0); /* also use the icon on the dialog */ gtk_window_set_title (GTK_WINDOW (dialog), mount_name); gtk_window_set_icon (GTK_WINDOW (dialog), pixbuf); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); g_object_unref (icon); if (pixbuf) { g_object_unref (pixbuf); } vbox = gtk_vbox_new (FALSE, 12); gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); label = gtk_label_new (NULL); /* Customize greeting for well-known x-content types */ if (strcmp (x_content_type, "x-content/audio-cdda") == 0) { media_greeting = _("You have just inserted an Audio CD."); } else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) { media_greeting = _("You have just inserted an Audio DVD."); } else if (strcmp (x_content_type, "x-content/video-dvd") == 0) { media_greeting = _("You have just inserted a Video DVD."); } else if (strcmp (x_content_type, "x-content/video-vcd") == 0) { media_greeting = _("You have just inserted a Video CD."); } else if (strcmp (x_content_type, "x-content/video-svcd") == 0) { media_greeting = _("You have just inserted a Super Video CD."); } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) { media_greeting = _("You have just inserted a blank CD."); } else if (strcmp (x_content_type, "x-content/blank-dvd") == 0) { media_greeting = _("You have just inserted a blank DVD."); } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) { media_greeting = _("You have just inserted a blank Blu-Ray disc."); } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) { media_greeting = _("You have just inserted a blank HD DVD."); } else if (strcmp (x_content_type, "x-content/image-photocd") == 0) { media_greeting = _("You have just inserted a Photo CD."); } else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) { media_greeting = _("You have just inserted a Picture CD."); } else if (strcmp (x_content_type, "x-content/image-dcf") == 0) { media_greeting = _("You have just inserted a medium with digital photos."); } else if (strcmp (x_content_type, "x-content/audio-player") == 0) { media_greeting = _("You have just inserted a digital audio player."); } else if (g_content_type_is_a (x_content_type, "x-content/software")) { media_greeting = _("You have just inserted a medium with software intended to be automatically started."); } else { /* fallback to generic greeting */ media_greeting = _("You have just inserted a medium."); } markup = g_strdup_printf ("%s %s", media_greeting, _("Choose what application to launch.")); gtk_label_set_markup (GTK_LABEL (label), markup); g_free (markup); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_max_width_chars (GTK_LABEL (label), 72); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); label = gtk_label_new (NULL); content_description = g_content_type_get_description (x_content_type); markup = g_strdup_printf (_("Select how to open \"%s\" and whether to perform this action in the future for other media of type \"%s\"."), mount_name, content_description); g_free (content_description); gtk_label_set_markup (GTK_LABEL (label), markup); g_free (markup); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_max_width_chars (GTK_LABEL (label), 72); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); data = g_new0 (AutorunDialogData, 1); data->dialog = dialog; data->mount = g_object_ref (mount); data->remember = !pref_ask; data->selected_ignore = pref_ignore; data->x_content_type = g_strdup (x_content_type); data->selected_app = g_app_info_get_default_for_type (x_content_type, FALSE); data->open_window_func = open_window_func; data->user_data = user_data; combo_box = gtk_app_chooser_button_new (x_content_type); prepare_combo_box (combo_box, data); g_signal_connect (G_OBJECT (combo_box), "key-press-event", G_CALLBACK (combo_box_enter_ok), dialog); gtk_box_pack_start (GTK_BOX (vbox), combo_box, TRUE, TRUE, 0); always_check_button = gtk_check_button_new_with_mnemonic (_("_Always perform this action")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (always_check_button), data->remember); g_signal_connect (G_OBJECT (always_check_button), "toggled", G_CALLBACK (autorun_always_toggled), data); gtk_box_pack_start (GTK_BOX (vbox), always_check_button, TRUE, TRUE, 0); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); if (g_mount_can_eject (mount)) { GtkWidget *eject_image; eject_button = gtk_button_new_with_mnemonic (_("_Eject")); eject_image = gtk_image_new_from_icon_name ("media-eject", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (eject_button), eject_image); data->should_eject = TRUE; } else { eject_button = gtk_button_new_with_mnemonic (_("_Unmount")); data->should_eject = FALSE; } gtk_dialog_add_action_widget (GTK_DIALOG (dialog), eject_button, AUTORUN_DIALOG_RESPONSE_EJECT); gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), eject_button, TRUE); /* show the dialog */ gtk_widget_show_all (dialog); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (autorun_dialog_response), data); g_signal_connect (G_OBJECT (data->mount), "unmounted", G_CALLBACK (autorun_dialog_mount_unmounted), data); out: g_free (mount_name); return ret; } typedef struct { GMount *mount; GsdAutorunOpenWindow open_window_func; gpointer user_data; GSettings *settings; } AutorunData; static void autorun_guessed_content_type_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error; char **guessed_content_type; AutorunData *data = user_data; gboolean open_folder; open_folder = FALSE; error = NULL; guessed_content_type = g_mount_guess_content_type_finish (G_MOUNT (source_object), res, &error); g_object_set_data_full (source_object, "gsd-content-type-cache", g_strdupv (guessed_content_type), (GDestroyNotify)g_strfreev); if (error != NULL) { g_warning ("Unable to guess content type for mount: %s", error->message); g_error_free (error); } else { if (guessed_content_type != NULL && g_strv_length (guessed_content_type) > 0) { int n; for (n = 0; guessed_content_type[n] != NULL; n++) { if (do_autorun_for_content_type (data->mount, guessed_content_type[n], data->open_window_func, data->user_data)) { open_folder = TRUE; } } g_strfreev (guessed_content_type); } else { if (g_settings_get_boolean (data->settings, "automount-open")) { open_folder = TRUE; } } } /* only open the folder once.. */ if (open_folder && data->open_window_func != NULL) { data->open_window_func (data->mount, data->user_data); } g_object_unref (data->mount); g_object_unref (data->settings); g_free (data); } void gsd_autorun (GMount *mount, GSettings *settings, GsdAutorunOpenWindow open_window_func, gpointer user_data) { AutorunData *data; if (!should_autorun_mount (mount) || g_settings_get_boolean (settings, "autorun-never")) { return; } data = g_new0 (AutorunData, 1); data->mount = g_object_ref (mount); data->open_window_func = open_window_func; data->user_data = user_data; data->settings = g_object_ref (settings); g_mount_guess_content_type (mount, FALSE, NULL, autorun_guessed_content_type_callback, data); } static gboolean remove_allow_volume (gpointer data) { GVolume *volume = data; g_object_set_data (G_OBJECT (volume), "gsd-allow-autorun", NULL); return FALSE; } void gsd_allow_autorun_for_volume (GVolume *volume) { g_object_set_data (G_OBJECT (volume), "gsd-allow-autorun", GINT_TO_POINTER (1)); } #define INHIBIT_AUTORUN_SECONDS 10 void gsd_allow_autorun_for_volume_finish (GVolume *volume) { if (g_object_get_data (G_OBJECT (volume), "gsd-allow-autorun") != NULL) { g_timeout_add_seconds_full (0, INHIBIT_AUTORUN_SECONDS, remove_allow_volume, g_object_ref (volume), g_object_unref); } } static gboolean should_skip_native_mount_root (GFile *root) { char *path; gboolean should_skip; /* skip any mounts in hidden directory hierarchies */ path = g_file_get_path (root); should_skip = strstr (path, "/.") != NULL; g_free (path); return should_skip; } static gboolean should_autorun_mount (GMount *mount) { GFile *root; GVolume *enclosing_volume; gboolean ignore_autorun; ignore_autorun = TRUE; enclosing_volume = g_mount_get_volume (mount); if (enclosing_volume != NULL) { if (g_object_get_data (G_OBJECT (enclosing_volume), "gsd-allow-autorun") != NULL) { ignore_autorun = FALSE; g_object_set_data (G_OBJECT (enclosing_volume), "gsd-allow-autorun", NULL); } } if (ignore_autorun) { if (enclosing_volume != NULL) { g_object_unref (enclosing_volume); } return FALSE; } root = g_mount_get_root (mount); /* only do autorun on local files or files where g_volume_should_automount() returns TRUE */ ignore_autorun = TRUE; if ((g_file_is_native (root) && !should_skip_native_mount_root (root)) || (enclosing_volume != NULL && g_volume_should_automount (enclosing_volume))) { ignore_autorun = FALSE; } if (enclosing_volume != NULL) { g_object_unref (enclosing_volume); } g_object_unref (root); return !ignore_autorun; } unity-settings-daemon/plugins/automount/gsd-autorun.h0000664000000000000000000000316115172222611020352 0ustar /* * gsd-automount.h:helpers for automounting hotplugged volumes * * Copyright (C) 2008 Red Hat, Inc. * * Nautilus is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: David Zeuthen * Cosimo Cecchi */ /* TODO: * * - unmount all the media we've automounted on shutdown * - finish x-content / * types * - finalize the semi-spec * - add probing/sniffing code * - implement missing features * - "Open Folder when mounted" * - Autorun spec (e.g. $ROOT/.autostart) * */ #ifndef __GSD_AUTORUN_H__ #define __GSD_AUTORUN_H__ #include #include typedef void (*GsdAutorunOpenWindow) (GMount *mount, gpointer user_data); void gsd_autorun (GMount *mount, GSettings *settings, GsdAutorunOpenWindow open_window_func, gpointer user_data); void gsd_allow_autorun_for_volume (GVolume *volume); void gsd_allow_autorun_for_volume_finish (GVolume *volume); #endif /* __GSD_AUTORUN_H__ */ unity-settings-daemon/plugins/automount/unity-fallback-mount-helper.desktop.in.in0000664000000000000000000000045515172222611025663 0ustar [Desktop Entry] _Name=Mount Helper _Comment=Automount and autorun plugged devices Exec=@LIBEXECDIR@/unity-fallback-mount-helper Icon=drive-optical Terminal=false Type=Application Categories= NoDisplay=true OnlyShowIn=Unity; X-GNOME-Autostart-Notify=true AutostartCondition=GNOME3 unless-session gnome unity-settings-daemon/plugins/background/0000775000000000000000000000000015172222611016014 5ustar unity-settings-daemon/plugins/background/Makefile.am0000664000000000000000000000456615172222611020063 0ustar NULL = plugin_name = background libexec_PROGRAMS = usd-test-background usd_test_background_SOURCES = \ test-background.c \ gsd-background-manager.h \ gsd-background-manager.c \ $(NULL) usd_test_background_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) usd_test_background_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(BACKGROUND_CFLAGS) \ $(AM_CFLAGS) usd_test_background_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(BACKGROUND_LIBS) \ $(NULL) libexec_PROGRAMS += gnome-update-wallpaper-cache gnome_update_wallpaper_cache_SOURCES = \ gnome-update-wallpaper-cache.c \ $(NULL) gnome_update_wallpaper_cache_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) gnome_update_wallpaper_cache_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(BACKGROUND_CFLAGS) \ $(AM_CFLAGS) gnome_update_wallpaper_cache_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(BACKGROUND_LIBS) \ $(NULL) plugin_LTLIBRARIES = \ libbackground.la \ $(NULL) libbackground_la_SOURCES = \ gsd-background-plugin.c \ gsd-background-manager.h \ gsd-background-manager.c \ $(NULL) libbackground_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/background/libbackground \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libbackground_la_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(BACKGROUND_CFLAGS) \ $(AM_CFLAGS) libbackground_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) \ $(NULL) libbackground_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(BACKGROUND_LIBS) \ $(NULL) plugin_in_files = \ background.gnome-settings-plugin.in \ $(NULL) plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) \ $(NULL) CLEANFILES = \ $(plugin_DATA) \ $(NULL) DISTCLEANFILES = \ $(plugin_DATA) \ $(NULL) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/background/background.gnome-settings-plugin.in0000664000000000000000000000021715172222611024721 0ustar [GNOME Settings Plugin] Module=background IAge=0 _Name=Background _Description=Background plugin Authors= Copyright=Copyright © 2007 Website= unity-settings-daemon/plugins/background/gnome-update-wallpaper-cache.c0000664000000000000000000000401715172222611023575 0ustar /* * Copyright (C) 2010 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License version 3.0 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authored by Didier Roche * * Bug: https://bugs.launchpad.net/bugs/530024 */ #include "config.h" #include #include #include "gsd-bg.h" static GOptionEntry entries[] = { { NULL } }; int main (int argc, char *argv[]) { GOptionContext *context = NULL; GError *error = NULL; GdkScreen *screen; GdkRectangle rect; GsdBG *bg; GSettings *settings; GdkPixbuf *pixbuf; gdk_init (&argc, &argv); context = g_option_context_new ("- refresh wallpaper cache"); g_option_context_add_main_entries (context, entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("option parsing failed: %s\n", error->message); g_option_context_free(context); g_error_free (error); return (1); } if (context) g_option_context_free (context); /* cache only the first monitor */ screen = gdk_screen_get_default (); gdk_screen_get_monitor_geometry (screen, 0, &rect); bg = gsd_bg_new (); settings = g_settings_new ("org.gnome.desktop.background"); gsd_bg_load_from_preferences (bg, settings); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, rect.width, rect.height); gsd_bg_draw (bg, pixbuf, screen, FALSE); g_object_unref (settings); return (0); } unity-settings-daemon/plugins/background/gsd-background-manager.c0000664000000000000000000005136315172222611022472 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright © 2001 Ximian, Inc. * Copyright (C) 2007 William Jon McCann * Copyright 2007 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gsd-bg.h" #include "gnome-settings-bus.h" #include "gnome-settings-profile.h" #include "gsd-background-manager.h" #define GSD_BACKGROUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerPrivate)) struct GsdBackgroundManagerPrivate { GSettings *settings; GSettings *usettings; GsdBG *bg; GsdBGCrossfade *fade; GDBusProxy *proxy; guint proxy_signal_id; }; static void gsd_background_manager_class_init (GsdBackgroundManagerClass *klass); static void gsd_background_manager_init (GsdBackgroundManager *background_manager); static void gsd_background_manager_finalize (GObject *object); static void setup_bg (GsdBackgroundManager *manager); static void connect_screen_signals (GsdBackgroundManager *manager); G_DEFINE_TYPE (GsdBackgroundManager, gsd_background_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static gboolean dont_draw_background (GsdBackgroundManager *manager) { return !g_settings_get_boolean (manager->priv->usettings, "draw-background"); } static gboolean nautilus_is_drawing_background (GsdBackgroundManager *manager) { Atom window_id_atom; Window nautilus_xid; Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *data; Atom wmclass_atom; gboolean running; gint error; gboolean show_desktop_icons; show_desktop_icons = g_settings_get_boolean (manager->priv->settings, "show-desktop-icons"); if (! show_desktop_icons) { return FALSE; } window_id_atom = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "NAUTILUS_DESKTOP_WINDOW_ID", True); if (window_id_atom == None) { return FALSE; } XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_ROOT_WINDOW (), window_id_atom, 0, 1, False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytes_after, &data); if (data != NULL) { nautilus_xid = *(Window *) data; XFree (data); } else { return FALSE; } if (actual_type != XA_WINDOW) { return FALSE; } if (actual_format != 32) { return FALSE; } wmclass_atom = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "WM_CLASS", False); gdk_error_trap_push (); XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), nautilus_xid, wmclass_atom, 0, 24, False, XA_STRING, &actual_type, &actual_format, &nitems, &bytes_after, &data); error = gdk_error_trap_pop (); if (error == BadWindow) { return FALSE; } if (actual_type == XA_STRING && nitems == 24 && bytes_after == 0 && actual_format == 8 && data != NULL && !strcmp ((char *)data, "desktop_window") && !strcmp ((char *)data + strlen ((char *)data) + 1, "Nautilus")) { running = TRUE; } else { running = FALSE; } if (data != NULL) { XFree (data); } return running; } static void on_crossfade_finished (GsdBackgroundManager *manager) { g_object_unref (manager->priv->fade); manager->priv->fade = NULL; } static void draw_background (GsdBackgroundManager *manager, gboolean use_crossfade) { GdkDisplay *display; int n_screens; int i; if (nautilus_is_drawing_background (manager) || dont_draw_background (manager)) { return; } gnome_settings_profile_start (NULL); display = gdk_display_get_default (); n_screens = gdk_display_get_n_screens (display); for (i = 0; i < n_screens; ++i) { GdkScreen *screen; GdkWindow *root_window; cairo_surface_t *surface; screen = gdk_display_get_screen (display, i); root_window = gdk_screen_get_root_window (screen); surface = gsd_bg_create_surface (manager->priv->bg, root_window, gdk_screen_get_width (screen), gdk_screen_get_height (screen), TRUE); if (use_crossfade) { if (manager->priv->fade != NULL) { g_object_unref (manager->priv->fade); } manager->priv->fade = gsd_bg_set_surface_as_root_with_crossfade (screen, surface); g_signal_connect_swapped (manager->priv->fade, "finished", G_CALLBACK (on_crossfade_finished), manager); } else { gsd_bg_set_surface_as_root (screen, surface); } cairo_surface_destroy (surface); } gnome_settings_profile_end (NULL); } static void on_bg_transitioned (GsdBG *bg, GsdBackgroundManager *manager) { draw_background (manager, FALSE); } static gboolean settings_change_event_cb (GSettings *settings, gpointer keys, gint n_keys, GsdBackgroundManager *manager) { gsd_bg_load_from_preferences (manager->priv->bg, manager->priv->settings); return FALSE; } static void on_screen_size_changed (GdkScreen *screen, GsdBackgroundManager *manager) { draw_background (manager, FALSE); } static void watch_bg_preferences (GsdBackgroundManager *manager) { g_signal_connect (manager->priv->settings, "change-event", G_CALLBACK (settings_change_event_cb), manager); } static void on_bg_changed (GsdBG *bg, GsdBackgroundManager *manager) { draw_background (manager, TRUE); } static void setup_bg (GsdBackgroundManager *manager) { g_return_if_fail (manager->priv->bg == NULL); manager->priv->bg = gsd_bg_new (); g_signal_connect (manager->priv->bg, "changed", G_CALLBACK (on_bg_changed), manager); g_signal_connect (manager->priv->bg, "transitioned", G_CALLBACK (on_bg_transitioned), manager); connect_screen_signals (manager); watch_bg_preferences (manager); gsd_bg_load_from_preferences (manager->priv->bg, manager->priv->settings); } static void setup_bg_and_draw_background (GsdBackgroundManager *manager) { setup_bg (manager); draw_background (manager, FALSE); } static void disconnect_session_manager_listener (GsdBackgroundManager *manager) { if (manager->priv->proxy && manager->priv->proxy_signal_id) { g_signal_handler_disconnect (manager->priv->proxy, manager->priv->proxy_signal_id); manager->priv->proxy_signal_id = 0; } } static void on_session_manager_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { GsdBackgroundManager *manager = GSD_BACKGROUND_MANAGER (user_data); if (g_strcmp0 (signal_name, "SessionRunning") == 0) { setup_bg_and_draw_background (manager); disconnect_session_manager_listener (manager); } } static void draw_background_after_session_loads (GsdBackgroundManager *manager) { manager->priv->proxy = G_DBUS_PROXY (gnome_settings_bus_get_session_proxy ()); manager->priv->proxy_signal_id = g_signal_connect (manager->priv->proxy, "g-signal", G_CALLBACK (on_session_manager_signal), manager); } static void disconnect_screen_signals (GsdBackgroundManager *manager) { GdkDisplay *display; int i; int n_screens; display = gdk_display_get_default (); n_screens = gdk_display_get_n_screens (display); for (i = 0; i < n_screens; ++i) { GdkScreen *screen; screen = gdk_display_get_screen (display, i); g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_size_changed), manager); } } static void connect_screen_signals (GsdBackgroundManager *manager) { GdkDisplay *display; int i; int n_screens; display = gdk_display_get_default (); n_screens = gdk_display_get_n_screens (display); for (i = 0; i < n_screens; ++i) { GdkScreen *screen; screen = gdk_display_get_screen (display, i); g_signal_connect (screen, "monitors-changed", G_CALLBACK (on_screen_size_changed), manager); g_signal_connect (screen, "size-changed", G_CALLBACK (on_screen_size_changed), manager); } } static void draw_background_changed (GSettings *settings, const char *key, GsdBackgroundManager *manager) { if (dont_draw_background (manager) == FALSE) setup_bg_and_draw_background (manager); } static void set_accountsservice_background (const gchar *background) { GDBusConnection *bus; GVariant *variant; GError *error = NULL; gchar *object_path = NULL; bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (bus == NULL) { g_warning ("Failed to get system bus: %s", error->message); g_error_free (error); return; } variant = g_dbus_connection_call_sync (bus, "org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", "FindUserByName", g_variant_new ("(s)", g_get_user_name ()), G_VARIANT_TYPE ("(o)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_warning ("Could not contact accounts service to look up '%s': %s", g_get_user_name (), error->message); g_error_free (error); g_object_unref (bus); return; } g_variant_get (variant, "(o)", &object_path); g_variant_unref (variant); variant = g_dbus_connection_call_sync (bus, "org.freedesktop.Accounts", object_path, "org.freedesktop.DBus.Properties", "Set", g_variant_new ("(ssv)", "org.freedesktop.DisplayManager.AccountsService", "BackgroundFile", g_variant_new_string (background ? background : "")), G_VARIANT_TYPE ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant != NULL) g_variant_unref (variant); else { g_warning ("Failed to set the background '%s': %s", background, error->message); g_clear_error (&error); } /* Also attempt the old method (patch not upstreamed into AccountsService */ variant = g_dbus_connection_call_sync (bus, "org.freedesktop.Accounts", object_path, "org.freedesktop.Accounts.User", "SetBackgroundFile", g_variant_new ("(s)", background ? background : ""), G_VARIANT_TYPE ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant != NULL) g_variant_unref (variant); else { g_warning ("Failed to set the background '%s': %s", background, error->message); g_clear_error (&error); } g_object_unref (bus); } static void picture_uri_changed (GSettings *settings, const char *key, GsdBackgroundManager *manager) { const char *picture_uri = g_settings_get_string (settings, key); GFile *picture_file = g_file_new_for_uri (picture_uri); char *picture_path = g_file_get_path (picture_file); set_accountsservice_background (picture_path); g_free (picture_path); g_object_unref (picture_file); } gboolean gsd_background_manager_start (GsdBackgroundManager *manager, GError **error) { gboolean show_desktop_icons; g_debug ("Starting background manager"); gnome_settings_profile_start (NULL); manager->priv->settings = g_settings_new ("org.gnome.desktop.background"); manager->priv->usettings = g_settings_new ("com.canonical.unity.desktop.background"); g_signal_connect (manager->priv->usettings, "changed::draw-background", G_CALLBACK (draw_background_changed), manager); g_signal_connect (manager->priv->settings, "changed::picture-uri", G_CALLBACK (picture_uri_changed), manager); /* If this is set, nautilus will draw the background and is * almost definitely in our session. however, it may not be * running yet (so is_nautilus_running() will fail). so, on * startup, just don't do anything if this key is set so we * don't waste time setting the background only to have * nautilus overwrite it. */ show_desktop_icons = g_settings_get_boolean (manager->priv->settings, "show-desktop-icons"); if (!show_desktop_icons) { setup_bg (manager); } else { draw_background_after_session_loads (manager); } gnome_settings_profile_end (NULL); return TRUE; } void gsd_background_manager_stop (GsdBackgroundManager *manager) { GsdBackgroundManagerPrivate *p = manager->priv; g_debug ("Stopping background manager"); disconnect_screen_signals (manager); if (manager->priv->proxy) { disconnect_session_manager_listener (manager); g_clear_object (&manager->priv->proxy); } g_signal_handlers_disconnect_by_func (manager->priv->settings, settings_change_event_cb, manager); g_signal_handlers_disconnect_by_func (manager->priv->usettings, settings_change_event_cb, manager); if (p->settings != NULL) { g_object_unref (p->settings); p->settings = NULL; } if (p->usettings != NULL) { g_object_unref (p->usettings); p->usettings = NULL; } if (p->bg != NULL) { g_object_unref (p->bg); p->bg = NULL; } } static GObject * gsd_background_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdBackgroundManager *background_manager; background_manager = GSD_BACKGROUND_MANAGER (G_OBJECT_CLASS (gsd_background_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (background_manager); } static void gsd_background_manager_class_init (GsdBackgroundManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_background_manager_constructor; object_class->finalize = gsd_background_manager_finalize; g_type_class_add_private (klass, sizeof (GsdBackgroundManagerPrivate)); } static void gsd_background_manager_init (GsdBackgroundManager *manager) { manager->priv = GSD_BACKGROUND_MANAGER_GET_PRIVATE (manager); } static void gsd_background_manager_finalize (GObject *object) { GsdBackgroundManager *background_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_BACKGROUND_MANAGER (object)); background_manager = GSD_BACKGROUND_MANAGER (object); g_return_if_fail (background_manager->priv != NULL); G_OBJECT_CLASS (gsd_background_manager_parent_class)->finalize (object); } GsdBackgroundManager * gsd_background_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_BACKGROUND_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_BACKGROUND_MANAGER (manager_object); } unity-settings-daemon/plugins/background/gsd-background-manager.h0000664000000000000000000000462315172222611022474 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_BACKGROUND_MANAGER_H #define __GSD_BACKGROUND_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_BACKGROUND_MANAGER (gsd_background_manager_get_type ()) #define GSD_BACKGROUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManager)) #define GSD_BACKGROUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerClass)) #define GSD_IS_BACKGROUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_BACKGROUND_MANAGER)) #define GSD_IS_BACKGROUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_BACKGROUND_MANAGER)) #define GSD_BACKGROUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerClass)) typedef struct GsdBackgroundManagerPrivate GsdBackgroundManagerPrivate; typedef struct { GObject parent; GsdBackgroundManagerPrivate *priv; } GsdBackgroundManager; typedef struct { GObjectClass parent_class; } GsdBackgroundManagerClass; GType gsd_background_manager_get_type (void); GsdBackgroundManager * gsd_background_manager_new (void); gboolean gsd_background_manager_start (GsdBackgroundManager *manager, GError **error); void gsd_background_manager_stop (GsdBackgroundManager *manager); G_END_DECLS #endif /* __GSD_BACKGROUND_MANAGER_H */ unity-settings-daemon/plugins/background/gsd-background-plugin.c0000664000000000000000000000203415172222611022345 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-background-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdBackground, gsd_background) unity-settings-daemon/plugins/background/test-background.c0000664000000000000000000000033615172222611021256 0ustar #define NEW gsd_background_manager_new #define START gsd_background_manager_start #define STOP gsd_background_manager_stop #define MANAGER GsdBackgroundManager #include "gsd-background-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/clipboard/0000775000000000000000000000000015172222611015634 5ustar unity-settings-daemon/plugins/clipboard/Makefile.am0000664000000000000000000000174415172222611017676 0ustar NULL = plugin_name = clipboard plugin_LTLIBRARIES = \ libclipboard.la \ $(NULL) libclipboard_la_SOURCES = \ gsd-clipboard-plugin.c \ gsd-clipboard-manager.h \ gsd-clipboard-manager.c \ xutils.h \ xutils.c \ list.h \ list.c \ $(NULL) libclipboard_la_CPPFLAGS = \ $(PLUGIN_CFLAGS) \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libclipboard_la_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libclipboard_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) \ $(NULL) libclipboard_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(NULL) plugin_in_files = \ clipboard.gnome-settings-plugin.in \ $(NULL) plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) \ $(NULL) CLEANFILES = \ $(plugin_DATA) \ $(NULL) DISTCLEANFILES = \ $(plugin_DATA) \ $(NULL) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/clipboard/clipboard.gnome-settings-plugin.in0000664000000000000000000000031515172222611024360 0ustar [GNOME Settings Plugin] Module=clipboard IAge=0 # Default Priority # Priority=100 _Name=Clipboard _Description=Clipboard plugin Authors=Matthias Clasen Copyright=Copyright © 2007 Matthias Clasen Website= unity-settings-daemon/plugins/clipboard/gsd-clipboard-manager.c0000664000000000000000000011642615172222611022134 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 Matthias Clasen * Copyright (C) 2007 Anders Carlsson * Copyright (C) 2007 Rodrigo Moya * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xutils.h" #include "list.h" #include "gnome-settings-profile.h" #include "gsd-clipboard-manager.h" #define GSD_CLIPBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerPrivate)) struct GsdClipboardManagerPrivate { guint start_idle_id; Display *display; Window window; Time timestamp; List *contents; List *conversions; Window requestor; Atom property; Time time; }; typedef struct { unsigned char *data; int length; Atom target; Atom type; int format; int refcount; } TargetData; typedef struct { Atom target; TargetData *data; Atom property; Window requestor; int offset; } IncrConversion; static void gsd_clipboard_manager_class_init (GsdClipboardManagerClass *klass); static void gsd_clipboard_manager_init (GsdClipboardManager *clipboard_manager); static void gsd_clipboard_manager_finalize (GObject *object); static void clipboard_manager_watch_cb (GsdClipboardManager *manager, Window window, Bool is_start, long mask, void *cb_data); G_DEFINE_TYPE (GsdClipboardManager, gsd_clipboard_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; /* We need to use reference counting for the target data, since we may * need to keep the data around after loosing the CLIPBOARD ownership * to complete incremental transfers. */ static TargetData * target_data_ref (TargetData *data) { data->refcount++; return data; } static void target_data_unref (TargetData *data) { data->refcount--; if (data->refcount == 0) { free (data->data); free (data); } } static void conversion_free (IncrConversion *rdata) { if (rdata->data) { target_data_unref (rdata->data); } free (rdata); } static void send_selection_notify (GsdClipboardManager *manager, Bool success) { XSelectionEvent notify; notify.type = SelectionNotify; notify.serial = 0; notify.send_event = True; notify.display = manager->priv->display; notify.requestor = manager->priv->requestor; notify.selection = XA_CLIPBOARD_MANAGER; notify.target = XA_SAVE_TARGETS; notify.property = success ? manager->priv->property : None; notify.time = manager->priv->time; gdk_error_trap_push (); XSendEvent (manager->priv->display, manager->priv->requestor, False, NoEventMask, (XEvent *)¬ify); XSync (manager->priv->display, False); gdk_error_trap_pop_ignored (); } static void finish_selection_request (GsdClipboardManager *manager, XEvent *xev, Bool success) { XSelectionEvent notify; notify.type = SelectionNotify; notify.serial = 0; notify.send_event = True; notify.display = xev->xselectionrequest.display; notify.requestor = xev->xselectionrequest.requestor; notify.selection = xev->xselectionrequest.selection; notify.target = xev->xselectionrequest.target; notify.property = success ? xev->xselectionrequest.property : None; notify.time = xev->xselectionrequest.time; gdk_error_trap_push (); XSendEvent (xev->xselectionrequest.display, xev->xselectionrequest.requestor, False, NoEventMask, (XEvent *) ¬ify); XSync (manager->priv->display, False); gdk_error_trap_pop_ignored (); } static int clipboard_bytes_per_item (int format) { switch (format) { case 8: return sizeof (char); case 16: return sizeof (short); case 32: return sizeof (long); default: ; } return 0; } static void save_targets (GsdClipboardManager *manager, Atom *save_targets, int nitems) { int nout, i; Atom *multiple; TargetData *tdata; multiple = (Atom *) malloc (2 * nitems * sizeof (Atom)); nout = 0; for (i = 0; i < nitems; i++) { if (save_targets[i] != XA_TARGETS && save_targets[i] != XA_MULTIPLE && save_targets[i] != XA_DELETE && save_targets[i] != XA_INSERT_PROPERTY && save_targets[i] != XA_INSERT_SELECTION && save_targets[i] != XA_PIXMAP) { tdata = (TargetData *) malloc (sizeof (TargetData)); tdata->data = NULL; tdata->length = 0; tdata->target = save_targets[i]; tdata->type = None; tdata->format = 0; tdata->refcount = 1; manager->priv->contents = list_prepend (manager->priv->contents, tdata); multiple[nout++] = save_targets[i]; multiple[nout++] = save_targets[i]; } } XFree (save_targets); XChangeProperty (manager->priv->display, manager->priv->window, XA_MULTIPLE, XA_ATOM_PAIR, 32, PropModeReplace, (const unsigned char *) multiple, nout); free (multiple); XConvertSelection (manager->priv->display, XA_CLIPBOARD, XA_MULTIPLE, XA_MULTIPLE, manager->priv->window, manager->priv->time); } static int find_content_target (TargetData *tdata, Atom target) { return tdata->target == target; } static int find_content_type (TargetData *tdata, Atom type) { return tdata->type == type; } static int find_conversion_requestor (IncrConversion *rdata, XEvent *xev) { return (rdata->requestor == xev->xproperty.window && rdata->property == xev->xproperty.atom); } static void get_property (TargetData *tdata, GsdClipboardManager *manager) { Atom type; int format; unsigned long length; unsigned long remaining; unsigned char *data; XGetWindowProperty (manager->priv->display, manager->priv->window, tdata->target, 0, 0x1FFFFFFF, True, AnyPropertyType, &type, &format, &length, &remaining, &data); if (type == None) { manager->priv->contents = list_remove (manager->priv->contents, tdata); free (tdata); } else if (type == XA_INCR) { tdata->type = type; tdata->length = 0; XFree (data); } else { tdata->type = type; tdata->data = data; tdata->length = length * clipboard_bytes_per_item (format); tdata->format = format; } } static Bool receive_incrementally (GsdClipboardManager *manager, XEvent *xev) { List *list; TargetData *tdata; Atom type; int format; unsigned long length, nitems, remaining; unsigned char *data; if (xev->xproperty.window != manager->priv->window) return False; list = list_find (manager->priv->contents, (ListFindFunc) find_content_target, (void *) xev->xproperty.atom); if (!list) return False; tdata = (TargetData *) list->data; if (tdata->type != XA_INCR) return False; XGetWindowProperty (xev->xproperty.display, xev->xproperty.window, xev->xproperty.atom, 0, 0x1FFFFFFF, True, AnyPropertyType, &type, &format, &nitems, &remaining, &data); length = nitems * clipboard_bytes_per_item (format); if (length == 0) { tdata->type = type; tdata->format = format; if (!list_find (manager->priv->contents, (ListFindFunc) find_content_type, (void *)XA_INCR)) { /* all incremental transfers done */ send_selection_notify (manager, True); manager->priv->requestor = None; } XFree (data); } else { if (!tdata->data) { tdata->data = data; tdata->length = length; } else { tdata->data = realloc (tdata->data, tdata->length + length + 1); memcpy (tdata->data + tdata->length, data, length + 1); tdata->length += length; XFree (data); } } return True; } static Bool send_incrementally (GsdClipboardManager *manager, XEvent *xev) { List *list; IncrConversion *rdata; unsigned long length; unsigned long items; unsigned char *data; list = list_find (manager->priv->conversions, (ListFindFunc) find_conversion_requestor, xev); if (list == NULL) return False; rdata = (IncrConversion *) list->data; data = rdata->data->data + rdata->offset; length = rdata->data->length - rdata->offset; if (length > SELECTION_MAX_SIZE) length = SELECTION_MAX_SIZE; rdata->offset += length; items = length / clipboard_bytes_per_item (rdata->data->format); XChangeProperty (manager->priv->display, rdata->requestor, rdata->property, rdata->data->type, rdata->data->format, PropModeAppend, data, items); if (length == 0) { clipboard_manager_watch_cb (manager, rdata->requestor, False, PropertyChangeMask, NULL); manager->priv->conversions = list_remove (manager->priv->conversions, rdata); conversion_free (rdata); } return True; } static void convert_clipboard_manager (GsdClipboardManager *manager, XEvent *xev) { Atom type = None; int format; unsigned long nitems; unsigned long remaining; Atom *targets = NULL; if (xev->xselectionrequest.target == XA_SAVE_TARGETS) { if (manager->priv->requestor != None || manager->priv->contents != NULL) { /* We're in the middle of a conversion request, or own * the CLIPBOARD already */ finish_selection_request (manager, xev, False); } else { gdk_error_trap_push (); clipboard_manager_watch_cb (manager, xev->xselectionrequest.requestor, True, StructureNotifyMask, NULL); XSelectInput (manager->priv->display, xev->xselectionrequest.requestor, StructureNotifyMask); XSync (manager->priv->display, False); if (gdk_error_trap_pop () != Success) return; gdk_error_trap_push (); if (xev->xselectionrequest.property != None) { XGetWindowProperty (manager->priv->display, xev->xselectionrequest.requestor, xev->xselectionrequest.property, 0, 0x1FFFFFFF, False, XA_ATOM, &type, &format, &nitems, &remaining, (unsigned char **) &targets); if (gdk_error_trap_pop () != Success) { if (targets) XFree (targets); return; } } manager->priv->requestor = xev->xselectionrequest.requestor; manager->priv->property = xev->xselectionrequest.property; manager->priv->time = xev->xselectionrequest.time; if (type == None) XConvertSelection (manager->priv->display, XA_CLIPBOARD, XA_TARGETS, XA_TARGETS, manager->priv->window, manager->priv->time); else save_targets (manager, targets, nitems); } } else if (xev->xselectionrequest.target == XA_TIMESTAMP) { XChangeProperty (manager->priv->display, xev->xselectionrequest.requestor, xev->xselectionrequest.property, XA_INTEGER, 32, PropModeReplace, (unsigned char *) &manager->priv->timestamp, 1); finish_selection_request (manager, xev, True); } else if (xev->xselectionrequest.target == XA_TARGETS) { int n_targets = 0; Atom targets[3]; targets[n_targets++] = XA_TARGETS; targets[n_targets++] = XA_TIMESTAMP; targets[n_targets++] = XA_SAVE_TARGETS; XChangeProperty (manager->priv->display, xev->xselectionrequest.requestor, xev->xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, n_targets); finish_selection_request (manager, xev, True); } else finish_selection_request (manager, xev, False); } static void convert_clipboard_target (IncrConversion *rdata, GsdClipboardManager *manager) { TargetData *tdata; Atom *targets; int n_targets; List *list; unsigned long items; XWindowAttributes atts; if (rdata->target == XA_TARGETS) { n_targets = list_length (manager->priv->contents) + 2; targets = (Atom *) malloc (n_targets * sizeof (Atom)); n_targets = 0; targets[n_targets++] = XA_TARGETS; targets[n_targets++] = XA_MULTIPLE; for (list = manager->priv->contents; list; list = list->next) { tdata = (TargetData *) list->data; targets[n_targets++] = tdata->target; } XChangeProperty (manager->priv->display, rdata->requestor, rdata->property, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, n_targets); free (targets); } else { /* Convert from stored CLIPBOARD data */ list = list_find (manager->priv->contents, (ListFindFunc) find_content_target, (void *) rdata->target); /* We got a target that we don't support */ if (!list) return; tdata = (TargetData *)list->data; if (tdata->type == XA_INCR) { /* we haven't completely received this target yet */ rdata->property = None; return; } rdata->data = target_data_ref (tdata); items = tdata->length / clipboard_bytes_per_item (tdata->format); if (tdata->length <= SELECTION_MAX_SIZE) XChangeProperty (manager->priv->display, rdata->requestor, rdata->property, tdata->type, tdata->format, PropModeReplace, tdata->data, items); else { /* start incremental transfer */ rdata->offset = 0; gdk_error_trap_push (); XGetWindowAttributes (manager->priv->display, rdata->requestor, &atts); clipboard_manager_watch_cb (manager, rdata->requestor, True, PropertyChangeMask, NULL); XSelectInput (manager->priv->display, rdata->requestor, atts.your_event_mask | PropertyChangeMask); XChangeProperty (manager->priv->display, rdata->requestor, rdata->property, XA_INCR, 32, PropModeReplace, (unsigned char *) &items, 1); XSync (manager->priv->display, False); gdk_error_trap_pop_ignored (); } } } static void collect_incremental (IncrConversion *rdata, GsdClipboardManager *manager) { if (rdata->offset >= 0) manager->priv->conversions = list_prepend (manager->priv->conversions, rdata); else { if (rdata->data) { target_data_unref (rdata->data); rdata->data = NULL; } free (rdata); } } static void convert_clipboard (GsdClipboardManager *manager, XEvent *xev) { List *list; List *conversions; IncrConversion *rdata; Atom type; int i; int format; unsigned long nitems; unsigned long remaining; Atom *multiple; conversions = NULL; type = None; if (xev->xselectionrequest.target == XA_MULTIPLE) { XGetWindowProperty (xev->xselectionrequest.display, xev->xselectionrequest.requestor, xev->xselectionrequest.property, 0, 0x1FFFFFFF, False, XA_ATOM_PAIR, &type, &format, &nitems, &remaining, (unsigned char **) &multiple); if (type != XA_ATOM_PAIR || nitems == 0) { if (multiple) free (multiple); return; } for (i = 0; i < nitems; i += 2) { rdata = (IncrConversion *) malloc (sizeof (IncrConversion)); rdata->requestor = xev->xselectionrequest.requestor; rdata->target = multiple[i]; rdata->property = multiple[i+1]; rdata->data = NULL; rdata->offset = -1; conversions = list_prepend (conversions, rdata); } } else { multiple = NULL; rdata = (IncrConversion *) malloc (sizeof (IncrConversion)); rdata->requestor = xev->xselectionrequest.requestor; rdata->target = xev->xselectionrequest.target; rdata->property = xev->xselectionrequest.property; rdata->data = NULL; rdata->offset = -1; conversions = list_prepend (conversions, rdata); } list_foreach (conversions, (Callback) convert_clipboard_target, manager); if (conversions->next == NULL && ((IncrConversion *) conversions->data)->property == None) { finish_selection_request (manager, xev, False); } else { if (multiple) { i = 0; for (list = conversions; list; list = list->next) { rdata = (IncrConversion *)list->data; multiple[i++] = rdata->target; multiple[i++] = rdata->property; } XChangeProperty (xev->xselectionrequest.display, xev->xselectionrequest.requestor, xev->xselectionrequest.property, XA_ATOM_PAIR, 32, PropModeReplace, (unsigned char *) multiple, nitems); } finish_selection_request (manager, xev, True); } list_foreach (conversions, (Callback) collect_incremental, manager); list_free (conversions); if (multiple) free (multiple); } static Bool clipboard_manager_process_event (GsdClipboardManager *manager, XEvent *xev) { Atom type; int format; unsigned long nitems; unsigned long remaining; Atom *targets; targets = NULL; switch (xev->xany.type) { case DestroyNotify: if (xev->xdestroywindow.window == manager->priv->requestor) { list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL); list_free (manager->priv->contents); manager->priv->contents = NULL; clipboard_manager_watch_cb (manager, manager->priv->requestor, False, 0, NULL); manager->priv->requestor = None; } break; case PropertyNotify: if (xev->xproperty.state == PropertyNewValue) { return receive_incrementally (manager, xev); } else { return send_incrementally (manager, xev); } case SelectionClear: if (xev->xany.window != manager->priv->window) return False; if (xev->xselectionclear.selection == XA_CLIPBOARD_MANAGER) { /* We lost the manager selection */ if (manager->priv->contents) { list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL); list_free (manager->priv->contents); manager->priv->contents = NULL; XSetSelectionOwner (manager->priv->display, XA_CLIPBOARD, None, manager->priv->time); } return True; } if (xev->xselectionclear.selection == XA_CLIPBOARD) { /* We lost the clipboard selection */ list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL); list_free (manager->priv->contents); manager->priv->contents = NULL; clipboard_manager_watch_cb (manager, manager->priv->requestor, False, 0, NULL); manager->priv->requestor = None; return True; } break; case SelectionNotify: if (xev->xany.window != manager->priv->window) return False; if (xev->xselection.selection == XA_CLIPBOARD) { /* a CLIPBOARD conversion is done */ if (xev->xselection.property == XA_TARGETS) { XGetWindowProperty (xev->xselection.display, xev->xselection.requestor, xev->xselection.property, 0, 0x1FFFFFFF, True, XA_ATOM, &type, &format, &nitems, &remaining, (unsigned char **) &targets); save_targets (manager, targets, nitems); } else if (xev->xselection.property == XA_MULTIPLE) { List *tmp; tmp = list_copy (manager->priv->contents); list_foreach (tmp, (Callback) get_property, manager); list_free (tmp); manager->priv->time = xev->xselection.time; XSetSelectionOwner (manager->priv->display, XA_CLIPBOARD, manager->priv->window, manager->priv->time); if (manager->priv->property != None) XChangeProperty (manager->priv->display, manager->priv->requestor, manager->priv->property, XA_ATOM, 32, PropModeReplace, (unsigned char *)&XA_NULL, 1); if (!list_find (manager->priv->contents, (ListFindFunc)find_content_type, (void *)XA_INCR)) { /* all transfers done */ send_selection_notify (manager, True); clipboard_manager_watch_cb (manager, manager->priv->requestor, False, 0, NULL); manager->priv->requestor = None; } } else if (xev->xselection.property == None) { send_selection_notify (manager, False); clipboard_manager_watch_cb (manager, manager->priv->requestor, False, 0, NULL); manager->priv->requestor = None; } return True; } break; case SelectionRequest: if (xev->xany.window != manager->priv->window) { return False; } if (xev->xselectionrequest.selection == XA_CLIPBOARD_MANAGER) { convert_clipboard_manager (manager, xev); return True; } else if (xev->xselectionrequest.selection == XA_CLIPBOARD) { convert_clipboard (manager, xev); return True; } break; default: ; } return False; } static GdkFilterReturn clipboard_manager_event_filter (GdkXEvent *xevent, GdkEvent *event, GsdClipboardManager *manager) { if (clipboard_manager_process_event (manager, (XEvent *)xevent)) { return GDK_FILTER_REMOVE; } else { return GDK_FILTER_CONTINUE; } } static void clipboard_manager_watch_cb (GsdClipboardManager *manager, Window window, Bool is_start, long mask, void *cb_data) { GdkWindow *gdkwin; GdkDisplay *display; display = gdk_display_get_default (); gdkwin = gdk_x11_window_lookup_for_display (display, window); if (is_start) { if (gdkwin == NULL) { gdkwin = gdk_x11_window_foreign_new_for_display (display, window); } else { g_object_ref (gdkwin); } gdk_window_add_filter (gdkwin, (GdkFilterFunc)clipboard_manager_event_filter, manager); } else { if (gdkwin == NULL) { return; } gdk_window_remove_filter (gdkwin, (GdkFilterFunc)clipboard_manager_event_filter, manager); g_object_unref (gdkwin); } } static gboolean start_clipboard_idle_cb (GsdClipboardManager *manager) { XClientMessageEvent xev; gnome_settings_profile_start (NULL); init_atoms (manager->priv->display); /* check if there is a clipboard manager running */ if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER)) { g_warning ("Clipboard manager is already running."); return FALSE; } manager->priv->contents = NULL; manager->priv->conversions = NULL; manager->priv->requestor = None; manager->priv->window = XCreateSimpleWindow (manager->priv->display, DefaultRootWindow (manager->priv->display), 0, 0, 10, 10, 0, WhitePixel (manager->priv->display, DefaultScreen (manager->priv->display)), WhitePixel (manager->priv->display, DefaultScreen (manager->priv->display))); clipboard_manager_watch_cb (manager, manager->priv->window, True, PropertyChangeMask, NULL); XSelectInput (manager->priv->display, manager->priv->window, PropertyChangeMask); manager->priv->timestamp = get_server_time (manager->priv->display, manager->priv->window); XSetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER, manager->priv->window, manager->priv->timestamp); /* Check to see if we managed to claim the selection. If not, * we treat it as if we got it then immediately lost it */ if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER) == manager->priv->window) { xev.type = ClientMessage; xev.window = DefaultRootWindow (manager->priv->display); xev.message_type = XA_MANAGER; xev.format = 32; xev.data.l[0] = manager->priv->timestamp; xev.data.l[1] = XA_CLIPBOARD_MANAGER; xev.data.l[2] = manager->priv->window; xev.data.l[3] = 0; /* manager specific data */ xev.data.l[4] = 0; /* manager specific data */ XSendEvent (manager->priv->display, DefaultRootWindow (manager->priv->display), False, StructureNotifyMask, (XEvent *)&xev); } else { clipboard_manager_watch_cb (manager, manager->priv->window, False, 0, NULL); /* FIXME: manager->priv->terminate (manager->priv->cb_data); */ } gnome_settings_profile_end (NULL); manager->priv->start_idle_id = 0; return FALSE; } gboolean gsd_clipboard_manager_start (GsdClipboardManager *manager, GError **error) { gnome_settings_profile_start (NULL); manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_clipboard_idle_cb, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_clipboard_manager_stop (GsdClipboardManager *manager) { g_debug ("Stopping clipboard manager"); if (manager->priv->window != None) { clipboard_manager_watch_cb (manager, manager->priv->window, FALSE, 0, NULL); XDestroyWindow (manager->priv->display, manager->priv->window); manager->priv->window = None; } if (manager->priv->conversions != NULL) { list_foreach (manager->priv->conversions, (Callback) conversion_free, NULL); list_free (manager->priv->conversions); manager->priv->conversions = NULL; } if (manager->priv->contents != NULL) { list_foreach (manager->priv->contents, (Callback) target_data_unref, NULL); list_free (manager->priv->contents); manager->priv->contents = NULL; } } static GObject * gsd_clipboard_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdClipboardManager *clipboard_manager; clipboard_manager = GSD_CLIPBOARD_MANAGER (G_OBJECT_CLASS (gsd_clipboard_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (clipboard_manager); } static void gsd_clipboard_manager_class_init (GsdClipboardManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_clipboard_manager_constructor; object_class->finalize = gsd_clipboard_manager_finalize; g_type_class_add_private (klass, sizeof (GsdClipboardManagerPrivate)); } static void gsd_clipboard_manager_init (GsdClipboardManager *manager) { manager->priv = GSD_CLIPBOARD_MANAGER_GET_PRIVATE (manager); manager->priv->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); } static void gsd_clipboard_manager_finalize (GObject *object) { GsdClipboardManager *clipboard_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_CLIPBOARD_MANAGER (object)); clipboard_manager = GSD_CLIPBOARD_MANAGER (object); g_return_if_fail (clipboard_manager->priv != NULL); if (clipboard_manager->priv->start_idle_id !=0) g_source_remove (clipboard_manager->priv->start_idle_id); G_OBJECT_CLASS (gsd_clipboard_manager_parent_class)->finalize (object); } GsdClipboardManager * gsd_clipboard_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_CLIPBOARD_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_CLIPBOARD_MANAGER (manager_object); } unity-settings-daemon/plugins/clipboard/gsd-clipboard-manager.h0000664000000000000000000000456015172222611022134 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_CLIPBOARD_MANAGER_H #define __GSD_CLIPBOARD_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_CLIPBOARD_MANAGER (gsd_clipboard_manager_get_type ()) #define GSD_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManager)) #define GSD_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerClass)) #define GSD_IS_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_CLIPBOARD_MANAGER)) #define GSD_IS_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_CLIPBOARD_MANAGER)) #define GSD_CLIPBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerClass)) typedef struct GsdClipboardManagerPrivate GsdClipboardManagerPrivate; typedef struct { GObject parent; GsdClipboardManagerPrivate *priv; } GsdClipboardManager; typedef struct { GObjectClass parent_class; } GsdClipboardManagerClass; GType gsd_clipboard_manager_get_type (void); GsdClipboardManager * gsd_clipboard_manager_new (void); gboolean gsd_clipboard_manager_start (GsdClipboardManager *manager, GError **error); void gsd_clipboard_manager_stop (GsdClipboardManager *manager); G_END_DECLS #endif /* __GSD_CLIPBOARD_MANAGER_H */ unity-settings-daemon/plugins/clipboard/gsd-clipboard-plugin.c0000664000000000000000000000203115172222611022002 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-clipboard-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdClipboard, gsd_clipboard) unity-settings-daemon/plugins/clipboard/list.c0000664000000000000000000000550415172222611016757 0ustar /* * Copyright © 2004 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Red Hat not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Red Hat makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Matthias Clasen, Red Hat, Inc. */ #include #include void list_foreach (List *list, Callback func, void *user_data) { while (list) { func (list->data, user_data); list = list->next; } } List * list_prepend (List *list, void *data) { List *link; link = (List *) malloc (sizeof (List)); link->next = list; link->data = data; return link; } void list_free (List *list) { while (list) { List *next = list->next; free (list); list = next; } } List * list_find (List *list, ListFindFunc func, void *user_data) { List *tmp; for (tmp = list; tmp; tmp = tmp->next) { if ((*func) (tmp->data, user_data)) break; } return tmp; } List * list_remove (List *list, void *data) { List *tmp, *prev; prev = NULL; for (tmp = list; tmp; tmp = tmp->next) { if (tmp->data == data) { if (prev) prev->next = tmp->next; else list = tmp->next; free (tmp); break; } prev = tmp; } return list; } int list_length (List *list) { List *tmp; int length; length = 0; for (tmp = list; tmp; tmp = tmp->next) length++; return length; } List * list_copy (List *list) { List *new_list = NULL; if (list) { List *last; new_list = (List *) malloc (sizeof (List)); new_list->data = list->data; new_list->next = NULL; last = new_list; list = list->next; while (list) { last->next = (List *) malloc (sizeof (List)); last = last->next; last->data = list->data; list = list->next; } last->next = NULL; } return new_list; } unity-settings-daemon/plugins/clipboard/list.h0000664000000000000000000000356615172222611016772 0ustar /* * Copyright © 2004 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Red Hat not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Red Hat makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Matthias Clasen, Red Hat, Inc. */ #ifndef LIST_H #define LIST_H typedef struct _List List; typedef void (*Callback) (void *data, void *user_data); struct _List { void *data; List *next; }; typedef int (*ListFindFunc) (void *data, void *user_data); void list_foreach (List *list, Callback func, void *user_data); List *list_prepend (List *list, void *data); void list_free (List *list); List *list_find (List *list, ListFindFunc func, void *user_data); List *list_remove (List *list, void *data); int list_length (List *list); List *list_copy (List *list); #endif /* LIST_H */ unity-settings-daemon/plugins/clipboard/xutils.c0000664000000000000000000000675615172222611017346 0ustar /* * Copyright © 2004 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Red Hat not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Red Hat makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Matthias Clasen, Red Hat, Inc. */ #include #include "xutils.h" Atom XA_ATOM_PAIR; Atom XA_CLIPBOARD_MANAGER; Atom XA_CLIPBOARD; Atom XA_DELETE; Atom XA_INCR; Atom XA_INSERT_PROPERTY; Atom XA_INSERT_SELECTION; Atom XA_MANAGER; Atom XA_MULTIPLE; Atom XA_NULL; Atom XA_SAVE_TARGETS; Atom XA_TARGETS; Atom XA_TIMESTAMP; unsigned long SELECTION_MAX_SIZE = 0; void init_atoms (Display *display) { unsigned long max_request_size; if (SELECTION_MAX_SIZE > 0) return; XA_ATOM_PAIR = XInternAtom (display, "ATOM_PAIR", False); XA_CLIPBOARD_MANAGER = XInternAtom (display, "CLIPBOARD_MANAGER", False); XA_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False); XA_DELETE = XInternAtom (display, "DELETE", False); XA_INCR = XInternAtom (display, "INCR", False); XA_INSERT_PROPERTY = XInternAtom (display, "INSERT_PROPERTY", False); XA_INSERT_SELECTION = XInternAtom (display, "INSERT_SELECTION", False); XA_MANAGER = XInternAtom (display, "MANAGER", False); XA_MULTIPLE = XInternAtom (display, "MULTIPLE", False); XA_NULL = XInternAtom (display, "NULL", False); XA_SAVE_TARGETS = XInternAtom (display, "SAVE_TARGETS", False); XA_TARGETS = XInternAtom (display, "TARGETS", False); XA_TIMESTAMP = XInternAtom (display, "TIMESTAMP", False); max_request_size = XExtendedMaxRequestSize (display); if (max_request_size == 0) max_request_size = XMaxRequestSize (display); SELECTION_MAX_SIZE = max_request_size - 100; if (SELECTION_MAX_SIZE > 262144) SELECTION_MAX_SIZE = 262144; } typedef struct { Window window; Atom timestamp_prop_atom; } TimeStampInfo; static Bool timestamp_predicate (Display *display, XEvent *xevent, XPointer arg) { TimeStampInfo *info = (TimeStampInfo *)arg; if (xevent->type == PropertyNotify && xevent->xproperty.window == info->window && xevent->xproperty.atom == info->timestamp_prop_atom) return True; return False; } Time get_server_time (Display *display, Window window) { unsigned char c = 'a'; XEvent xevent; TimeStampInfo info; info.timestamp_prop_atom = XInternAtom (display, "_TIMESTAMP_PROP", False); info.window = window; XChangeProperty (display, window, info.timestamp_prop_atom, info.timestamp_prop_atom, 8, PropModeReplace, &c, 1); XIfEvent (display, &xevent, timestamp_predicate, (XPointer)&info); return xevent.xproperty.time; } unity-settings-daemon/plugins/clipboard/xutils.h0000664000000000000000000000334015172222611017335 0ustar /* * Copyright © 2004 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Red Hat not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Red Hat makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Matthias Clasen, Red Hat, Inc. */ #ifndef X_UTILS_H #define X_UTILS_H #include extern Atom XA_ATOM_PAIR; extern Atom XA_CLIPBOARD_MANAGER; extern Atom XA_CLIPBOARD; extern Atom XA_DELETE; extern Atom XA_INCR; extern Atom XA_INSERT_PROPERTY; extern Atom XA_INSERT_SELECTION; extern Atom XA_MANAGER; extern Atom XA_MULTIPLE; extern Atom XA_NULL; extern Atom XA_SAVE_TARGETS; extern Atom XA_TARGETS; extern Atom XA_TIMESTAMP; extern unsigned long SELECTION_MAX_SIZE; void init_atoms (Display *display); Time get_server_time (Display *display, Window window); #endif /* X_UTILS_H */ unity-settings-daemon/plugins/color/0000775000000000000000000000000015172222611015013 5ustar unity-settings-daemon/plugins/color/Makefile.am0000664000000000000000000000342315172222611017051 0ustar plugin_name = color plugin_LTLIBRARIES = \ libcolor.la libcolor_la_SOURCES = \ gcm-profile-store.c \ gcm-profile-store.h \ gcm-dmi.c \ gcm-dmi.h \ gcm-edid.c \ gcm-edid.h \ gsd-color-manager.c \ gsd-color-manager.h \ gsd-color-plugin.c libcolor_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DBINDIR=\"$(bindir)\" \ $(AM_CPPFLAGS) libcolor_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(COLOR_CFLAGS) \ $(LCMS_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(AM_CFLAGS) libcolor_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libcolor_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(COLOR_LIBS) \ $(LCMS_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(LIBNOTIFY_LIBS) check_PROGRAMS = \ gcm-self-test gcm_self_test_CPPFLAGS = \ -DTESTDATADIR=\""$(top_srcdir)/plugins/color/test-data"\" \ $(AM_CPPFLAGS) gcm_self_test_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(COLOR_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(AM_CFLAGS) gcm_self_test_SOURCES = \ gcm-dmi.c \ gcm-dmi.h \ gcm-edid.c \ gcm-edid.h \ gcm-self-test.c gcm_self_test_LDADD = \ $(COLOR_LIBS) \ $(LCMS_LIBS) \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ -lm TESTS = gcm-self-test plugin_in_files = \ color.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) \ test-data/Lenovo-T61-Internal.bin \ test-data/LG-L225W-External.bin CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/color/color.gnome-settings-plugin.in0000664000000000000000000000027715172222611022725 0ustar [GNOME Settings Plugin] Module=color IAge=0 Priority=10 _Name=Color _Description=Color plugin Authors=Richard Hughes Copyright=Copyright © 2011 Richard Hughes Website= unity-settings-daemon/plugins/color/gcm-dmi.c0000664000000000000000000001206315172222611016476 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include "gcm-dmi.h" static void gcm_dmi_finalize (GObject *object); #define GCM_DMI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_DMI, GcmDmiPrivate)) struct _GcmDmiPrivate { gchar *name; gchar *version; gchar *vendor; }; static gpointer gcm_dmi_object = NULL; G_DEFINE_TYPE (GcmDmi, gcm_dmi, G_TYPE_OBJECT) static gchar * gcm_dmi_get_from_filename (const gchar *filename) { gboolean ret; GError *error = NULL; gchar *data = NULL; /* get the contents */ ret = g_file_get_contents (filename, &data, NULL, &error); if (!ret) { if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) g_warning ("failed to get contents of %s: %s", filename, error->message); g_error_free (error); } /* process the random chars and trailing spaces */ if (data != NULL) { g_strdelimit (data, "\t_", ' '); g_strdelimit (data, "\n\r", '\0'); g_strchomp (data); } /* don't return an empty string */ if (data != NULL && data[0] == '\0') { g_free (data); data = NULL; } return data; } static gchar * gcm_dmi_get_from_filenames (const gchar * const * filenames) { guint i; gchar *tmp = NULL; /* try each one in preference order */ for (i = 0; filenames[i] != NULL; i++) { tmp = gcm_dmi_get_from_filename (filenames[i]); if (tmp != NULL) break; } return tmp; } const gchar * gcm_dmi_get_name (GcmDmi *dmi) { g_return_val_if_fail (GCM_IS_DMI (dmi), NULL); return dmi->priv->name; } const gchar * gcm_dmi_get_version (GcmDmi *dmi) { g_return_val_if_fail (GCM_IS_DMI (dmi), NULL); return dmi->priv->version; } const gchar * gcm_dmi_get_vendor (GcmDmi *dmi) { g_return_val_if_fail (GCM_IS_DMI (dmi), NULL); return dmi->priv->vendor; } static void gcm_dmi_class_init (GcmDmiClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gcm_dmi_finalize; g_type_class_add_private (klass, sizeof (GcmDmiPrivate)); } static void gcm_dmi_init (GcmDmi *dmi) { #if defined(__linux__) const gchar *sysfs_name[] = { "/sys/class/dmi/id/product_name", "/sys/class/dmi/id/board_name", NULL}; const gchar *sysfs_version[] = { "/sys/class/dmi/id/product_version", "/sys/class/dmi/id/chassis_version", "/sys/class/dmi/id/board_version", NULL}; const gchar *sysfs_vendor[] = { "/sys/class/dmi/id/sys_vendor", "/sys/class/dmi/id/chassis_vendor", "/sys/class/dmi/id/board_vendor", NULL}; #else #warning Please add dmi support for your OS const gchar *sysfs_name[] = { NULL }; const gchar *sysfs_version[] = { NULL }; const gchar *sysfs_vendor[] = { NULL }; #endif dmi->priv = GCM_DMI_GET_PRIVATE (dmi); /* get all the possible data now */ dmi->priv->name = gcm_dmi_get_from_filenames (sysfs_name); dmi->priv->version = gcm_dmi_get_from_filenames (sysfs_version); dmi->priv->vendor = gcm_dmi_get_from_filenames (sysfs_vendor); } static void gcm_dmi_finalize (GObject *object) { GcmDmi *dmi = GCM_DMI (object); g_free (dmi->priv->name); g_free (dmi->priv->version); g_free (dmi->priv->vendor); G_OBJECT_CLASS (gcm_dmi_parent_class)->finalize (object); } GcmDmi * gcm_dmi_new (void) { if (gcm_dmi_object != NULL) { g_object_ref (gcm_dmi_object); } else { gcm_dmi_object = g_object_new (GCM_TYPE_DMI, NULL); g_object_add_weak_pointer (gcm_dmi_object, &gcm_dmi_object); } return GCM_DMI (gcm_dmi_object); } unity-settings-daemon/plugins/color/gcm-dmi.h0000664000000000000000000000422615172222611016505 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2010 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GCM_DMI_H #define __GCM_DMI_H #include G_BEGIN_DECLS #define GCM_TYPE_DMI (gcm_dmi_get_type ()) #define GCM_DMI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GCM_TYPE_DMI, GcmDmi)) #define GCM_DMI_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GCM_TYPE_DMI, GcmDmiClass)) #define GCM_IS_DMI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GCM_TYPE_DMI)) #define GCM_IS_DMI_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GCM_TYPE_DMI)) #define GCM_DMI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GCM_TYPE_DMI, GcmDmiClass)) typedef struct _GcmDmiPrivate GcmDmiPrivate; typedef struct _GcmDmi GcmDmi; typedef struct _GcmDmiClass GcmDmiClass; struct _GcmDmi { GObject parent; GcmDmiPrivate *priv; }; struct _GcmDmiClass { GObjectClass parent_class; }; GType gcm_dmi_get_type (void); GcmDmi *gcm_dmi_new (void); const gchar *gcm_dmi_get_name (GcmDmi *dmi); const gchar *gcm_dmi_get_version (GcmDmi *dmi); const gchar *gcm_dmi_get_vendor (GcmDmi *dmi); G_END_DECLS #endif /* __GCM_DMI_H */ unity-settings-daemon/plugins/color/gcm-edid.c0000664000000000000000000003432715172222611016641 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2008 Soren Sandmann * Copyright (C) 2009-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include "gcm-edid.h" #include "../../gnome-settings-daemon/gsd-pnp-ids.h" static void gcm_edid_finalize (GObject *object); #define GCM_EDID_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_EDID, GcmEdidPrivate)) struct _GcmEdidPrivate { gchar *monitor_name; gchar *vendor_name; gchar *serial_number; gchar *eisa_id; gchar *checksum; gchar *pnp_id; guint width; guint height; gfloat gamma; CdColorYxy *red; CdColorYxy *green; CdColorYxy *blue; CdColorYxy *white; GsdPnpIds *pnp_ids; }; G_DEFINE_TYPE (GcmEdid, gcm_edid, G_TYPE_OBJECT) #define GCM_EDID_OFFSET_PNPID 0x08 #define GCM_EDID_OFFSET_SERIAL 0x0c #define GCM_EDID_OFFSET_SIZE 0x15 #define GCM_EDID_OFFSET_GAMMA 0x17 #define GCM_EDID_OFFSET_DATA_BLOCKS 0x36 #define GCM_EDID_OFFSET_LAST_BLOCK 0x6c #define GCM_EDID_OFFSET_EXTENSION_BLOCK_COUNT 0x7e #define GCM_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc #define GCM_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff #define GCM_DESCRIPTOR_COLOR_MANAGEMENT_DATA 0xf9 #define GCM_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe #define GCM_DESCRIPTOR_COLOR_POINT 0xfb GQuark gcm_edid_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gcm_edid_error"); return quark; } const gchar * gcm_edid_get_monitor_name (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->monitor_name; } const gchar * gcm_edid_get_vendor_name (GcmEdid *edid) { GcmEdidPrivate *priv = edid->priv; g_return_val_if_fail (GCM_IS_EDID (edid), NULL); if (priv->vendor_name == NULL) priv->vendor_name = gsd_pnp_ids_get_pnp_id (priv->pnp_ids, priv->pnp_id); return priv->vendor_name; } const gchar * gcm_edid_get_serial_number (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->serial_number; } const gchar * gcm_edid_get_eisa_id (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->eisa_id; } const gchar * gcm_edid_get_checksum (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->checksum; } const gchar * gcm_edid_get_pnp_id (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->pnp_id; } guint gcm_edid_get_width (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), 0); return edid->priv->width; } guint gcm_edid_get_height (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), 0); return edid->priv->height; } gfloat gcm_edid_get_gamma (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), 0.0f); return edid->priv->gamma; } const CdColorYxy * gcm_edid_get_red (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->red; } const CdColorYxy * gcm_edid_get_green (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->green; } const CdColorYxy * gcm_edid_get_blue (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->blue; } const CdColorYxy * gcm_edid_get_white (GcmEdid *edid) { g_return_val_if_fail (GCM_IS_EDID (edid), NULL); return edid->priv->white; } void gcm_edid_reset (GcmEdid *edid) { GcmEdidPrivate *priv = edid->priv; g_return_if_fail (GCM_IS_EDID (edid)); /* free old data */ g_free (priv->monitor_name); g_free (priv->vendor_name); g_free (priv->serial_number); g_free (priv->eisa_id); g_free (priv->checksum); /* do not deallocate, just blank */ priv->pnp_id[0] = '\0'; /* set to default values */ priv->monitor_name = NULL; priv->vendor_name = NULL; priv->serial_number = NULL; priv->eisa_id = NULL; priv->checksum = NULL; priv->width = 0; priv->height = 0; priv->gamma = 0.0f; } static gint gcm_edid_get_bit (gint in, gint bit) { return (in & (1 << bit)) >> bit; } /** * gcm_edid_get_bits: **/ static gint gcm_edid_get_bits (gint in, gint begin, gint end) { gint mask = (1 << (end - begin + 1)) - 1; return (in >> begin) & mask; } /** * gcm_edid_decode_fraction: **/ static gdouble gcm_edid_decode_fraction (gint high, gint low) { gdouble result = 0.0; gint i; high = (high << 2) | low; for (i = 0; i < 10; ++i) result += gcm_edid_get_bit (high, i) * pow (2, i - 10); return result; } static gchar * gcm_edid_parse_string (const guint8 *data) { gchar *text; guint i; guint replaced = 0; /* this is always 12 bytes, but we can't guarantee it's null * terminated or not junk. */ text = g_strndup ((const gchar *) data, 12); /* remove insane newline chars */ g_strdelimit (text, "\n\r", '\0'); /* remove spaces */ g_strchomp (text); /* nothing left? */ if (text[0] == '\0') { g_free (text); text = NULL; goto out; } /* ensure string is printable */ for (i = 0; text[i] != '\0'; i++) { if (!g_ascii_isprint (text[i])) { text[i] = '-'; replaced++; } } /* if the string is junk, ignore the string */ if (replaced > 4) { g_free (text); text = NULL; goto out; } out: return text; } gboolean gcm_edid_parse (GcmEdid *edid, const guint8 *data, gsize length, GError **error) { gboolean ret = TRUE; guint i; GcmEdidPrivate *priv = edid->priv; guint32 serial; gchar *tmp; /* check header */ if (length < 128) { g_set_error_literal (error, GCM_EDID_ERROR, GCM_EDID_ERROR_FAILED_TO_PARSE, "EDID length is too small"); ret = FALSE; goto out; } if (data[0] != 0x00 || data[1] != 0xff) { g_set_error_literal (error, GCM_EDID_ERROR, GCM_EDID_ERROR_FAILED_TO_PARSE, "Failed to parse EDID header"); ret = FALSE; goto out; } /* free old data */ gcm_edid_reset (edid); /* decode the PNP ID from three 5 bit words packed into 2 bytes * /--08--\/--09--\ * 7654321076543210 * |\---/\---/\---/ * R C1 C2 C3 */ priv->pnp_id[0] = 'A' + ((data[GCM_EDID_OFFSET_PNPID+0] & 0x7c) / 4) - 1; priv->pnp_id[1] = 'A' + ((data[GCM_EDID_OFFSET_PNPID+0] & 0x3) * 8) + ((data[GCM_EDID_OFFSET_PNPID+1] & 0xe0) / 32) - 1; priv->pnp_id[2] = 'A' + (data[GCM_EDID_OFFSET_PNPID+1] & 0x1f) - 1; /* maybe there isn't a ASCII serial number descriptor, so use this instead */ serial = (guint32) data[GCM_EDID_OFFSET_SERIAL+0]; serial += (guint32) data[GCM_EDID_OFFSET_SERIAL+1] * 0x100; serial += (guint32) data[GCM_EDID_OFFSET_SERIAL+2] * 0x10000; serial += (guint32) data[GCM_EDID_OFFSET_SERIAL+3] * 0x1000000; if (serial > 0) priv->serial_number = g_strdup_printf ("%" G_GUINT32_FORMAT, serial); /* get the size */ priv->width = data[GCM_EDID_OFFSET_SIZE+0]; priv->height = data[GCM_EDID_OFFSET_SIZE+1]; /* we don't care about aspect */ if (priv->width == 0 || priv->height == 0) { priv->width = 0; priv->height = 0; } /* get gamma */ if (data[GCM_EDID_OFFSET_GAMMA] == 0xff) { priv->gamma = 1.0f; } else { priv->gamma = ((gfloat) data[GCM_EDID_OFFSET_GAMMA] / 100) + 1; } /* get color red */ priv->red->x = gcm_edid_decode_fraction (data[0x1b], gcm_edid_get_bits (data[0x19], 6, 7)); priv->red->y = gcm_edid_decode_fraction (data[0x1c], gcm_edid_get_bits (data[0x19], 5, 4)); /* get color green */ priv->green->x = gcm_edid_decode_fraction (data[0x1d], gcm_edid_get_bits (data[0x19], 2, 3)); priv->green->y = gcm_edid_decode_fraction (data[0x1e], gcm_edid_get_bits (data[0x19], 0, 1)); /* get color blue */ priv->blue->x = gcm_edid_decode_fraction (data[0x1f], gcm_edid_get_bits (data[0x1a], 6, 7)); priv->blue->y = gcm_edid_decode_fraction (data[0x20], gcm_edid_get_bits (data[0x1a], 4, 5)); /* get color white */ priv->white->x = gcm_edid_decode_fraction (data[0x21], gcm_edid_get_bits (data[0x1a], 2, 3)); priv->white->y = gcm_edid_decode_fraction (data[0x22], gcm_edid_get_bits (data[0x1a], 0, 1)); /* parse EDID data */ for (i = GCM_EDID_OFFSET_DATA_BLOCKS; i <= GCM_EDID_OFFSET_LAST_BLOCK; i += 18) { /* ignore pixel clock data */ if (data[i] != 0) continue; if (data[i+2] != 0) continue; /* any useful blocks? */ if (data[i+3] == GCM_DESCRIPTOR_DISPLAY_PRODUCT_NAME) { tmp = gcm_edid_parse_string (&data[i+5]); if (tmp != NULL) { g_free (priv->monitor_name); priv->monitor_name = tmp; } } else if (data[i+3] == GCM_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) { tmp = gcm_edid_parse_string (&data[i+5]); if (tmp != NULL) { g_free (priv->serial_number); priv->serial_number = tmp; } } else if (data[i+3] == GCM_DESCRIPTOR_COLOR_MANAGEMENT_DATA) { g_warning ("failing to parse color management data"); } else if (data[i+3] == GCM_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) { tmp = gcm_edid_parse_string (&data[i+5]); if (tmp != NULL) { g_free (priv->eisa_id); priv->eisa_id = tmp; } } else if (data[i+3] == GCM_DESCRIPTOR_COLOR_POINT) { if (data[i+3+9] != 0xff) { /* extended EDID block(1) which contains * a better gamma value */ priv->gamma = ((gfloat) data[i+3+9] / 100) + 1; } if (data[i+3+14] != 0xff) { /* extended EDID block(2) which contains * a better gamma value */ priv->gamma = ((gfloat) data[i+3+9] / 100) + 1; } } } /* calculate checksum */ priv->checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, data, length); out: return ret; } static void gcm_edid_class_init (GcmEdidClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gcm_edid_finalize; g_type_class_add_private (klass, sizeof (GcmEdidPrivate)); } static void gcm_edid_init (GcmEdid *edid) { edid->priv = GCM_EDID_GET_PRIVATE (edid); edid->priv->pnp_ids = gsd_pnp_ids_new (); edid->priv->pnp_id = g_new0 (gchar, 4); edid->priv->red = cd_color_yxy_new (); edid->priv->green = cd_color_yxy_new (); edid->priv->blue = cd_color_yxy_new (); edid->priv->white = cd_color_yxy_new (); } static void gcm_edid_finalize (GObject *object) { GcmEdid *edid = GCM_EDID (object); GcmEdidPrivate *priv = edid->priv; g_free (priv->monitor_name); g_free (priv->vendor_name); g_free (priv->serial_number); g_free (priv->eisa_id); g_free (priv->checksum); g_free (priv->pnp_id); cd_color_yxy_free (priv->white); cd_color_yxy_free (priv->red); cd_color_yxy_free (priv->green); cd_color_yxy_free (priv->blue); g_object_unref (priv->pnp_ids); G_OBJECT_CLASS (gcm_edid_parent_class)->finalize (object); } GcmEdid * gcm_edid_new (void) { GcmEdid *edid; edid = g_object_new (GCM_TYPE_EDID, NULL); return GCM_EDID (edid); } unity-settings-daemon/plugins/color/gcm-edid.h0000664000000000000000000000725315172222611016644 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2010 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GCM_EDID_H #define __GCM_EDID_H #include #include G_BEGIN_DECLS #define GCM_TYPE_EDID (gcm_edid_get_type ()) #define GCM_EDID(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GCM_TYPE_EDID, GcmEdid)) #define GCM_EDID_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GCM_TYPE_EDID, GcmEdidClass)) #define GCM_IS_EDID(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GCM_TYPE_EDID)) #define GCM_IS_EDID_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GCM_TYPE_EDID)) #define GCM_EDID_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GCM_TYPE_EDID, GcmEdidClass)) #define GCM_EDID_ERROR (gcm_edid_error_quark ()) typedef struct _GcmEdidPrivate GcmEdidPrivate; typedef struct _GcmEdid GcmEdid; typedef struct _GcmEdidClass GcmEdidClass; struct _GcmEdid { GObject parent; GcmEdidPrivate *priv; }; struct _GcmEdidClass { GObjectClass parent_class; }; enum { GCM_EDID_ERROR_FAILED_TO_PARSE }; GType gcm_edid_get_type (void); GQuark gcm_edid_error_quark (void); GcmEdid *gcm_edid_new (void); void gcm_edid_reset (GcmEdid *edid); gboolean gcm_edid_parse (GcmEdid *edid, const guint8 *data, gsize length, GError **error); const gchar *gcm_edid_get_monitor_name (GcmEdid *edid); const gchar *gcm_edid_get_vendor_name (GcmEdid *edid); const gchar *gcm_edid_get_serial_number (GcmEdid *edid); const gchar *gcm_edid_get_eisa_id (GcmEdid *edid); const gchar *gcm_edid_get_checksum (GcmEdid *edid); const gchar *gcm_edid_get_pnp_id (GcmEdid *edid); guint gcm_edid_get_width (GcmEdid *edid); guint gcm_edid_get_height (GcmEdid *edid); gfloat gcm_edid_get_gamma (GcmEdid *edid); const CdColorYxy *gcm_edid_get_red (GcmEdid *edid); const CdColorYxy *gcm_edid_get_green (GcmEdid *edid); const CdColorYxy *gcm_edid_get_blue (GcmEdid *edid); const CdColorYxy *gcm_edid_get_white (GcmEdid *edid); G_END_DECLS #endif /* __GCM_EDID_H */ unity-settings-daemon/plugins/color/gcm-profile-store.c0000664000000000000000000004570715172222611020532 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include "gcm-profile-store.h" static void gcm_profile_store_finalize (GObject *object); #define GCM_PROFILE_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_PROFILE_STORE, GcmProfileStorePrivate)) struct _GcmProfileStorePrivate { GPtrArray *filename_array; GPtrArray *directory_array; GCancellable *cancellable; }; enum { SIGNAL_ADDED, SIGNAL_REMOVED, SIGNAL_CHANGED, SIGNAL_LAST }; static guint signals[SIGNAL_LAST] = { 0 }; G_DEFINE_TYPE (GcmProfileStore, gcm_profile_store, G_TYPE_OBJECT) static void gcm_profile_store_search_path (GcmProfileStore *profile_store, const gchar *path, guint depth); static void gcm_profile_store_process_child (GcmProfileStore *profile_store, const gchar *path, GFileInfo *info); #define GCM_PROFILE_STORE_MAX_RECURSION_LEVELS 2 typedef struct { gchar *path; GFileMonitor *monitor; guint depth; } GcmProfileStoreDirHelper; static void gcm_profile_store_helper_free (GcmProfileStoreDirHelper *helper) { g_free (helper->path); if (helper->monitor != NULL) g_object_unref (helper->monitor); g_free (helper); } static const gchar * gcm_profile_store_find_filename (GcmProfileStore *profile_store, const gchar *filename) { const gchar *tmp; guint i; GPtrArray *array = profile_store->priv->filename_array; for (i=0; ilen; i++) { tmp = g_ptr_array_index (array, i); if (g_strcmp0 (filename, tmp) == 0) return tmp; } return NULL; } static GcmProfileStoreDirHelper * gcm_profile_store_find_directory (GcmProfileStore *profile_store, const gchar *path) { GcmProfileStoreDirHelper *tmp; guint i; GPtrArray *array = profile_store->priv->directory_array; for (i=0; ilen; i++) { tmp = g_ptr_array_index (array, i); if (g_strcmp0 (path, tmp->path) == 0) return tmp; } return NULL; } static gboolean gcm_profile_store_remove_profile (GcmProfileStore *profile_store, const gchar *filename) { gboolean ret = FALSE; const gchar *tmp; gchar *filename_dup = NULL; GcmProfileStorePrivate *priv = profile_store->priv; /* find exact pointer */ tmp = gcm_profile_store_find_filename (profile_store, filename); if (tmp == NULL) goto out; /* dup so we can emit the signal */ filename_dup = g_strdup (tmp); ret = g_ptr_array_remove (priv->filename_array, (gpointer)tmp); if (!ret) { g_warning ("failed to remove %s", filename); goto out; } /* emit a signal */ g_debug ("emit removed: %s", filename_dup); g_signal_emit (profile_store, signals[SIGNAL_REMOVED], 0, filename_dup); out: g_free (filename_dup); return ret; } static void gcm_profile_store_add_profile (GcmProfileStore *profile_store, const gchar *filename) { GcmProfileStorePrivate *priv = profile_store->priv; /* add to list */ g_ptr_array_add (priv->filename_array, g_strdup (filename)); /* emit a signal */ g_debug ("emit add: %s", filename); g_signal_emit (profile_store, signals[SIGNAL_ADDED], 0, filename); } static void gcm_profile_store_created_query_info_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GFileInfo *info; GError *error = NULL; gchar *path; GFile *file = G_FILE (source_object); GFile *parent; GcmProfileStore *profile_store = GCM_PROFILE_STORE (user_data); info = g_file_query_info_finish (file, res, &error); if (info == NULL) { g_warning ("failed to get info about deleted file: %s", error->message); g_error_free (error); return; } parent = g_file_get_parent (file); path = g_file_get_path (parent); gcm_profile_store_process_child (profile_store, path, info); g_free (path); g_object_unref (info); g_object_unref (parent); } static void gcm_profile_store_remove_from_prefix (GcmProfileStore *profile_store, const gchar *prefix) { guint i; const gchar *path; GcmProfileStorePrivate *priv = profile_store->priv; for (i = 0; i < priv->filename_array->len; i++) { path = g_ptr_array_index (priv->filename_array, i); if (g_str_has_prefix (path, prefix)) { g_debug ("auto-removed %s as path removed", path); gcm_profile_store_remove_profile (profile_store, path); } } } static void gcm_profile_store_file_monitor_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, GcmProfileStore *profile_store) { gchar *path = NULL; gchar *parent_path = NULL; const gchar *tmp; GcmProfileStoreDirHelper *helper; /* profile was deleted */ if (event_type == G_FILE_MONITOR_EVENT_DELETED) { /* we can either have two things here, a directory or a * file. We can't call g_file_query_info_async() as the * inode doesn't exist anymore */ path = g_file_get_path (file); tmp = gcm_profile_store_find_filename (profile_store, path); if (tmp != NULL) { /* is a file */ gcm_profile_store_remove_profile (profile_store, path); goto out; } /* is a directory, urgh. Remove all profiles there. */ gcm_profile_store_remove_from_prefix (profile_store, path); helper = gcm_profile_store_find_directory (profile_store, path); if (helper != NULL) { g_ptr_array_remove (profile_store->priv->directory_array, helper); } goto out; } /* ignore temp files */ path = g_file_get_path (file); if (g_strrstr (path, ".goutputstream") != NULL) { g_debug ("ignoring gvfs temporary file"); goto out; } /* only care about created objects */ if (event_type == G_FILE_MONITOR_EVENT_CREATED) { g_file_query_info_async (file, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_PRIORITY_LOW, NULL, gcm_profile_store_created_query_info_cb, profile_store); goto out; } out: g_free (path); g_free (parent_path); } static void gcm_profile_store_process_child (GcmProfileStore *profile_store, const gchar *path, GFileInfo *info) { gchar *full_path = NULL; const gchar *name; GcmProfileStoreDirHelper *helper; /* check we're not in a loop */ helper = gcm_profile_store_find_directory (profile_store, path); if (helper == NULL) goto out; if (helper->depth > GCM_PROFILE_STORE_MAX_RECURSION_LEVELS) { g_warning ("recursing more than %i levels deep is insane", GCM_PROFILE_STORE_MAX_RECURSION_LEVELS); goto out; } /* make the compete path */ name = g_file_info_get_name (info); full_path = g_build_filename (path, name, NULL); /* if a directory */ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { gcm_profile_store_search_path (profile_store, full_path, helper->depth + 1); goto out; } /* ignore temp files */ if (g_strrstr (full_path, ".goutputstream") != NULL) { g_debug ("ignoring gvfs temporary file"); goto out; } /* is a file */ gcm_profile_store_add_profile (profile_store, full_path); out: g_free (full_path); } static void gcm_profile_store_next_files_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GList *files; GList *f; GError *error = NULL; GFileInfo *info; GFile *file; gchar *path; GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object); GcmProfileStore *profile_store = GCM_PROFILE_STORE (user_data); files = g_file_enumerator_next_files_finish (enumerator, res, &error); if (files == NULL) { /* special value, meaning "no more files to process" */ return; } if (error != NULL) { g_warning ("failed to get data about enumerated directory: %s", error->message); g_error_free (error); return; } /* get each file */ file = g_file_enumerator_get_container (enumerator); path = g_file_get_path (file); for (f = files; f != NULL; f = f->next) { info = G_FILE_INFO (f->data); gcm_profile_store_process_child (profile_store, path, info); } /* continue to get the rest of the data in chunks */ g_file_enumerator_next_files_async (enumerator, 5, G_PRIORITY_LOW, profile_store->priv->cancellable, gcm_profile_store_next_files_cb, user_data); g_free (path); g_list_foreach (files, (GFunc) g_object_unref, NULL); g_list_free (files); } static void gcm_profile_store_enumerate_children_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GFileEnumerator *enumerator; GcmProfileStore *profile_store = GCM_PROFILE_STORE (user_data); enumerator = g_file_enumerate_children_finish (G_FILE (source_object), res, &error); if (enumerator == NULL) { GcmProfileStoreDirHelper *helper; gchar *path = NULL; path = g_file_get_path (G_FILE (source_object)); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) g_debug ("failed to enumerate directory %s: %s", path, error->message); else g_warning ("failed to enumerate directory %s: %s", path, error->message); helper = gcm_profile_store_find_directory (profile_store, path); if (helper) g_ptr_array_remove (profile_store->priv->directory_array, helper); g_error_free (error); g_free (path); return; } /* get the first chunk of data */ g_file_enumerator_next_files_async (enumerator, 5, G_PRIORITY_LOW, profile_store->priv->cancellable, gcm_profile_store_next_files_cb, user_data); g_object_unref (enumerator); } static void gcm_profile_store_search_path (GcmProfileStore *profile_store, const gchar *path, guint depth) { GFile *file = NULL; GError *error = NULL; GcmProfileStoreDirHelper *helper; file = g_file_new_for_path (path); /* add an inotify watch if not already added */ helper = gcm_profile_store_find_directory (profile_store, path); if (helper == NULL) { helper = g_new0 (GcmProfileStoreDirHelper, 1); helper->depth = depth; helper->path = g_strdup (path); helper->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, &error); if (helper->monitor == NULL) { g_debug ("failed to monitor path: %s", error->message); g_error_free (error); gcm_profile_store_helper_free (helper); goto out; } g_signal_connect (helper->monitor, "changed", G_CALLBACK(gcm_profile_store_file_monitor_changed_cb), profile_store); g_ptr_array_add (profile_store->priv->directory_array, helper); } /* get contents of directory */ g_file_enumerate_children_async (file, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_PRIORITY_LOW, profile_store->priv->cancellable, gcm_profile_store_enumerate_children_cb, profile_store); out: g_object_unref (file); } static gboolean gcm_profile_store_mkdir_with_parents (const gchar *filename, GCancellable *cancellable, GError **error) { gboolean ret; GFile *file; /* ensure destination exists */ file = g_file_new_for_path (filename); ret = g_file_make_directory_with_parents (file, cancellable, error); g_object_unref (file); return ret; } gboolean gcm_profile_store_search (GcmProfileStore *profile_store) { gchar *path; gboolean ret; GError *error = NULL; /* get Linux per-user profiles */ path = g_build_filename (g_get_user_data_dir (), "icc", NULL); ret = gcm_profile_store_mkdir_with_parents (path, profile_store->priv->cancellable, &error); if (!ret && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) { g_warning ("failed to create directory on startup: %s", error->message); } else { gcm_profile_store_search_path (profile_store, path, 0); } g_free (path); g_clear_error (&error); /* get per-user profiles from obsolete location */ path = g_build_filename (g_get_home_dir (), ".color", "icc", NULL); gcm_profile_store_search_path (profile_store, path, 0); g_free (path); return TRUE; } static void gcm_profile_store_class_init (GcmProfileStoreClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gcm_profile_store_finalize; signals[SIGNAL_ADDED] = g_signal_new ("added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcmProfileStoreClass, added), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); signals[SIGNAL_REMOVED] = g_signal_new ("removed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcmProfileStoreClass, removed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private (klass, sizeof (GcmProfileStorePrivate)); } static void gcm_profile_store_init (GcmProfileStore *profile_store) { profile_store->priv = GCM_PROFILE_STORE_GET_PRIVATE (profile_store); profile_store->priv->cancellable = g_cancellable_new (); profile_store->priv->filename_array = g_ptr_array_new_with_free_func (g_free); profile_store->priv->directory_array = g_ptr_array_new_with_free_func ((GDestroyNotify) gcm_profile_store_helper_free); } static void gcm_profile_store_finalize (GObject *object) { GcmProfileStore *profile_store = GCM_PROFILE_STORE (object); GcmProfileStorePrivate *priv = profile_store->priv; g_cancellable_cancel (profile_store->priv->cancellable); g_object_unref (profile_store->priv->cancellable); g_ptr_array_unref (priv->filename_array); g_ptr_array_unref (priv->directory_array); G_OBJECT_CLASS (gcm_profile_store_parent_class)->finalize (object); } GcmProfileStore * gcm_profile_store_new (void) { GcmProfileStore *profile_store; profile_store = g_object_new (GCM_TYPE_PROFILE_STORE, NULL); return GCM_PROFILE_STORE (profile_store); } unity-settings-daemon/plugins/color/gcm-profile-store.h0000664000000000000000000000467315172222611020534 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2009-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GCM_PROFILE_STORE_H #define __GCM_PROFILE_STORE_H #include G_BEGIN_DECLS #define GCM_TYPE_PROFILE_STORE (gcm_profile_store_get_type ()) #define GCM_PROFILE_STORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GCM_TYPE_PROFILE_STORE, GcmProfileStore)) #define GCM_PROFILE_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GCM_TYPE_PROFILE_STORE, GcmProfileStoreClass)) #define GCM_IS_PROFILE_STORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GCM_TYPE_PROFILE_STORE)) #define GCM_IS_PROFILE_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GCM_TYPE_PROFILE_STORE)) #define GCM_PROFILE_STORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GCM_TYPE_PROFILE_STORE, GcmProfileStoreClass)) typedef struct _GcmProfileStorePrivate GcmProfileStorePrivate; typedef struct _GcmProfileStore GcmProfileStore; typedef struct _GcmProfileStoreClass GcmProfileStoreClass; struct _GcmProfileStore { GObject parent; GcmProfileStorePrivate *priv; }; struct _GcmProfileStoreClass { GObjectClass parent_class; void (* added) (const gchar *filename); void (* removed) (const gchar *filename); }; GType gcm_profile_store_get_type (void); GcmProfileStore *gcm_profile_store_new (void); gboolean gcm_profile_store_search (GcmProfileStore *profile_store); G_END_DECLS #endif /* __GCM_PROFILE_STORE_H */ unity-settings-daemon/plugins/color/gcm-self-test.c0000664000000000000000000001037415172222611017636 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2007-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include "gcm-edid.h" #include "gcm-dmi.h" static void gcm_test_dmi_func (void) { GcmDmi *dmi; dmi = gcm_dmi_new (); g_assert (dmi != NULL); g_assert (gcm_dmi_get_name (dmi) != NULL); g_assert (gcm_dmi_get_vendor (dmi) != NULL); g_object_unref (dmi); } static void gcm_test_edid_func (void) { GcmEdid *edid; gchar *data; gboolean ret; GError *error = NULL; gsize length = 0; edid = gcm_edid_new (); g_assert (edid != NULL); /* LG 21" LCD panel */ ret = g_file_get_contents (TESTDATADIR "/LG-L225W-External.bin", &data, &length, &error); g_assert_no_error (error); g_assert (ret); ret = gcm_edid_parse (edid, (const guint8 *) data, length, &error); g_assert_no_error (error); g_assert (ret); g_assert_cmpstr (gcm_edid_get_monitor_name (edid), ==, "L225W"); g_assert_cmpstr (gcm_edid_get_vendor_name (edid), ==, "LG Electronics"); g_assert_cmpstr (gcm_edid_get_serial_number (edid), ==, "34398"); g_assert_cmpstr (gcm_edid_get_eisa_id (edid), ==, NULL); g_assert_cmpstr (gcm_edid_get_checksum (edid), ==, "0bb44865bb29984a4bae620656c31368"); g_assert_cmpstr (gcm_edid_get_pnp_id (edid), ==, "GSM"); g_assert_cmpint (gcm_edid_get_height (edid), ==, 30); g_assert_cmpint (gcm_edid_get_width (edid), ==, 47); g_assert_cmpfloat (gcm_edid_get_gamma (edid), >=, 2.2f - 0.01); g_assert_cmpfloat (gcm_edid_get_gamma (edid), <, 2.2f + 0.01); g_free (data); /* Lenovo T61 internal Panel */ ret = g_file_get_contents (TESTDATADIR "/Lenovo-T61-Internal.bin", &data, &length, &error); g_assert_no_error (error); g_assert (ret); ret = gcm_edid_parse (edid, (const guint8 *) data, length, &error); g_assert_no_error (error); g_assert (ret); g_assert_cmpstr (gcm_edid_get_monitor_name (edid), ==, NULL); g_assert_cmpstr (gcm_edid_get_vendor_name (edid), ==, "IBM Brasil"); g_assert_cmpstr (gcm_edid_get_serial_number (edid), ==, NULL); g_assert_cmpstr (gcm_edid_get_eisa_id (edid), ==, "LTN154P2-L05"); g_assert_cmpstr (gcm_edid_get_checksum (edid), ==, "e1865128c7cd5e5ed49ecfc8102f6f9c"); g_assert_cmpstr (gcm_edid_get_pnp_id (edid), ==, "IBM"); g_assert_cmpint (gcm_edid_get_height (edid), ==, 21); g_assert_cmpint (gcm_edid_get_width (edid), ==, 33); g_assert_cmpfloat (gcm_edid_get_gamma (edid), >=, 2.2f - 0.01); g_assert_cmpfloat (gcm_edid_get_gamma (edid), <, 2.2f + 0.01); g_free (data); g_object_unref (edid); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); #if !defined(__s390x__) && !defined(__powerpc64__) /* * This test is disabled for s390x and pp64el, because DMI * information is not available for these CPU architectures * during package building. */ g_test_add_func ("/color/dmi", gcm_test_dmi_func); #endif g_test_add_func ("/color/edid", gcm_test_edid_func); return g_test_run (); } unity-settings-daemon/plugins/color/gsd-color-manager.c0000664000000000000000000024013115172222611020461 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #include "gnome-settings-bus.h" #include "gsd-color-manager.h" #include "gcm-profile-store.h" #include "gcm-dmi.h" #include "gcm-edid.h" #include "gsd-rr.h" #define GSD_COLOR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_COLOR_MANAGER, GsdColorManagerPrivate)) #define GCM_SESSION_NOTIFY_TIMEOUT 30000 /* ms */ #define GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD "recalibrate-printer-threshold" #define GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD "recalibrate-display-threshold" struct GsdColorManagerPrivate { GsdSessionManager *session; CdClient *client; GSettings *settings; GcmProfileStore *profile_store; GcmDmi *dmi; GsdRRScreen *x11_screen; GHashTable *edid_cache; GdkWindow *gdk_window; gboolean session_is_active; GHashTable *device_assign_hash; }; enum { PROP_0, }; static void gsd_color_manager_class_init (GsdColorManagerClass *klass); static void gsd_color_manager_init (GsdColorManager *color_manager); static void gsd_color_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdColorManager, gsd_color_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; /* see http://www.oyranos.org/wiki/index.php?title=ICC_Profiles_in_X_Specification_0.3 */ #define GCM_ICC_PROFILE_IN_X_VERSION_MAJOR 0 #define GCM_ICC_PROFILE_IN_X_VERSION_MINOR 3 typedef struct { guint32 red; guint32 green; guint32 blue; } GsdRROutputClutItem; GQuark gsd_color_manager_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gsd_color_manager_error"); return quark; } static GcmEdid * gcm_session_get_output_edid (GsdColorManager *manager, GsdRROutput *output, GError **error) { const guint8 *data; gsize size; GcmEdid *edid = NULL; gboolean ret; /* can we find it in the cache */ edid = g_hash_table_lookup (manager->priv->edid_cache, gsd_rr_output_get_name (output)); if (edid != NULL) { g_object_ref (edid); goto out; } /* parse edid */ data = gsd_rr_output_get_edid_data (output, &size); if (data == NULL || size == 0) { g_set_error_literal (error, GSD_RR_ERROR, GSD_RR_ERROR_UNKNOWN, "unable to get EDID for output"); goto out; } edid = gcm_edid_new (); ret = gcm_edid_parse (edid, data, size, error); if (!ret) { g_object_unref (edid); edid = NULL; goto out; } /* add to cache */ g_hash_table_insert (manager->priv->edid_cache, g_strdup (gsd_rr_output_get_name (output)), g_object_ref (edid)); out: return edid; } static gboolean gcm_session_screen_set_icc_profile (GsdColorManager *manager, const gchar *filename, GError **error) { gboolean ret; gchar *data = NULL; gsize length; guint version_data; GsdColorManagerPrivate *priv = manager->priv; g_return_val_if_fail (filename != NULL, FALSE); g_debug ("setting root window ICC profile atom from %s", filename); /* get contents of file */ ret = g_file_get_contents (filename, &data, &length, error); if (!ret) goto out; /* set profile property */ gdk_property_change (priv->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE"), gdk_atom_intern_static_string ("CARDINAL"), 8, GDK_PROP_MODE_REPLACE, (const guchar *) data, length); /* set version property */ version_data = GCM_ICC_PROFILE_IN_X_VERSION_MAJOR * 100 + GCM_ICC_PROFILE_IN_X_VERSION_MINOR * 1; gdk_property_change (priv->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE_IN_X_VERSION"), gdk_atom_intern_static_string ("CARDINAL"), 8, GDK_PROP_MODE_REPLACE, (const guchar *) &version_data, 1); out: g_free (data); return ret; } static gchar * gcm_session_get_output_id (GsdColorManager *manager, GsdRROutput *output) { const gchar *name; const gchar *serial; const gchar *vendor; GcmEdid *edid = NULL; GString *device_id; GError *error = NULL; /* all output devices are prefixed with this */ device_id = g_string_new ("xrandr"); /* get the output EDID if possible */ edid = gcm_session_get_output_edid (manager, output, &error); if (edid == NULL) { g_debug ("no edid for %s [%s], falling back to connection name", gsd_rr_output_get_name (output), error->message); g_error_free (error); g_string_append_printf (device_id, "-%s", gsd_rr_output_get_name (output)); goto out; } /* check EDID data is okay to use */ vendor = gcm_edid_get_vendor_name (edid); name = gcm_edid_get_monitor_name (edid); serial = gcm_edid_get_serial_number (edid); if (vendor == NULL && name == NULL && serial == NULL) { g_debug ("edid invalid for %s, falling back to connection name", gsd_rr_output_get_name (output)); g_string_append_printf (device_id, "-%s", gsd_rr_output_get_name (output)); goto out; } /* use EDID data */ if (vendor != NULL) g_string_append_printf (device_id, "-%s", vendor); if (name != NULL) g_string_append_printf (device_id, "-%s", name); if (serial != NULL) g_string_append_printf (device_id, "-%s", serial); out: if (edid != NULL) g_object_unref (edid); return g_string_free (device_id, FALSE); } typedef struct { GsdColorManager *manager; CdProfile *profile; CdDevice *device; guint32 output_id; } GcmSessionAsyncHelper; static void gcm_session_async_helper_free (GcmSessionAsyncHelper *helper) { if (helper->manager != NULL) g_object_unref (helper->manager); if (helper->profile != NULL) g_object_unref (helper->profile); if (helper->device != NULL) g_object_unref (helper->device); g_free (helper); } static cmsBool _cmsWriteTagTextAscii (cmsHPROFILE lcms_profile, cmsTagSignature sig, const gchar *text) { cmsBool ret; cmsMLU *mlu = cmsMLUalloc (0, 1); cmsMLUsetASCII (mlu, "en", "US", text); ret = cmsWriteTag (lcms_profile, sig, mlu); cmsMLUfree (mlu); return ret; } static gboolean gcm_utils_mkdir_for_filename (const gchar *filename, GError **error) { gboolean ret = FALSE; GFile *file; GFile *parent_dir = NULL; /* get parent directory */ file = g_file_new_for_path (filename); parent_dir = g_file_get_parent (file); if (parent_dir == NULL) { g_set_error (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "could not get parent dir %s", filename); goto out; } /* ensure desination does not already exist */ ret = g_file_query_exists (parent_dir, NULL); if (ret) goto out; ret = g_file_make_directory_with_parents (parent_dir, NULL, error); if (!ret) goto out; out: if (file != NULL) g_object_unref (file); if (parent_dir != NULL) g_object_unref (parent_dir); return ret; } #ifdef HAVE_NEW_LCMS static wchar_t * utf8_to_wchar_t (const char *src) { size_t len; size_t converted; wchar_t *buf = NULL; len = mbstowcs (NULL, src, 0); if (len == (size_t) -1) { g_warning ("Invalid UTF-8 in string %s", src); goto out; } len += 1; buf = g_malloc (sizeof (wchar_t) * len); converted = mbstowcs (buf, src, len - 1); g_assert (converted != -1); buf[converted] = '\0'; out: return buf; } static cmsBool _cmsDictAddEntryAscii (cmsHANDLE dict, const gchar *key, const gchar *value) { cmsBool ret = FALSE; wchar_t *mb_key = NULL; wchar_t *mb_value = NULL; mb_key = utf8_to_wchar_t (key); if (mb_key == NULL) goto out; mb_value = utf8_to_wchar_t (value); if (mb_value == NULL) goto out; ret = cmsDictAddEntry (dict, mb_key, mb_value, NULL, NULL); out: g_free (mb_key); g_free (mb_value); return ret; } #endif /* HAVE_NEW_LCMS */ static gboolean gcm_apply_create_icc_profile_for_edid (GsdColorManager *manager, CdDevice *device, GcmEdid *edid, const gchar *filename, GError **error) { const CdColorYxy *tmp; cmsCIExyYTRIPLE chroma; cmsCIExyY white_point; cmsHPROFILE lcms_profile = NULL; cmsToneCurve *transfer_curve[3] = { NULL, NULL, NULL }; const gchar *data; gboolean ret = FALSE; gchar *str; gfloat edid_gamma; gfloat localgamma; #ifdef HAVE_NEW_LCMS cmsHANDLE dict = NULL; #endif GsdColorManagerPrivate *priv = manager->priv; /* ensure the per-user directory exists */ ret = gcm_utils_mkdir_for_filename (filename, error); if (!ret) goto out; /* copy color data from our structures */ tmp = gcm_edid_get_red (edid); chroma.Red.x = tmp->x; chroma.Red.y = tmp->y; tmp = gcm_edid_get_green (edid); chroma.Green.x = tmp->x; chroma.Green.y = tmp->y; tmp = gcm_edid_get_blue (edid); chroma.Blue.x = tmp->x; chroma.Blue.y = tmp->y; tmp = gcm_edid_get_white (edid); white_point.x = tmp->x; white_point.y = tmp->y; white_point.Y = 1.0; /* estimate the transfer function for the gamma */ localgamma = gcm_edid_get_gamma (edid); transfer_curve[0] = transfer_curve[1] = transfer_curve[2] = cmsBuildGamma (NULL, localgamma); /* create our generated profile */ lcms_profile = cmsCreateRGBProfile (&white_point, &chroma, transfer_curve); if (lcms_profile == NULL) { g_set_error (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to create profile"); goto out; } cmsSetColorSpace (lcms_profile, cmsSigRgbData); cmsSetPCS (lcms_profile, cmsSigXYZData); cmsSetHeaderRenderingIntent (lcms_profile, INTENT_PERCEPTUAL); cmsSetDeviceClass (lcms_profile, cmsSigDisplayClass); /* copyright */ ret = _cmsWriteTagTextAscii (lcms_profile, cmsSigCopyrightTag, /* deliberately not translated */ "This profile is free of known copyright restrictions."); if (!ret) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to write copyright"); goto out; } /* set model */ data = gcm_edid_get_monitor_name (edid); if (data == NULL) data = gcm_dmi_get_name (priv->dmi); if (data == NULL) data = "Unknown monitor"; ret = _cmsWriteTagTextAscii (lcms_profile, cmsSigDeviceModelDescTag, data); if (!ret) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to write model"); goto out; } /* write title */ ret = _cmsWriteTagTextAscii (lcms_profile, cmsSigProfileDescriptionTag, data); if (!ret) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to write description"); goto out; } /* get manufacturer */ data = gcm_edid_get_vendor_name (edid); if (data == NULL) data = gcm_dmi_get_vendor (priv->dmi); if (data == NULL) data = "Unknown vendor"; ret = _cmsWriteTagTextAscii (lcms_profile, cmsSigDeviceMfgDescTag, data); if (!ret) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to write manufacturer"); goto out; } #ifdef HAVE_NEW_LCMS /* just create a new dict */ dict = cmsDictAlloc (NULL); /* set the framework creator metadata */ _cmsDictAddEntryAscii (dict, CD_PROFILE_METADATA_CMF_PRODUCT, PACKAGE_NAME); _cmsDictAddEntryAscii (dict, CD_PROFILE_METADATA_CMF_BINARY, PACKAGE_NAME); _cmsDictAddEntryAscii (dict, CD_PROFILE_METADATA_CMF_VERSION, PACKAGE_VERSION); _cmsDictAddEntryAscii (dict, CD_PROFILE_METADATA_MAPPING_DEVICE_ID, cd_device_get_id (device)); /* set the data source so we don't ever prompt the user to * recalibrate (as the EDID data won't have changed) */ _cmsDictAddEntryAscii (dict, CD_PROFILE_METADATA_DATA_SOURCE, CD_PROFILE_METADATA_DATA_SOURCE_EDID); /* set 'ICC meta Tag for Monitor Profiles' data */ _cmsDictAddEntryAscii (dict, "EDID_md5", gcm_edid_get_checksum (edid)); data = gcm_edid_get_monitor_name (edid); if (data != NULL) _cmsDictAddEntryAscii (dict, "EDID_model", data); data = gcm_edid_get_serial_number (edid); if (data != NULL) _cmsDictAddEntryAscii (dict, "EDID_serial", data); data = gcm_edid_get_pnp_id (edid); if (data != NULL) _cmsDictAddEntryAscii (dict, "EDID_mnft", data); data = gcm_edid_get_vendor_name (edid); if (data != NULL) _cmsDictAddEntryAscii (dict, "EDID_manufacturer", data); edid_gamma = gcm_edid_get_gamma (edid); if (edid_gamma > 0.0 && edid_gamma < 10.0) { str = g_strdup_printf ("%f", edid_gamma); _cmsDictAddEntryAscii (dict, "EDID_gamma", str); g_free (str); } /* also add the primaries */ str = g_strdup_printf ("%f", chroma.Red.x); _cmsDictAddEntryAscii (dict, "EDID_red_x", str); g_free (str); str = g_strdup_printf ("%f", chroma.Red.y); _cmsDictAddEntryAscii (dict, "EDID_red_y", str); g_free (str); str = g_strdup_printf ("%f", chroma.Green.x); _cmsDictAddEntryAscii (dict, "EDID_green_x", str); g_free (str); str = g_strdup_printf ("%f", chroma.Green.y); _cmsDictAddEntryAscii (dict, "EDID_green_y", str); g_free (str); str = g_strdup_printf ("%f", chroma.Blue.x); _cmsDictAddEntryAscii (dict, "EDID_blue_x", str); g_free (str); str = g_strdup_printf ("%f", chroma.Blue.y); _cmsDictAddEntryAscii (dict, "EDID_blue_y", str); g_free (str); /* write new tag */ ret = cmsWriteTag (lcms_profile, cmsSigMetaTag, dict); if (!ret) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to write profile metadata"); goto out; } #endif /* HAVE_NEW_LCMS */ /* write profile id */ ret = cmsMD5computeID (lcms_profile); if (!ret) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to write profile id"); goto out; } /* save, TODO: get error */ cmsSaveProfileToFile (lcms_profile, filename); ret = TRUE; out: #ifdef HAVE_NEW_LCMS if (dict != NULL) cmsDictFree (dict); #endif if (*transfer_curve != NULL) cmsFreeToneCurve (*transfer_curve); return ret; } static GPtrArray * gcm_session_generate_vcgt (CdProfile *profile, guint size) { GsdRROutputClutItem *tmp; GPtrArray *array = NULL; const cmsToneCurve **vcgt; cmsFloat32Number in; guint i; const gchar *filename; cmsHPROFILE lcms_profile = NULL; /* invalid size */ if (size == 0) goto out; /* not an actual profile */ filename = cd_profile_get_filename (profile); if (filename == NULL) goto out; /* open file */ lcms_profile = cmsOpenProfileFromFile (filename, "r"); if (lcms_profile == NULL) goto out; /* get tone curves from profile */ vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag); if (vcgt == NULL || vcgt[0] == NULL) { g_debug ("profile does not have any VCGT data"); goto out; } /* create array */ array = g_ptr_array_new_with_free_func (g_free); for (i = 0; i < size; i++) { in = (gdouble) i / (gdouble) (size - 1); tmp = g_new0 (GsdRROutputClutItem, 1); tmp->red = cmsEvalToneCurveFloat(vcgt[0], in) * (gdouble) 0xffff; tmp->green = cmsEvalToneCurveFloat(vcgt[1], in) * (gdouble) 0xffff; tmp->blue = cmsEvalToneCurveFloat(vcgt[2], in) * (gdouble) 0xffff; g_ptr_array_add (array, tmp); } out: if (lcms_profile != NULL) cmsCloseProfile (lcms_profile); return array; } static guint gsd_rr_output_get_gamma_size (GsdRROutput *output) { GsdRRCrtc *crtc; gint len = 0; crtc = gsd_rr_output_get_crtc (output); if (crtc == NULL) return 0; gsd_rr_crtc_get_gamma (crtc, &len, NULL, NULL, NULL); return (guint) len; } static gboolean gcm_session_output_set_gamma (GsdRROutput *output, GPtrArray *array, GError **error) { gboolean ret = TRUE; guint16 *red = NULL; guint16 *green = NULL; guint16 *blue = NULL; guint i; GsdRROutputClutItem *data; GsdRRCrtc *crtc; /* no length? */ if (array->len == 0) { ret = FALSE; g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "no data in the CLUT array"); goto out; } /* convert to a type X understands */ red = g_new (guint16, array->len); green = g_new (guint16, array->len); blue = g_new (guint16, array->len); for (i = 0; i < array->len; i++) { data = g_ptr_array_index (array, i); red[i] = data->red; green[i] = data->green; blue[i] = data->blue; } /* send to LUT */ crtc = gsd_rr_output_get_crtc (output); if (crtc == NULL) { ret = FALSE; g_set_error (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to get ctrc for %s", gsd_rr_output_get_name (output)); goto out; } gsd_rr_crtc_set_gamma (crtc, array->len, red, green, blue); out: g_free (red); g_free (green); g_free (blue); return ret; } static gboolean gcm_session_device_set_gamma (GsdRROutput *output, CdProfile *profile, GError **error) { gboolean ret = FALSE; guint size; GPtrArray *clut = NULL; /* create a lookup table */ size = gsd_rr_output_get_gamma_size (output); if (size == 0) { ret = TRUE; goto out; } clut = gcm_session_generate_vcgt (profile, size); if (clut == NULL) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to generate vcgt"); goto out; } /* apply the vcgt to this output */ ret = gcm_session_output_set_gamma (output, clut, error); if (!ret) goto out; out: if (clut != NULL) g_ptr_array_unref (clut); return ret; } static gboolean gcm_session_device_reset_gamma (GsdRROutput *output, GError **error) { gboolean ret; guint i; guint size; guint32 value; GPtrArray *clut; GsdRROutputClutItem *data; /* create a linear ramp */ g_debug ("falling back to dummy ramp"); clut = g_ptr_array_new_with_free_func (g_free); size = gsd_rr_output_get_gamma_size (output); if (size == 0) { ret = TRUE; goto out; } for (i = 0; i < size; i++) { value = (i * 0xffff) / (size - 1); data = g_new0 (GsdRROutputClutItem, 1); data->red = value; data->green = value; data->blue = value; g_ptr_array_add (clut, data); } /* apply the vcgt to this output */ ret = gcm_session_output_set_gamma (output, clut, error); if (!ret) goto out; out: g_ptr_array_unref (clut); return ret; } static GsdRROutput * gcm_session_get_x11_output_by_id (GsdColorManager *manager, const gchar *device_id, GError **error) { gchar *output_id; GsdRROutput *output = NULL; GsdRROutput **outputs = NULL; guint i; GsdColorManagerPrivate *priv = manager->priv; /* search all X11 outputs for the device id */ outputs = gsd_rr_screen_list_outputs (priv->x11_screen); if (outputs == NULL) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "Failed to get outputs"); goto out; } for (i = 0; outputs[i] != NULL && output == NULL; i++) { if (!gsd_rr_output_is_connected (outputs[i])) continue; output_id = gcm_session_get_output_id (manager, outputs[i]); if (g_strcmp0 (output_id, device_id) == 0) output = outputs[i]; g_free (output_id); } if (output == NULL) { g_set_error (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "Failed to find output %s", device_id); } out: return output; } /* this function is more complicated than it should be, due to the * fact that XOrg sometimes assigns no primary devices when using * "xrandr --auto" or when the version of RANDR is < 1.3 */ static gboolean gcm_session_use_output_profile_for_screen (GsdColorManager *manager, GsdRROutput *output) { gboolean has_laptop = FALSE; gboolean has_primary = FALSE; GsdRROutput **outputs; GsdRROutput *connected = NULL; guint i; /* do we have any screens marked as primary */ outputs = gsd_rr_screen_list_outputs (manager->priv->x11_screen); if (outputs == NULL || outputs[0] == NULL) { g_warning ("failed to get outputs"); return FALSE; } for (i = 0; outputs[i] != NULL; i++) { if (!gsd_rr_output_is_connected (outputs[i])) continue; if (connected == NULL) connected = outputs[i]; if (gsd_rr_output_get_is_primary (outputs[i])) has_primary = TRUE; if (gsd_rr_output_is_laptop (outputs[i])) has_laptop = TRUE; } /* we have an assigned primary device, are we that? */ if (has_primary) return gsd_rr_output_get_is_primary (output); /* choosing the internal panel is probably sane */ if (has_laptop) return gsd_rr_output_is_laptop (output); /* we have to choose one, so go for the first connected device */ if (connected != NULL) return gsd_rr_output_get_id (connected) == gsd_rr_output_get_id (output); return FALSE; } /* TODO: remove when we can dep on a released version of colord */ #ifndef CD_PROFILE_METADATA_SCREEN_BRIGHTNESS #define CD_PROFILE_METADATA_SCREEN_BRIGHTNESS "SCREEN_brightness" #endif #define GSD_DBUS_NAME_POWER GSD_DBUS_NAME ".Power" #define GSD_DBUS_INTERFACE_POWER_SCREEN GSD_DBUS_BASE_INTERFACE ".Power.Screen" #define GSD_DBUS_PATH_POWER GSD_DBUS_PATH "/Power" static void gcm_session_set_output_percentage_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GDBusConnection *connection = G_DBUS_CONNECTION (source_object); GError *error = NULL; GVariant *retval; retval = g_dbus_connection_call_finish (connection, res, &error); if (retval == NULL) { g_warning ("failed to set output brightness: %s", error->message); g_error_free (error); return; } g_variant_unref (retval); } static void gcm_session_set_output_percentage (guint percentage) { GDBusConnection *connection; /* get a ref to the existing bus connection */ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (connection == NULL) return; g_dbus_connection_call (connection, GSD_DBUS_NAME_POWER, GSD_DBUS_PATH_POWER, GSD_DBUS_INTERFACE_POWER_SCREEN, "SetPercentage", g_variant_new ("(u)", percentage), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, gcm_session_set_output_percentage_cb, NULL); g_object_unref (connection); } static void gcm_session_device_assign_profile_connect_cb (GObject *object, GAsyncResult *res, gpointer user_data) { CdProfile *profile = CD_PROFILE (object); const gchar *brightness_profile; const gchar *filename; gboolean ret; GError *error = NULL; GsdRROutput *output; guint brightness_percentage; GcmSessionAsyncHelper *helper = (GcmSessionAsyncHelper *) user_data; GsdColorManager *manager = GSD_COLOR_MANAGER (helper->manager); /* get properties */ ret = cd_profile_connect_finish (profile, res, &error); if (!ret) { g_warning ("failed to connect to profile: %s", error->message); g_error_free (error); goto out; } /* get the filename */ filename = cd_profile_get_filename (profile); g_assert (filename != NULL); /* get the output (can't save in helper as GsdRROutput isn't * a GObject, just a pointer */ output = gsd_rr_screen_get_output_by_id (manager->priv->x11_screen, helper->output_id); if (output == NULL) goto out; /* if output is a laptop screen and the profile has a * calibration brightness then set this new brightness */ brightness_profile = cd_profile_get_metadata_item (profile, CD_PROFILE_METADATA_SCREEN_BRIGHTNESS); if (gsd_rr_output_is_laptop (output) && brightness_profile != NULL) { /* the percentage is stored in the profile metadata as * a string, not ideal, but it's all we have... */ brightness_percentage = atoi (brightness_profile); gcm_session_set_output_percentage (brightness_percentage); } /* set the _ICC_PROFILE atom */ ret = gcm_session_use_output_profile_for_screen (manager, output); if (ret) { ret = gcm_session_screen_set_icc_profile (manager, filename, &error); if (!ret) { g_warning ("failed to set screen _ICC_PROFILE: %s", error->message); g_clear_error (&error); } } /* create a vcgt for this icc file */ ret = cd_profile_get_has_vcgt (profile); if (ret) { ret = gcm_session_device_set_gamma (output, profile, &error); if (!ret) { g_warning ("failed to set %s gamma tables: %s", cd_device_get_id (helper->device), error->message); g_error_free (error); goto out; } } else { ret = gcm_session_device_reset_gamma (output, &error); if (!ret) { g_warning ("failed to reset %s gamma tables: %s", cd_device_get_id (helper->device), error->message); g_error_free (error); goto out; } } out: gcm_session_async_helper_free (helper); } /* * Check to see if the on-disk profile has the MAPPING_device_id * metadata, and if not, we should delete the profile and re-create it * so that it gets mapped by the daemon. */ static gboolean gcm_session_check_profile_device_md (const gchar *filename) { cmsHANDLE dict; cmsHPROFILE lcms_profile; const cmsDICTentry *entry; gboolean ret = FALSE; gchar ascii_name[1024]; gsize len; /* parse the ICC file */ lcms_profile = cmsOpenProfileFromFile (filename, "r"); if (lcms_profile == NULL) goto out; /* does profile have metadata? */ dict = cmsReadTag (lcms_profile, cmsSigMetaTag); if (dict == NULL) { g_debug ("auto-edid profile is old, and contains no metadata"); goto out; } for (entry = cmsDictGetEntryList (dict); entry != NULL; entry = cmsDictNextEntry (entry)) { if (entry->Name == NULL) continue; len = wcstombs (ascii_name, entry->Name, sizeof (ascii_name)); if (len == (gsize) -1) continue; if (g_strcmp0 (ascii_name, CD_PROFILE_METADATA_MAPPING_DEVICE_ID) == 0) { ret = TRUE; goto out; } } g_debug ("auto-edid profile is old, and contains no %s data", CD_PROFILE_METADATA_MAPPING_DEVICE_ID); out: if (lcms_profile != NULL) cmsCloseProfile (lcms_profile); return ret; } static void gcm_session_device_assign_connect_cb (GObject *object, GAsyncResult *res, gpointer user_data) { CdDeviceKind kind; CdProfile *profile = NULL; gboolean ret; gchar *autogen_filename = NULL; gchar *autogen_path = NULL; GcmEdid *edid = NULL; GsdRROutput *output = NULL; GError *error = NULL; const gchar *xrandr_id; GcmSessionAsyncHelper *helper; CdDevice *device = CD_DEVICE (object); GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); GsdColorManagerPrivate *priv = manager->priv; /* remove from assign array */ g_hash_table_remove (manager->priv->device_assign_hash, cd_device_get_object_path (device)); /* get properties */ ret = cd_device_connect_finish (device, res, &error); if (!ret) { g_warning ("failed to connect to device: %s", error->message); g_error_free (error); goto out; } /* check we care */ kind = cd_device_get_kind (device); if (kind != CD_DEVICE_KIND_DISPLAY) goto out; g_debug ("need to assign display device %s", cd_device_get_id (device)); /* get the GsdRROutput for the device id */ xrandr_id = cd_device_get_id (device); output = gcm_session_get_x11_output_by_id (manager, xrandr_id, &error); if (output == NULL) { g_warning ("no %s device found: %s", cd_device_get_id (device), error->message); g_error_free (error); goto out; } /* create profile from device edid if it exists */ edid = gcm_session_get_output_edid (manager, output, &error); if (edid == NULL) { g_warning ("unable to get EDID for %s: %s", cd_device_get_id (device), error->message); g_clear_error (&error); } else { autogen_filename = g_strdup_printf ("edid-%s.icc", gcm_edid_get_checksum (edid)); autogen_path = g_build_filename (g_get_user_data_dir (), "icc", autogen_filename, NULL); /* check if auto-profile has up-to-date metadata */ if (gcm_session_check_profile_device_md (autogen_path)) { g_debug ("auto-profile edid %s exists with md", autogen_path); } else { g_debug ("auto-profile edid does not exist, creating as %s", autogen_path); ret = gcm_apply_create_icc_profile_for_edid (manager, device, edid, autogen_path, &error); if (!ret) { g_warning ("failed to create profile from EDID data: %s", error->message); g_clear_error (&error); } } } /* get the default profile for the device */ profile = cd_device_get_default_profile (device); if (profile == NULL) { g_debug ("%s has no default profile to set", cd_device_get_id (device)); /* the default output? */ if (gsd_rr_output_get_is_primary (output)) { gdk_property_delete (priv->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE")); gdk_property_delete (priv->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE_IN_X_VERSION")); } /* reset, as we want linear profiles for profiling */ ret = gcm_session_device_reset_gamma (output, &error); if (!ret) { g_warning ("failed to reset %s gamma tables: %s", cd_device_get_id (device), error->message); g_error_free (error); goto out; } goto out; } /* get properties */ helper = g_new0 (GcmSessionAsyncHelper, 1); helper->output_id = gsd_rr_output_get_id (output); helper->manager = g_object_ref (manager); helper->device = g_object_ref (device); cd_profile_connect (profile, NULL, gcm_session_device_assign_profile_connect_cb, helper); out: g_free (autogen_filename); g_free (autogen_path); if (edid != NULL) g_object_unref (edid); if (profile != NULL) g_object_unref (profile); } static void gcm_session_device_assign (GsdColorManager *manager, CdDevice *device) { const gchar *key; gpointer found; /* are we already assigning this device */ key = cd_device_get_object_path (device); found = g_hash_table_lookup (manager->priv->device_assign_hash, key); if (found != NULL) { g_debug ("assign for %s already in progress", key); return; } g_hash_table_insert (manager->priv->device_assign_hash, g_strdup (key), GINT_TO_POINTER (TRUE)); cd_device_connect (device, NULL, gcm_session_device_assign_connect_cb, manager); } static void gcm_session_device_added_assign_cb (CdClient *client, CdDevice *device, GsdColorManager *manager) { gcm_session_device_assign (manager, device); } static void gcm_session_device_changed_assign_cb (CdClient *client, CdDevice *device, GsdColorManager *manager) { g_debug ("%s changed", cd_device_get_object_path (device)); gcm_session_device_assign (manager, device); } static void gcm_session_create_device_cb (GObject *object, GAsyncResult *res, gpointer user_data) { CdDevice *device; GError *error = NULL; device = cd_client_create_device_finish (CD_CLIENT (object), res, &error); if (device == NULL) { if (error->domain != CD_CLIENT_ERROR || error->code != CD_CLIENT_ERROR_ALREADY_EXISTS) { g_warning ("failed to create device: %s", error->message); } g_error_free (error); return; } g_object_unref (device); } static void gcm_session_add_x11_output (GsdColorManager *manager, GsdRROutput *output) { const gchar *edid_checksum = NULL; const gchar *model = NULL; const gchar *serial = NULL; const gchar *vendor = NULL; gboolean ret; gchar *device_id = NULL; GcmEdid *edid; GError *error = NULL; GHashTable *device_props = NULL; GsdColorManagerPrivate *priv = manager->priv; /* try to get edid */ edid = gcm_session_get_output_edid (manager, output, &error); if (edid == NULL) { g_warning ("failed to get edid: %s", error->message); g_clear_error (&error); } /* prefer DMI data for the internal output */ ret = gsd_rr_output_is_laptop (output); if (ret) { model = gcm_dmi_get_name (priv->dmi); vendor = gcm_dmi_get_vendor (priv->dmi); } /* use EDID data if we have it */ if (edid != NULL) { edid_checksum = gcm_edid_get_checksum (edid); if (model == NULL) model = gcm_edid_get_monitor_name (edid); if (vendor == NULL) vendor = gcm_edid_get_vendor_name (edid); if (serial == NULL) serial = gcm_edid_get_serial_number (edid); } /* ensure mandatory fields are set */ if (model == NULL) model = gsd_rr_output_get_name (output); if (vendor == NULL) vendor = "unknown"; if (serial == NULL) serial = "unknown"; device_id = gcm_session_get_output_id (manager, output); g_debug ("output %s added", device_id); device_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_KIND, (gpointer) cd_device_kind_to_string (CD_DEVICE_KIND_DISPLAY)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_MODE, (gpointer) cd_device_mode_to_string (CD_DEVICE_MODE_PHYSICAL)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_COLORSPACE, (gpointer) cd_colorspace_to_string (CD_COLORSPACE_RGB)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_VENDOR, (gpointer) vendor); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_MODEL, (gpointer) model); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_SERIAL, (gpointer) serial); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_METADATA_XRANDR_NAME, (gpointer) gsd_rr_output_get_name (output)); #if CD_CHECK_VERSION(0,1,25) g_hash_table_insert (device_props, (gpointer) CD_DEVICE_METADATA_OUTPUT_PRIORITY, gsd_rr_output_get_is_primary (output) ? (gpointer) CD_DEVICE_METADATA_OUTPUT_PRIORITY_PRIMARY : (gpointer) CD_DEVICE_METADATA_OUTPUT_PRIORITY_SECONDARY); #endif #if CD_CHECK_VERSION(0,1,34) if (edid_checksum != NULL) { g_hash_table_insert (device_props, (gpointer) CD_DEVICE_METADATA_OUTPUT_EDID_MD5, (gpointer) edid_checksum); } #endif #if CD_CHECK_VERSION(0,1,27) /* set this so we can call the device a 'Laptop Screen' in the * control center main panel */ if (gsd_rr_output_is_laptop (output)) { g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_EMBEDDED, NULL); } #endif cd_client_create_device (priv->client, device_id, CD_OBJECT_SCOPE_TEMP, device_props, NULL, gcm_session_create_device_cb, manager); g_free (device_id); if (device_props != NULL) g_hash_table_unref (device_props); if (edid != NULL) g_object_unref (edid); } static void gsd_rr_screen_output_added_cb (GsdRRScreen *screen, GsdRROutput *output, GsdColorManager *manager) { gcm_session_add_x11_output (manager, output); } static void gcm_session_screen_removed_delete_device_cb (GObject *object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; /* deleted device */ ret = cd_client_delete_device_finish (CD_CLIENT (object), res, &error); if (!ret) { g_warning ("failed to delete device: %s", error->message); g_error_free (error); } } static void gcm_session_screen_removed_find_device_cb (GObject *object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; CdDevice *device; GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); device = cd_client_find_device_finish (manager->priv->client, res, &error); if (device == NULL) { g_warning ("failed to find device: %s", error->message); g_error_free (error); return; } g_debug ("output %s found, and will be removed", cd_device_get_object_path (device)); cd_client_delete_device (manager->priv->client, device, NULL, gcm_session_screen_removed_delete_device_cb, manager); g_object_unref (device); } static void gsd_rr_screen_output_removed_cb (GsdRRScreen *screen, GsdRROutput *output, GsdColorManager *manager) { g_debug ("output %s removed", gsd_rr_output_get_name (output)); g_hash_table_remove (manager->priv->edid_cache, gsd_rr_output_get_name (output)); cd_client_find_device_by_property (manager->priv->client, CD_DEVICE_METADATA_XRANDR_NAME, gsd_rr_output_get_name (output), NULL, gcm_session_screen_removed_find_device_cb, manager); } static void gcm_session_get_devices_cb (GObject *object, GAsyncResult *res, gpointer user_data) { CdDevice *device; GError *error = NULL; GPtrArray *array; guint i; GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); array = cd_client_get_devices_finish (CD_CLIENT (object), res, &error); if (array == NULL) { g_warning ("failed to get devices: %s", error->message); g_error_free (error); goto out; } for (i = 0; i < array->len; i++) { device = g_ptr_array_index (array, i); gcm_session_device_assign (manager, device); } out: if (array != NULL) g_ptr_array_unref (array); } static void gcm_session_profile_gamma_find_device_cb (GObject *object, GAsyncResult *res, gpointer user_data) { CdClient *client = CD_CLIENT (object); CdDevice *device = NULL; GError *error = NULL; GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); device = cd_client_find_device_by_property_finish (client, res, &error); if (device == NULL) { g_warning ("could not find device: %s", error->message); g_error_free (error); goto out; } /* get properties */ cd_device_connect (device, NULL, gcm_session_device_assign_connect_cb, manager); out: if (device != NULL) g_object_unref (device); } /* We have to reset the gamma tables each time as if the primary output * has changed then different crtcs are going to be used. * See https://bugzilla.gnome.org/show_bug.cgi?id=660164 for an example */ static void gsd_rr_screen_output_changed_cb (GsdRRScreen *screen, GsdColorManager *manager) { GsdRROutput **outputs; GsdColorManagerPrivate *priv = manager->priv; guint i; /* get X11 outputs */ outputs = gsd_rr_screen_list_outputs (priv->x11_screen); if (outputs == NULL) { g_warning ("failed to get outputs"); return; } for (i = 0; outputs[i] != NULL; i++) { if (!gsd_rr_output_is_connected (outputs[i])) continue; /* get CdDevice for this output */ cd_client_find_device_by_property (manager->priv->client, CD_DEVICE_METADATA_XRANDR_NAME, gsd_rr_output_get_name (outputs[i]), NULL, gcm_session_profile_gamma_find_device_cb, manager); } } static void gcm_session_client_connect_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; GsdRROutput **outputs; guint i; GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); GsdColorManagerPrivate *priv = manager->priv; /* connected */ g_debug ("connected to colord"); ret = cd_client_connect_finish (manager->priv->client, res, &error); if (!ret) { g_warning ("failed to connect to colord: %s", error->message); g_error_free (error); return; } #if CD_CHECK_VERSION(0,1,12) /* is there an available colord instance? */ ret = cd_client_get_has_server (manager->priv->client); if (!ret) { g_warning ("There is no colord server available"); goto out; } #endif /* add profiles */ gcm_profile_store_search (priv->profile_store); /* add screens */ gsd_rr_screen_refresh (priv->x11_screen, &error); if (error != NULL) { g_warning ("failed to refresh: %s", error->message); g_error_free (error); goto out; } /* get X11 outputs */ outputs = gsd_rr_screen_list_outputs (priv->x11_screen); if (outputs == NULL) { g_warning ("failed to get outputs"); goto out; } for (i = 0; outputs[i] != NULL; i++) { if (gsd_rr_output_is_connected (outputs[i])) gcm_session_add_x11_output (manager, outputs[i]); } /* only connect when colord is awake */ g_signal_connect (priv->x11_screen, "output-connected", G_CALLBACK (gsd_rr_screen_output_added_cb), manager); g_signal_connect (priv->x11_screen, "output-disconnected", G_CALLBACK (gsd_rr_screen_output_removed_cb), manager); g_signal_connect (priv->x11_screen, "changed", G_CALLBACK (gsd_rr_screen_output_changed_cb), manager); g_signal_connect (priv->client, "device-added", G_CALLBACK (gcm_session_device_added_assign_cb), manager); g_signal_connect (priv->client, "device-changed", G_CALLBACK (gcm_session_device_changed_assign_cb), manager); /* set for each device that already exist */ cd_client_get_devices (priv->client, NULL, gcm_session_get_devices_cb, manager); out: return; } gboolean gsd_color_manager_start (GsdColorManager *manager, GError **error) { GsdColorManagerPrivate *priv = manager->priv; gboolean ret = FALSE; g_debug ("Starting color manager"); gnome_settings_profile_start (NULL); /* coldplug the list of screens */ priv->x11_screen = gsd_rr_screen_new (gdk_screen_get_default (), error); if (priv->x11_screen == NULL) goto out; cd_client_connect (priv->client, NULL, gcm_session_client_connect_cb, manager); /* success */ ret = TRUE; out: gnome_settings_profile_end (NULL); return ret; } void gsd_color_manager_stop (GsdColorManager *manager) { g_debug ("Stopping color manager"); g_clear_object (&manager->priv->settings); g_clear_object (&manager->priv->client); g_clear_object (&manager->priv->profile_store); g_clear_object (&manager->priv->dmi); g_clear_object (&manager->priv->session); g_clear_pointer (&manager->priv->edid_cache, g_hash_table_destroy); g_clear_pointer (&manager->priv->device_assign_hash, g_hash_table_destroy); g_clear_object (&manager->priv->x11_screen); } static void gcm_session_exec_control_center (GsdColorManager *manager) { gboolean ret; GError *error = NULL; GAppInfo *app_info; GdkAppLaunchContext *launch_context; /* setup the launch context so the startup notification is correct */ launch_context = gdk_display_get_app_launch_context (gdk_display_get_default ()); app_info = g_app_info_create_from_commandline (BINDIR "/gnome-control-center color", "gnome-control-center", G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION, &error); if (app_info == NULL) { g_warning ("failed to create application info: %s", error->message); g_error_free (error); goto out; } /* launch gnome-control-center */ ret = g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error); if (!ret) { g_warning ("failed to launch gnome-control-center: %s", error->message); g_error_free (error); goto out; } out: g_object_unref (launch_context); if (app_info != NULL) g_object_unref (app_info); } static void gcm_session_notify_cb (NotifyNotification *notification, gchar *action, gpointer user_data) { GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); if (g_strcmp0 (action, "recalibrate") == 0) { notify_notification_close (notification, NULL); gcm_session_exec_control_center (manager); } } static void closed_cb (NotifyNotification *notification, gpointer data) { g_object_unref (notification); } static gboolean gcm_session_notify_recalibrate (GsdColorManager *manager, const gchar *title, const gchar *message, CdDeviceKind kind) { gboolean ret; GError *error = NULL; NotifyNotification *notification; GsdColorManagerPrivate *priv = manager->priv; /* show a bubble */ notification = notify_notification_new (title, message, "preferences-color"); notify_notification_set_timeout (notification, GCM_SESSION_NOTIFY_TIMEOUT); notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW); notify_notification_set_app_name (notification, _("Color")); /* TRANSLATORS: button: this is to open GCM */ notify_notification_add_action (notification, "recalibrate", _("Recalibrate now"), gcm_session_notify_cb, priv, NULL); g_signal_connect (notification, "closed", G_CALLBACK (closed_cb), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("failed to show notification: %s", error->message); g_error_free (error); } return ret; } static gchar * gcm_session_device_get_title (CdDevice *device) { const gchar *vendor; const gchar *model; model = cd_device_get_model (device); vendor = cd_device_get_vendor (device); if (model != NULL && vendor != NULL) return g_strdup_printf ("%s - %s", vendor, model); if (vendor != NULL) return g_strdup (vendor); if (model != NULL) return g_strdup (model); return g_strdup (cd_device_get_id (device)); } static void gcm_session_notify_device (GsdColorManager *manager, CdDevice *device) { CdDeviceKind kind; const gchar *title; gchar *device_title = NULL; gchar *message; guint threshold; glong since; GsdColorManagerPrivate *priv = manager->priv; /* TRANSLATORS: this is when the device has not been recalibrated in a while */ title = _("Recalibration required"); device_title = gcm_session_device_get_title (device); /* check we care */ kind = cd_device_get_kind (device); if (kind == CD_DEVICE_KIND_DISPLAY) { /* get from GSettings */ threshold = g_settings_get_uint (priv->settings, GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD); /* TRANSLATORS: this is when the display has not been recalibrated in a while */ message = g_strdup_printf (_("The display '%s' should be recalibrated soon."), device_title); } else { /* get from GSettings */ threshold = g_settings_get_uint (priv->settings, GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD); /* TRANSLATORS: this is when the printer has not been recalibrated in a while */ message = g_strdup_printf (_("The printer '%s' should be recalibrated soon."), device_title); } /* check if we need to notify */ since = (g_get_real_time () - cd_device_get_modified (device)) / G_USEC_PER_SEC; if (threshold > since) gcm_session_notify_recalibrate (manager, title, message, kind); g_free (device_title); g_free (message); } static void gcm_session_profile_connect_cb (GObject *object, GAsyncResult *res, gpointer user_data) { const gchar *filename; gboolean ret; gchar *basename = NULL; const gchar *data_source; GError *error = NULL; CdProfile *profile = CD_PROFILE (object); GcmSessionAsyncHelper *helper = (GcmSessionAsyncHelper *) user_data; GsdColorManager *manager = GSD_COLOR_MANAGER (helper->manager); ret = cd_profile_connect_finish (profile, res, &error); if (!ret) { g_warning ("failed to connect to profile: %s", error->message); g_error_free (error); goto out; } /* ensure it's a profile generated by us */ data_source = cd_profile_get_metadata_item (profile, CD_PROFILE_METADATA_DATA_SOURCE); if (data_source == NULL) { /* existing profiles from gnome-color-manager < 3.1 * won't have the extra metadata values added */ filename = cd_profile_get_filename (profile); if (filename == NULL) goto out; basename = g_path_get_basename (filename); if (!g_str_has_prefix (basename, "GCM")) { g_debug ("not a GCM profile for %s: %s", cd_device_get_id (helper->device), filename); goto out; } /* ensure it's been created from a calibration, rather than from * auto-EDID */ } else if (g_strcmp0 (data_source, CD_PROFILE_METADATA_DATA_SOURCE_CALIB) != 0) { g_debug ("not a calib profile for %s", cd_device_get_id (helper->device)); goto out; } /* handle device */ gcm_session_notify_device (manager, helper->device); out: gcm_session_async_helper_free (helper); g_free (basename); } static void gcm_session_device_connect_cb (GObject *object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; CdDeviceKind kind; CdProfile *profile = NULL; CdDevice *device = CD_DEVICE (object); GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); GcmSessionAsyncHelper *helper; ret = cd_device_connect_finish (device, res, &error); if (!ret) { g_warning ("failed to connect to device: %s", error->message); g_error_free (error); goto out; } /* check we care */ kind = cd_device_get_kind (device); if (kind != CD_DEVICE_KIND_DISPLAY && kind != CD_DEVICE_KIND_PRINTER) goto out; /* ensure we have a profile */ profile = cd_device_get_default_profile (device); if (profile == NULL) { g_debug ("no profile set for %s", cd_device_get_id (device)); goto out; } /* connect to the profile */ helper = g_new0 (GcmSessionAsyncHelper, 1); helper->manager = g_object_ref (manager); helper->device = g_object_ref (device); cd_profile_connect (profile, NULL, gcm_session_profile_connect_cb, helper); out: if (profile != NULL) g_object_unref (profile); } static void gcm_session_device_added_notify_cb (CdClient *client, CdDevice *device, GsdColorManager *manager) { /* connect to the device to get properties */ cd_device_connect (device, NULL, gcm_session_device_connect_cb, manager); } static gchar * gcm_session_get_precooked_md5 (cmsHPROFILE lcms_profile) { cmsUInt8Number profile_id[16]; gboolean md5_precooked = FALSE; guint i; gchar *md5 = NULL; /* check to see if we have a pre-cooked MD5 */ cmsGetHeaderProfileID (lcms_profile, profile_id); for (i = 0; i < 16; i++) { if (profile_id[i] != 0) { md5_precooked = TRUE; break; } } if (!md5_precooked) goto out; /* convert to a hex string */ md5 = g_new0 (gchar, 32 + 1); for (i = 0; i < 16; i++) g_snprintf (md5 + i*2, 3, "%02x", profile_id[i]); out: return md5; } static gchar * gcm_session_get_md5_for_filename (const gchar *filename, GError **error) { gboolean ret; gchar *checksum = NULL; gchar *data = NULL; gsize length; cmsHPROFILE lcms_profile = NULL; /* get the internal profile id, if it exists */ lcms_profile = cmsOpenProfileFromFile (filename, "r"); if (lcms_profile == NULL) { g_set_error_literal (error, GSD_COLOR_MANAGER_ERROR, GSD_COLOR_MANAGER_ERROR_FAILED, "failed to load: not an ICC profile"); goto out; } checksum = gcm_session_get_precooked_md5 (lcms_profile); if (checksum != NULL) goto out; /* generate checksum */ ret = g_file_get_contents (filename, &data, &length, error); if (!ret) goto out; checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, (const guchar *) data, length); out: g_free (data); if (lcms_profile != NULL) cmsCloseProfile (lcms_profile); return checksum; } static void gcm_session_create_profile_cb (GObject *object, GAsyncResult *res, gpointer user_data) { CdProfile *profile; GError *error = NULL; CdClient *client = CD_CLIENT (object); profile = cd_client_create_profile_finish (client, res, &error); if (profile == NULL) { if (error->domain != CD_CLIENT_ERROR || error->code != CD_CLIENT_ERROR_ALREADY_EXISTS) g_warning ("%s", error->message); g_error_free (error); return; } g_object_unref (profile); } static void gcm_session_profile_store_added_cb (GcmProfileStore *profile_store, const gchar *filename, GsdColorManager *manager) { gchar *checksum = NULL; gchar *profile_id = NULL; GError *error = NULL; GHashTable *profile_props = NULL; GsdColorManagerPrivate *priv = manager->priv; g_debug ("profile %s added", filename); /* generate ID */ checksum = gcm_session_get_md5_for_filename (filename, &error); if (checksum == NULL) { g_debug ("failed to get profile checksum for %s: %s", filename, error->message); g_error_free (error); goto out; } profile_id = g_strdup_printf ("icc-%s", checksum); profile_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert (profile_props, CD_PROFILE_PROPERTY_FILENAME, (gpointer) filename); g_hash_table_insert (profile_props, CD_PROFILE_METADATA_FILE_CHECKSUM, (gpointer) checksum); cd_client_create_profile (priv->client, profile_id, CD_OBJECT_SCOPE_TEMP, profile_props, NULL, gcm_session_create_profile_cb, manager); out: g_free (checksum); g_free (profile_id); if (profile_props != NULL) g_hash_table_unref (profile_props); } static void gcm_session_delete_profile_cb (GObject *object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; CdClient *client = CD_CLIENT (object); ret = cd_client_delete_profile_finish (client, res, &error); if (!ret) { g_warning ("%s", error->message); g_error_free (error); } } static void gcm_session_find_profile_by_filename_cb (GObject *object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; CdProfile *profile; CdClient *client = CD_CLIENT (object); GsdColorManager *manager = GSD_COLOR_MANAGER (user_data); profile = cd_client_find_profile_by_filename_finish (client, res, &error); if (profile == NULL) { g_warning ("%s", error->message); g_error_free (error); goto out; } /* remove it from colord */ cd_client_delete_profile (manager->priv->client, profile, NULL, gcm_session_delete_profile_cb, manager); out: if (profile != NULL) g_object_unref (profile); } static void gcm_session_profile_store_removed_cb (GcmProfileStore *profile_store, const gchar *filename, GsdColorManager *manager) { /* find the ID for the filename */ g_debug ("filename %s removed", filename); cd_client_find_profile_by_filename (manager->priv->client, filename, NULL, gcm_session_find_profile_by_filename_cb, manager); } static void gcm_session_sensor_added_cb (CdClient *client, CdSensor *sensor, GsdColorManager *manager) { ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "device-added", /* TRANSLATORS: this is the application name */ CA_PROP_APPLICATION_NAME, _("GNOME Settings Daemon Color Plugin"), /* TRANSLATORS: this is a sound description */ CA_PROP_EVENT_DESCRIPTION, _("Color calibration device added"), NULL); /* open up the color prefs window */ gcm_session_exec_control_center (manager); } static void gcm_session_sensor_removed_cb (CdClient *client, CdSensor *sensor, GsdColorManager *manager) { ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "device-removed", /* TRANSLATORS: this is the application name */ CA_PROP_APPLICATION_NAME, _("GNOME Settings Daemon Color Plugin"), /* TRANSLATORS: this is a sound description */ CA_PROP_EVENT_DESCRIPTION, _("Color calibration device removed"), NULL); } static gboolean has_changed (char **strv, const char *str) { guint i; for (i = 0; strv[i] != NULL; i++) { if (g_str_equal (str, strv[i])) return TRUE; } return FALSE; } static void gcm_session_active_changed_cb (GDBusProxy *session, GVariant *changed, char **invalidated, GsdColorManager *manager) { GsdColorManagerPrivate *priv = manager->priv; GVariant *active_v = NULL; gboolean is_active; if (has_changed (invalidated, "SessionIsActive")) return; /* not yet connected to the daemon */ if (!cd_client_get_connected (priv->client)) return; active_v = g_dbus_proxy_get_cached_property (session, "SessionIsActive"); g_return_if_fail (active_v != NULL); is_active = g_variant_get_boolean (active_v); g_variant_unref (active_v); /* When doing the fast-user-switch into a new account, load the * new users chosen profiles. * * If this is the first time the GnomeSettingsSession has been * loaded, then we'll get a change from unknown to active * and we want to avoid reprobing the devices for that. */ if (is_active && !priv->session_is_active) { g_debug ("Done switch to new account, reload devices"); cd_client_get_devices (manager->priv->client, NULL, gcm_session_get_devices_cb, manager); } priv->session_is_active = is_active; } static void gsd_color_manager_class_init (GsdColorManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_color_manager_finalize; g_type_class_add_private (klass, sizeof (GsdColorManagerPrivate)); } static void gsd_color_manager_init (GsdColorManager *manager) { GsdColorManagerPrivate *priv; priv = manager->priv = GSD_COLOR_MANAGER_GET_PRIVATE (manager); /* track the active session */ priv->session = gnome_settings_bus_get_session_proxy (); g_signal_connect (priv->session, "g-properties-changed", G_CALLBACK (gcm_session_active_changed_cb), manager); /* set the _ICC_PROFILE atoms on the root screen */ priv->gdk_window = gdk_screen_get_root_window (gdk_screen_get_default ()); /* parsing the EDID is expensive */ priv->edid_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); /* we don't want to assign devices multiple times at startup */ priv->device_assign_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* use DMI data for internal panels */ priv->dmi = gcm_dmi_new (); priv->settings = g_settings_new ("com.canonical.unity.settings-daemon.plugins.color"); priv->client = cd_client_new (); g_signal_connect (priv->client, "device-added", G_CALLBACK (gcm_session_device_added_notify_cb), manager); g_signal_connect (priv->client, "sensor-added", G_CALLBACK (gcm_session_sensor_added_cb), manager); g_signal_connect (priv->client, "sensor-removed", G_CALLBACK (gcm_session_sensor_removed_cb), manager); /* have access to all user profiles */ priv->profile_store = gcm_profile_store_new (); g_signal_connect (priv->profile_store, "added", G_CALLBACK (gcm_session_profile_store_added_cb), manager); g_signal_connect (priv->profile_store, "removed", G_CALLBACK (gcm_session_profile_store_removed_cb), manager); } static void gsd_color_manager_finalize (GObject *object) { GsdColorManager *manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_COLOR_MANAGER (object)); manager = GSD_COLOR_MANAGER (object); g_signal_handlers_disconnect_by_data (manager->priv->session, manager); g_clear_object (&manager->priv->settings); g_clear_object (&manager->priv->client); g_clear_object (&manager->priv->profile_store); g_clear_object (&manager->priv->dmi); g_clear_object (&manager->priv->session); g_clear_pointer (&manager->priv->edid_cache, g_hash_table_destroy); g_clear_pointer (&manager->priv->device_assign_hash, g_hash_table_destroy); g_clear_object (&manager->priv->x11_screen); G_OBJECT_CLASS (gsd_color_manager_parent_class)->finalize (object); } GsdColorManager * gsd_color_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_COLOR_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_COLOR_MANAGER (manager_object); } unity-settings-daemon/plugins/color/gsd-color-manager.h0000664000000000000000000000476515172222611020501 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_COLOR_MANAGER_H #define __GSD_COLOR_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_COLOR_MANAGER (gsd_color_manager_get_type ()) #define GSD_COLOR_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_COLOR_MANAGER, GsdColorManager)) #define GSD_COLOR_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_COLOR_MANAGER, GsdColorManagerClass)) #define GSD_IS_COLOR_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_COLOR_MANAGER)) #define GSD_IS_COLOR_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_COLOR_MANAGER)) #define GSD_COLOR_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_COLOR_MANAGER, GsdColorManagerClass)) #define GSD_COLOR_MANAGER_ERROR (gsd_color_manager_error_quark ()) typedef struct GsdColorManagerPrivate GsdColorManagerPrivate; typedef struct { GObject parent; GsdColorManagerPrivate *priv; } GsdColorManager; typedef struct { GObjectClass parent_class; } GsdColorManagerClass; enum { GSD_COLOR_MANAGER_ERROR_FAILED }; GType gsd_color_manager_get_type (void); GQuark gsd_color_manager_error_quark (void); GsdColorManager * gsd_color_manager_new (void); gboolean gsd_color_manager_start (GsdColorManager *manager, GError **error); void gsd_color_manager_stop (GsdColorManager *manager); G_END_DECLS #endif /* __GSD_COLOR_MANAGER_H */ unity-settings-daemon/plugins/color/gsd-color-plugin.c0000664000000000000000000000211015172222611020336 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-color-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdColor, gsd_color) unity-settings-daemon/plugins/color/test-data/0000775000000000000000000000000015172222611016701 5ustar unity-settings-daemon/plugins/color/test-data/LG-L225W-External.bin0000664000000000000000000000020015172222611022216 0ustar mcV^ /x%UI'PTk@qO|.`@0 6(!90b'@h6(8KS L225W tunity-settings-daemon/plugins/color/test-data/Lenovo-T61-Internal.bin0000664000000000000000000000020015172222611022747 0ustar $M(!x uUO&!PT/`@ @K'`@ @K 2 (LX3LTN154P2-L05 unity-settings-daemon/plugins/common/0000775000000000000000000000000015172222611015165 5ustar unity-settings-daemon/plugins/common/Makefile.am0000664000000000000000000000200615172222611017217 0ustar plugin_name = common noinst_LTLIBRARIES = libcommon.la libcommon_la_SOURCES = \ gsd-keygrab.c \ gsd-keygrab.h \ gsd-input-helper.c \ gsd-input-helper.h \ gsd-settings-migrate.c \ gsd-settings-migrate.h libcommon_la_CPPFLAGS = \ $(AM_CPPFLAGS) libcommon_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(COMMON_CFLAGS) \ $(AM_CFLAGS) libcommon_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libcommon_la_LIBADD = \ $(SETTINGS_PLUGIN_LIBS) \ $(COMMON_LIBS) libexec_PROGRAMS = usd-test-input-helper usd_test_input_helper_SOURCES = test-input-helper.c usd_test_input_helper_LDADD = libcommon.la usd_test_input_helper_CFLAGS = $(libcommon_la_CFLAGS) noinst_PROGRAMS = test-egg-key-parsing test_egg_key_parsing_SOURCES = test-egg-key-parsing.c test_egg_key_parsing_LDADD = libcommon.la $(COMMON_LIBS) test_egg_key_parsing_CFLAGS = $(libcommon_la_CFLAGS) scriptsdir = $(datadir)/unity-settings-daemon-@GSD_API_VERSION@ scripts_DATA = input-device-example.sh EXTRA_DIST = $(scripts_DATA) test-plugin.h unity-settings-daemon/plugins/common/gsd-input-helper.c0000664000000000000000000004367715172222611020541 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gsd-input-helper.h" #define INPUT_DEVICES_SCHEMA "com.canonical.unity.settings-daemon.peripherals.input-devices" #define KEY_HOTPLUG_COMMAND "hotplug-command" #define ABS_MT_X "Abs MT Position X" #define ABS_MT_Y "Abs MT Position Y" #define ABS_X "Abs X" #define ABS_Y "Abs Y" typedef gboolean (* InfoIdentifyFunc) (XDeviceInfo *device_info); typedef gboolean (* DeviceIdentifyFunc) (XDevice *xdevice); gboolean device_set_property (XDevice *xdevice, const char *device_name, PropertyHelper *property) { int rc, i; Atom prop; Atom realtype; int realformat; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), property->name, False); if (!prop) return FALSE; gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, property->nitems, False, AnyPropertyType, &realtype, &realformat, &nitems, &bytes_after, &data); if (rc != Success || realtype != property->type || realformat != property->format || nitems < property->nitems) { gdk_error_trap_pop_ignored (); g_warning ("Error reading property \"%s\" for \"%s\"", property->name, device_name); return FALSE; } for (i = 0; i < nitems; i++) { switch (property->format) { case 8: data[i] = property->data.c[i]; break; case 32: ((long*)data)[i] = property->data.i[i]; break; } } XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, realtype, realformat, PropModeReplace, data, nitems); XFree (data); if (gdk_error_trap_pop ()) { g_warning ("Error in setting \"%s\" for \"%s\"", property->name, device_name); return FALSE; } return TRUE; } static gboolean supports_xinput_devices_with_opcode (int *opcode) { gint op_code, event, error; gboolean retval; retval = XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "XInputExtension", &op_code, &event, &error); if (opcode) *opcode = op_code; return retval; } gboolean supports_xinput_devices (void) { return supports_xinput_devices_with_opcode (NULL); } gboolean supports_xtest (void) { gint op_code, event, error; gboolean retval; retval = XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "XTEST", &op_code, &event, &error); return retval; } gboolean supports_xinput2_devices (int *opcode) { int major, minor; if (supports_xinput_devices_with_opcode (opcode) == FALSE) return FALSE; gdk_error_trap_push (); major = 2; minor = 3; if (XIQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor) != Success) { gdk_error_trap_pop_ignored (); return FALSE; } gdk_error_trap_pop_ignored (); if ((major * 1000 + minor) < (2000)) return FALSE; return TRUE; } gboolean device_is_touchpad (XDevice *xdevice) { Atom realtype, prop; int realformat; unsigned long nitems, bytes_after; unsigned char *data; /* we don't check on the type being XI_TOUCHPAD here, * but having a "Synaptics Off" property should be enough */ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Off", False); if (!prop) return FALSE; gdk_error_trap_push (); if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 1, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { gdk_error_trap_pop_ignored (); XFree (data); return TRUE; } gdk_error_trap_pop_ignored (); return FALSE; } gboolean device_info_is_touchpad (XDeviceInfo *device_info) { return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHPAD, False)); } gboolean device_info_is_touchscreen (XDeviceInfo *device_info) { return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHSCREEN, False)); } gboolean device_info_is_tablet (XDeviceInfo *device_info) { /* Note that this doesn't match Wacom tablets */ return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TABLET, False)); } gboolean device_info_is_mouse (XDeviceInfo *device_info) { return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_MOUSE, False)); } gboolean device_info_is_trackball (XDeviceInfo *device_info) { gboolean retval; retval = (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TRACKBALL, False)); if (retval == FALSE && device_info->name != NULL) { char *lowercase; lowercase = g_ascii_strdown (device_info->name, -1); retval = strstr (lowercase, "trackball") != NULL; g_free (lowercase); } return retval; } static gboolean device_type_is_present (InfoIdentifyFunc info_func, DeviceIdentifyFunc device_func) { XDeviceInfo *device_info; gint n_devices; guint i; gboolean retval; if (supports_xinput_devices () == FALSE) return TRUE; retval = FALSE; device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) return FALSE; for (i = 0; i < n_devices; i++) { XDevice *device; /* Check with the device info first */ retval = (info_func) (&device_info[i]); if (retval == FALSE) continue; /* If we only have an info func, we're done checking */ if (device_func == NULL) break; gdk_error_trap_push (); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id); if (gdk_error_trap_pop () || (device == NULL)) continue; retval = (device_func) (device); xdevice_close (device); if (retval) break; } XFreeDeviceList (device_info); return retval; } gboolean touchscreen_is_present (void) { return device_type_is_present (device_info_is_touchscreen, NULL); } gboolean touchpad_is_present (void) { return device_type_is_present (device_info_is_touchpad, device_is_touchpad); } gboolean mouse_is_present (void) { return device_type_is_present (device_info_is_mouse, NULL); } gboolean trackball_is_present (void) { return device_type_is_present (device_info_is_trackball, NULL); } char * xdevice_get_device_node (int deviceid) { Atom prop; Atom act_type; int act_format; unsigned long nitems, bytes_after; unsigned char *data; char *ret; gdk_display_sync (gdk_display_get_default ()); prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Device Node", False); if (!prop) return NULL; gdk_error_trap_push (); if (!XIGetProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), deviceid, prop, 0, 1000, False, AnyPropertyType, &act_type, &act_format, &nitems, &bytes_after, &data) == Success) { gdk_error_trap_pop_ignored (); return NULL; } if (gdk_error_trap_pop ()) goto out; if (nitems == 0) goto out; if (act_type != XA_STRING) goto out; /* Unknown string format */ if (act_format != 8) goto out; ret = g_strdup ((char *) data); XFree (data); return ret; out: XFree (data); return NULL; } #define TOOL_ID_FORMAT_SIZE 32 static int get_id_for_index (guchar *data, guint idx) { guchar *ptr; int id; ptr = data; ptr += TOOL_ID_FORMAT_SIZE / 8 * idx; id = *((int32_t*)ptr); id = id & 0xfffff; return id; } #define STYLUS_DEVICE_ID 0x02 #define ERASER_DEVICE_ID 0x0A int xdevice_get_last_tool_id (int deviceid) { Atom prop; Atom act_type; int act_format; unsigned long nitems, bytes_after; unsigned char *data; int id; id = -1; gdk_display_sync (gdk_display_get_default ()); prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), WACOM_SERIAL_IDS_PROP, False); if (!prop) return -1; data = NULL; gdk_error_trap_push (); if (XIGetProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), deviceid, prop, 0, 1000, False, AnyPropertyType, &act_type, &act_format, &nitems, &bytes_after, &data) != Success) { gdk_error_trap_pop_ignored (); goto out; } if (gdk_error_trap_pop ()) goto out; if (nitems != 4 && nitems != 5) goto out; if (act_type != XA_INTEGER) goto out; if (act_format != TOOL_ID_FORMAT_SIZE) goto out; /* item 0 = tablet ID * item 1 = old device serial number (== last tool in proximity) * item 2 = old hardware serial number (including tool ID) * item 3 = current serial number (0 if no tool in proximity) * item 4 = current tool ID (since Feb 2012) * * Get the current tool ID first, if available, then the old one */ id = 0x0; if (nitems == 5) id = get_id_for_index (data, 4); if (id == 0x0) id = get_id_for_index (data, 2); /* That means that no tool was set down yet */ if (id == STYLUS_DEVICE_ID || id == ERASER_DEVICE_ID) id = 0x0; out: if (data != NULL) XFree (data); return id; } gboolean set_device_enabled (int device_id, gboolean enabled) { Atom prop; guchar value; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Device Enabled", False); if (!prop) return FALSE; gdk_error_trap_push (); value = enabled ? 1 : 0; XIChangeProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_id, prop, XA_INTEGER, 8, PropModeReplace, &value, 1); if (gdk_error_trap_pop ()) return FALSE; return TRUE; } static const char * custom_command_to_string (CustomCommand command) { switch (command) { case COMMAND_DEVICE_ADDED: return "added"; case COMMAND_DEVICE_REMOVED: return "removed"; case COMMAND_DEVICE_PRESENT: return "present"; default: g_assert_not_reached (); } } /* Run a custom command on device presence events. Parameters passed into * the custom command are: * command -t [added|removed|present] -i * Type 'added' and 'removed' signal 'device added' and 'device removed', * respectively. Type 'present' signals 'device present at * gnome-settings-daemon init'. * * The script is expected to run synchronously, and an exit value * of "1" means that no other settings will be applied to this * particular device. * * More options may be added in the future. * * This function returns TRUE if we should not apply any more settings * to the device. */ gboolean run_custom_command (GdkDevice *device, CustomCommand command) { GSettings *settings; GError *error = NULL; char *cmd; char *argv[7]; int exit_status; gboolean rc; int id; settings = g_settings_new (INPUT_DEVICES_SCHEMA); cmd = g_settings_get_string (settings, KEY_HOTPLUG_COMMAND); g_object_unref (settings); if (!cmd || cmd[0] == '\0') { g_free (cmd); return FALSE; } /* Easter egg! */ g_object_get (device, "device-id", &id, NULL); argv[0] = cmd; argv[1] = "-t"; argv[2] = (char *) custom_command_to_string (command); argv[3] = "-i"; argv[4] = g_strdup_printf ("%d", id); argv[5] = (char*) gdk_device_get_name (device); argv[6] = NULL; rc = g_spawn_sync (g_get_home_dir (), argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &exit_status, &error); if (rc == FALSE) { g_warning ("Couldn't execute command '%s', verify that this is a valid command: %s", cmd, error->message); g_clear_error (&error); } g_free (argv[0]); g_free (argv[4]); if (!g_spawn_check_exit_status (exit_status, &error)) { if (g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)) { g_clear_error (&error); return TRUE; } g_clear_error (&error); } return FALSE; } GList * get_disabled_devices (GdkDeviceManager *manager) { XDeviceInfo *device_info; gint n_devices; guint i; GList *ret; ret = NULL; device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) return ret; for (i = 0; i < n_devices; i++) { GdkDevice *device; /* Ignore core devices */ if (device_info[i].use == IsXKeyboard || device_info[i].use == IsXPointer) continue; /* Check whether the device is actually available */ device = gdk_x11_device_manager_lookup (manager, device_info[i].id); if (device != NULL) continue; ret = g_list_prepend (ret, GINT_TO_POINTER (device_info[i].id)); } XFreeDeviceList (device_info); return ret; } gboolean xdevice_get_dimensions (int deviceid, guint *width, guint *height) { GdkDisplay *display = gdk_display_get_default (); XIDeviceInfo *info; guint *value, w, h; int i, n_info; /* ignore errors, device might be removed before config is done as in #1503758 */ gdk_error_trap_push(); info = XIQueryDevice (GDK_DISPLAY_XDISPLAY (display), deviceid, &n_info); gdk_error_trap_pop_ignored (); *width = *height = w = h = 0; if (!info) return FALSE; for (i = 0; i < info->num_classes; i++) { XIValuatorClassInfo *valuator_info; if (info->classes[i]->type != XIValuatorClass) continue; valuator_info = (XIValuatorClassInfo *) info->classes[i]; if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_X) || valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_X)) value = &w; else if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_Y) || valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_Y)) value = &h; else continue; *value = (valuator_info->max - valuator_info->min) * 1000 / valuator_info->resolution; } *width = w; *height = h; XIFreeDeviceInfo (info); return (w != 0 && h != 0); } void xdevice_close (XDevice *xdevice) { gdk_error_trap_push (); XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); gdk_error_trap_pop_ignored(); } unity-settings-daemon/plugins/common/gsd-input-helper.h0000664000000000000000000000702415172222611020530 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __GSD_INPUT_HELPER_H #define __GSD_INPUT_HELPER_H G_BEGIN_DECLS #include #include #include #define WACOM_SERIAL_IDS_PROP "Wacom Serial IDs" typedef enum { COMMAND_DEVICE_ADDED, COMMAND_DEVICE_REMOVED, COMMAND_DEVICE_PRESENT } CustomCommand; /* Generic property setting code. Fill up the struct property with the property * data and pass it into device_set_property together with the device to be * changed. Note: doesn't cater for non-zero offsets yet, but we don't have * any settings that require that. */ typedef struct { const char *name; /* property name */ gint nitems; /* number of items in data */ gint format; /* CARD8 or CARD32 sized-items */ gint type; /* Atom representing data type */ union { const gchar *c; /* 8 bit data */ const gint *i; /* 32 bit data */ } data; } PropertyHelper; gboolean supports_xinput_devices (void); gboolean supports_xinput2_devices (int *opcode); gboolean supports_xtest (void); gboolean set_device_enabled (int device_id, gboolean enabled); gboolean device_is_touchpad (XDevice *xdevice); gboolean device_info_is_touchpad (XDeviceInfo *device_info); gboolean device_info_is_touchscreen (XDeviceInfo *device_info); gboolean device_info_is_tablet (XDeviceInfo *device_info); gboolean device_info_is_mouse (XDeviceInfo *device_info); gboolean device_info_is_trackball (XDeviceInfo *device_info); gboolean touchpad_is_present (void); gboolean touchscreen_is_present (void); gboolean mouse_is_present (void); gboolean trackball_is_present (void); gboolean device_set_property (XDevice *xdevice, const char *device_name, PropertyHelper *property); gboolean run_custom_command (GdkDevice *device, CustomCommand command); GList * get_disabled_devices (GdkDeviceManager *manager); char * xdevice_get_device_node (int deviceid); int xdevice_get_last_tool_id (int deviceid); gboolean xdevice_get_dimensions (int deviceid, guint *width, guint *height); void xdevice_close (XDevice *xdevice); G_END_DECLS #endif /* __GSD_INPUT_HELPER_H */ unity-settings-daemon/plugins/common/gsd-keygrab.c0000664000000000000000000005532015172222611017535 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2001-2003 Bastien Nocera * Copyright (C) 2006-2007 William Jon McCann * Copyright (C) 2008 Jens Granseuer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "gsd-keygrab.h" /* these are the mods whose combinations are ignored by the keygrabbing code */ static GdkModifierType gsd_ignored_mods = 0; /* these are the ones we actually use for global keys, we always only check * for these set */ static GdkModifierType gsd_used_mods = 0; /* Taken from a comment in XF86keysym.h */ #define XF86KEYS_RANGE_MIN 0x10080001 #define XF86KEYS_RANGE_MAX 0x1008FFFF #define FKEYS_RANGE_MIN GDK_KEY_F1 #define FKEYS_RANGE_MAX GDK_KEY_R15 #define IN_RANGE(x, min, max) (x >= min && x <= max) static void setup_modifiers (void) { if (gsd_used_mods == 0 || gsd_ignored_mods == 0) { GdkModifierType dynmods; /* default modifiers */ gsd_ignored_mods = \ 0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | GDK_HYPER_MASK; gsd_used_mods = \ GDK_SHIFT_MASK | GDK_CONTROL_MASK |\ GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK |\ GDK_MOD5_MASK | GDK_SUPER_MASK | GDK_META_MASK; /* NumLock can be assigned to varying keys so we need to * resolve and ignore it specially */ dynmods = XkbKeysymToModifiers (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Num_Lock); gsd_ignored_mods |= dynmods; gsd_used_mods &= ~dynmods; } } static void grab_key_real (guint keycode, GdkWindow *root, gboolean grab, gboolean synchronous, XIGrabModifiers *mods, int num_mods) { XIEventMask evmask; unsigned char mask[(XI_LASTEVENT + 7)/8]; memset (mask, 0, sizeof (mask)); XISetMask (mask, XI_KeyPress); XISetMask (mask, XI_KeyRelease); evmask.deviceid = XIAllMasterDevices; evmask.mask_len = sizeof (mask); evmask.mask = mask; if (grab) { XIGrabKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XIAllMasterDevices, keycode, GDK_WINDOW_XID (root), GrabModeAsync, synchronous ? GrabModeSync : GrabModeAsync, False, &evmask, num_mods, mods); } else { XIUngrabKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XIAllMasterDevices, keycode, GDK_WINDOW_XID (root), num_mods, mods); } } /* Grab the key. In order to ignore GSD_IGNORED_MODS we need to grab * all combinations of the ignored modifiers and those actually used * for the binding (if any). * * inspired by all_combinations from gnome-panel/gnome-panel/global-keys.c * * This may generate X errors. The correct way to use this is like: * * gdk_error_trap_push (); * * grab_key_unsafe (key, grab, screens); * * gdk_flush (); * if (gdk_error_trap_pop ()) * g_warning ("Grab failed, another application may already have access to key '%u'", * key->keycode); * * This is not done in the function itself, to allow doing multiple grab_key * operations with one flush only. */ #define N_BITS 32 static void grab_key_internal (Key *key, gboolean grab, GsdKeygrabFlags flags, GSList *screens) { int indexes[N_BITS]; /* indexes of bits we need to flip */ int i; int bit; int bits_set_cnt; int uppervalue; guint mask, modifiers; GArray *all_mods; GSList *l; setup_modifiers (); mask = gsd_ignored_mods & ~key->state & GDK_MODIFIER_MASK; /* XGrabKey requires real modifiers, not virtual ones */ modifiers = key->state; gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &modifiers); modifiers &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK); /* If key doesn't have a usable modifier, we don't want * to grab it, since the user might lose a useful key. * * The exception is the XFree86 keys and the Function keys * (which are useful to grab without a modifier). */ if (!(flags & GSD_KEYGRAB_ALLOW_UNMODIFIED) && (modifiers & gsd_used_mods) == 0 && !IN_RANGE(key->keysym, XF86KEYS_RANGE_MIN, XF86KEYS_RANGE_MAX) && !IN_RANGE(key->keysym, FKEYS_RANGE_MIN, FKEYS_RANGE_MAX) && key->keysym != GDK_KEY_Pause && key->keysym != GDK_KEY_Print && key->keysym != GDK_KEY_Scroll_Lock && key->keysym != GDK_KEY_Caps_Lock && key->keysym != GDK_KEY_Pause && key->keysym != GDK_KEY_Break && key->keysym != GDK_KEY_Menu) { GString *keycodes; keycodes = g_string_new (""); if (key->keycodes != NULL) { guint *c; for (c = key->keycodes; *c; ++c) { g_string_printf (keycodes, " %u", *c); } } g_warning ("Key 0x%x (keycodes: %s) with state 0x%x (resolved to 0x%x) " " has no usable modifiers (usable modifiers are 0x%x)", key->keysym, keycodes->str, key->state, modifiers, gsd_used_mods); g_string_free (keycodes, TRUE); return; } bit = 0; /* store the indexes of all set bits in mask in the array */ for (i = 0; mask; ++i, mask >>= 1) { if (mask & 0x1) { indexes[bit++] = i; } } bits_set_cnt = bit; all_mods = g_array_new (FALSE, TRUE, sizeof(XIGrabModifiers)); uppervalue = 1 << bits_set_cnt; /* store all possible modifier combinations for our mask into all_mods */ for (i = 0; i < uppervalue; ++i) { int j; int result = 0; XIGrabModifiers *mod; /* map bits in the counter to those in the mask */ for (j = 0; j < bits_set_cnt; ++j) { if (i & (1 << j)) { result |= (1 << indexes[j]); } } /* Grow the array by one, to fit our new XIGrabModifiers item */ g_array_set_size (all_mods, all_mods->len + 1); mod = &g_array_index (all_mods, XIGrabModifiers, all_mods->len - 1); mod->modifiers = result | modifiers; } /* Capture the actual keycodes with the modifier array */ for (l = screens; l; l = l->next) { GdkScreen *screen = l->data; guint *code; for (code = key->keycodes; *code; ++code) { grab_key_real (*code, gdk_screen_get_root_window (screen), grab, flags & GSD_KEYGRAB_SYNCHRONOUS, (XIGrabModifiers *) all_mods->data, all_mods->len); } } g_array_free (all_mods, TRUE); } static void get_keys_for_bit (guint bit, guint *left, guint *right) { guint left_dummy; guint right_dummy; if (left == NULL) left = &left_dummy; if (right == NULL) right = &right_dummy; *left = 0; *right = 0; switch (1 << bit) { case GDK_SHIFT_MASK: *left = GDK_KEY_Shift_L; *right = GDK_KEY_Shift_R; break; case GDK_CONTROL_MASK: *left = GDK_KEY_Control_L; *right = GDK_KEY_Control_R; break; case GDK_LOCK_MASK: *left = GDK_KEY_Caps_Lock; *right = GDK_KEY_Shift_Lock; break; case GDK_META_MASK: case GDK_MOD1_MASK: *left = GDK_KEY_Alt_L; *right = GDK_KEY_Alt_R; break; case GDK_SUPER_MASK: *left = GDK_KEY_Super_L; *right = GDK_KEY_Super_R; break; } } static guint get_mask_for_key (guint key) { switch (key) { case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: return GDK_SHIFT_MASK; case GDK_KEY_Control_L: case GDK_KEY_Control_R: return GDK_CONTROL_MASK; case GDK_KEY_Caps_Lock: case GDK_KEY_Shift_Lock: return GDK_LOCK_MASK; case GDK_KEY_Meta_L: case GDK_KEY_Meta_R: case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: return GDK_MOD1_MASK; case GDK_KEY_Super_L: case GDK_KEY_Super_R: return GDK_SUPER_MASK; } return 0; } static guint get_mirrored_key (guint key) { switch (key) { case GDK_KEY_Shift_L: return GDK_KEY_Shift_R; case GDK_KEY_Shift_R: return GDK_KEY_Shift_L; case GDK_KEY_Control_L: return GDK_KEY_Control_R; case GDK_KEY_Control_R: return GDK_KEY_Control_L; case GDK_KEY_Meta_L: return GDK_KEY_Meta_R; case GDK_KEY_Meta_R: return GDK_KEY_Meta_L; case GDK_KEY_Alt_L: return GDK_KEY_Alt_R; case GDK_KEY_Alt_R: return GDK_KEY_Alt_L; case GDK_KEY_Super_L: return GDK_KEY_Super_R; case GDK_KEY_Super_R: return GDK_KEY_Super_L; case GDK_KEY_Hyper_L: return GDK_KEY_Hyper_R; case GDK_KEY_Hyper_R: return GDK_KEY_Hyper_L; } return 0; } void grab_key_unsafe (Key *key, GsdKeygrabFlags flags, GSList *screens) { guint key_mask = get_mask_for_key (key->keysym); grab_key_internal (key, TRUE, flags, screens); if (key_mask != 0) { Key copy; guint i, j; if ((key->state & key_mask) != 0) { guint mirror = get_mirrored_key (key->keysym); if (mirror != 0) { gint mirror_keys_len; GdkKeymapKey *mirror_keys; gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), mirror, &mirror_keys, &mirror_keys_len); copy.keysym = mirror; copy.state = key->state; copy.keycodes = g_new0 (guint, mirror_keys_len + 1); for (j = 0; j < mirror_keys_len; j++) copy.keycodes[j] = mirror_keys[j].keycode; grab_key_internal (©, TRUE, flags, screens); g_free (copy.keycodes); g_free (mirror_keys); } } for (i = 0; i < 8 * sizeof (guint); i++) { guint left, right; gint left_keys_len, right_keys_len; GdkKeymapKey *left_keys, *right_keys; if (1 << i == key_mask || (key->state & 1 << i) == 0) continue; get_keys_for_bit (i, &left, &right); if (left == 0 && right == 0) continue; left_keys_len = 0; right_keys_len = 0; left_keys = NULL; right_keys = NULL; if (left != 0) gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), left, &left_keys, &left_keys_len); if (right != 0) gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), right, &right_keys, &right_keys_len); copy.keysym = left != 0 ? left : right; copy.state = (key->state | key_mask) & ~(1 << i); copy.keycodes = g_new0 (guint, left_keys_len + right_keys_len + 1); for (j = 0; j < left_keys_len; j++) copy.keycodes[j] = left_keys[j].keycode; for (j = 0; j < right_keys_len; j++) copy.keycodes[left_keys_len + j] = right_keys[j].keycode; grab_key_internal (©, TRUE, flags, screens); g_free (copy.keycodes); g_free (right_keys); g_free (left_keys); } } } void ungrab_key_unsafe (Key *key, GSList *screens) { guint key_mask = get_mask_for_key (key->keysym); grab_key_internal (key, FALSE, 0, screens); if (key_mask != 0) { Key copy; guint i, j; if ((key->state & key_mask) != 0) { guint mirror = get_mirrored_key (key->keysym); if (mirror != 0) { gint mirror_keys_len; GdkKeymapKey *mirror_keys; gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), mirror, &mirror_keys, &mirror_keys_len); copy.keysym = mirror; copy.state = key->state; copy.keycodes = g_new0 (guint, mirror_keys_len + 1); for (j = 0; j < mirror_keys_len; j++) copy.keycodes[j] = mirror_keys[j].keycode; grab_key_internal (©, FALSE, 0, screens); g_free (copy.keycodes); g_free (mirror_keys); } } for (i = 0; i < 8 * sizeof (guint); i++) { guint left, right; gint left_keys_len, right_keys_len; GdkKeymapKey *left_keys, *right_keys; if (1 << i == key_mask || (key->state & 1 << i) == 0) continue; get_keys_for_bit (i, &left, &right); if (left == 0 && right == 0) continue; left_keys_len = 0; right_keys_len = 0; left_keys = NULL; right_keys = NULL; if (left != 0) gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), left, &left_keys, &left_keys_len); if (right != 0) gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), right, &right_keys, &right_keys_len); copy.keysym = left != 0 ? left : right; copy.state = (key->state | key_mask) & ~(1 << i); copy.keycodes = g_new0 (guint, left_keys_len + right_keys_len + 1); for (j = 0; j < left_keys_len; j++) copy.keycodes[j] = left_keys[j].keycode; for (j = 0; j < right_keys_len; j++) copy.keycodes[left_keys_len + j] = right_keys[j].keycode; grab_key_internal (©, FALSE, 0, screens); g_free (copy.keycodes); g_free (right_keys); g_free (left_keys); } } } static gboolean have_xkb (Display *dpy) { static int have_xkb = -1; if (have_xkb == -1) { int opcode, error_base, major, minor, xkb_event_base; have_xkb = XkbQueryExtension (dpy, &opcode, &xkb_event_base, &error_base, &major, &minor) && XkbUseExtension (dpy, &major, &minor); } return have_xkb; } gboolean key_uses_keycode (const Key *key, guint keycode) { if (key->keycodes != NULL) { guint *c; for (c = key->keycodes; *c; ++c) { if (*c == keycode) return TRUE; } } return FALSE; } /* Adapted from _gdk_x11_device_xi2_translate_state() * in gtk+/gdk/x11/gdkdevice-xi2.c */ static guint device_xi2_translate_state (XIModifierState *mods_state, XIGroupState *group_state) { guint state; gint group; state = (guint) mods_state->base | mods_state->latched | mods_state->locked; group = group_state->base | group_state->latched | group_state->locked; /* FIXME: do we need the XKB complications for this ? */ group = CLAMP(group, 0, 3); state |= group << 13; return state; } gboolean match_xi2_key (Key *key, XIDeviceEvent *event) { guint keyval; GdkModifierType consumed; gint group; guint keycode, state; if (key == NULL) return FALSE; setup_modifiers (); state = device_xi2_translate_state (&event->mods, &event->group); if (have_xkb (event->display)) group = XkbGroupForCoreState (state); else group = (state & GDK_KEY_Mode_switch) ? 1 : 0; keycode = event->detail; /* Check if we find a keysym that matches our current state */ if (gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), keycode, state, group, &keyval, NULL, NULL, &consumed)) { guint key_bit, event_bit; guint lower, upper; guint mask, full_mask; /* HACK: we don't want to use SysRq as a keybinding, so we avoid * its translation from Alt+Print. */ if (keyval == GDK_KEY_Sys_Req && (state & GDK_MOD1_MASK) != 0) { consumed = 0; keyval = GDK_KEY_Print; } /* The Key structure contains virtual modifiers, whereas * the XEvent will be using the real modifier, so translate those */ key_bit = get_mask_for_key (key->keysym); event_bit = get_mask_for_key (keyval); mask = key->state; full_mask = mask | key_bit; gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &mask); gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &full_mask); mask &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK); full_mask &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK); gdk_keyval_convert_case (keyval, &lower, &upper); /* If we are checking against the lower version of the * keysym, we might need the Shift state for matching, * so remove it from the consumed modifiers */ if (lower == key->keysym || event_bit != 0) consumed &= ~GDK_SHIFT_MASK; state &= ~consumed & gsd_used_mods; if (key_bit != 0 && event_bit != 0) { state |= event_bit; gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &state); state &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK); return state == full_mask; } return (lower == key->keysym || upper == key->keysym) && state == mask; } /* The key we passed doesn't have a keysym, so try with just the keycode */ return (key != NULL && key->state == (state & gsd_used_mods) && key_uses_keycode (key, keycode)); } Key * parse_key (const char *str) { Key *key; if (str == NULL || *str == '\0' || g_str_equal (str, "disabled")) { return NULL; } key = g_new0 (Key, 1); gtk_accelerator_parse_with_keycode (str, &key->keysym, &key->keycodes, &key->state); if (key->keysym == 0 && key->keycodes == NULL && key->state == 0) { g_free (key); return NULL; } return key; } void free_key (Key *key) { if (key == NULL) return; g_free (key->keycodes); g_free (key); } static void grab_button_real (int deviceid, gboolean grab, GdkWindow *root) { XIGrabModifiers mods; mods.modifiers = XIAnyModifier; if (grab) { XIEventMask evmask; unsigned char mask[(XI_LASTEVENT + 7)/8]; memset (mask, 0, sizeof (mask)); XISetMask (mask, XI_ButtonRelease); XISetMask (mask, XI_ButtonPress); evmask.deviceid = deviceid; evmask.mask_len = sizeof (mask); evmask.mask = mask; XIGrabButton (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), deviceid, XIAnyButton, GDK_WINDOW_XID (root), None, GrabModeAsync, GrabModeAsync, False, &evmask, 1, &mods); } else { XIUngrabButton (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), deviceid, XIAnyButton, GDK_WINDOW_XID (root), 1, &mods); } } void grab_button (int deviceid, gboolean grab, GSList *screens) { GSList *l; for (l = screens; l; l = l->next) { GdkScreen *screen = l->data; grab_button_real (deviceid, grab, gdk_screen_get_root_window (screen)); } } unity-settings-daemon/plugins/common/gsd-keygrab.h0000664000000000000000000000373115172222611017541 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Jens Granseuer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __GSD_COMMON_KEYGRAB_H #define __GSD_COMMON_KEYGRAB_H G_BEGIN_DECLS #include #include #include typedef struct { guint keysym; guint state; guint *keycodes; } Key; typedef enum { GSD_KEYGRAB_NORMAL = 0, GSD_KEYGRAB_ALLOW_UNMODIFIED = 1 << 0, GSD_KEYGRAB_SYNCHRONOUS = 1 << 1 } GsdKeygrabFlags; void grab_key_unsafe (Key *key, GsdKeygrabFlags flags, GSList *screens); void ungrab_key_unsafe (Key *key, GSList *screens); gboolean match_xi2_key (Key *key, XIDeviceEvent *event); gboolean key_uses_keycode (const Key *key, guint keycode); Key * parse_key (const char *str); void free_key (Key *key); void grab_button (int deviceid, gboolean grab, GSList *screens); G_END_DECLS #endif /* __GSD_COMMON_KEYGRAB_H */ unity-settings-daemon/plugins/common/gsd-settings-migrate.c0000664000000000000000000000471515172222611021401 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2015 Red Hat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Author: Carlos Garnacho */ #include "config.h" #include #include "gsd-settings-migrate.h" void gsd_settings_migrate_check (const gchar *origin_schema, const gchar *origin_path, const gchar *dest_schema, const gchar *dest_path, GsdSettingsMigrateEntry entries[], guint n_entries) { GSettings *origin_settings, *dest_settings; GVariant *variant; guint i; origin_settings = g_settings_new_with_path (origin_schema, origin_path); dest_settings = g_settings_new_with_path (dest_schema, dest_path); for (i = 0; i < n_entries; i++) { variant = g_settings_get_user_value (origin_settings, entries[i].origin_key); if (!variant) continue; if (entries[i].dest_key) { if (entries[i].func) { GVariant *modified; modified = entries[i].func (variant); g_variant_unref (variant); variant = g_variant_ref_sink (modified); } g_settings_set_value (dest_settings, entries[i].dest_key, variant); } g_settings_reset (origin_settings, entries[i].origin_key); g_variant_unref (variant); } g_object_unref (origin_settings); g_object_unref (dest_settings); } unity-settings-daemon/plugins/common/gsd-settings-migrate.h0000664000000000000000000000323015172222611021375 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2015 Red Hat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Author: Carlos Garnacho */ #ifndef __GSD_SETTINGS_MIGRATE_H__ #define __GSD_SETTINGS_MIGRATE_H__ typedef struct _GsdSettingsMigrateEntry GsdSettingsMigrateEntry; typedef GVariant * (* GsdSettingsMigrateFunc) (GVariant *variant); struct _GsdSettingsMigrateEntry { const gchar *origin_key; const gchar *dest_key; GsdSettingsMigrateFunc func; }; void gsd_settings_migrate_check (const gchar *origin_schema, const gchar *origin_path, const gchar *dest_schema, const gchar *dest_path, GsdSettingsMigrateEntry entries[], guint n_entries); #endif /* __GSD_SETTINGS_MIGRATE_H__ */ unity-settings-daemon/plugins/common/input-device-example.sh0000664000000000000000000000302015172222611021541 0ustar #!/bin/sh # # This script is an example hotplug script for use with the various # input devices plugins. # # The script is called with the arguments: # -t [added|present|removed] # added ... device was just plugged in # present.. device was present at gnome-settings-daemon startup # removed.. device was just removed # -i # device ID being the XInput device ID # The name of the device # # The script should return 0 if the device is to be # ignored from future configuration. # # Set the script to be used with: # gsettings set com.canonical.unity.settings-daemon.peripherals.input-devices hotplug-command /path/to/script/input-devices.sh # args=`getopt "t:i:" $*` set -- $args while [ $# -gt 0 ] do case $1 in -t) shift; type="$1" ;; -i) shift; id="$1" ;; --) shift; device="$@" break; ;; *) echo "Unknown option $1"; exit 1 ;; esac shift done retval=0 case $type in added) echo "Device '$device' (ID=$id) was added" ;; present) echo "Device '$device' (ID=$id) was already present at startup" ;; removed) echo "Device '$device' (ID=$id) was removed" ;; *) echo "Unknown operation" retval=1 ;; esac # All further processing will be disabled if $retval == 1 exit $retval unity-settings-daemon/plugins/common/test-egg-key-parsing.c0000664000000000000000000000110515172222611021274 0ustar #include #define KEY "XF86AudioMute" int main (int argc, char **argv) { guint gdk_accel_key; guint *gdk_accel_codes; GdkModifierType gdk_mods; gtk_init (&argc, &argv); g_message ("gdk_keyval_from_name ('%s') == %d", KEY, gdk_keyval_from_name(KEY)); gtk_accelerator_parse_with_keycode (KEY, &gdk_accel_key, &gdk_accel_codes, &gdk_mods); g_message ("gtk_accelerator_parse_full ('%s') returned keyval '%d' keycode[0]: '%d' mods: 0x%x", KEY, gdk_accel_key, gdk_accel_codes ? gdk_accel_codes[0] : 0, gdk_mods); g_free (gdk_accel_codes); return 0; } unity-settings-daemon/plugins/common/test-input-helper.c0000664000000000000000000000772215172222611020732 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2011 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include "gsd-input-helper.h" static void print_disabled_devices (void) { GList *devices, *l; GdkDeviceManager *manager; manager = gdk_display_get_device_manager (gdk_display_get_default ()); devices = get_disabled_devices (manager); g_print ("Disabled devices:\t\t\t"); if (devices == NULL) { g_print ("no\n"); return; } for (l = devices; l != NULL; l = l->next) { g_print ("%d ", GPOINTER_TO_INT (l->data)); } g_list_free (devices); g_print ("\n"); } int main (int argc, char **argv) { gboolean supports_xinput; gboolean has_touchpad, has_touchscreen, has_trackball; XDeviceInfo *device_info; gint n_devices, opcode; guint i; gtk_init (&argc, &argv); supports_xinput = supports_xinput_devices (); if (supports_xinput) { g_print ("Supports XInput:\t\t\tyes\n"); } else { g_print ("Supports XInput:\t\t\tno\n"); return 0; } supports_xinput = supports_xinput2_devices (&opcode); if (supports_xinput) { g_print ("Supports XInput2:\t\t\tyes (opcode: %d)\n", opcode); } else { g_print ("Supports XInput2:\t\t\tno\n"); return 0; } has_touchpad = touchpad_is_present (); g_print ("Has touchpad:\t\t\t\t%s\n", has_touchpad ? "yes" : "no"); has_touchscreen = touchscreen_is_present (); g_print ("Has touchscreen:\t\t\t%s\n", has_touchscreen ? "yes" : "no"); has_trackball = trackball_is_present (); g_print ("Has trackball:\t\t\t\t%s\n", has_trackball ? "yes" : "no"); device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) { g_warning ("Has no input devices"); return 1; } print_disabled_devices (); for (i = 0; i < n_devices; i++) { XDevice *device; if (device_info_is_touchscreen (&device_info[i])) { g_print ("Device %d is touchscreen:\t\t%s\n", (int) device_info[i].id, "yes"); continue; } if (device_info_is_trackball (&device_info[i])) { g_print ("Device %d is trackball:\t\t\t%s\n", (int) device_info[i].id, "yes"); continue; } if (device_info_is_tablet (&device_info[i])) { g_print ("Device %d is tablet:\t\t\t%s\n", (int) device_info[i].id, "yes"); continue; } gdk_error_trap_push (); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id); if (gdk_error_trap_pop () || (device == NULL)) continue; if (device_is_touchpad (device)) g_print ("Device %d is touchpad:\t\t%s\n", (int) device_info[i].id, "yes"); else { int tool_id; tool_id = xdevice_get_last_tool_id (device_info[i].id); if (tool_id >= 0x0) g_print ("Device %d is touchpad/touchscreen:\t%s (tool ID: 0x%x)\n", (int) device_info[i].id, "no", tool_id); else g_print ("Device %d is touchpad/touchscreen:\t%s\n", (int) device_info[i].id, "no"); } XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); } XFreeDeviceList (device_info); return 0; } unity-settings-daemon/plugins/common/test-plugin.h0000664000000000000000000000467015172222611017620 0ustar /** * Create a test app for your plugin quickly. * * #define NEW gsd_media_keys_manager_new * #define START gsd_media_keys_manager_start * #define MANAGER GsdMediaKeysManager * #include "gsd-media-keys-manager.h" * * #include "test-plugin.h" */ #include "config.h" #include #include #include #include #ifndef SCHEMA_NAME #define SCHEMA_NAME PLUGIN_NAME #endif #ifndef PLUGIN_NAME #error Include PLUGIN_CFLAGS in the test application s CFLAGS #endif /* !PLUGIN_NAME */ static MANAGER *manager = NULL; static gboolean has_settings (void) { const gchar * const * list; guint i; list = g_settings_list_schemas (); for (i = 0; list[i] != NULL; i++) { if (g_str_equal (list[i], "com.canonical.unity.settings-daemon.plugins." SCHEMA_NAME)) return TRUE; } return FALSE; } static void print_enable_disable_help (void) { fprintf (stderr, "To deactivate:\n"); fprintf (stderr, "\tgsettings set com.canonical.unity.settings-daemon.plugins." SCHEMA_NAME " active false\n"); fprintf (stderr, "To reactivate:\n"); fprintf (stderr, "\tgsettings set com.canonical.unity.settings-daemon.plugins." SCHEMA_NAME " active true\n"); } int main (int argc, char **argv) { GError *error; GSettings *settings; bindtextdomain (GETTEXT_PACKAGE, GNOME_SETTINGS_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); notify_init ("gnome-settings-daemon"); g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); error = NULL; if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) { fprintf (stderr, "%s\n", error->message); g_error_free (error); exit (1); } if (has_settings () == FALSE) { fprintf (stderr, "The schemas for plugin '%s' isn't available, check your installation.\n", SCHEMA_NAME); } else { settings = g_settings_new ("com.canonical.unity.settings-daemon.plugins." SCHEMA_NAME); if (g_settings_get_boolean (settings, "active") != FALSE) { fprintf (stderr, "Plugin '%s' is not disabled. You need to disable it before launching the test application.\n", SCHEMA_NAME); print_enable_disable_help (); exit (1); } print_enable_disable_help(); } manager = NEW (); error = NULL; START (manager, &error); gtk_main (); STOP (manager); g_object_unref (manager); return 0; } unity-settings-daemon/plugins/cursor/0000775000000000000000000000000015172222611015212 5ustar unity-settings-daemon/plugins/cursor/Makefile.am0000664000000000000000000000340615172222611017251 0ustar plugin_name = cursor plugin_LTLIBRARIES = \ libcursor.la libcursor_la_SOURCES = \ gsd-cursor-manager.c \ gsd-cursor-manager.h \ gsd-cursor-plugin.c libcursor_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common/ \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libcursor_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(CURSOR_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libcursor_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libcursor_la_LIBADD = \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(CURSOR_LIBS) \ $(SETTINGS_PLUGIN_LIBS) libexec_PROGRAMS = usd-test-cursor usd_test_cursor_SOURCES = \ test-cursor.c \ gsd-cursor-manager.c \ gsd-cursor-manager.h usd_test_cursor_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) usd_test_cursor_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(CURSOR_CFLAGS) \ $(AM_CFLAGS) usd_test_cursor_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(CURSOR_LIBS) \ -lm plugin_in_files = \ cursor.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/cursor/cursor.gnome-settings-plugin.in0000664000000000000000000000035215172222611023315 0ustar [GNOME Settings Plugin] Module=cursor IAge=0 # Default Priority # Priority=100 _Name=Cursor _Description=Show/hide cursor on tablet devices Authors=Bastien Nocera Copyright=Copyright © 2011 Red Hat, Inc. Website= unity-settings-daemon/plugins/cursor/gsd-cursor-manager.c0000664000000000000000000003246115172222611021064 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2011-2013 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-profile.h" #include "gsd-cursor-manager.h" #include "gsd-input-helper.h" #include "gsd-idle-monitor.h" #define XFIXES_CURSOR_HIDING_MAJOR 4 #define GSD_CURSOR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_CURSOR_MANAGER, GsdCursorManagerPrivate)) struct GsdCursorManagerPrivate { guint added_id; guint removed_id; guint changed_id; gboolean cursor_shown; GHashTable *monitors; }; static void gsd_cursor_manager_class_init (GsdCursorManagerClass *klass); static void gsd_cursor_manager_init (GsdCursorManager *cursor_manager); static void gsd_cursor_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdCursorManager, gsd_cursor_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static gboolean add_all_devices (GsdCursorManager *manager, GdkDevice *exception, GError **error); typedef void (*ForeachScreenFunc) (GdkDisplay *display, GdkScreen *screen, GsdCursorManager *manager, gpointer user_data); static void foreach_screen (GsdCursorManager *manager, ForeachScreenFunc func, gpointer user_data) { GdkDisplay *display; guint n_screens; guint i; display = gdk_display_get_default (); n_screens = gdk_display_get_n_screens (display); for (i = 0; i < n_screens; i++) { GdkScreen *screen; screen = gdk_display_get_screen (display, i); (func) (display, screen, manager, user_data); } } static void set_cursor_visibility_foreach (GdkDisplay *display, GdkScreen *screen, GsdCursorManager *manager, gpointer user_data) { Display *xdisplay; gboolean visible = GPOINTER_TO_INT (user_data); xdisplay = GDK_DISPLAY_XDISPLAY (display); if (visible) XFixesShowCursor (xdisplay, GDK_WINDOW_XID (gdk_screen_get_root_window (screen))); else XFixesHideCursor (xdisplay, GDK_WINDOW_XID (gdk_screen_get_root_window (screen))); } static void set_cursor_visibility (GsdCursorManager *manager, gboolean visible) { g_debug ("Attempting to %s the cursor", visible ? "show" : "hide"); if (manager->priv->cursor_shown == visible) return; gdk_error_trap_push (); foreach_screen (manager, set_cursor_visibility_foreach, GINT_TO_POINTER (visible)); if (gdk_error_trap_pop ()) { g_warning ("An error occurred trying to %s the cursor", visible ? "show" : "hide"); } manager->priv->cursor_shown = visible; } static void monitor_became_active (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data) { GdkDevice *device; int device_id; GsdCursorManager *manager = GSD_CURSOR_MANAGER (user_data); GdkDeviceManager *device_manager; /* Oh, so you're active? */ g_object_get (G_OBJECT (monitor), "device_id", &device_id, NULL); device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); device = gdk_x11_device_manager_lookup (device_manager, device_id); g_debug ("Device %d '%s' became active", gdk_x11_device_get_id (device), gdk_device_get_name (device)); set_cursor_visibility (manager, gdk_device_get_source (device) != GDK_SOURCE_TOUCHSCREEN); /* Remove the device from the watch */ g_hash_table_remove (manager->priv->monitors, device); /* Make sure that all the other devices are watched * (but not the one we just stopped monitoring */ add_all_devices (manager, device, NULL); } static gboolean add_device (GdkDeviceManager *device_manager, GdkDevice *device, GsdCursorManager *manager, GError **error) { GsdIdleMonitor *monitor; int device_id; if (g_hash_table_lookup (manager->priv->monitors, device) != NULL) return TRUE; if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE) return TRUE; if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) return TRUE; if (strstr (gdk_device_get_name (device), "XTEST") != NULL) return TRUE; /* Create IdleMonitors for each pointer device */ device_id = gdk_x11_device_get_id (device); monitor = gsd_idle_monitor_get_for_device (device_id); if (!monitor) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Per-device idletime monitor not available"); return FALSE; } g_hash_table_insert (manager->priv->monitors, device, g_object_ref (monitor)); gsd_idle_monitor_add_user_active_watch (monitor, monitor_became_active, manager, NULL); return TRUE; } static void device_added_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdCursorManager *manager) { add_device (device_manager, device, manager, NULL); } static void device_removed_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdCursorManager *manager) { g_hash_table_remove (manager->priv->monitors, device); } static void device_changed_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdCursorManager *manager) { if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_FLOATING) device_removed_cb (device_manager, device, manager); else device_added_cb (device_manager, device, manager); } static gboolean supports_xfixes (void) { gint op_code, event, error; return XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "XFIXES", &op_code, &event, &error); } static gboolean supports_cursor_xfixes (void) { int major = XFIXES_CURSOR_HIDING_MAJOR; int minor = 0; gdk_error_trap_push (); if (!supports_xfixes ()) { gdk_error_trap_pop_ignored (); return FALSE; } if (!XFixesQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor)) { gdk_error_trap_pop_ignored (); return FALSE; } gdk_error_trap_pop_ignored (); if (major >= XFIXES_CURSOR_HIDING_MAJOR) return TRUE; return FALSE; } static gboolean add_all_devices (GsdCursorManager *manager, GdkDevice *exception, GError **error) { GdkDeviceManager *device_manager; GList *devices, *l; gboolean ret = TRUE; device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE); for (l = devices; l != NULL; l = l->next) { GdkDevice *device = l->data; if (device == exception) continue; if (!add_device (device_manager, device, manager, error)) { ret = FALSE; break; } } g_list_free (devices); return ret; } gboolean gsd_cursor_manager_start (GsdCursorManager *manager, GError **error) { GdkDeviceManager *device_manager; g_debug ("Starting cursor manager"); gnome_settings_profile_start (NULL); if (supports_cursor_xfixes () == FALSE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "XFixes cursor extension not available"); return FALSE; } if (supports_xinput_devices () == FALSE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "XInput support not available"); return FALSE; } device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); manager->priv->added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", G_CALLBACK (device_added_cb), manager); manager->priv->removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", G_CALLBACK (device_removed_cb), manager); manager->priv->changed_id = g_signal_connect (G_OBJECT (device_manager), "device-changed", G_CALLBACK (device_changed_cb), manager); if (!add_all_devices (manager, NULL, error)) { g_debug ("Per-device idletime monitor not available, will not hide the cursor"); gnome_settings_profile_end (NULL); return FALSE; } /* Start by hiding the cursor, and then initialising the default * root window cursor, as the window manager shouldn't do that. */ set_cursor_visibility (manager, FALSE); gnome_settings_profile_end (NULL); return TRUE; } void gsd_cursor_manager_stop (GsdCursorManager *manager) { GdkDeviceManager *device_manager; g_debug ("Stopping cursor manager"); device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); if (manager->priv->added_id > 0) { g_signal_handler_disconnect (G_OBJECT (device_manager), manager->priv->added_id); manager->priv->added_id = 0; } if (manager->priv->removed_id > 0) { g_signal_handler_disconnect (G_OBJECT (device_manager), manager->priv->removed_id); manager->priv->removed_id = 0; } if (manager->priv->changed_id > 0) { g_signal_handler_disconnect (G_OBJECT (device_manager), manager->priv->changed_id); manager->priv->changed_id = 0; } if (manager->priv->cursor_shown == FALSE) set_cursor_visibility (manager, TRUE); } static void gsd_cursor_manager_class_init (GsdCursorManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_cursor_manager_finalize; g_type_class_add_private (klass, sizeof (GsdCursorManagerPrivate)); } static void gsd_cursor_manager_init (GsdCursorManager *manager) { manager->priv = GSD_CURSOR_MANAGER_GET_PRIVATE (manager); manager->priv->cursor_shown = TRUE; manager->priv->monitors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); } static void gsd_cursor_manager_finalize (GObject *object) { GsdCursorManager *cursor_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_CURSOR_MANAGER (object)); cursor_manager = GSD_CURSOR_MANAGER (object); g_clear_pointer (&cursor_manager->priv->monitors, g_hash_table_destroy); G_OBJECT_CLASS (gsd_cursor_manager_parent_class)->finalize (object); } GsdCursorManager * gsd_cursor_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_CURSOR_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_CURSOR_MANAGER (manager_object); } unity-settings-daemon/plugins/cursor/gsd-cursor-manager.h0000664000000000000000000000442615172222611021071 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_CURSOR_MANAGER_H #define __GSD_CURSOR_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_CURSOR_MANAGER (gsd_cursor_manager_get_type ()) #define GSD_CURSOR_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_CURSOR_MANAGER, GsdCursorManager)) #define GSD_CURSOR_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_CURSOR_MANAGER, GsdCursorManagerClass)) #define GSD_IS_CURSOR_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_CURSOR_MANAGER)) #define GSD_IS_CURSOR_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_CURSOR_MANAGER)) #define GSD_CURSOR_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_CURSOR_MANAGER, GsdCursorManagerClass)) typedef struct GsdCursorManagerPrivate GsdCursorManagerPrivate; typedef struct { GObject parent; GsdCursorManagerPrivate *priv; } GsdCursorManager; typedef struct { GObjectClass parent_class; } GsdCursorManagerClass; GType gsd_cursor_manager_get_type (void); GsdCursorManager * gsd_cursor_manager_new (void); gboolean gsd_cursor_manager_start (GsdCursorManager *manager, GError **error); void gsd_cursor_manager_stop (GsdCursorManager *manager); G_END_DECLS #endif /* __GSD_CURSOR_MANAGER_H */ unity-settings-daemon/plugins/cursor/gsd-cursor-plugin.c0000664000000000000000000000202015172222611020734 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-cursor-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdCursor, gsd_cursor) unity-settings-daemon/plugins/cursor/test-cursor.c0000664000000000000000000000031215172222611017644 0ustar #define NEW gsd_cursor_manager_new #define START gsd_cursor_manager_start #define STOP gsd_cursor_manager_stop #define MANAGER GsdCursorManager #include "gsd-cursor-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/dummy/0000775000000000000000000000000015172222611015030 5ustar unity-settings-daemon/plugins/dummy/Makefile.am0000664000000000000000000000165415172222611017072 0ustar plugin_name = dummy plugin_LTLIBRARIES = \ libdummy.la libdummy_la_SOURCES = \ gsd-dummy-manager.c \ gsd-dummy-manager.h \ gsd-dummy-plugin.c libdummy_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libdummy_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libdummy_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libdummy_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(NULL) plugin_in_files = \ dummy.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ # override to _not_ install the test plugin # do not copy into your plugin install-pluginDATA: install-pluginLTLIBRARIES: unity-settings-daemon/plugins/dummy/dummy.gnome-settings-plugin.in0000664000000000000000000000027515172222611022755 0ustar [GNOME Settings Plugin] Module=dummy IAge=0 # 100 is the default load Priority Priority=100 _Name=Dummy _Description=Dummy plugin Authors=AUTHOR Copyright=Copyright © 2007 AUTHOR Website= unity-settings-daemon/plugins/dummy/gsd-dummy-manager.c0000664000000000000000000001221315172222611020511 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-profile.h" #include "gsd-dummy-manager.h" #define GSD_DUMMY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerPrivate)) struct GsdDummyManagerPrivate { gboolean padding; }; enum { PROP_0, }; static void gsd_dummy_manager_class_init (GsdDummyManagerClass *klass); static void gsd_dummy_manager_init (GsdDummyManager *dummy_manager); static void gsd_dummy_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdDummyManager, gsd_dummy_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; gboolean gsd_dummy_manager_start (GsdDummyManager *manager, GError **error) { g_debug ("Starting dummy manager"); gnome_settings_profile_start (NULL); gnome_settings_profile_end (NULL); return TRUE; } void gsd_dummy_manager_stop (GsdDummyManager *manager) { g_debug ("Stopping dummy manager"); } static void gsd_dummy_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gsd_dummy_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GObject * gsd_dummy_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdDummyManager *dummy_manager; dummy_manager = GSD_DUMMY_MANAGER (G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (dummy_manager); } static void gsd_dummy_manager_dispose (GObject *object) { G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->dispose (object); } static void gsd_dummy_manager_class_init (GsdDummyManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->get_property = gsd_dummy_manager_get_property; object_class->set_property = gsd_dummy_manager_set_property; object_class->constructor = gsd_dummy_manager_constructor; object_class->dispose = gsd_dummy_manager_dispose; object_class->finalize = gsd_dummy_manager_finalize; g_type_class_add_private (klass, sizeof (GsdDummyManagerPrivate)); } static void gsd_dummy_manager_init (GsdDummyManager *manager) { manager->priv = GSD_DUMMY_MANAGER_GET_PRIVATE (manager); } static void gsd_dummy_manager_finalize (GObject *object) { GsdDummyManager *dummy_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_DUMMY_MANAGER (object)); dummy_manager = GSD_DUMMY_MANAGER (object); g_return_if_fail (dummy_manager->priv != NULL); G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->finalize (object); } GsdDummyManager * gsd_dummy_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_DUMMY_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_DUMMY_MANAGER (manager_object); } unity-settings-daemon/plugins/dummy/gsd-dummy-manager.h0000664000000000000000000000437015172222611020523 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_DUMMY_MANAGER_H #define __GSD_DUMMY_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_DUMMY_MANAGER (gsd_dummy_manager_get_type ()) #define GSD_DUMMY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManager)) #define GSD_DUMMY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerClass)) #define GSD_IS_DUMMY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DUMMY_MANAGER)) #define GSD_IS_DUMMY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DUMMY_MANAGER)) #define GSD_DUMMY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerClass)) typedef struct GsdDummyManagerPrivate GsdDummyManagerPrivate; typedef struct { GObject parent; GsdDummyManagerPrivate *priv; } GsdDummyManager; typedef struct { GObjectClass parent_class; } GsdDummyManagerClass; GType gsd_dummy_manager_get_type (void); GsdDummyManager * gsd_dummy_manager_new (void); gboolean gsd_dummy_manager_start (GsdDummyManager *manager, GError **error); void gsd_dummy_manager_stop (GsdDummyManager *manager); G_END_DECLS #endif /* __GSD_DUMMY_MANAGER_H */ unity-settings-daemon/plugins/dummy/gsd-dummy-plugin.c0000664000000000000000000000201515172222611020374 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-dummy-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdDummy, gsd_dummy) unity-settings-daemon/plugins/housekeeping/0000775000000000000000000000000015172222611016363 5ustar unity-settings-daemon/plugins/housekeeping/Makefile.am0000664000000000000000000000503015172222611020415 0ustar plugin_name = housekeeping COMMON_FILES = \ gsd-disk-space.c \ gsd-disk-space.h \ gsd-ldsm-dialog.c \ gsd-ldsm-dialog.h \ gsd-disk-space-helper.h \ gsd-disk-space-helper.c noinst_PROGRAMS = gsd-disk-space-test gsd-empty-trash-test gsd_disk_space_test_SOURCES = \ gsd-disk-space-test.c \ $(COMMON_FILES) gsd_disk_space_test_LDADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS) gsd_disk_space_test_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(GIOUNIX_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(AM_CFLAGS) gsd_empty_trash_test_SOURCES = \ gsd-empty-trash-test.c \ $(COMMON_FILES) gsd_empty_trash_test_LDADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS) gsd_empty_trash_test_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(GIOUNIX_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(AM_CFLAGS) libexec_PROGRAMS = usd-test-housekeeping usd_test_housekeeping_SOURCES = \ test-housekeeping.c \ gsd-housekeeping-manager.c \ gsd-housekeeping-manager.h \ $(COMMON_FILES) usd_test_housekeeping_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) usd_test_housekeeping_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(MOUSE_CFLAGS) \ $(AM_CFLAGS) usd_test_housekeeping_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = libhousekeeping.la libhousekeeping_la_SOURCES = \ $(COMMON_FILES) \ gsd-housekeeping-manager.c \ gsd-housekeeping-manager.h \ gsd-housekeeping-plugin.c libhousekeeping_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libhousekeeping_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(GIOUNIX_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(AM_CFLAGS) libhousekeeping_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS) libhousekeeping_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(GIOUNIX_LIBS) \ $(LIBNOTIFY_LIBS) \ $(NULL) plugin_in_files = housekeeping.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = $(plugin_in_files) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = (plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/housekeeping/gsd-disk-space-helper.c0000664000000000000000000000667215172222611022615 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * vim: set et sw=8 ts=8: * * Copyright (c) 2008, Novell, Inc. * Copyright (c) 2012, Red Hat, Inc. * * Authors: Vincent Untz * Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gsd-disk-space-helper.h" gboolean gsd_should_ignore_unix_mount (GUnixMountEntry *mount) { const char *fs, *device; guint i; /* This is borrowed from GLib and used as a way to determine * which mounts we should ignore by default. GLib doesn't * expose this in a way that allows it to be used for this * purpose */ /* We also ignore network filesystems */ const gchar *ignore_fs[] = { "adfs", "afs", "auto", "autofs", "autofs4", "cifs", "cxfs", "devfs", "devpts", "ecryptfs", "fdescfs", "gfs", "gfs2", "kernfs", "linprocfs", "linsysfs", "lustre", "lustre_lite", "ncpfs", "nfs", "nfs4", "nfsd", "ocfs2", "proc", "procfs", "ptyfs", "rpc_pipefs", "selinuxfs", "smbfs", "sysfs", "tmpfs", "usbfs", "zfs", NULL }; const gchar *ignore_devices[] = { "none", "sunrpc", "devpts", "nfsd", "/dev/loop", "/dev/vn", NULL }; fs = g_unix_mount_get_fs_type (mount); device = g_unix_mount_get_device_path (mount); for (i = 0; ignore_fs[i] != NULL; i++) if (g_str_equal (ignore_fs[i], fs)) return TRUE; for (i = 0; ignore_devices[i] != NULL; i++) if (g_str_equal (ignore_devices[i], device)) return TRUE; return FALSE; } gboolean gsd_is_removable_mount (GUnixMountEntry *mount) { const char *mount_path; char *path; mount_path = g_unix_mount_get_mount_path (mount); if (mount_path == NULL) return FALSE; path = g_strdup_printf ("/run/media/%s", g_get_user_name ()); if (g_str_has_prefix (mount_path, path)) { g_free (path); return TRUE; } g_free (path); return FALSE; } unity-settings-daemon/plugins/housekeeping/gsd-disk-space-helper.h0000664000000000000000000000242315172222611022610 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * vim: set et sw=8 ts=8: * * Copyright (c) 2008, Novell, Inc. * Copyright (c) 2012, Red Hat, Inc. * * Authors: Vincent Untz * Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_DISK_SPACE_HELPER_H #define __GSD_DISK_SPACE_HELPER_H #include #include G_BEGIN_DECLS gboolean gsd_should_ignore_unix_mount (GUnixMountEntry *mount); gboolean gsd_is_removable_mount (GUnixMountEntry *mount); G_END_DECLS #endif /* __GSD_DISK_SPACE_HELPER_H */ unity-settings-daemon/plugins/housekeeping/gsd-disk-space-test.c0000664000000000000000000000251315172222611022303 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * vim: set et sw=8 ts=8: * * Copyright (c) 2008, Novell, Inc. * * Authors: Vincent Untz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gsd-disk-space.h" int main (int argc, char **argv) { GMainLoop *loop; gtk_init (&argc, &argv); notify_init ("gsd-disk-space-test"); loop = g_main_loop_new (NULL, FALSE); gsd_ldsm_setup (TRUE); g_main_loop_run (loop); gsd_ldsm_clean (); g_main_loop_unref (loop); return 0; } unity-settings-daemon/plugins/housekeeping/gsd-disk-space.c0000664000000000000000000011472015172222611021332 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * vim: set et sw=8 ts=8: * * Copyright (c) 2008, Novell, Inc. * * Authors: Vincent Untz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "gsd-disk-space.h" #include "gsd-ldsm-dialog.h" #include "gsd-disk-space-helper.h" #define GIGABYTE 1024 * 1024 * 1024 #define CHECK_EVERY_X_SECONDS 60 #define DISK_SPACE_ANALYZER "baobab" #define SETTINGS_HOUSEKEEPING_DIR "com.canonical.unity.settings-daemon.plugins.housekeeping" #define SETTINGS_FREE_PC_NOTIFY_KEY "free-percent-notify" #define SETTINGS_FREE_PC_NOTIFY_AGAIN_KEY "free-percent-notify-again" #define SETTINGS_FREE_SIZE_NO_NOTIFY "free-size-gb-no-notify" #define SETTINGS_MIN_NOTIFY_PERIOD "min-notify-period" #define SETTINGS_IGNORE_PATHS "ignore-paths" #define PRIVACY_SETTINGS "org.gnome.desktop.privacy" #define SETTINGS_PURGE_TRASH "remove-old-trash-files" #define SETTINGS_PURGE_TEMP_FILES "remove-old-temp-files" #define SETTINGS_PURGE_AFTER "old-files-age" typedef struct { GUnixMountEntry *mount; struct statvfs buf; time_t notify_time; } LdsmMountInfo; static GHashTable *ldsm_notified_hash = NULL; static unsigned int ldsm_timeout_id = 0; static GUnixMountMonitor *ldsm_monitor = NULL; static double free_percent_notify = 0.05; static double free_percent_notify_again = 0.01; static unsigned int free_size_gb_no_notify = 2; static unsigned int min_notify_period = 10; static GSList *ignore_paths = NULL; static GSettings *settings = NULL; static GSettings *privacy_settings = NULL; static GsdLdsmDialog *dialog = NULL; static NotifyNotification *notification = NULL; static guint64 *time_read; static gboolean purge_trash; static gboolean purge_temp_files; static guint purge_after; static guint purge_trash_id = 0; static guint purge_temp_id = 0; static gchar* ldsm_get_fs_id_for_path (const gchar *path) { GFile *file; GFileInfo *fileinfo; gchar *attr_id_fs; file = g_file_new_for_path (path); fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); if (fileinfo) { attr_id_fs = g_strdup (g_file_info_get_attribute_string (fileinfo, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); g_object_unref (fileinfo); } else { attr_id_fs = NULL; } g_object_unref (file); return attr_id_fs; } static gboolean ldsm_mount_has_trash (LdsmMountInfo *mount) { const gchar *user_data_dir; gchar *user_data_attr_id_fs; gchar *path_attr_id_fs; gboolean mount_uses_user_trash = FALSE; gchar *trash_files_dir; gboolean has_trash = FALSE; GDir *dir; const gchar *path; user_data_dir = g_get_user_data_dir (); user_data_attr_id_fs = ldsm_get_fs_id_for_path (user_data_dir); path = g_unix_mount_get_mount_path (mount->mount); path_attr_id_fs = ldsm_get_fs_id_for_path (path); if (g_strcmp0 (user_data_attr_id_fs, path_attr_id_fs) == 0) { /* The volume that is low on space is on the same volume as our home * directory. This means the trash is at $XDG_DATA_HOME/Trash, * not at the root of the volume which is full. */ mount_uses_user_trash = TRUE; } g_free (user_data_attr_id_fs); g_free (path_attr_id_fs); /* I can't think of a better way to find out if a volume has any trash. Any suggestions? */ if (mount_uses_user_trash) { trash_files_dir = g_build_filename (g_get_user_data_dir (), "Trash", "files", NULL); } else { gchar *uid; uid = g_strdup_printf ("%d", getuid ()); trash_files_dir = g_build_filename (path, ".Trash", uid, "files", NULL); if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) { gchar *trash_dir; g_free (trash_files_dir); trash_dir = g_strdup_printf (".Trash-%s", uid); trash_files_dir = g_build_filename (path, trash_dir, "files", NULL); g_free (trash_dir); if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) { g_free (trash_files_dir); g_free (uid); return has_trash; } } g_free (uid); } dir = g_dir_open (trash_files_dir, 0, NULL); if (dir) { if (g_dir_read_name (dir)) has_trash = TRUE; g_dir_close (dir); } g_free (trash_files_dir); return has_trash; } static void ldsm_analyze_path (const gchar *path) { const gchar *argv[] = { DISK_SPACE_ANALYZER, path, NULL }; g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); } static gboolean server_has_actions (void) { gboolean has; GList *caps; GList *l; caps = notify_get_server_caps (); if (caps == NULL) { fprintf (stderr, "Failed to receive server caps.\n"); return FALSE; } l = g_list_find_custom (caps, "actions", (GCompareFunc)strcmp); has = l != NULL; g_list_foreach (caps, (GFunc) g_free, NULL); g_list_free (caps); return has; } static void ignore_callback (NotifyNotification *n, const char *action) { g_assert (action != NULL); g_assert (strcmp (action, "ignore") == 0); /* Do nothing */ notify_notification_close (n, NULL); } static void examine_callback (NotifyNotification *n, const char *action, const char *path) { g_assert (action != NULL); g_assert (strcmp (action, "examine") == 0); ldsm_analyze_path (path); notify_notification_close (n, NULL); } static gboolean should_purge_file (GFile *file, GCancellable *cancellable, GDateTime *old) { GFileInfo *info; GDateTime *date; gboolean should_purge; should_purge = FALSE; info = g_file_query_info (file, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE "," G_FILE_ATTRIBUTE_UNIX_UID "," G_FILE_ATTRIBUTE_TIME_CHANGED, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, NULL); date = g_file_info_get_deletion_date (info); if (date == NULL) { guint uid; guint64 ctime; uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID); if (uid != getuid ()) { should_purge = FALSE; goto out; } ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED); date = g_date_time_new_from_unix_local ((gint64) ctime); } should_purge = g_date_time_difference (old, date) >= 0; g_date_time_unref (date); out: g_object_unref (info); return should_purge; } DeleteData * delete_data_new (GFile *file, GCancellable *cancellable, GDateTime *old, gboolean dry_run, gboolean trash, gint depth) { DeleteData *data; data = g_new (DeleteData, 1); data->ref_count = 1; data->file = g_object_ref (file); data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; data->old = g_date_time_ref (old); data->dry_run = dry_run; data->trash = trash; data->depth = depth; data->name = g_file_get_parse_name (data->file); return data; } static DeleteData * delete_data_ref (DeleteData *data) { data->ref_count += 1; return data; } void delete_data_unref (DeleteData *data) { data->ref_count -= 1; if (data->ref_count > 0) return; g_object_unref (data->file); if (data->cancellable) g_object_unref (data->cancellable); g_date_time_unref (data->old); g_free (data->name); g_free (data); } static void delete_batch (GObject *source, GAsyncResult *res, gpointer user_data) { GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source); DeleteData *data = user_data; GList *files, *f; GFile *child_file; DeleteData *child; GFileInfo *info; GError *error = NULL; files = g_file_enumerator_next_files_finish (enumerator, res, &error); g_debug ("GsdHousekeeping: purging %d children of %s", g_list_length (files), data->name); if (files) { for (f = files; f; f = f->next) { if (g_cancellable_is_cancelled (data->cancellable)) break; info = f->data; child_file = g_file_get_child (data->file, g_file_info_get_name (info)); child = delete_data_new (child_file, data->cancellable, data->old, data->dry_run, data->trash, data->depth + 1); delete_recursively_by_age (child); delete_data_unref (child); g_object_unref (child_file); } g_list_free_full (files, g_object_unref); if (!g_cancellable_is_cancelled (data->cancellable)) { g_file_enumerator_next_files_async (enumerator, 20, 0, data->cancellable, delete_batch, data); return; } } g_file_enumerator_close (enumerator, data->cancellable, NULL); g_object_unref (enumerator); if (data->depth > 0 && !g_cancellable_is_cancelled (data->cancellable)) { if ((data->trash && data->depth > 1) || should_purge_file (data->file, data->cancellable, data->old)) { g_debug ("GsdHousekeeping: purging %s\n", data->name); if (!data->dry_run) { g_file_delete (data->file, data->cancellable, NULL); } } } delete_data_unref (data); } static void delete_subdir (GObject *source, GAsyncResult *res, gpointer user_data) { GFile *file = G_FILE (source); DeleteData *data = user_data; GFileEnumerator *enumerator; GError *error = NULL; g_debug ("GsdHousekeeping: purging %s in %s\n", data->trash ? "trash" : "temporary files", data->name); enumerator = g_file_enumerate_children_finish (file, res, &error); if (error) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) g_warning ("Failed to enumerate children of %s: %s\n", data->name, error->message); } if (enumerator) { g_file_enumerator_next_files_async (enumerator, 20, 0, data->cancellable, delete_batch, delete_data_ref (data)); } else if (data->depth > 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) { if ((data->trash && data->depth > 1) || should_purge_file (data->file, data->cancellable, data->old)) { if (!data->dry_run) { g_file_delete (data->file, data->cancellable, NULL); } } } if (error) g_error_free (error); delete_data_unref (data); } static void delete_subdir_check_symlink (GObject *source, GAsyncResult *res, gpointer user_data) { GFile *file = G_FILE (source); DeleteData *data = user_data; GFileInfo *info; GFileType type; info = g_file_query_info_finish (file, res, NULL); if (!info) { delete_data_unref (data); return; } type = g_file_info_get_file_type (info); g_object_unref (info); if (type == G_FILE_TYPE_SYMBOLIC_LINK) { if (should_purge_file (data->file, data->cancellable, data->old)) { g_debug ("Purging %s leaf node", data->name); if (!data->dry_run) { g_file_delete (data->file, data->cancellable, NULL); } } } else { g_file_enumerate_children_async (data->file, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 0, data->cancellable, delete_subdir, delete_data_ref (data)); } delete_data_unref (data); } void delete_recursively_by_age (DeleteData *data) { if (data->trash && (data->depth == 1) && !should_purge_file (data->file, data->cancellable, data->old)) { /* no need to recurse into trashed directories */ return; } g_file_query_info_async (data->file, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 0, data->cancellable, delete_subdir_check_symlink, delete_data_ref (data)); } void gsd_ldsm_purge_trash (GDateTime *old) { GFile *file; DeleteData *data; file = g_file_new_for_uri ("trash:"); data = delete_data_new (file, NULL, old, FALSE, TRUE, 0); delete_recursively_by_age (data); delete_data_unref (data); g_object_unref (file); } void gsd_ldsm_purge_temp_files (GDateTime *old) { DeleteData *data; GFile *file; file = g_file_new_for_path (g_get_tmp_dir ()); data = delete_data_new (file, NULL, old, FALSE, FALSE, 0); delete_recursively_by_age (data); delete_data_unref (data); g_object_unref (file); if (g_strcmp0 (g_get_tmp_dir (), "/var/tmp") != 0) { file = g_file_new_for_path ("/var/tmp"); data = delete_data_new (file, NULL, old, FALSE, FALSE, 0); delete_recursively_by_age (data); delete_data_unref (data); g_object_unref (file); } if (g_strcmp0 (g_get_tmp_dir (), "/tmp") != 0) { file = g_file_new_for_path ("/tmp"); data = delete_data_new (file, NULL, old, FALSE, FALSE, 0); delete_recursively_by_age (data); delete_data_unref (data); g_object_unref (file); } } void gsd_ldsm_show_empty_trash (void) { GFile *file; GDateTime *old; DeleteData *data; old = g_date_time_new_now_local (); file = g_file_new_for_uri ("trash:"); data = delete_data_new (file, NULL, old, TRUE, TRUE, 0); g_object_unref (file); g_date_time_unref (old); delete_recursively_by_age (data); delete_data_unref (data); } static gboolean ldsm_purge_trash_and_temp (gpointer data) { GDateTime *now, *old; now = g_date_time_new_now_local (); old = g_date_time_add_days (now, - purge_after); if (purge_trash) { g_debug ("housekeeping: purge trash older than %u days", purge_after); gsd_ldsm_purge_trash (old); } if (purge_temp_files) { g_debug ("housekeeping: purge temp files older than %u days", purge_after); gsd_ldsm_purge_temp_files (old); } g_date_time_unref (old); g_date_time_unref (now); return G_SOURCE_CONTINUE; } static void empty_trash_callback (NotifyNotification *n, const char *action) { GDateTime *old; g_assert (action != NULL); g_assert (strcmp (action, "empty-trash") == 0); old = g_date_time_new_now_local (); gsd_ldsm_purge_trash (old); g_date_time_unref (old); notify_notification_close (n, NULL); } static void on_notification_closed (NotifyNotification *n) { g_object_unref (notification); notification = NULL; } static gboolean ldsm_notify_for_mount (LdsmMountInfo *mount, gboolean multiple_volumes, gboolean other_usable_volumes) { gchar *name, *program; gint64 free_space; gint response; gboolean has_trash; gboolean has_disk_analyzer; gboolean retval = TRUE; gchar *path; /* Don't show a notice if one is already displayed */ if (dialog != NULL || notification != NULL) return retval; name = g_unix_mount_guess_name (mount->mount); free_space = (gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail; has_trash = ldsm_mount_has_trash (mount); path = g_strdup (g_unix_mount_get_mount_path (mount->mount)); program = g_find_program_in_path (DISK_SPACE_ANALYZER); has_disk_analyzer = (program != NULL); g_free (program); if (server_has_actions ()) { char *free_space_str; char *summary; char *body; free_space_str = g_format_size (free_space); if (multiple_volumes) { summary = g_strdup_printf (_("Low Disk Space on \"%s\""), name); if (has_trash) { body = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining. You may free up some space by emptying the trash."), name, free_space_str); } else { body = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining."), name, free_space_str); } } else { summary = g_strdup (_("Low Disk Space")); if (has_trash) { body = g_strdup_printf (_("This computer has only %s disk space remaining. You may free up some space by emptying the trash."), free_space_str); } else { body = g_strdup_printf (_("This computer has only %s disk space remaining."), free_space_str); } } g_free (free_space_str); notification = notify_notification_new (summary, body, "drive-harddisk-symbolic"); g_free (summary); g_free (body); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); notify_notification_set_app_name (notification, _("Disk space")); notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE)); notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL); notify_notification_set_timeout (notification, NOTIFY_EXPIRES_DEFAULT); if (has_disk_analyzer) { notify_notification_add_action (notification, "examine", _("Examine"), (NotifyActionCallback) examine_callback, g_strdup (path), g_free); } if (has_trash) { notify_notification_add_action (notification, "empty-trash", _("Empty Trash"), (NotifyActionCallback) empty_trash_callback, NULL, NULL); } notify_notification_add_action (notification, "ignore", _("Ignore"), (NotifyActionCallback) ignore_callback, NULL, NULL); notify_notification_set_category (notification, "device"); if (!notify_notification_show (notification, NULL)) { g_warning ("failed to send disk space notification\n"); } } else { dialog = gsd_ldsm_dialog_new (other_usable_volumes, multiple_volumes, has_disk_analyzer, has_trash, free_space, name, path); g_object_ref (G_OBJECT (dialog)); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog)); dialog = NULL; switch (response) { case GTK_RESPONSE_CANCEL: retval = FALSE; break; case GSD_LDSM_DIALOG_RESPONSE_ANALYZE: retval = FALSE; ldsm_analyze_path (path); break; case GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH: retval = TRUE; gsd_ldsm_show_empty_trash (); break; case GTK_RESPONSE_NONE: case GTK_RESPONSE_DELETE_EVENT: retval = TRUE; break; default: g_assert_not_reached (); } } g_free (name); g_free (path); return retval; } static gboolean ldsm_mount_has_space (LdsmMountInfo *mount) { gdouble free_space; free_space = (double) mount->buf.f_bavail / (double) mount->buf.f_blocks; /* enough free space, nothing to do */ if (free_space > free_percent_notify) return TRUE; if (((gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail) > ((gint64) free_size_gb_no_notify * GIGABYTE)) return TRUE; /* If we got here, then this volume is low on space */ return FALSE; } static gboolean ldsm_mount_is_virtual (LdsmMountInfo *mount) { if (mount->buf.f_blocks == 0) { /* Filesystems with zero blocks are virtual */ return TRUE; } return FALSE; } static gint ldsm_ignore_path_compare (gconstpointer a, gconstpointer b) { return g_strcmp0 ((const gchar *)a, (const gchar *)b); } static gboolean ldsm_mount_is_user_ignore (const gchar *path) { if (g_slist_find_custom (ignore_paths, path, (GCompareFunc) ldsm_ignore_path_compare) != NULL) return TRUE; else return FALSE; } static void ldsm_free_mount_info (gpointer data) { LdsmMountInfo *mount = data; g_return_if_fail (mount != NULL); g_unix_mount_free (mount->mount); g_free (mount); } static void ldsm_maybe_warn_mounts (GList *mounts, gboolean multiple_volumes, gboolean other_usable_volumes) { GList *l; gboolean done = FALSE; for (l = mounts; l != NULL; l = l->next) { LdsmMountInfo *mount_info = l->data; LdsmMountInfo *previous_mount_info; gdouble free_space; gdouble previous_free_space; time_t curr_time; const gchar *path; gboolean show_notify; if (done) { /* Don't show any more dialogs if the user took action with the last one. The user action * might free up space on multiple volumes, making the next dialog redundant. */ ldsm_free_mount_info (mount_info); continue; } path = g_unix_mount_get_mount_path (mount_info->mount); previous_mount_info = g_hash_table_lookup (ldsm_notified_hash, path); if (previous_mount_info != NULL) previous_free_space = (gdouble) previous_mount_info->buf.f_bavail / (gdouble) previous_mount_info->buf.f_blocks; free_space = (gdouble) mount_info->buf.f_bavail / (gdouble) mount_info->buf.f_blocks; if (previous_mount_info == NULL) { /* We haven't notified for this mount yet */ show_notify = TRUE; mount_info->notify_time = time (NULL); g_hash_table_replace (ldsm_notified_hash, g_strdup (path), mount_info); } else if ((previous_free_space - free_space) > free_percent_notify_again) { /* We've notified for this mount before and free space has decreased sufficiently since last time to notify again */ curr_time = time (NULL); if (difftime (curr_time, previous_mount_info->notify_time) > (gdouble)(min_notify_period * 60)) { show_notify = TRUE; mount_info->notify_time = curr_time; } else { /* It's too soon to show the dialog again. However, we still replace the LdsmMountInfo * struct in the hash table, but give it the notfiy time from the previous dialog. * This will stop the notification from reappearing unnecessarily as soon as the timeout expires. */ show_notify = FALSE; mount_info->notify_time = previous_mount_info->notify_time; } g_hash_table_replace (ldsm_notified_hash, g_strdup (path), mount_info); } else { /* We've notified for this mount before, but the free space hasn't decreased sufficiently to notify again */ ldsm_free_mount_info (mount_info); show_notify = FALSE; } if (show_notify) { if (ldsm_notify_for_mount (mount_info, multiple_volumes, other_usable_volumes)) done = TRUE; } } } static gboolean ldsm_check_all_mounts (gpointer data) { GList *mounts; GList *l; GList *check_mounts = NULL; GList *full_mounts = NULL; guint number_of_mounts; guint number_of_full_mounts; gboolean multiple_volumes = FALSE; gboolean other_usable_volumes = FALSE; /* We iterate through the static mounts in /etc/fstab first, seeing if * they're mounted by checking if the GUnixMountPoint has a corresponding GUnixMountEntry. * Iterating through the static mounts means we automatically ignore dynamically mounted media. */ mounts = g_unix_mount_points_get (time_read); for (l = mounts; l != NULL; l = l->next) { GUnixMountPoint *mount_point = l->data; GUnixMountEntry *mount; LdsmMountInfo *mount_info; const gchar *path; path = g_unix_mount_point_get_mount_path (mount_point); mount = g_unix_mount_at (path, time_read); g_unix_mount_point_free (mount_point); if (mount == NULL) { /* The GUnixMountPoint is not mounted */ continue; } mount_info = g_new0 (LdsmMountInfo, 1); mount_info->mount = mount; path = g_unix_mount_get_mount_path (mount); if (g_unix_mount_is_readonly (mount)) { ldsm_free_mount_info (mount_info); continue; } if (ldsm_mount_is_user_ignore (g_unix_mount_get_mount_path (mount))) { ldsm_free_mount_info (mount_info); continue; } if (gsd_should_ignore_unix_mount (mount)) { ldsm_free_mount_info (mount_info); continue; } if (statvfs (path, &mount_info->buf) != 0) { ldsm_free_mount_info (mount_info); continue; } if (ldsm_mount_is_virtual (mount_info)) { ldsm_free_mount_info (mount_info); continue; } check_mounts = g_list_prepend (check_mounts, mount_info); } g_list_free (mounts); number_of_mounts = g_list_length (check_mounts); if (number_of_mounts > 1) multiple_volumes = TRUE; for (l = check_mounts; l != NULL; l = l->next) { LdsmMountInfo *mount_info = l->data; if (!ldsm_mount_has_space (mount_info)) { full_mounts = g_list_prepend (full_mounts, mount_info); } else { g_hash_table_remove (ldsm_notified_hash, g_unix_mount_get_mount_path (mount_info->mount)); ldsm_free_mount_info (mount_info); } } number_of_full_mounts = g_list_length (full_mounts); if (number_of_mounts > number_of_full_mounts) other_usable_volumes = TRUE; ldsm_maybe_warn_mounts (full_mounts, multiple_volumes, other_usable_volumes); g_list_free (check_mounts); g_list_free (full_mounts); return TRUE; } static gboolean ldsm_is_hash_item_not_in_mounts (gpointer key, gpointer value, gpointer user_data) { GList *l; for (l = (GList *) user_data; l != NULL; l = l->next) { GUnixMountEntry *mount = l->data; const char *path; path = g_unix_mount_get_mount_path (mount); if (strcmp (path, key) == 0) return FALSE; } return TRUE; } static void ldsm_mounts_changed (GObject *monitor, gpointer data) { GList *mounts; /* remove the saved data for mounts that got removed */ mounts = g_unix_mounts_get (time_read); g_hash_table_foreach_remove (ldsm_notified_hash, ldsm_is_hash_item_not_in_mounts, mounts); g_list_free_full (mounts, (GDestroyNotify) g_unix_mount_free); /* check the status now, for the new mounts */ ldsm_check_all_mounts (NULL); /* and reset the timeout */ if (ldsm_timeout_id) g_source_remove (ldsm_timeout_id); ldsm_timeout_id = g_timeout_add_seconds (CHECK_EVERY_X_SECONDS, ldsm_check_all_mounts, NULL); } static gboolean ldsm_is_hash_item_in_ignore_paths (gpointer key, gpointer value, gpointer user_data) { return ldsm_mount_is_user_ignore (key); } static void gsd_ldsm_get_config (void) { gchar **settings_list; free_percent_notify = g_settings_get_double (settings, SETTINGS_FREE_PC_NOTIFY_KEY); free_percent_notify_again = g_settings_get_double (settings, SETTINGS_FREE_PC_NOTIFY_AGAIN_KEY); free_size_gb_no_notify = g_settings_get_int (settings, SETTINGS_FREE_SIZE_NO_NOTIFY); min_notify_period = g_settings_get_int (settings, SETTINGS_MIN_NOTIFY_PERIOD); if (ignore_paths != NULL) { g_slist_foreach (ignore_paths, (GFunc) g_free, NULL); g_clear_pointer (&ignore_paths, g_slist_free); } settings_list = g_settings_get_strv (settings, SETTINGS_IGNORE_PATHS); if (settings_list != NULL) { guint i; for (i = 0; settings_list[i] != NULL; i++) ignore_paths = g_slist_prepend (ignore_paths, g_strdup (settings_list[i])); /* Make sure we dont leave stale entries in ldsm_notified_hash */ g_hash_table_foreach_remove (ldsm_notified_hash, ldsm_is_hash_item_in_ignore_paths, NULL); g_strfreev (settings_list); } purge_trash = g_settings_get_boolean (privacy_settings, SETTINGS_PURGE_TRASH); purge_temp_files = g_settings_get_boolean (privacy_settings, SETTINGS_PURGE_TEMP_FILES); purge_after = g_settings_get_uint (privacy_settings, SETTINGS_PURGE_AFTER); } static void gsd_ldsm_update_config (GSettings *settings, const gchar *key, gpointer user_data) { gsd_ldsm_get_config (); } void gsd_ldsm_setup (gboolean check_now) { if (ldsm_notified_hash || ldsm_timeout_id || ldsm_monitor) { g_warning ("Low disk space monitor already initialized."); return; } ldsm_notified_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, ldsm_free_mount_info); settings = g_settings_new (SETTINGS_HOUSEKEEPING_DIR); privacy_settings = g_settings_new (PRIVACY_SETTINGS); gsd_ldsm_get_config (); g_signal_connect (G_OBJECT (settings), "changed", G_CALLBACK (gsd_ldsm_update_config), NULL); ldsm_monitor = g_unix_mount_monitor_new (); g_unix_mount_monitor_set_rate_limit (ldsm_monitor, 1000); g_signal_connect (ldsm_monitor, "mounts-changed", G_CALLBACK (ldsm_mounts_changed), NULL); if (check_now) ldsm_check_all_mounts (NULL); ldsm_timeout_id = g_timeout_add_seconds (CHECK_EVERY_X_SECONDS, ldsm_check_all_mounts, NULL); purge_trash_id = g_timeout_add_seconds (3600, ldsm_purge_trash_and_temp, NULL); } void gsd_ldsm_clean (void) { if (purge_trash_id) g_source_remove (purge_trash_id); purge_trash_id = 0; if (purge_temp_id) g_source_remove (purge_temp_id); purge_temp_id = 0; if (ldsm_timeout_id) g_source_remove (ldsm_timeout_id); ldsm_timeout_id = 0; if (ldsm_notified_hash) g_hash_table_destroy (ldsm_notified_hash); ldsm_notified_hash = NULL; if (ldsm_monitor) g_object_unref (ldsm_monitor); ldsm_monitor = NULL; if (settings != NULL) { g_object_unref (settings); } g_clear_object (&privacy_settings); if (dialog) { gtk_widget_destroy (GTK_WIDGET (dialog)); dialog = NULL; } if (notification != NULL) { notify_notification_close (notification, NULL); notification = NULL; } if (ignore_paths) { g_slist_foreach (ignore_paths, (GFunc) g_free, NULL); g_slist_free (ignore_paths); } } unity-settings-daemon/plugins/housekeeping/gsd-disk-space.h0000664000000000000000000000364615172222611021343 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * vim: set et sw=8 ts=8: * * Copyright (c) 2008, Novell, Inc. * * Authors: Vincent Untz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_DISK_SPACE_H #define __GSD_DISK_SPACE_H #include G_BEGIN_DECLS typedef struct { gint ref_count; GFile *file; GCancellable *cancellable; GDateTime *old; gboolean dry_run; gboolean trash; gchar *name; gint depth; } DeleteData; void delete_data_unref (DeleteData *data); DeleteData *delete_data_new (GFile *file, GCancellable *cancellable, GDateTime *old, gboolean dry_run, gboolean trash, gint depth); void delete_recursively_by_age (DeleteData *data); void gsd_ldsm_setup (gboolean check_now); void gsd_ldsm_clean (void); /* for the test */ void gsd_ldsm_show_empty_trash (void); void gsd_ldsm_purge_trash (GDateTime *old); void gsd_ldsm_purge_temp_files (GDateTime *old); G_END_DECLS #endif /* __GSD_DISK_SPACE_H */ unity-settings-daemon/plugins/housekeeping/gsd-empty-trash-test.c0000664000000000000000000000236015172222611022535 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * vim: set et sw=8 ts=8: * * Copyright (c) 2011, Red Hat, Inc. * * Authors: Cosimo Cecchi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include "gsd-disk-space.h" int main (int argc, char **argv) { GMainLoop *loop; gtk_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); gsd_ldsm_show_empty_trash (); g_main_loop_run (loop); g_main_loop_unref (loop); return 0; } unity-settings-daemon/plugins/housekeeping/gsd-housekeeping-manager.c0000664000000000000000000003736515172222611023416 0ustar /* * Copyright (C) 2008 Michael J. Chudobiak * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include "gnome-settings-profile.h" #include "gsd-housekeeping-manager.h" #include "gsd-disk-space.h" /* General */ #define INTERVAL_ONCE_A_DAY 24*60*60 #define INTERVAL_TWO_MINUTES 2*60 /* Thumbnail cleaner */ #define THUMB_PREFIX "org.gnome.desktop.thumbnail-cache" #define THUMB_AGE_KEY "maximum-age" #define THUMB_SIZE_KEY "maximum-size" #define GSD_HOUSEKEEPING_DBUS_PATH "/org/gnome/SettingsDaemon/Housekeeping" static const gchar introspection_xml[] = "" " " " " " " " " ""; struct GsdHousekeepingManagerPrivate { GSettings *settings; guint long_term_cb; guint short_term_cb; GDBusNodeInfo *introspection_data; GDBusConnection *connection; GCancellable *bus_cancellable; }; #define GSD_HOUSEKEEPING_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerPrivate)) static void gsd_housekeeping_manager_class_init (GsdHousekeepingManagerClass *klass); static void gsd_housekeeping_manager_init (GsdHousekeepingManager *housekeeping_manager); G_DEFINE_TYPE (GsdHousekeepingManager, gsd_housekeeping_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; typedef struct { glong now; glong max_age; goffset total_size; goffset max_size; } PurgeData; typedef struct { time_t mtime; char *path; glong size; } ThumbData; static void thumb_data_free (gpointer data) { ThumbData *info = data; if (info) { g_free (info->path); g_free (info); } } static GList * read_dir_for_purge (const char *path, GList *files) { GFile *read_path; GFileEnumerator *enum_dir; read_path = g_file_new_for_path (path); enum_dir = g_file_enumerate_children (read_path, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (enum_dir != NULL) { GFileInfo *info; while ((info = g_file_enumerator_next_file (enum_dir, NULL, NULL)) != NULL) { const char *name; name = g_file_info_get_name (info); if (strlen (name) == 36 && strcmp (name + 32, ".png") == 0) { ThumbData *td; GFile *entry; char *entry_path; GTimeVal mod_time; entry = g_file_get_child (read_path, name); entry_path = g_file_get_path (entry); g_object_unref (entry); g_file_info_get_modification_time (info, &mod_time); td = g_new0 (ThumbData, 1); td->path = entry_path; td->mtime = mod_time.tv_sec; td->size = g_file_info_get_size (info); files = g_list_prepend (files, td); } g_object_unref (info); } g_object_unref (enum_dir); } g_object_unref (read_path); return files; } static void purge_old_thumbnails (ThumbData *info, PurgeData *purge_data) { if ((purge_data->now - info->mtime) > purge_data->max_age) { g_unlink (info->path); info->size = 0; } else { purge_data->total_size += info->size; } } static int sort_file_mtime (ThumbData *file1, ThumbData *file2) { return file1->mtime - file2->mtime; } static char ** get_thumbnail_dirs (void) { GPtrArray *array; char *path; array = g_ptr_array_new (); /* check new XDG cache */ path = g_build_filename (g_get_user_cache_dir (), "thumbnails", "normal", NULL); g_ptr_array_add (array, path); path = g_build_filename (g_get_user_cache_dir (), "thumbnails", "large", NULL); g_ptr_array_add (array, path); path = g_build_filename (g_get_user_cache_dir (), "thumbnails", "fail", "gnome-thumbnail-factory", NULL); g_ptr_array_add (array, path); /* cleanup obsolete locations too */ path = g_build_filename (g_get_home_dir (), ".thumbnails", "normal", NULL); g_ptr_array_add (array, path); path = g_build_filename (g_get_home_dir (), ".thumbnails", "large", NULL); g_ptr_array_add (array, path); path = g_build_filename (g_get_home_dir (), ".thumbnails", "fail", "gnome-thumbnail-factory", NULL); g_ptr_array_add (array, path); g_ptr_array_add (array, NULL); return (char **) g_ptr_array_free (array, FALSE); } static void purge_thumbnail_cache (GsdHousekeepingManager *manager) { char **paths; GList *files; PurgeData purge_data; GTimeVal current_time; guint i; g_debug ("housekeeping: checking thumbnail cache size and freshness"); purge_data.max_age = g_settings_get_int (manager->priv->settings, THUMB_AGE_KEY) * 24 * 60 * 60; purge_data.max_size = g_settings_get_int (manager->priv->settings, THUMB_SIZE_KEY) * 1024 * 1024; /* if both are set to -1, we don't need to read anything */ if ((purge_data.max_age < 0) && (purge_data.max_size < 0)) return; paths = get_thumbnail_dirs (); files = NULL; for (i = 0; paths[i] != NULL; i++) files = read_dir_for_purge (paths[i], files); g_strfreev (paths); g_get_current_time (¤t_time); purge_data.now = current_time.tv_sec; purge_data.total_size = 0; if (purge_data.max_age >= 0) g_list_foreach (files, (GFunc) purge_old_thumbnails, &purge_data); if ((purge_data.total_size > purge_data.max_size) && (purge_data.max_size >= 0)) { GList *scan; files = g_list_sort (files, (GCompareFunc) sort_file_mtime); for (scan = files; scan && (purge_data.total_size > purge_data.max_size); scan = scan->next) { ThumbData *info = scan->data; g_unlink (info->path); purge_data.total_size -= info->size; } } g_list_foreach (files, (GFunc) thumb_data_free, NULL); g_list_free (files); } static gboolean do_cleanup (GsdHousekeepingManager *manager) { purge_thumbnail_cache (manager); return TRUE; } static gboolean do_cleanup_once (GsdHousekeepingManager *manager) { do_cleanup (manager); manager->priv->short_term_cb = 0; return FALSE; } static void do_cleanup_soon (GsdHousekeepingManager *manager) { if (manager->priv->short_term_cb == 0) { g_debug ("housekeeping: will tidy up in 2 minutes"); manager->priv->short_term_cb = g_timeout_add_seconds (INTERVAL_TWO_MINUTES, (GSourceFunc) do_cleanup_once, manager); } } static void settings_changed_callback (GSettings *settings, const char *key, GsdHousekeepingManager *manager) { do_cleanup_soon (manager); } static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GDateTime *now; now = g_date_time_new_now_local (); if (g_strcmp0 (method_name, "EmptyTrash") == 0) { gsd_ldsm_purge_trash (now); g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_strcmp0 (method_name, "RemoveTempFiles") == 0) { gsd_ldsm_purge_temp_files (now); g_dbus_method_invocation_return_value (invocation, NULL); } g_date_time_unref (now); } static const GDBusInterfaceVTable interface_vtable = { handle_method_call, NULL, /* Get Property */ NULL, /* Set Property */ }; static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdHousekeepingManager *manager) { GDBusConnection *connection; GError *error = NULL; GDBusInterfaceInfo **infos; int i; if (manager->priv->bus_cancellable == NULL || g_cancellable_is_cancelled (manager->priv->bus_cancellable)) { g_warning ("Operation has been cancelled, so not retrieving session bus"); return; } connection = g_bus_get_finish (res, &error); if (connection == NULL) { g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; infos = manager->priv->introspection_data->interfaces; for (i = 0; infos[i] != NULL; i++) { g_dbus_connection_register_object (connection, GSD_HOUSEKEEPING_DBUS_PATH, infos[i], &interface_vtable, manager, NULL, NULL); } } static void register_manager_dbus (GsdHousekeepingManager *manager) { manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (manager->priv->introspection_data != NULL); manager->priv->bus_cancellable = g_cancellable_new (); g_bus_get (G_BUS_TYPE_SESSION, manager->priv->bus_cancellable, (GAsyncReadyCallback) on_bus_gotten, manager); } gboolean gsd_housekeeping_manager_start (GsdHousekeepingManager *manager, GError **error) { gchar *dir; g_debug ("Starting housekeeping manager"); gnome_settings_profile_start (NULL); /* Create ~/.local/ as early as possible */ g_mkdir_with_parents(g_get_user_data_dir (), 0700); /* Create ~/.local/share/applications/, see * https://bugzilla.gnome.org/show_bug.cgi?id=703048 */ dir = g_build_filename (g_get_user_data_dir (), "applications", NULL); g_mkdir (dir, 0700); g_free (dir); gsd_ldsm_setup (FALSE); manager->priv->settings = g_settings_new (THUMB_PREFIX); g_signal_connect (G_OBJECT (manager->priv->settings), "changed", G_CALLBACK (settings_changed_callback), manager); /* Clean once, a few minutes after start-up */ do_cleanup_soon (manager); /* Clean periodically, on a daily basis. */ manager->priv->long_term_cb = g_timeout_add_seconds (INTERVAL_ONCE_A_DAY, (GSourceFunc) do_cleanup, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_housekeeping_manager_stop (GsdHousekeepingManager *manager) { GsdHousekeepingManagerPrivate *p = manager->priv; g_debug ("Stopping housekeeping manager"); if (manager->priv->bus_cancellable != NULL) { g_cancellable_cancel (manager->priv->bus_cancellable); g_object_unref (manager->priv->bus_cancellable); manager->priv->bus_cancellable = NULL; } if (manager->priv->introspection_data) { g_dbus_node_info_unref (manager->priv->introspection_data); manager->priv->introspection_data = NULL; } if (manager->priv->connection != NULL) { g_object_unref (manager->priv->connection); manager->priv->connection = NULL; } if (p->short_term_cb) { g_source_remove (p->short_term_cb); p->short_term_cb = 0; } if (p->long_term_cb) { g_source_remove (p->long_term_cb); p->long_term_cb = 0; /* Do a clean-up on shutdown if and only if the size or age limits have been set to paranoid levels (zero) */ if ((g_settings_get_int (p->settings, THUMB_AGE_KEY) == 0) || (g_settings_get_int (p->settings, THUMB_SIZE_KEY) == 0)) { do_cleanup (manager); } g_object_unref (p->settings); p->settings = NULL; } gsd_ldsm_clean (); } static void gsd_housekeeping_manager_class_init (GsdHousekeepingManagerClass *klass) { g_type_class_add_private (klass, sizeof (GsdHousekeepingManagerPrivate)); } static void gsd_housekeeping_manager_init (GsdHousekeepingManager *manager) { manager->priv = GSD_HOUSEKEEPING_MANAGER_GET_PRIVATE (manager); } GsdHousekeepingManager * gsd_housekeeping_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_HOUSEKEEPING_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); register_manager_dbus (manager_object); } return GSD_HOUSEKEEPING_MANAGER (manager_object); } unity-settings-daemon/plugins/housekeeping/gsd-housekeeping-manager.h0000664000000000000000000000470515172222611023413 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Michael J. Chudobiak * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_HOUSEKEEPING_MANAGER_H #define __GSD_HOUSEKEEPING_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_HOUSEKEEPING_MANAGER (gsd_housekeeping_manager_get_type ()) #define GSD_HOUSEKEEPING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManager)) #define GSD_HOUSEKEEPING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerClass)) #define GSD_IS_HOUSEKEEPING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_HOUSEKEEPING_MANAGER)) #define GSD_IS_HOUSEKEEPING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_HOUSEKEEPING_MANAGER)) #define GSD_HOUSEKEEPING_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerClass)) typedef struct GsdHousekeepingManagerPrivate GsdHousekeepingManagerPrivate; typedef struct { GObject parent; GsdHousekeepingManagerPrivate *priv; } GsdHousekeepingManager; typedef struct { GObjectClass parent_class; } GsdHousekeepingManagerClass; GType gsd_housekeeping_manager_get_type (void); GsdHousekeepingManager * gsd_housekeeping_manager_new (void); gboolean gsd_housekeeping_manager_start (GsdHousekeepingManager *manager, GError **error); void gsd_housekeeping_manager_stop (GsdHousekeepingManager *manager); G_END_DECLS #endif /* __GSD_HOUSEKEEPING_MANAGER_H */ unity-settings-daemon/plugins/housekeeping/gsd-housekeeping-plugin.c0000664000000000000000000000205115172222611023262 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Michael J. Chudobiak * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-housekeeping-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdHousekeeping, gsd_housekeeping) unity-settings-daemon/plugins/housekeeping/gsd-ldsm-dialog.c0000664000000000000000000005053515172222611021506 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * gsd-ldsm-dialog.c * Copyright (C) Chris Coulson 2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include "gsd-ldsm-dialog.h" #define SETTINGS_HOUSEKEEPING_DIR "com.canonical.unity.settings-daemon.plugins.housekeeping" enum { PROP_0, PROP_OTHER_USABLE_PARTITIONS, PROP_OTHER_PARTITIONS, PROP_HAS_TRASH, PROP_SPACE_REMAINING, PROP_PARTITION_NAME, PROP_MOUNT_PATH }; struct GsdLdsmDialogPrivate { GtkWidget *primary_label; GtkWidget *secondary_label; GtkWidget *ignore_check_button; gboolean other_usable_partitions; gboolean other_partitions; gboolean has_trash; gint64 space_remaining; gchar *partition_name; gchar *mount_path; }; #define GSD_LDSM_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogPrivate)) static void gsd_ldsm_dialog_class_init (GsdLdsmDialogClass *klass); static void gsd_ldsm_dialog_init (GsdLdsmDialog *dialog); G_DEFINE_TYPE (GsdLdsmDialog, gsd_ldsm_dialog, GTK_TYPE_DIALOG); static const gchar* gsd_ldsm_dialog_get_checkbutton_text (GsdLdsmDialog *dialog) { g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL); if (dialog->priv->other_partitions) return _("Don't show any warnings again for this file system"); else return _("Don't show any warnings again"); } static gchar* gsd_ldsm_dialog_get_primary_text (GsdLdsmDialog *dialog) { gchar *primary_text, *free_space; g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL); free_space = g_format_size (dialog->priv->space_remaining); if (dialog->priv->other_partitions) { primary_text = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining."), dialog->priv->partition_name, free_space); } else { primary_text = g_strdup_printf (_("This computer has only %s disk space remaining."), free_space); } g_free (free_space); return primary_text; } static const gchar* gsd_ldsm_dialog_get_secondary_text (GsdLdsmDialog *dialog) { g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL); if (dialog->priv->other_usable_partitions) { if (dialog->priv->has_trash) { return _("You can free up disk space by emptying the Trash, removing " \ "unused programs or files, or moving files to another disk or partition."); } else { return _("You can free up disk space by removing unused programs or files, " \ "or by moving files to another disk or partition."); } } else { if (dialog->priv->has_trash) { return _("You can free up disk space by emptying the Trash, removing unused " \ "programs or files, or moving files to an external disk."); } else { return _("You can free up disk space by removing unused programs or files, " \ "or by moving files to an external disk."); } } } static gint ignore_path_compare (gconstpointer a, gconstpointer b) { return g_strcmp0 ((const gchar *)a, (const gchar *)b); } static gboolean update_ignore_paths (GSList **ignore_paths, const gchar *mount_path, gboolean ignore) { GSList *found; gchar *path_to_remove; found = g_slist_find_custom (*ignore_paths, mount_path, (GCompareFunc) ignore_path_compare); if (ignore && (found == NULL)) { *ignore_paths = g_slist_prepend (*ignore_paths, g_strdup (mount_path)); return TRUE; } if (!ignore && (found != NULL)) { path_to_remove = found->data; *ignore_paths = g_slist_remove (*ignore_paths, path_to_remove); g_free (path_to_remove); return TRUE; } return FALSE; } static void ignore_check_button_toggled_cb (GtkToggleButton *button, gpointer user_data) { GsdLdsmDialog *dialog = (GsdLdsmDialog *)user_data; GSettings *settings; gchar **settings_list; gboolean ignore, updated; gint i; GSList *ignore_paths = NULL; settings = g_settings_new (SETTINGS_HOUSEKEEPING_DIR); settings_list = g_settings_get_strv (settings, "ignore-paths"); for (i = 0; i < G_N_ELEMENTS (settings_list); i++) { if (settings_list[i] != NULL) ignore_paths = g_slist_append (ignore_paths, g_strdup (settings_list[i])); } ignore = gtk_toggle_button_get_active (button); updated = update_ignore_paths (&ignore_paths, dialog->priv->mount_path, ignore); g_strfreev (settings_list); if (updated) { GSList *l; GPtrArray *array = g_ptr_array_new (); for (l = ignore_paths; l != NULL; l = l->next) g_ptr_array_add (array, l->data); g_ptr_array_add (array, NULL); if (!g_settings_set_strv (settings, "ignore-paths", (const gchar **) array->pdata)) { g_warning ("Cannot change ignore preference - failed to commit changes"); } g_ptr_array_free (array, FALSE); } g_slist_foreach (ignore_paths, (GFunc) g_free, NULL); g_slist_free (ignore_paths); g_object_unref (settings); } static void gsd_ldsm_dialog_init (GsdLdsmDialog *dialog) { GtkWidget *main_vbox, *text_vbox, *hbox; GtkWidget *image; dialog->priv = GSD_LDSM_DIALOG_GET_PRIVATE (dialog); main_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); /* Set up all the window stuff here */ gtk_window_set_title (GTK_WINDOW (dialog), _("Low Disk Space")); gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_WARNING); gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE); gtk_window_set_focus_on_map (GTK_WINDOW (dialog), FALSE); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); /* Create the image */ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); /* Create the labels */ dialog->priv->primary_label = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (dialog->priv->primary_label), TRUE); gtk_label_set_single_line_mode (GTK_LABEL (dialog->priv->primary_label), FALSE); gtk_misc_set_alignment (GTK_MISC (dialog->priv->primary_label), 0.0, 0.0); gtk_label_set_max_width_chars (GTK_LABEL (dialog->priv->primary_label), 72); dialog->priv->secondary_label = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (dialog->priv->secondary_label), TRUE); gtk_label_set_single_line_mode (GTK_LABEL (dialog->priv->secondary_label), FALSE); gtk_misc_set_alignment (GTK_MISC (dialog->priv->secondary_label), 0.0, 0.0); gtk_label_set_max_width_chars (GTK_LABEL (dialog->priv->secondary_label), 72); /* Create the check button to ignore future warnings */ dialog->priv->ignore_check_button = gtk_check_button_new (); /* The button should be inactive if the dialog was just called. * I suppose it could be possible for the user to manually edit the GSettings key between * the mount being checked and the dialog appearing, but I don't think it matters * too much */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->ignore_check_button), FALSE); g_signal_connect (dialog->priv->ignore_check_button, "toggled", G_CALLBACK (ignore_check_button_toggled_cb), dialog); /* Now set up the dialog's GtkBox's' */ gtk_box_set_spacing (GTK_BOX (main_vbox), 14); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); text_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->primary_label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->secondary_label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->ignore_check_button, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), text_vbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); /* Set up the action area */ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), 6); gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), 5); gtk_widget_show_all (hbox); } static void gsd_ldsm_dialog_finalize (GObject *object) { GsdLdsmDialog *self; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_LDSM_DIALOG (object)); self = GSD_LDSM_DIALOG (object); if (self->priv->partition_name) g_free (self->priv->partition_name); if (self->priv->mount_path) g_free (self->priv->mount_path); G_OBJECT_CLASS (gsd_ldsm_dialog_parent_class)->finalize (object); } static void gsd_ldsm_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GsdLdsmDialog *self; g_return_if_fail (GSD_IS_LDSM_DIALOG (object)); self = GSD_LDSM_DIALOG (object); switch (prop_id) { case PROP_OTHER_USABLE_PARTITIONS: self->priv->other_usable_partitions = g_value_get_boolean (value); break; case PROP_OTHER_PARTITIONS: self->priv->other_partitions = g_value_get_boolean (value); break; case PROP_HAS_TRASH: self->priv->has_trash = g_value_get_boolean (value); break; case PROP_SPACE_REMAINING: self->priv->space_remaining = g_value_get_int64 (value); break; case PROP_PARTITION_NAME: self->priv->partition_name = g_value_dup_string (value); break; case PROP_MOUNT_PATH: self->priv->mount_path = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gsd_ldsm_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GsdLdsmDialog *self; g_return_if_fail (GSD_IS_LDSM_DIALOG (object)); self = GSD_LDSM_DIALOG (object); switch (prop_id) { case PROP_OTHER_USABLE_PARTITIONS: g_value_set_boolean (value, self->priv->other_usable_partitions); break; case PROP_OTHER_PARTITIONS: g_value_set_boolean (value, self->priv->other_partitions); break; case PROP_HAS_TRASH: g_value_set_boolean (value, self->priv->has_trash); break; case PROP_SPACE_REMAINING: g_value_set_int64 (value, self->priv->space_remaining); break; case PROP_PARTITION_NAME: g_value_set_string (value, self->priv->partition_name); break; case PROP_MOUNT_PATH: g_value_set_string (value, self->priv->mount_path); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gsd_ldsm_dialog_class_init (GsdLdsmDialogClass *klass) { GObjectClass* object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_ldsm_dialog_finalize; object_class->set_property = gsd_ldsm_dialog_set_property; object_class->get_property = gsd_ldsm_dialog_get_property; g_object_class_install_property (object_class, PROP_OTHER_USABLE_PARTITIONS, g_param_spec_boolean ("other-usable-partitions", "other-usable-partitions", "Set to TRUE if there are other usable partitions on the system", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_OTHER_PARTITIONS, g_param_spec_boolean ("other-partitions", "other-partitions", "Set to TRUE if there are other partitions on the system", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_HAS_TRASH, g_param_spec_boolean ("has-trash", "has-trash", "Set to TRUE if the partition has files in it's trash folder that can be deleted", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_SPACE_REMAINING, g_param_spec_int64 ("space-remaining", "space-remaining", "Specify how much space is remaining in bytes", G_MININT64, G_MAXINT64, 0, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_PARTITION_NAME, g_param_spec_string ("partition-name", "partition-name", "Specify the name of the partition", "Unknown", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_MOUNT_PATH, g_param_spec_string ("mount-path", "mount-path", "Specify the mount path for the partition", "Unknown", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_type_class_add_private (klass, sizeof (GsdLdsmDialogPrivate)); } GsdLdsmDialog* gsd_ldsm_dialog_new (gboolean other_usable_partitions, gboolean other_partitions, gboolean display_baobab, gboolean display_empty_trash, gint64 space_remaining, const gchar *partition_name, const gchar *mount_path) { GsdLdsmDialog *dialog; GtkWidget *button_empty_trash, *button_ignore, *button_analyze; GtkWidget *empty_trash_image, *analyze_image, *ignore_image; gchar *primary_text, *primary_text_markup; const gchar *secondary_text, *checkbutton_text; dialog = GSD_LDSM_DIALOG (g_object_new (GSD_TYPE_LDSM_DIALOG, "other-usable-partitions", other_usable_partitions, "other-partitions", other_partitions, "has-trash", display_empty_trash, "space-remaining", space_remaining, "partition-name", partition_name, "mount-path", mount_path, NULL)); /* Add some buttons */ if (dialog->priv->has_trash) { button_empty_trash = gtk_dialog_add_button (GTK_DIALOG (dialog), _("Empty Trash"), GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH); empty_trash_image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button_empty_trash), empty_trash_image); } if (display_baobab) { button_analyze = gtk_dialog_add_button (GTK_DIALOG (dialog), _("Examine…"), GSD_LDSM_DIALOG_RESPONSE_ANALYZE); analyze_image = gtk_image_new_from_icon_name ("baobab", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button_analyze), analyze_image); } button_ignore = gtk_dialog_add_button (GTK_DIALOG (dialog), _("Ignore"), GTK_RESPONSE_CANCEL); ignore_image = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button_ignore), ignore_image); gtk_widget_grab_default (button_ignore); /* Set the label text */ primary_text = gsd_ldsm_dialog_get_primary_text (dialog); primary_text_markup = g_markup_printf_escaped ("%s", primary_text); gtk_label_set_markup (GTK_LABEL (dialog->priv->primary_label), primary_text_markup); secondary_text = gsd_ldsm_dialog_get_secondary_text (dialog); gtk_label_set_text (GTK_LABEL (dialog->priv->secondary_label), secondary_text); checkbutton_text = gsd_ldsm_dialog_get_checkbutton_text (dialog); gtk_button_set_label (GTK_BUTTON (dialog->priv->ignore_check_button), checkbutton_text); g_free (primary_text); g_free (primary_text_markup); return dialog; } unity-settings-daemon/plugins/housekeeping/gsd-ldsm-dialog.h0000664000000000000000000000507715172222611021514 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * gsd-ldsm-dialog.c * Copyright (C) Chris Coulson 2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GSD_LDSM_DIALOG_H_ #define _GSD_LDSM_DIALOG_H_ #include #include G_BEGIN_DECLS #define GSD_TYPE_LDSM_DIALOG (gsd_ldsm_dialog_get_type ()) #define GSD_LDSM_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialog)) #define GSD_LDSM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogClass)) #define GSD_IS_LDSM_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_LDSM_DIALOG)) #define GSD_IS_LDSM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_LDSM_DIALOG)) #define GSD_LDSM_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogClass)) enum { GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH = -20, GSD_LDSM_DIALOG_RESPONSE_ANALYZE = -21 }; typedef struct GsdLdsmDialogPrivate GsdLdsmDialogPrivate; typedef struct _GsdLdsmDialogClass GsdLdsmDialogClass; typedef struct _GsdLdsmDialog GsdLdsmDialog; struct _GsdLdsmDialogClass { GtkDialogClass parent_class; }; struct _GsdLdsmDialog { GtkDialog parent_instance; GsdLdsmDialogPrivate *priv; }; GType gsd_ldsm_dialog_get_type (void) G_GNUC_CONST; GsdLdsmDialog * gsd_ldsm_dialog_new (gboolean other_usable_partitions, gboolean other_partitions, gboolean display_baobab, gboolean display_empty_trash, gint64 space_remaining, const gchar *partition_name, const gchar *mount_path); G_END_DECLS #endif /* _GSD_LDSM_DIALOG_H_ */ unity-settings-daemon/plugins/housekeeping/housekeeping.gnome-settings-plugin.in0000664000000000000000000000042515172222611025640 0ustar [GNOME Settings Plugin] Module=housekeeping IAge=0 Priority=1 _Name=Housekeeping _Description=Automatically prunes thumbnail caches and other transient files, and warns about low disk space Authors=Michael J. Chudobiak Copyright=Copyright © 2008 Michael J. Chudobiak Website= unity-settings-daemon/plugins/housekeeping/test-housekeeping.c0000664000000000000000000000035015172222611022170 0ustar #define NEW gsd_housekeeping_manager_new #define START gsd_housekeeping_manager_start #define STOP gsd_housekeeping_manager_stop #define MANAGER GsdHousekeepingManager #include "gsd-housekeeping-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/keyboard/0000775000000000000000000000000015172222611015475 5ustar unity-settings-daemon/plugins/keyboard/.indent.pro0000664000000000000000000000003015172222611017547 0ustar -kr -i8 -pcs -lps -psl unity-settings-daemon/plugins/keyboard/Makefile.am0000664000000000000000000000513115172222611017531 0ustar NULL = plugin_name = keyboard plugin_LTLIBRARIES = \ libkeyboard.la \ $(NULL) themedir = $(pkgdatadir)/icons/hicolor size = 64x64 context = devices iconsdir = $(themedir)/$(size)/$(context) icons_DATA = \ kbd-capslock-off.png kbd-numlock-off.png kbd-scrolllock-off.png \ kbd-capslock-on.png kbd-numlock-on.png kbd-scrolllock-on.png if HAVE_FCITX BUILT_SOURCES = input-method-engines.c endif input-method-engines.c: $(srcdir)/input-method-engines.gperf $(AM_V_GEN) gperf --output-file=input-method-engines.c $< libkeyboard_la_SOURCES = \ gsd-keyboard-plugin.c \ gsd-keyboard-manager.h \ gsd-keyboard-manager.c \ gsd-xkb-utils.h \ gsd-xkb-utils.c \ $(NULL) libkeyboard_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/data \ -I$(top_srcdir)/plugins/common \ -DDATADIR=\""$(pkgdatadir)"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DXKB_BASE=\""$(XKB_BASE)"\" \ $(AM_CPPFLAGS) libkeyboard_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(KEYBOARD_CFLAGS) \ $(AM_CFLAGS) libkeyboard_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) \ $(NULL) libkeyboard_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(XF86MISC_LIBS) \ $(KEYBOARD_LIBS) \ $(NULL) libexec_PROGRAMS = usd-test-keyboard usd_test_keyboard_SOURCES = \ test-keyboard.c \ gsd-keyboard-manager.h \ gsd-keyboard-manager.c \ gsd-xkb-utils.h \ gsd-xkb-utils.c \ $(NULL) usd_test_keyboard_CFLAGS = $(libkeyboard_la_CFLAGS) usd_test_keyboard_CPPFLAGS = $(libkeyboard_la_CPPFLAGS) usd_test_keyboard_LDADD = $(libkeyboard_la_LIBADD) $(top_builddir)/gnome-settings-daemon/libgsd.la plugin_in_files = \ keyboard.gnome-settings-plugin.in \ $(NULL) plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) if HAVE_IBUS noinst_PROGRAMS = test-keyboard-ibus-utils test_keyboard_ibus_utils_SOURCES = test-keyboard-ibus-utils.c test_keyboard_ibus_utils_CFLAGS = $(libkeyboard_la_CFLAGS) test_keyboard_ibus_utils_CPPFLAGS = $(libkeyboard_la_CPPFLAGS) test_keyboard_ibus_utils_LDADD = $(libkeyboard_la_LIBADD) $(top_builddir)/gnome-settings-daemon/libgsd.la check-local: test-keyboard-ibus-utils $(builddir)/test-keyboard-ibus-utils > /dev/null endif EXTRA_DIST = \ $(icons_DATA) \ $(plugin_in_files) \ $(ui_DATA) \ $(NULL) CLEANFILES = \ $(plugin_DATA) \ $(NULL) DISTCLEANFILES = \ $(plugin_DATA) \ $(NULL) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/keyboard/gsd-keyboard-manager.c0000664000000000000000000026232115172222611021632 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright © 2001 Ximian, Inc. * Copyright (C) 2007 William Jon McCann * Written by Sergey V. Oudaltsov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define GNOME_DESKTOP_USE_UNSTABLE_API #include #include #ifdef HAVE_IBUS #include #endif #ifdef HAVE_FCITX #include #include #endif #include #include "gnome-settings-bus.h" #include "gnome-settings-profile.h" #include "gsd-keyboard-manager.h" #include "gsd-input-helper.h" #include "gsd-enums.h" #include "gsd-settings-migrate.h" #include "gsd-xkb-utils.h" #ifdef HAVE_FCITX #include "input-method-engines.c" #endif #define GSD_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerPrivate)) #define GSD_KEYBOARD_DIR "com.canonical.unity.settings-daemon.peripherals.keyboard" #define GSETTINGS_KEYBOARD_SCHEMA "org.gnome.desktop.peripherals.keyboard" #define KEY_REPEAT "repeat" #define KEY_CLICK "click" #define KEY_INTERVAL "repeat-interval" #define KEY_DELAY "delay" #define KEY_CLICK_VOLUME "click-volume" #define KEY_REMEMBER_NUMLOCK_STATE "remember-numlock-state" #define KEY_NUMLOCK_STATE "numlock-state" #define KEY_BELL_VOLUME "bell-volume" #define KEY_BELL_PITCH "bell-pitch" #define KEY_BELL_DURATION "bell-duration" #define KEY_BELL_MODE "bell-mode" #define KEY_BELL_CUSTOM_FILE "bell-custom-file" #define GNOME_DESKTOP_INTERFACE_DIR "org.gnome.desktop.interface" #define ENV_GTK_IM_MODULE "GTK_IM_MODULE" #define KEY_GTK_IM_MODULE "gtk-im-module" #define GTK_IM_MODULE_SIMPLE "gtk-im-context-simple" #define GTK_IM_MODULE_IBUS "ibus" #define GTK_IM_MODULE_FCITX "fcitx" #define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources" #define KEY_CURRENT_INPUT_SOURCE "current" #define KEY_INPUT_SOURCES "sources" #define KEY_KEYBOARD_OPTIONS "xkb-options" #define INPUT_SOURCE_TYPE_XKB "xkb" #define INPUT_SOURCE_TYPE_IBUS "ibus" #define INPUT_SOURCE_TYPE_FCITX "fcitx" #define FCITX_XKB_PREFIX "fcitx-keyboard-" #define DEFAULT_LANGUAGE "en_US" #define DEFAULT_LAYOUT "us" #define GSD_KEYBOARD_DBUS_NAME "org.gnome.SettingsDaemon.Keyboard" #define GSD_KEYBOARD_DBUS_PATH "/org/gnome/SettingsDaemon/Keyboard" struct GsdKeyboardManagerPrivate { guint start_idle_id; GSettings *settings; GSettings *gsettings; GSettings *input_sources_settings; GSettings *interface_settings; GnomeXkbInfo *xkb_info; GDBusProxy *localed; GCancellable *cancellable; #ifdef HAVE_IBUS IBusBus *ibus; GHashTable *ibus_engines; GCancellable *ibus_cancellable; gboolean is_ibus_active; #endif #ifdef HAVE_FCITX FcitxInputMethod *fcitx; GCancellable *fcitx_cancellable; gulong fcitx_signal_id; gboolean is_fcitx_active; #endif gint xkb_event_base; GsdNumLockState old_state; GdkDeviceManager *device_manager; guint device_added_id; guint device_removed_id; GDBusConnection *dbus_connection; GDBusNodeInfo *dbus_introspection; guint dbus_own_name_id; GSList *dbus_register_object_ids; GDBusMethodInvocation *invocation; guint pending_ops; gint active_input_source; }; static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass); static void gsd_keyboard_manager_init (GsdKeyboardManager *keyboard_manager); static void gsd_keyboard_manager_finalize (GObject *object); static gboolean apply_input_sources_settings (GSettings *settings, gpointer keys, gint n_keys, GsdKeyboardManager *manager); static void set_gtk_im_module (GsdKeyboardManager *manager, GVariant *sources); static void maybe_return_from_set_input_source (GsdKeyboardManager *manager); static void increment_set_input_source_ops (GsdKeyboardManager *manager); G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT) static const gchar introspection_xml[] = "" " " " " " " " " " " /* Ubuntu-specific */ " " " " " " " " " " ""; static gpointer manager_object = NULL; static void init_builder_with_sources (GVariantBuilder *builder, GSettings *settings) { const gchar *type; const gchar *id; GVariantIter iter; GVariant *sources; sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); g_variant_builder_init (builder, G_VARIANT_TYPE ("a(ss)")); g_variant_iter_init (&iter, sources); while (g_variant_iter_next (&iter, "(&s&s)", &type, &id)) g_variant_builder_add (builder, "(ss)", type, id); g_variant_unref (sources); } static gboolean schema_is_installed (const gchar *name) { const gchar * const *schemas; const gchar * const *s; schemas = g_settings_list_schemas (); for (s = schemas; *s; ++s) if (g_str_equal (*s, name)) return TRUE; return FALSE; } #ifdef HAVE_IBUS static void clear_ibus (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; g_cancellable_cancel (priv->ibus_cancellable); g_clear_object (&priv->ibus_cancellable); g_clear_pointer (&priv->ibus_engines, g_hash_table_destroy); g_clear_object (&priv->ibus); } static void fetch_ibus_engines_result (GObject *object, GAsyncResult *result, GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; GList *list, *l; GError *error = NULL; /* engines shouldn't be there yet */ g_return_if_fail (priv->ibus_engines == NULL); g_clear_object (&priv->ibus_cancellable); list = ibus_bus_list_engines_async_finish (priv->ibus, result, &error); if (!list && error) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Couldn't finish IBus request: %s", error->message); g_error_free (error); clear_ibus (manager); return; } /* Maps IBus engine ids to engine description objects */ priv->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); for (l = list; l; l = l->next) { IBusEngineDesc *engine = l->data; const gchar *engine_id = ibus_engine_desc_get_name (engine); g_hash_table_replace (priv->ibus_engines, (gpointer)engine_id, engine); } g_list_free (list); apply_input_sources_settings (priv->input_sources_settings, NULL, 0, manager); } static void fetch_ibus_engines (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; /* engines shouldn't be there yet */ g_return_if_fail (priv->ibus_engines == NULL); g_return_if_fail (priv->ibus_cancellable == NULL); priv->ibus_cancellable = g_cancellable_new (); ibus_bus_list_engines_async (priv->ibus, -1, priv->ibus_cancellable, (GAsyncReadyCallback)fetch_ibus_engines_result, manager); } static void maybe_start_ibus (GsdKeyboardManager *manager) { if (!manager->priv->ibus) { ibus_init (); manager->priv->ibus = ibus_bus_new_async (); g_signal_connect_swapped (manager->priv->ibus, "connected", G_CALLBACK (fetch_ibus_engines), manager); g_signal_connect_swapped (manager->priv->ibus, "disconnected", G_CALLBACK (clear_ibus), manager); } /* IBus doesn't export API in the session bus. The only thing * we have there is a well known name which we can use as a * sure-fire way to activate it. */ g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION, IBUS_SERVICE_IBUS, G_BUS_NAME_WATCHER_FLAGS_AUTO_START, NULL, NULL, NULL, NULL)); } static void set_ibus_engine_finish (GObject *object, GAsyncResult *res, GsdKeyboardManager *manager) { gboolean result; IBusBus *ibus = IBUS_BUS (object); GsdKeyboardManagerPrivate *priv = manager->priv; GError *error = NULL; g_clear_object (&priv->ibus_cancellable); result = ibus_bus_set_global_engine_async_finish (ibus, res, &error); if (!result) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Couldn't set IBus engine: %s", error->message); g_error_free (error); return; } maybe_return_from_set_input_source (manager); } static void set_ibus_engine (GsdKeyboardManager *manager, const gchar *engine_id) { GsdKeyboardManagerPrivate *priv = manager->priv; g_return_if_fail (priv->ibus != NULL); g_return_if_fail (priv->ibus_engines != NULL); g_cancellable_cancel (priv->ibus_cancellable); g_clear_object (&priv->ibus_cancellable); priv->ibus_cancellable = g_cancellable_new (); increment_set_input_source_ops (manager); ibus_bus_set_global_engine_async (priv->ibus, engine_id, -1, priv->ibus_cancellable, (GAsyncReadyCallback)set_ibus_engine_finish, manager); } static void set_ibus_xkb_engine (GsdKeyboardManager *manager) { IBusEngineDesc *engine; GsdKeyboardManagerPrivate *priv = manager->priv; if (!priv->ibus_engines) return; /* All the "xkb:..." IBus engines simply "echo" back symbols, despite their naming implying differently, so we always set one in order for XIM applications to work given that we set XMODIFIERS=@im=ibus in the first place so that they can work without restarting when/if the user adds an IBus input source. */ engine = g_hash_table_lookup (priv->ibus_engines, "xkb:us::eng"); if (!engine) return; set_ibus_engine (manager, ibus_engine_desc_get_name (engine)); } static gboolean need_ibus (GVariant *sources) { GVariantIter iter; const gchar *type; g_variant_iter_init (&iter, sources); while (g_variant_iter_next (&iter, "(&s&s)", &type, NULL)) if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) return TRUE; return FALSE; } static void set_gtk_im_module (GsdKeyboardManager *manager, GVariant *sources) { GsdKeyboardManagerPrivate *priv = manager->priv; const gchar *new_module; gchar *current_module; if (!sources || need_ibus (sources)) new_module = GTK_IM_MODULE_IBUS; else new_module = GTK_IM_MODULE_SIMPLE; current_module = g_settings_get_string (priv->interface_settings, KEY_GTK_IM_MODULE); if (!g_str_equal (current_module, new_module)) g_settings_set_string (priv->interface_settings, KEY_GTK_IM_MODULE, new_module); g_free (current_module); } /* XXX: See upstream bug: * https://codereview.appspot.com/6586075/ */ static gchar * layout_from_ibus_layout (const gchar *ibus_layout) { const gchar *p; /* we get something like "layout(variant)[option1,option2]" */ p = ibus_layout; while (*p) { if (*p == '(' || *p == '[') break; p += 1; } return g_strndup (ibus_layout, p - ibus_layout); } static gchar * variant_from_ibus_layout (const gchar *ibus_layout) { const gchar *a, *b; /* we get something like "layout(variant)[option1,option2]" */ a = ibus_layout; while (*a) { if (*a == '(') break; a += 1; } if (!*a) return NULL; a += 1; b = a; while (*b) { if (*b == ')') break; b += 1; } if (!*b) return NULL; return g_strndup (a, b - a); } static gchar ** options_from_ibus_layout (const gchar *ibus_layout) { const gchar *a, *b; GPtrArray *opt_array; /* we get something like "layout(variant)[option1,option2]" */ a = ibus_layout; while (*a) { if (*a == '[') break; a += 1; } if (!*a) return NULL; opt_array = g_ptr_array_new (); do { a += 1; b = a; while (*b) { if (*b == ',' || *b == ']') break; b += 1; } if (!*b) goto out; g_ptr_array_add (opt_array, g_strndup (a, b - a)); a = b; } while (*a && *a == ','); out: g_ptr_array_add (opt_array, NULL); return (gchar **) g_ptr_array_free (opt_array, FALSE); } static const gchar * engine_from_locale (void) { const gchar *locale; const gchar *locale_engine[][2] = { { "as_IN", "m17n:as:phonetic" }, { "bn_IN", "m17n:bn:inscript" }, { "gu_IN", "m17n:gu:inscript" }, { "hi_IN", "m17n:hi:inscript" }, { "ja_JP", "mozc" }, { "kn_IN", "m17n:kn:kgp" }, { "ko_KR", "hangul" }, { "mai_IN", "m17n:mai:inscript" }, { "ml_IN", "m17n:ml:inscript" }, { "mr_IN", "m17n:mr:inscript" }, { "or_IN", "m17n:or:inscript" }, { "pa_IN", "m17n:pa:inscript" }, { "sd_IN", "m17n:sd:inscript" }, { "ta_IN", "m17n:ta:tamil99" }, { "te_IN", "m17n:te:inscript" }, { "zh_CN", "pinyin" }, { "zh_HK", "cangjie3" }, { "zh_TW", "chewing" }, }; gint i; locale = setlocale (LC_CTYPE, NULL); if (!locale) return NULL; for (i = 0; i < G_N_ELEMENTS (locale_engine); ++i) if (g_str_has_prefix (locale, locale_engine[i][0])) return locale_engine[i][1]; return NULL; } static void add_sources_from_locale (GsdKeyboardManager *manager, GSettings *settings) { const gchar *locale_engine; GVariantBuilder builder; locale_engine = engine_from_locale (); if (!locale_engine) return; init_builder_with_sources (&builder, settings); #ifdef HAVE_IBUS if (manager->priv->is_ibus_active) { g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_IBUS, locale_engine); } #endif #ifdef HAVE_FCITX if (manager->priv->is_fcitx_active) { g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_FCITX, locale_engine); } #endif g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); } static void convert_ibus (GSettings *settings) { GVariantBuilder builder; GSettings *ibus_settings; gchar **engines, **e; if (!schema_is_installed ("org.freedesktop.ibus.general")) return; init_builder_with_sources (&builder, settings); ibus_settings = g_settings_new ("org.freedesktop.ibus.general"); engines = g_settings_get_strv (ibus_settings, "preload-engines"); for (e = engines; *e; ++e) { if (g_str_has_prefix (*e, "xkb:")) continue; g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_IBUS, *e); } g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); g_strfreev (engines); g_object_unref (ibus_settings); } #endif /* HAVE_IBUS */ static gboolean xkb_set_keyboard_autorepeat_rate (guint delay, guint interval) { return XkbSetAutoRepeatRate (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbUseCoreKbd, delay, interval); } static gboolean check_xkb_extension (GsdKeyboardManager *manager) { Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); int opcode, error_base, major, minor; gboolean have_xkb; have_xkb = XkbQueryExtension (dpy, &opcode, &manager->priv->xkb_event_base, &error_base, &major, &minor); return have_xkb; } static void xkb_init (GsdKeyboardManager *manager) { Display *dpy; dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); XkbSelectEventDetails (dpy, XkbUseCoreKbd, XkbStateNotify, XkbModifierLockMask, XkbModifierLockMask); } static unsigned numlock_NumLock_modifier_mask (void) { Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); return XkbKeysymToModifiers (dpy, XK_Num_Lock); } static void numlock_set_xkb_state (GsdNumLockState new_state) { unsigned int num_mask; Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); if (new_state != GSD_NUM_LOCK_STATE_ON && new_state != GSD_NUM_LOCK_STATE_OFF) return; num_mask = numlock_NumLock_modifier_mask (); XkbLockModifiers (dpy, XkbUseCoreKbd, num_mask, new_state == GSD_NUM_LOCK_STATE_ON ? num_mask : 0); } static const char * num_lock_state_to_string (GsdNumLockState numlock_state) { switch (numlock_state) { case GSD_NUM_LOCK_STATE_UNKNOWN: return "GSD_NUM_LOCK_STATE_UNKNOWN"; case GSD_NUM_LOCK_STATE_ON: return "GSD_NUM_LOCK_STATE_ON"; case GSD_NUM_LOCK_STATE_OFF: return "GSD_NUM_LOCK_STATE_OFF"; default: return "UNKNOWN"; } } static GdkFilterReturn xkb_events_filter (GdkXEvent *xev_, GdkEvent *gdkev_, gpointer user_data) { XEvent *xev = (XEvent *) xev_; XkbEvent *xkbev = (XkbEvent *) xev; GsdKeyboardManager *manager = (GsdKeyboardManager *) user_data; if (xev->type != manager->priv->xkb_event_base || xkbev->any.xkb_type != XkbStateNotify) return GDK_FILTER_CONTINUE; if (xkbev->state.changed & XkbModifierLockMask) { unsigned num_mask = numlock_NumLock_modifier_mask (); unsigned locked_mods = xkbev->state.locked_mods; GsdNumLockState numlock_state; numlock_state = (num_mask & locked_mods) ? GSD_NUM_LOCK_STATE_ON : GSD_NUM_LOCK_STATE_OFF; if (numlock_state != manager->priv->old_state) { g_debug ("New num-lock state '%s' != Old num-lock state '%s'", num_lock_state_to_string (numlock_state), num_lock_state_to_string (manager->priv->old_state)); g_settings_set_enum (manager->priv->settings, KEY_NUMLOCK_STATE, numlock_state); manager->priv->old_state = numlock_state; } } return GDK_FILTER_CONTINUE; } static void install_xkb_filter (GsdKeyboardManager *manager) { gdk_window_add_filter (NULL, xkb_events_filter, manager); } static void remove_xkb_filter (GsdKeyboardManager *manager) { gdk_window_remove_filter (NULL, xkb_events_filter, manager); } static void free_xkb_component_names (XkbComponentNamesRec *p) { g_return_if_fail (p != NULL); free (p->keymap); free (p->keycodes); free (p->types); free (p->compat); free (p->symbols); free (p->geometry); g_free (p); } static void upload_xkb_description (const gchar *rules_file_path, XkbRF_VarDefsRec *var_defs, XkbComponentNamesRec *comp_names) { Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); XkbDescRec *xkb_desc; gchar *rules_file; /* The layout we want is always in the first XKB group index * so we should enforce it to make sure we never end up with * the wrong one. */ XkbLockGroup (display, XkbUseCoreKbd, 0); /* Upload it to the X server using the same method as setxkbmap */ xkb_desc = XkbGetKeyboardByName (display, XkbUseCoreKbd, comp_names, XkbGBN_AllComponentsMask, XkbGBN_AllComponentsMask & (~XkbGBN_GeometryMask), True); if (!xkb_desc) { g_warning ("Couldn't upload new XKB keyboard description"); return; } XkbFreeKeyboard (xkb_desc, 0, True); rules_file = g_path_get_basename (rules_file_path); if (!XkbRF_SetNamesProp (display, rules_file, var_defs)) g_warning ("Couldn't update the XKB root window property"); g_free (rules_file); } static gchar * build_xkb_group_string (const gchar *user, const gchar *locale, const gchar *latin) { gchar *string; gsize length = 0; guint commas = 2; if (latin) length += strlen (latin); else commas -= 1; if (locale) length += strlen (locale); else commas -= 1; length += strlen (user) + commas + 1; string = malloc (length); if (locale && latin) sprintf (string, "%s,%s,%s", user, locale, latin); else if (locale) sprintf (string, "%s,%s", user, locale); else if (latin) sprintf (string, "%s,%s", user, latin); else sprintf (string, "%s", user); return string; } static gboolean layout_equal (const gchar *layout_a, const gchar *variant_a, const gchar *layout_b, const gchar *variant_b) { return !g_strcmp0 (layout_a, layout_b) && !g_strcmp0 (variant_a, variant_b); } static void get_locale_layout (GsdKeyboardManager *manager, const gchar **layout, const gchar **variant) { const gchar *locale; const gchar *type; const gchar *id; gboolean got_info; *layout = NULL; *variant = NULL; locale = setlocale (LC_MESSAGES, NULL); /* If LANG is empty, default to en_US */ if (!locale) locale = DEFAULT_LANGUAGE; got_info = gnome_get_input_source_from_locale (locale, &type, &id); if (!got_info) if (!gnome_get_input_source_from_locale (DEFAULT_LANGUAGE, &type, &id)) return; if (!g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) return; gnome_xkb_info_get_layout_info (manager->priv->xkb_info, id, NULL, NULL, layout, variant); } static void replace_layout_and_variant (GsdKeyboardManager *manager, XkbRF_VarDefsRec *xkb_var_defs, const gchar *layout, const gchar *variant) { /* Toolkits need to know about both a latin layout to handle * accelerators which are usually defined like Ctrl+C and a * layout with the symbols for the language used in UI strings * to handle mnemonics like Alt+Ф, so we try to find and add * them in XKB group slots after the layout which the user * actually intends to type with. */ const gchar *latin_layout = "us"; const gchar *latin_variant = ""; const gchar *locale_layout = NULL; const gchar *locale_variant = NULL; if (!layout) return; if (!variant) variant = ""; get_locale_layout (manager, &locale_layout, &locale_variant); /* We want to minimize the number of XKB groups if we have * duplicated layout+variant pairs. * * Also, if a layout doesn't have a variant we still have to * include it in the variants string because the number of * variants must agree with the number of layouts. For * instance: * * layouts: "us,ru,us" * variants: "dvorak,," */ if (layout_equal (latin_layout, latin_variant, locale_layout, locale_variant) || layout_equal (latin_layout, latin_variant, layout, variant)) { latin_layout = NULL; latin_variant = NULL; } if (layout_equal (locale_layout, locale_variant, layout, variant)) { locale_layout = NULL; locale_variant = NULL; } free (xkb_var_defs->layout); xkb_var_defs->layout = build_xkb_group_string (layout, locale_layout, latin_layout); free (xkb_var_defs->variant); xkb_var_defs->variant = build_xkb_group_string (variant, locale_variant, latin_variant); } static gchar * build_xkb_options_string (gchar **options) { gchar *string; if (*options) { gint i; gsize len; gchar *ptr; /* First part, getting length */ len = 1 + strlen (options[0]); for (i = 1; options[i] != NULL; i++) len += strlen (options[i]); len += (i - 1); /* commas */ /* Second part, building string */ string = malloc (len); ptr = g_stpcpy (string, *options); for (i = 1; options[i] != NULL; i++) { ptr = g_stpcpy (ptr, ","); ptr = g_stpcpy (ptr, options[i]); } } else { string = malloc (1); *string = '\0'; } return string; } static gchar ** append_options (gchar **a, gchar **b) { gchar **c, **p; if (!a && !b) return NULL; else if (!a) return g_strdupv (b); else if (!b) return g_strdupv (a); c = g_new0 (gchar *, g_strv_length (a) + g_strv_length (b) + 1); p = c; while (*a) { *p = g_strdup (*a); p += 1; a += 1; } while (*b) { *p = g_strdup (*b); p += 1; b += 1; } return c; } static void strip_xkb_option (gchar **options, const gchar *prefix) { guint last; gchar **p = options; if (!p) return; while (*p) { if (g_str_has_prefix (*p, prefix)) { last = g_strv_length (options) - 1; g_free (*p); *p = options[last]; options[last] = NULL; } else { p += 1; } } } static gboolean in_desktop (const gchar *name) { const gchar *desktop_name_list; gchar **names; gboolean in_list = FALSE; gint i; desktop_name_list = g_getenv ("XDG_CURRENT_DESKTOP"); if (!desktop_name_list) return FALSE; names = g_strsplit (desktop_name_list, ":", -1); for (i = 0; names[i] && !in_list; i++) if (strcmp (names[i], name) == 0) { in_list = TRUE; break; } g_strfreev (names); return in_list; } static gchar * prepare_xkb_options (GsdKeyboardManager *manager, guint n_sources, gchar **extra_options) { gchar **options; gchar **settings_options; gchar *options_str; settings_options = g_settings_get_strv (manager->priv->input_sources_settings, KEY_KEYBOARD_OPTIONS); options = append_options (settings_options, extra_options); g_strfreev (settings_options); /* We might set up different layouts in different groups - see * replace_layout_and_variant(). But we don't want the X * server group switching feature to actually switch * them. Regularly, if we have at least two input sources, * gnome-shell will tell us to switch input source at that * point so we fix that automatically. But when there's only * one source, gnome-shell short circuits as an optimization * and doesn't call us so we can't set the group switching XKB * option in the first place otherwise the X server's switch * will take effect and we get a broken configuration. */ if (n_sources < 2 || in_desktop ("Unity")) strip_xkb_option (options, "grp:"); options_str = build_xkb_options_string (options); g_strfreev (options); return options_str; } static void apply_xkb_settings (GsdKeyboardManager *manager, const gchar *layout, const gchar *variant, gchar *options) { XkbRF_RulesRec *xkb_rules; XkbRF_VarDefsRec *xkb_var_defs; gchar *rules_file_path; gsd_xkb_get_var_defs (&rules_file_path, &xkb_var_defs); free (xkb_var_defs->options); xkb_var_defs->options = options; replace_layout_and_variant (manager, xkb_var_defs, layout, variant); gdk_error_trap_push (); xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True); if (xkb_rules) { XkbComponentNamesRec *xkb_comp_names; xkb_comp_names = g_new0 (XkbComponentNamesRec, 1); XkbRF_GetComponents (xkb_rules, xkb_var_defs, xkb_comp_names); upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names); free_xkb_component_names (xkb_comp_names); XkbRF_Free (xkb_rules, True); } else { g_warning ("Couldn't load XKB rules"); } if (gdk_error_trap_pop ()) g_warning ("Error loading XKB rules"); gsd_xkb_free_var_defs (xkb_var_defs); g_free (rules_file_path); XkbLockModifiers (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbUseCoreKbd, LockMask, 0); } static void user_notify_is_loaded_cb (GObject *object, GParamSpec *pspec, gpointer user_data) { ActUser *user = ACT_USER (object); GSettings *settings = user_data; if (act_user_is_loaded (user)) { GVariant *sources; GVariantIter iter; const gchar *type; const gchar *name; GVariantBuilder builder; g_signal_handlers_disconnect_by_data (user, user_data); sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{ss}")); g_variant_iter_init (&iter, sources); while (g_variant_iter_next (&iter, "(&s&s)", &type, &name)) { g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}")); g_variant_builder_add (&builder, "{ss}", type, name); g_variant_builder_close (&builder); } g_variant_unref (sources); sources = g_variant_ref_sink (g_variant_builder_end (&builder)); act_user_set_input_sources (user, sources); g_variant_unref (sources); } } static void manager_notify_is_loaded_cb (GObject *object, GParamSpec *pspec, gpointer user_data) { ActUserManager *manager = ACT_USER_MANAGER (object); gboolean loaded; g_object_get (manager, "is-loaded", &loaded, NULL); if (loaded) { ActUser *user; g_signal_handlers_disconnect_by_data (manager, user_data); user = act_user_manager_get_user (manager, g_get_user_name ()); if (act_user_is_loaded (user)) user_notify_is_loaded_cb (G_OBJECT (user), NULL, user_data); else g_signal_connect (user, "notify::is-loaded", G_CALLBACK(user_notify_is_loaded_cb), user_data); } } #ifdef HAVE_FCITX static gchar * get_xkb_name (const gchar *name) { gchar *xkb_name; gchar *separator; if (g_str_has_prefix (name, FCITX_XKB_PREFIX)) name += strlen (FCITX_XKB_PREFIX); xkb_name = g_strdup (name); separator = strchr (xkb_name, '-'); if (separator) *separator = '+'; return xkb_name; } static gchar * get_fcitx_name (const gchar *name) { gchar *fcitx_name = g_strdup (name); gchar *separator = strchr (fcitx_name, '+'); if (separator) *separator = '-'; return fcitx_name; } static gboolean input_source_is_fcitx_engine (const gchar *type, const gchar *name, const gchar *engine) { if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { if (g_str_has_prefix (engine, FCITX_XKB_PREFIX)) { gboolean equal; gchar *fcitx_name = get_fcitx_name (name); equal = g_str_equal (fcitx_name, engine + strlen (FCITX_XKB_PREFIX)); g_free (fcitx_name); return equal; } } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { return g_str_equal (name, engine); } return FALSE; } static void fcitx_engine_changed (GsdKeyboardManager *manager, GParamSpec *pspec, FcitxInputMethod *fcitx) { GSettings *settings = manager->priv->input_sources_settings; gchar *engine = fcitx_input_method_get_current_im (manager->priv->fcitx); if (engine) { GVariant *sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); guint current = g_settings_get_uint (settings, KEY_CURRENT_INPUT_SOURCE); gboolean update = TRUE; if (current >= 0 && current < g_variant_n_children (sources)) { const gchar *type; const gchar *name; g_variant_get_child (sources, current, "(&s&s)", &type, &name); update = !input_source_is_fcitx_engine (type, name, engine); } if (update) { gsize i; for (i = 0; i < g_variant_n_children (sources); i++) { const gchar *type; const gchar *name; if (i == current) continue; g_variant_get_child (sources, i, "(&s&s)", &type, &name); if (input_source_is_fcitx_engine (type, name, engine)) { g_settings_set_uint (settings, KEY_CURRENT_INPUT_SOURCE, i); break; } } } g_variant_unref (sources); g_free (engine); } } static gboolean should_update_input_sources (GVariant *sources, GPtrArray *engines) { GVariantIter iter; const gchar *type; const gchar *name; guint i = 0; g_variant_iter_init (&iter, sources); while (g_variant_iter_next (&iter, "(&s&s)", &type, &name)) { if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB) || g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { FcitxIMItem *engine; /* get the next enabled fcitx engine */ for (; i < engines->len; i++) { engine = g_ptr_array_index (engines, i); if (engine->enable) break; } /* there should be an enabled engine and it should match, otherwise we need to update */ if (i++ >= engines->len || !input_source_is_fcitx_engine (type, name, engine->unique_name)) return TRUE; } } /* if there are more enabled engines, we need to update */ for (; i < engines->len; i++) { FcitxIMItem *engine = g_ptr_array_index (engines, i); if (engine->enable) return TRUE; } return FALSE; } static void update_input_sources_from_fcitx_engines (GsdKeyboardManager *manager, FcitxInputMethod *fcitx) { GPtrArray *engines = fcitx_input_method_get_imlist (manager->priv->fcitx); if (engines) { GVariant *sources = g_settings_get_value (manager->priv->input_sources_settings, KEY_INPUT_SOURCES); if (should_update_input_sources (sources, engines)) { GVariantBuilder builder; gboolean update = FALSE; guint i; g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)")); for (i = 0; i < engines->len; i++) { FcitxIMItem *engine = g_ptr_array_index (engines, i); if (engine->enable) { if (g_str_has_prefix (engine->unique_name, FCITX_XKB_PREFIX)) { gchar *name = get_xkb_name (engine->unique_name); g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, name); g_free (name); } else { g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_FCITX, engine->unique_name); } update = TRUE; } } if (update) g_settings_set_value (manager->priv->input_sources_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); else g_variant_builder_clear (&builder); } g_variant_unref (sources); g_ptr_array_unref (engines); } } #endif static gboolean apply_input_source (GsdKeyboardManager *manager, guint current) { GsdKeyboardManagerPrivate *priv = manager->priv; GVariant *sources; guint n_sources; const gchar *type = NULL; const gchar *id = NULL; gchar *layout = NULL; gchar *variant = NULL; gchar **options = NULL; sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES); n_sources = g_variant_n_children (sources); if (n_sources < 1) goto exit; else if (current >= n_sources) current = n_sources - 1; priv->active_input_source = current; #ifdef HAVE_IBUS if (priv->is_ibus_active) { maybe_start_ibus (manager); } #endif g_variant_get_child (sources, current, "(&s&s)", &type, &id); if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { const gchar *l, *v; gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &l, &v); layout = g_strdup (l); variant = g_strdup (v); if (!layout || !layout[0]) { g_warning ("Couldn't find XKB input source '%s'", id); goto exit; } #ifdef HAVE_FCITX if (priv->is_fcitx_active && priv->fcitx) { gchar *name = g_strdup_printf (FCITX_XKB_PREFIX "%s", id); gchar *fcitx_name = get_fcitx_name (name); fcitx_input_method_set_current_im (priv->fcitx, fcitx_name); g_free (fcitx_name); g_free (name); } #endif #ifdef HAVE_IBUS if (priv->is_ibus_active) { set_gtk_im_module (manager, sources); set_ibus_xkb_engine (manager); } #endif } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) { #ifdef HAVE_IBUS if (priv->is_ibus_active) { IBusEngineDesc *engine_desc = NULL; if (priv->ibus_engines) engine_desc = g_hash_table_lookup (priv->ibus_engines, id); else goto exit; /* we'll be called again when ibus is up and running */ if (engine_desc) { const gchar *ibus_layout; ibus_layout = ibus_engine_desc_get_layout (engine_desc); if (ibus_layout) { layout = layout_from_ibus_layout (ibus_layout); variant = variant_from_ibus_layout (ibus_layout); options = options_from_ibus_layout (ibus_layout); } } else { g_warning ("Couldn't find IBus input source '%s'", id); goto exit; } /* NULL here is a shortcut for "I already know I need the IBus module". */ set_gtk_im_module (manager, NULL); set_ibus_engine (manager, id); } else { g_warning ("IBus input source type specified but IBus is not active"); } #else g_warning ("IBus input source type specified but IBus support was not compiled"); #endif } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { #ifdef HAVE_FCITX if (priv->is_fcitx_active) { if (priv->fcitx) { gchar *name = g_strdup (id); fcitx_input_method_set_current_im (priv->fcitx, name); g_free (name); } else { g_warning ("Fcitx input method framework unavailable"); } } else { g_warning ("Fcitx input source type specified but Fcitx is not active"); } #else g_warning ("Fcitx input source type specified but Fcitx support was not compiled"); #endif } else { g_warning ("Unknown input source type '%s'", type); } #ifdef HAVE_FCITX if (priv->is_fcitx_active && priv->fcitx && !priv->fcitx_signal_id) { priv->fcitx_signal_id = g_signal_connect_swapped (manager->priv->fcitx, "notify::current-im", G_CALLBACK (fcitx_engine_changed), manager); g_signal_connect_swapped (manager->priv->fcitx, "imlist-changed", G_CALLBACK (update_input_sources_from_fcitx_engines), manager); } #endif exit: apply_xkb_settings (manager, layout, variant, prepare_xkb_options (manager, n_sources, options)); maybe_return_from_set_input_source (manager); g_variant_unref (sources); g_free (layout); g_free (variant); g_strfreev (options); return TRUE; } #ifdef HAVE_FCITX static const gchar * get_fcitx_engine_for_ibus_engine (const gchar *ibus_engine) { const struct Engine *engine; if (!ibus_engine) return NULL; engine = get_engine_for_ibus_engine (ibus_engine, strlen (ibus_engine)); return engine ? engine->fcitx_engine : NULL; } static void enable_fcitx_engines (GsdKeyboardManager *manager, gboolean migrate) { GsdKeyboardManagerPrivate *priv = manager->priv; GPtrArray *engines; GVariant *sources; GVariantIter iter; const gchar *type; const gchar *name; gboolean changed; guint i; guint j; engines = fcitx_input_method_get_imlist (priv->fcitx); if (!engines) { g_warning ("Cannot update Fcitx engine list"); return; } sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES); changed = FALSE; i = 0; g_variant_iter_init (&iter, sources); while (g_variant_iter_next (&iter, "(&s&s)", &type, &name)) { if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { gchar *fcitx_name = get_fcitx_name (name); for (j = i; j < engines->len; j++) { FcitxIMItem *engine = g_ptr_array_index (engines, j); if (g_str_has_prefix (engine->unique_name, FCITX_XKB_PREFIX) && g_str_equal (engine->unique_name + strlen (FCITX_XKB_PREFIX), fcitx_name)) { if (!engine->enable) { engine->enable = TRUE; changed = TRUE; } break; } } g_free (fcitx_name); /* j is either the index of the engine "fcitx-keyboard-" * or engines->len, meaning it wasn't found. */ } else if (migrate && g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) { const gchar *fcitx_name = get_fcitx_engine_for_ibus_engine (name); if (!fcitx_name) continue; for (j = i; j < engines->len; j++) { FcitxIMItem *engine = g_ptr_array_index (engines, j); if (g_str_equal (engine->unique_name, fcitx_name)) { if (!engine->enable) { engine->enable = TRUE; changed = TRUE; } break; } } /* j is either the index of the engine "" * or engines->len, meaning it wasn't found. */ } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { for (j = i; j < engines->len; j++) { FcitxIMItem *engine = g_ptr_array_index (engines, j); if (g_str_equal (engine->unique_name, name)) { if (!engine->enable) { engine->enable = TRUE; changed = TRUE; } break; } } /* j is either the index of the engine "" * or engines->len, meaning it wasn't found. */ } else { continue; } if (j < engines->len) { if (j != i) { gpointer ptr = engines->pdata[i]; engines->pdata[i] = engines->pdata[j]; engines->pdata[j] = ptr; changed = TRUE; } i++; } else { g_warning ("Fcitx engine not found for %s", name); } } /* we should have i enabled fcitx engines: disable everything else. */ for (; i < engines->len; i++) { FcitxIMItem *engine = g_ptr_array_index (engines, i); if (engine->enable) { engine->enable = FALSE; changed = TRUE; } } if (changed) { fcitx_input_method_set_imlist (priv->fcitx, engines); } g_variant_unref (sources); g_ptr_array_unref (engines); } struct _FcitxShareStateConfig { FcitxGenericConfig config; gint share_state; }; typedef struct _FcitxShareStateConfig FcitxShareStateConfig; static CONFIG_BINDING_BEGIN (FcitxShareStateConfig) CONFIG_BINDING_REGISTER ("Program", "ShareStateAmongWindow", share_state) CONFIG_BINDING_END () static CONFIG_DESC_DEFINE (get_fcitx_config_desc, "config.desc") static void update_share_state_from_per_window (GsdKeyboardManager *manager) { FcitxConfigFileDesc *config_file_desc = get_fcitx_config_desc (); if (config_file_desc) { /* Set Fcitx' share state setting based on the GSettings per-window option. */ GSettings *settings = g_settings_new ("org.gnome.libgnomekbd.desktop"); gboolean per_window = g_settings_get_boolean (settings, "group-per-window"); FcitxShareStateConfig config = { { NULL } }; /* Load the user's Fcitx configuration. */ FILE *file = FcitxXDGGetFileUserWithPrefix (NULL, "config", "r", NULL); FcitxConfigFile *config_file = FcitxConfigParseConfigFileFp (file, config_file_desc); FcitxShareStateConfigConfigBind (&config, config_file, config_file_desc); if (file) fclose (file); config.share_state = per_window ? 0 : 1; /* Save the user's Fcitx configuration. */ file = FcitxXDGGetFileUserWithPrefix (NULL, "config", "w", NULL); FcitxConfigSaveConfigFileFp (file, &config.config, config_file_desc); if (file) fclose (file); fcitx_input_method_reload_config (manager->priv->fcitx); g_object_unref (settings); } } static void migrate_fcitx_engines (GsdKeyboardManager *manager) { GPtrArray *engines = fcitx_input_method_get_imlist (manager->priv->fcitx); if (engines) { gboolean migrate = FALSE; gboolean second = FALSE; guint i; /* Migrate if there are at least two enabled fcitx engines or * there is one fcitx engine which is not a keyboard layout. * These are our criteria for determining which direction to * sync fcitx engines with input sources. */ for (i = 0; i < engines->len; i++) { FcitxIMItem *engine = g_ptr_array_index (engines, i); if (engine->enable) { if (second || !g_str_has_prefix (engine->unique_name, FCITX_XKB_PREFIX)) { migrate = TRUE; break; } second = TRUE; } } if (migrate) { /* Migrate Fcitx to GSettings. */ update_input_sources_from_fcitx_engines (manager, manager->priv->fcitx); } else { /* Migrate GSettings to Fcitx. */ enable_fcitx_engines (manager, TRUE); update_share_state_from_per_window (manager); } g_ptr_array_unref (engines); } } #endif static gboolean apply_input_sources_settings (GSettings *settings, gpointer keys, gint n_keys, GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; GVariant *sources; guint n_sources; guint current; ActUserManager *user_manager; gboolean user_manager_loaded; #ifdef HAVE_FCITX if (priv->is_fcitx_active) { gboolean sources_changed = FALSE; if (keys) { GQuark *quarks = keys; gint i; for (i = 0; i < n_keys; i++) { if (quarks[i] == g_quark_try_string (KEY_INPUT_SOURCES)) { sources_changed = TRUE; break; } } } else { sources_changed = TRUE; } if (sources_changed) { enable_fcitx_engines (manager, FALSE); } } #endif sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES); n_sources = g_variant_n_children (sources); if (n_sources < 1) { apply_xkb_settings (manager, NULL, NULL, prepare_xkb_options (manager, 0, NULL)); maybe_return_from_set_input_source (manager); goto exit; } current = g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE); if (current >= n_sources) { g_settings_set_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE, n_sources - 1); goto exit; } user_manager = act_user_manager_get_default (); g_object_get (user_manager, "is-loaded", &user_manager_loaded, NULL); if (user_manager_loaded) manager_notify_is_loaded_cb (G_OBJECT (user_manager), NULL, priv->input_sources_settings); else g_signal_connect (user_manager, "notify::is-loaded", G_CALLBACK (manager_notify_is_loaded_cb), priv->input_sources_settings); apply_input_source (manager, current); exit: g_variant_unref (sources); /* Prevent individual "changed" signal invocations since we don't need them. */ return TRUE; } static void apply_bell (GsdKeyboardManager *manager) { GSettings *settings; XKeyboardControl kbdcontrol; gboolean click; int bell_volume; int bell_pitch; int bell_duration; GsdBellMode bell_mode; int click_volume; g_debug ("Applying the bell settings"); settings = manager->priv->settings; click = g_settings_get_boolean (settings, KEY_CLICK); click_volume = g_settings_get_int (settings, KEY_CLICK_VOLUME); bell_pitch = g_settings_get_int (settings, KEY_BELL_PITCH); bell_duration = g_settings_get_int (settings, KEY_BELL_DURATION); bell_mode = g_settings_get_enum (settings, KEY_BELL_MODE); bell_volume = (bell_mode == GSD_BELL_MODE_ON) ? 50 : 0; /* as percentage from 0..100 inclusive */ if (click_volume < 0) { click_volume = 0; } else if (click_volume > 100) { click_volume = 100; } kbdcontrol.key_click_percent = click ? click_volume : 0; kbdcontrol.bell_percent = bell_volume; kbdcontrol.bell_pitch = bell_pitch; kbdcontrol.bell_duration = bell_duration; gdk_error_trap_push (); XChangeKeyboardControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration, &kbdcontrol); XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); gdk_error_trap_pop_ignored (); } static void apply_numlock (GsdKeyboardManager *manager) { GSettings *settings; gboolean rnumlock; g_debug ("Applying the num-lock settings"); settings = manager->priv->settings; rnumlock = g_settings_get_boolean (settings, KEY_REMEMBER_NUMLOCK_STATE); manager->priv->old_state = g_settings_get_enum (manager->priv->settings, KEY_NUMLOCK_STATE); gdk_error_trap_push (); if (rnumlock) { g_debug ("Remember num-lock is set, so applying setting '%s'", num_lock_state_to_string (manager->priv->old_state)); numlock_set_xkb_state (manager->priv->old_state); } XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); gdk_error_trap_pop_ignored (); } static void apply_repeat (GsdKeyboardManager *manager) { GSettings *settings; gboolean repeat; guint interval; guint delay; g_debug ("Applying the repeat settings"); settings = manager->priv->gsettings; repeat = g_settings_get_boolean (settings, KEY_REPEAT); interval = g_settings_get_uint (settings, KEY_INTERVAL); delay = g_settings_get_uint (settings, KEY_DELAY); gdk_error_trap_push (); if (repeat) { gboolean rate_set = FALSE; XAutoRepeatOn (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); /* Use XKB in preference */ rate_set = xkb_set_keyboard_autorepeat_rate (delay, interval); if (!rate_set) g_warning ("Neither XKeyboard not Xfree86's keyboard extensions are available,\n" "no way to support keyboard autorepeat rate settings"); } else { XAutoRepeatOff (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); } XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); gdk_error_trap_pop_ignored (); } static void apply_all_settings (GsdKeyboardManager *manager) { apply_repeat (manager); apply_bell (manager); apply_numlock (manager); } static void settings_changed (GSettings *settings, const char *key, GsdKeyboardManager *manager) { if (g_strcmp0 (key, KEY_CLICK) == 0|| g_strcmp0 (key, KEY_CLICK_VOLUME) == 0 || g_strcmp0 (key, KEY_BELL_PITCH) == 0 || g_strcmp0 (key, KEY_BELL_DURATION) == 0 || g_strcmp0 (key, KEY_BELL_MODE) == 0) { g_debug ("Bell setting '%s' changed, applying bell settings", key); apply_bell (manager); } else if (g_strcmp0 (key, KEY_REMEMBER_NUMLOCK_STATE) == 0) { g_debug ("Remember Num-Lock state '%s' changed, applying num-lock settings", key); apply_numlock (manager); } else if (g_strcmp0 (key, KEY_NUMLOCK_STATE) == 0) { g_debug ("Num-Lock state '%s' changed, will apply at next startup", key); } else { g_warning ("Unhandled settings change, key '%s'", key); } } static void gsettings_changed (GSettings *settings, const char *key, GsdKeyboardManager *manager) { if (g_strcmp0 (key, KEY_REPEAT) == 0 || g_strcmp0 (key, KEY_INTERVAL) == 0 || g_strcmp0 (key, KEY_DELAY) == 0) { g_debug ("Key repeat setting '%s' changed, applying key repeat settings", key); apply_repeat (manager); } else if (g_strcmp0 (key, KEY_BELL_CUSTOM_FILE) == 0){ g_debug ("Ignoring '%s' setting change", KEY_BELL_CUSTOM_FILE); } else { g_warning ("Unhandled settings change, key '%s'", key); } } static void device_added_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdKeyboardManager *manager) { GdkInputSource source; source = gdk_device_get_source (device); if (source == GDK_SOURCE_KEYBOARD) { g_debug ("New keyboard plugged in, applying all settings"); apply_numlock (manager); apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager); run_custom_command (device, COMMAND_DEVICE_ADDED); } } static void device_removed_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdKeyboardManager *manager) { GdkInputSource source; source = gdk_device_get_source (device); if (source == GDK_SOURCE_KEYBOARD) { run_custom_command (device, COMMAND_DEVICE_REMOVED); } } static void set_devicepresence_handler (GsdKeyboardManager *manager) { GdkDeviceManager *device_manager; device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", G_CALLBACK (device_added_cb), manager); manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", G_CALLBACK (device_removed_cb), manager); manager->priv->device_manager = device_manager; } static void get_sources_from_xkb_config (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; GVariantBuilder builder; GVariant *v; gint i, n; gchar **layouts = NULL; gchar **variants = NULL; gboolean have_default_layout = FALSE; v = g_dbus_proxy_get_cached_property (priv->localed, "X11Layout"); if (v) { const gchar *s = g_variant_get_string (v, NULL); if (*s) layouts = g_strsplit (s, ",", -1); g_variant_unref (v); } if (!layouts) return; v = g_dbus_proxy_get_cached_property (priv->localed, "X11Variant"); if (v) { const gchar *s = g_variant_get_string (v, NULL); if (*s) variants = g_strsplit (s, ",", -1); g_variant_unref (v); } if (variants && variants[0]) n = MIN (g_strv_length (layouts), g_strv_length (variants)); else n = g_strv_length (layouts); init_builder_with_sources (&builder, priv->input_sources_settings); for (i = 0; i < n && layouts[i][0]; ++i) { gchar *id; if (variants && variants[i] && variants[i][0]) id = g_strdup_printf ("%s+%s", layouts[i], variants[i]); else id = g_strdup (layouts[i]); if (g_str_equal (id, DEFAULT_LAYOUT)) have_default_layout = TRUE; g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, id); g_free (id); } if (!have_default_layout) g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, DEFAULT_LAYOUT); g_settings_set_value (priv->input_sources_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); g_strfreev (layouts); g_strfreev (variants); } static void get_options_from_xkb_config (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; GVariant *v; gchar **options = NULL; v = g_dbus_proxy_get_cached_property (priv->localed, "X11Options"); if (v) { const gchar *s = g_variant_get_string (v, NULL); if (*s) options = g_strsplit (s, ",", -1); g_variant_unref (v); } if (!options) return; g_settings_set_strv (priv->input_sources_settings, KEY_KEYBOARD_OPTIONS, (const gchar * const*) options); g_strfreev (options); } static void convert_libgnomekbd_options (GSettings *settings) { GPtrArray *opt_array; GSettings *libgnomekbd_settings; gchar **options, **o; if (!schema_is_installed ("org.gnome.libgnomekbd.keyboard")) return; opt_array = g_ptr_array_new_with_free_func (g_free); libgnomekbd_settings = g_settings_new ("org.gnome.libgnomekbd.keyboard"); options = g_settings_get_strv (libgnomekbd_settings, "options"); for (o = options; *o; ++o) { gchar **strv; strv = g_strsplit (*o, "\t", 2); if (strv[0] && strv[1]) g_ptr_array_add (opt_array, g_strdup (strv[1])); g_strfreev (strv); } g_ptr_array_add (opt_array, NULL); g_settings_set_strv (settings, KEY_KEYBOARD_OPTIONS, (const gchar * const*) opt_array->pdata); g_strfreev (options); g_object_unref (libgnomekbd_settings); g_ptr_array_free (opt_array, TRUE); } static void convert_libgnomekbd_layouts (GSettings *settings) { GVariantBuilder builder; GSettings *libgnomekbd_settings; gchar **layouts, **l; if (!schema_is_installed ("org.gnome.libgnomekbd.keyboard")) return; init_builder_with_sources (&builder, settings); libgnomekbd_settings = g_settings_new ("org.gnome.libgnomekbd.keyboard"); layouts = g_settings_get_strv (libgnomekbd_settings, "layouts"); for (l = layouts; *l; ++l) { gchar *id; gchar **strv; strv = g_strsplit (*l, "\t", 2); if (strv[0] && !strv[1]) id = g_strdup (strv[0]); else if (strv[0] && strv[1]) id = g_strdup_printf ("%s+%s", strv[0], strv[1]); else id = NULL; if (id) g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, id); g_free (id); g_strfreev (strv); } g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); g_strfreev (layouts); g_object_unref (libgnomekbd_settings); } static gboolean should_migrate (const gchar *id) { gboolean migrate = FALSE; gchar *stamp_dir_path = NULL; gchar *stamp_file_path = NULL; GError *error = NULL; stamp_dir_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, NULL); if (g_mkdir_with_parents (stamp_dir_path, 0755)) { g_warning ("Failed to create directory %s: %s", stamp_dir_path, g_strerror (errno)); goto out; } stamp_file_path = g_build_filename (stamp_dir_path, id, NULL); if (g_file_test (stamp_file_path, G_FILE_TEST_EXISTS)) goto out; migrate = TRUE; if (!g_file_set_contents (stamp_file_path, "", 0, &error)) { g_warning ("%s", error->message); g_error_free (error); } out: g_free (stamp_file_path); g_free (stamp_dir_path); return migrate; } static void maybe_convert_old_settings (GSettings *settings) { if (should_migrate ("input-sources-converted")) { GVariant *sources; gchar **options; sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); if (g_variant_n_children (sources) < 1) { convert_libgnomekbd_layouts (settings); #ifdef HAVE_IBUS convert_ibus (settings); #endif } g_variant_unref (sources); options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS); if (g_strv_length (options) < 1) convert_libgnomekbd_options (settings); g_strfreev (options); } } static void maybe_create_initial_settings (GsdKeyboardManager *manager) { GSettings *settings; GVariant *sources; gchar **options; settings = manager->priv->input_sources_settings; if (g_getenv ("RUNNING_UNDER_GDM")) { GVariantBuilder builder; /* clean the settings and get them from the "system" */ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)")); g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); get_sources_from_xkb_config (manager); g_settings_set_strv (settings, KEY_KEYBOARD_OPTIONS, NULL); get_options_from_xkb_config (manager); return; } maybe_convert_old_settings (settings); /* if we still don't have anything do some educated guesses */ sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); if (g_variant_n_children (sources) < 1) { get_sources_from_xkb_config (manager); #if defined(HAVE_IBUS) || defined(HAVE_FCITX) add_sources_from_locale (manager, settings); #endif } g_variant_unref (sources); options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS); if (g_strv_length (options) < 1) get_options_from_xkb_config (manager); g_strfreev (options); } static void set_input_source_return (GDBusMethodInvocation *invocation) { g_dbus_method_invocation_return_value (invocation, NULL); } static void maybe_return_from_set_input_source (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; if (!priv->invocation) return; if (priv->pending_ops > 0) { priv->pending_ops -= 1; return; } g_clear_pointer (&priv->invocation, set_input_source_return); } static void increment_set_input_source_ops (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; if (!priv->invocation) return; priv->pending_ops += 1; } static void set_input_source (GsdKeyboardManager *manager, gboolean persist) { GsdKeyboardManagerPrivate *priv = manager->priv; guint idx; g_variant_get (g_dbus_method_invocation_get_parameters (priv->invocation), "(u)", &idx); if (persist) { if (idx == priv->active_input_source) { if (idx == g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE)) { maybe_return_from_set_input_source (manager); return; } } g_settings_set_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE, idx); } else { if (idx == priv->active_input_source) { maybe_return_from_set_input_source (manager); return; } apply_input_source (manager, idx); } } static void handle_dbus_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv = manager->priv; gboolean is_set_input_source; gboolean is_activate_input_source; is_set_input_source = g_str_equal (method_name, "SetInputSource"); is_activate_input_source = g_str_equal (method_name, "ActivateInputSource"); if (is_set_input_source || is_activate_input_source) { if (priv->invocation) { #ifdef HAVE_IBUS if (priv->is_ibus_active) { /* This can only happen if there's an * ibus_bus_set_global_engine_async() call * going on. */ g_cancellable_cancel (priv->ibus_cancellable); } #endif g_clear_pointer (&priv->invocation, set_input_source_return); priv->pending_ops = 0; } priv->invocation = invocation; set_input_source (manager, is_set_input_source); } } static void on_bus_name_lost (GDBusConnection *connection, const gchar *name, gpointer data) { g_warning ("DBus name %s lost", name); } static void got_session_bus (GObject *source, GAsyncResult *res, GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *priv; GDBusConnection *connection; GDBusInterfaceInfo **interfaces; GError *error = NULL; GDBusInterfaceVTable vtable = { (GDBusInterfaceMethodCallFunc) handle_dbus_method_call, NULL, NULL, }; connection = g_bus_get_finish (res, &error); if (!connection) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Couldn't get session bus: %s", error->message); g_error_free (error); return; } priv = manager->priv; priv->dbus_connection = connection; interfaces = priv->dbus_introspection->interfaces; if (interfaces) { for (; *interfaces; interfaces++) { guint id = g_dbus_connection_register_object (priv->dbus_connection, GSD_KEYBOARD_DBUS_PATH, *interfaces, &vtable, manager, NULL, &error); if (!id) { GSList *ids; for (ids = priv->dbus_register_object_ids; ids; ids = g_slist_next (ids)) g_dbus_connection_unregister_object (priv->dbus_connection, GPOINTER_TO_UINT (ids->data)); g_slist_free (priv->dbus_register_object_ids); priv->dbus_register_object_ids = NULL; g_warning ("Error registering object: %s", error->message); g_error_free (error); return; } priv->dbus_register_object_ids = g_slist_prepend (priv->dbus_register_object_ids, GUINT_TO_POINTER (id)); } } priv->dbus_own_name_id = g_bus_own_name_on_connection (priv->dbus_connection, GSD_KEYBOARD_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, on_bus_name_lost, NULL, NULL); } static void register_manager_dbus (GsdKeyboardManager *manager) { GError *error = NULL; manager->priv->dbus_introspection = g_dbus_node_info_new_for_xml (introspection_xml, &error); if (error) { g_warning ("Error creating introspection data: %s", error->message); g_error_free (error); return; } g_bus_get (G_BUS_TYPE_SESSION, manager->priv->cancellable, (GAsyncReadyCallback) got_session_bus, manager); } static void localed_proxy_ready (GObject *source, GAsyncResult *res, gpointer data) { GsdKeyboardManager *manager = data; GDBusProxy *proxy; GError *error = NULL; proxy = g_dbus_proxy_new_finish (res, &error); if (!proxy) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } g_warning ("Failed to contact localed: %s", error->message); g_error_free (error); goto out; } manager->priv->localed = proxy; maybe_create_initial_settings (manager); out: apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager); register_manager_dbus (manager); } #ifdef HAVE_FCITX static void fcitx_appeared (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { GsdKeyboardManager *manager = user_data; apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager); } static void fcitx_vanished (GDBusConnection *connection, const gchar *name, gpointer user_data) { GsdKeyboardManager *manager = user_data; g_signal_handlers_disconnect_by_data (manager->priv->fcitx, manager); manager->priv->fcitx_signal_id = 0; } #endif static gboolean start_keyboard_idle_cb (GsdKeyboardManager *manager) { const gchar *module; GError *error = NULL; gnome_settings_profile_start (NULL); g_debug ("Starting keyboard manager"); module = g_getenv (ENV_GTK_IM_MODULE); #ifdef HAVE_IBUS manager->priv->is_ibus_active = g_strcmp0 (module, GTK_IM_MODULE_IBUS) == 0; #endif #ifdef HAVE_FCITX manager->priv->is_fcitx_active = g_strcmp0 (module, GTK_IM_MODULE_FCITX) == 0; #endif manager->priv->settings = g_settings_new (GSD_KEYBOARD_DIR); manager->priv->gsettings = g_settings_new (GSETTINGS_KEYBOARD_SCHEMA); xkb_init (manager); set_devicepresence_handler (manager); manager->priv->input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR); manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR); manager->priv->xkb_info = gnome_xkb_info_new (); #ifdef HAVE_FCITX if (manager->priv->is_fcitx_active) { manager->priv->fcitx_cancellable = g_cancellable_new (); manager->priv->fcitx = fcitx_input_method_new (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, 0, manager->priv->fcitx_cancellable, &error); g_clear_object (&manager->priv->fcitx_cancellable); if (manager->priv->fcitx) { manager->priv->fcitx_signal_id = 0; g_bus_watch_name (G_BUS_TYPE_SESSION, "org.fcitx.Fcitx", G_BUS_NAME_WATCHER_FLAGS_NONE, fcitx_appeared, fcitx_vanished, manager, NULL); if (should_migrate ("fcitx-engines-migrated")) migrate_fcitx_engines (manager); else enable_fcitx_engines (manager, FALSE); } else { g_warning ("Fcitx input method framework unavailable: %s", error->message); g_error_free (error); } } #endif manager->priv->cancellable = g_cancellable_new (); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.locale1", "/org/freedesktop/locale1", "org.freedesktop.locale1", manager->priv->cancellable, localed_proxy_ready, manager); /* apply current settings before we install the callback */ g_debug ("Started the keyboard plugin, applying all settings"); apply_all_settings (manager); g_signal_connect (G_OBJECT (manager->priv->settings), "changed", G_CALLBACK (settings_changed), manager); g_signal_connect (G_OBJECT (manager->priv->gsettings), "changed", G_CALLBACK (gsettings_changed), manager); g_signal_connect (G_OBJECT (manager->priv->input_sources_settings), "change-event", G_CALLBACK (apply_input_sources_settings), manager); install_xkb_filter (manager); gnome_settings_profile_end (NULL); manager->priv->start_idle_id = 0; return FALSE; } gboolean gsd_keyboard_manager_start (GsdKeyboardManager *manager, GError **error) { gnome_settings_profile_start (NULL); if (check_xkb_extension (manager) == FALSE) { g_debug ("XKB is not supported, not applying any settings"); return TRUE; } manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_keyboard_idle_cb, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_keyboard_manager_stop (GsdKeyboardManager *manager) { GsdKeyboardManagerPrivate *p = manager->priv; GSList *ids; g_debug ("Stopping keyboard manager"); if (p->dbus_own_name_id) { g_bus_unown_name (p->dbus_own_name_id); p->dbus_own_name_id = 0; } for (ids = p->dbus_register_object_ids; ids; ids = g_slist_next (ids)) g_dbus_connection_unregister_object (p->dbus_connection, GPOINTER_TO_UINT (ids->data)); g_slist_free (p->dbus_register_object_ids); p->dbus_register_object_ids = NULL; g_cancellable_cancel (p->cancellable); g_clear_object (&p->cancellable); g_clear_object (&p->settings); g_clear_object (&p->input_sources_settings); g_clear_object (&p->interface_settings); g_clear_object (&p->xkb_info); g_clear_object (&p->localed); #ifdef HAVE_FCITX if (p->is_fcitx_active) { if (p->fcitx_cancellable) { g_cancellable_cancel (p->fcitx_cancellable); } g_clear_object (&p->fcitx_cancellable); g_clear_object (&p->fcitx); } #endif #ifdef HAVE_IBUS if (p->is_ibus_active) { clear_ibus (manager); } #endif if (p->device_manager != NULL) { g_signal_handler_disconnect (p->device_manager, p->device_added_id); g_signal_handler_disconnect (p->device_manager, p->device_removed_id); p->device_manager = NULL; } remove_xkb_filter (manager); g_clear_pointer (&p->invocation, set_input_source_return); g_clear_pointer (&p->dbus_introspection, g_dbus_node_info_unref); g_clear_object (&p->dbus_connection); } static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_keyboard_manager_finalize; g_type_class_add_private (klass, sizeof (GsdKeyboardManagerPrivate)); } static void gsd_keyboard_manager_init (GsdKeyboardManager *manager) { manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager); manager->priv->active_input_source = -1; } static void gsd_keyboard_manager_finalize (GObject *object) { GsdKeyboardManager *keyboard_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_KEYBOARD_MANAGER (object)); keyboard_manager = GSD_KEYBOARD_MANAGER (object); g_return_if_fail (keyboard_manager->priv != NULL); if (keyboard_manager->priv->start_idle_id != 0) g_source_remove (keyboard_manager->priv->start_idle_id); G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->finalize (object); } static void migrate_keyboard_settings (void) { GsdSettingsMigrateEntry entries[] = { { "repeat", "repeat", NULL }, { "repeat-interval", "repeat-interval", NULL }, { "delay", "delay", NULL } }; gsd_settings_migrate_check ("com.canonical.unity.settings-daemon.peripherals.keyboard.deprecated", "/com/canonical/unity/settings-daemon/peripherals/keyboard/", "org.gnome.desktop.peripherals.keyboard", "/org/gnome/desktop/peripherals/keyboard/", entries, G_N_ELEMENTS (entries)); } GsdKeyboardManager * gsd_keyboard_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { migrate_keyboard_settings (); manager_object = g_object_new (GSD_TYPE_KEYBOARD_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_KEYBOARD_MANAGER (manager_object); } unity-settings-daemon/plugins/keyboard/gsd-keyboard-manager.h0000664000000000000000000000452215172222611021634 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_KEYBOARD_MANAGER_H #define __GSD_KEYBOARD_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_KEYBOARD_MANAGER (gsd_keyboard_manager_get_type ()) #define GSD_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManager)) #define GSD_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerClass)) #define GSD_IS_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_KEYBOARD_MANAGER)) #define GSD_IS_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_KEYBOARD_MANAGER)) #define GSD_KEYBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerClass)) typedef struct GsdKeyboardManagerPrivate GsdKeyboardManagerPrivate; typedef struct { GObject parent; GsdKeyboardManagerPrivate *priv; } GsdKeyboardManager; typedef struct { GObjectClass parent_class; } GsdKeyboardManagerClass; GType gsd_keyboard_manager_get_type (void); GsdKeyboardManager * gsd_keyboard_manager_new (void); gboolean gsd_keyboard_manager_start (GsdKeyboardManager *manager, GError **error); void gsd_keyboard_manager_stop (GsdKeyboardManager *manager); G_END_DECLS #endif /* __GSD_KEYBOARD_MANAGER_H */ unity-settings-daemon/plugins/keyboard/gsd-keyboard-plugin.c0000664000000000000000000000202615172222611021510 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-keyboard-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdKeyboard, gsd_keyboard) unity-settings-daemon/plugins/keyboard/gsd-xkb-utils.c0000664000000000000000000000460115172222611020337 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #include "config.h" #include #include #include #include #include #include #include "gsd-xkb-utils.h" #ifndef XKB_RULES_FILE #define XKB_RULES_FILE "evdev" #endif #ifndef XKB_LAYOUT #define XKB_LAYOUT "us" #endif #ifndef XKB_MODEL #define XKB_MODEL "pc105+inet" #endif void gsd_xkb_get_var_defs (char **rules, XkbRF_VarDefsRec **var_defs) { Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); char *tmp; g_return_if_fail (rules != NULL); g_return_if_fail (var_defs != NULL); *rules = NULL; *var_defs = g_new0 (XkbRF_VarDefsRec, 1); gdk_error_trap_push (); /* Get it from the X property or fallback on defaults */ if (!XkbRF_GetNamesProp (display, rules, *var_defs) || !*rules) { *rules = strdup (XKB_RULES_FILE); (*var_defs)->model = strdup (XKB_MODEL); (*var_defs)->layout = strdup (XKB_LAYOUT); (*var_defs)->variant = NULL; (*var_defs)->options = NULL; } gdk_error_trap_pop_ignored (); tmp = *rules; if (*rules[0] == '/') *rules = g_strdup (*rules); else *rules = g_build_filename (XKB_BASE, "rules", *rules, NULL); free (tmp); } void gsd_xkb_free_var_defs (XkbRF_VarDefsRec *var_defs) { g_return_if_fail (var_defs != NULL); free (var_defs->model); free (var_defs->layout); free (var_defs->variant); free (var_defs->options); g_free (var_defs); } unity-settings-daemon/plugins/keyboard/gsd-xkb-utils.h0000664000000000000000000000207015172222611020342 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #ifndef __GSD_XKB_UTILS_H #define __GSD_XKB_UTILS_H #include #include void gsd_xkb_get_var_defs (char **rules, XkbRF_VarDefsRec **var_defs); void gsd_xkb_free_var_defs (XkbRF_VarDefsRec *var_defs); #endif /* __GSD_XKB_UTILS_H */ unity-settings-daemon/plugins/keyboard/input-method-engines.gperf0000664000000000000000000001405615172222611022573 0ustar %pic %struct-type %readonly-tables %define slot-name ibus_engine %define hash-function-name ibus_engine_hash %define lookup-function-name get_engine_for_ibus_engine struct Engine { int ibus_engine; const char *fcitx_engine; }; %% Unikey, "unikey" anthy, "anthy" array, "array30" array30, "array30" array30-big, "array30-big" bopomofo, "zhuyin-libpinyin" cangjie, "cangjie3" cangjie-big, "cangjie-big" cangjie3, "cangjie3" cangjie5, "cangjie5" cantonese, "cantonese" cantonhk, "cantonhk" chewing, "chewing" cns11643, "cns11643" compose, "compose" easy-big, "easy-big" emoji-table, "emoji" erbi, "erbi" erbi-qs, "erbi" googlepinyin, "googlepinyin" hangul, "hangul" # input-pad, NULL ipa-x-sampa, "ipa-x-sampa" jyutping, "jyutping" latex, "latex" libbopomofo, "zhuyin-libpinyin" libpinyin, "pinyin-libpinyin" libthai, "thai" m17n:am:sera, "m17n_am_sera" m17n:ar:kbd, "arabic" m17n:as:inscript, "m17n_as_inscript" m17n:as:itrans, "m17n_as_itrans" m17n:as:phonetic, "m17n_as_phonetic" m17n:ath:phonetic, "m17n_ath_phonetic" m17n:be:kbd, "fcitx-keyboard-by" m17n:bla:phonetic, "m17n_bla_phonetic" m17n:bn:disha, "m17n_bn_disha" m17n:bn:inscript, "m17n_bn_inscript" m17n:bn:itrans, "m17n_bn_itrans" m17n:bn:probhat, "m17n_bn_probhat" m17n:bn:unijoy, "m17n_bn_unijoy" m17n:bo:ewts, "m17n_bo_ewts" m17n:bo:tcrc, "m17n_bo_tcrc" m17n:bo:wylie, "m17n_bo_wylie" # m17n:cmc:kbd, NULL m17n:cr:western, "m17n_cr_western" m17n:cs:kbd, "fcitx-keyboard-cz-qwerty_bksl" m17n:da:post, "m17n_da_post" m17n:dv:phonetic, "m17n_dv_phonetic" m17n:el:kbd, "fcitx-keyboard-gr-simple" m17n:eo:h-fundamente, "m17n_eo_h-fundamente" m17n:eo:h-sistemo, "m17n_eo_h-sistemo" m17n:eo:plena, "m17n_eo_plena" m17n:eo:q-sistemo, "m17n_eo_q-sistemo" m17n:eo:vi-sistemo, "m17n_eo_vi-sistemo" m17n:eo:x-sistemo, "m17n_eo_x-sistemo" m17n:fa:isiri, "m17n_fa_isiri" m17n:fr:azerty, "m17n_fr_azerty" m17n:grc:mizuochi, "m17n_grc_mizuochi" m17n:gu:inscript, "m17n_gu_inscript" m17n:gu:itrans, "m17n_gu_itrans" m17n:gu:phonetic, "m17n_gu_phonetic" m17n:he:kbd, "fcitx-keyboard-il" m17n:hi:inscript, "m17n_hi_inscript" m17n:hi:itrans, "m17n_hi_itrans" m17n:hi:phonetic, "m17n_hi_phonetic" m17n:hi:remington, "m17n_hi_remington" m17n:hi:typewriter, "m17n_hi_typewriter" m17n:hi:vedmata, "m17n_hi_vedmata" m17n:hr:kbd, "fcitx-keyboard-hr" m17n:hy:kbd, "fcitx-keyboard-am-eastern-alt" m17n:ii:phonetic, "m17n_ii_phonetic" m17n:iu:phonetic, "m17n_iu_phonetic" m17n:ja:tcode, "m17n_ja_tcode" m17n:ja:trycode, "m17n_ja_trycode" m17n:ka:kbd, "fcitx-keyboard-ge" m17n:kk:arabic, "m17n_kk_arabic" m17n:kk:kbd, "fcitx-keyboard-kz" m17n:km:yannis, "m17n_km_yannis" m17n:kn:inscript, "m17n_kn_inscript" m17n:kn:itrans, "m17n_kn_itrans" m17n:kn:kgp, "m17n_kn_kgp" m17n:kn:typewriter, "m17n_kn_typewriter" # m17n:ko:han2, NULL # m17n:ko:romaja, NULL m17n:ks:inscript, "m17n_ks_inscript" m17n:ks:kbd, "m17n_ks_kbd" m17n:lo:kbd, "fcitx-keyboard-la-stea" m17n:lo:lrt, "m17n_lo_lrt" m17n:mai:inscript, "m17n_mai_inscript" m17n:ml:inscript, "m17n_ml_inscript" m17n:ml:itrans, "m17n_ml_itrans" m17n:ml:mozhi, "m17n_ml_mozhi" m17n:ml:remington, "m17n_ml_remington" m17n:ml:swanalekha, "m17n_ml_swanalekha" m17n:mr:inscript, "m17n_mr_inscript" m17n:mr:itrans, "m17n_mr_itrans" m17n:mr:phonetic, "m17n_mr_phonetic" m17n:my:kbd, "fcitx-keyboard-mm" m17n:ne:rom, "m17n_ne_rom" m17n:ne:trad, "m17n_ne_trad" m17n:nsk:phonetic, "m17n_nsk_phonetic" m17n:oj:phonetic, "m17n_oj_phonetic" m17n:or:inscript, "m17n_or_inscript" m17n:or:itrans, "m17n_or_itrans" m17n:or:phonetic, "m17n_or_phonetic" m17n:pa:anmollipi, "m17n_pa_anmollipi" m17n:pa:inscript, "m17n_pa_inscript" m17n:pa:itrans, "m17n_pa_itrans" m17n:pa:jhelum, "m17n_pa_jhelum" m17n:pa:phonetic, "m17n_pa_phonetic" m17n:ps:phonetic, "m17n_ps_phonetic" m17n:ru:kbd, "fcitx-keyboard-ru" m17n:ru:phonetic, "m17n_ru_phonetic" m17n:ru:translit, "m17n_ru_translit" m17n:ru:yawerty, "m17n_ru_yawerty" m17n:sa:IAST, "m17n_sa_IAST" m17n:sa:harvard-kyoto, "m17n_sa_harvard-kyoto" m17n:sa:itrans, "m17n_sa_itrans" m17n:sd:inscript, "m17n_sd_inscript" m17n:si:phonetic-dynamic, "m17n_si_phonetic-dynamic" m17n:si:samanala, "m17n_si_samanala" m17n:si:singlish, "m17n_si_singlish" m17n:si:sumihiri, "m17n_si_sumihiri" m17n:si:transliteration, "m17n_si_transliteration" m17n:si:wijesekera, "m17n_si_wijesekera" m17n:sk:kbd, "fcitx-keyboard-sk" m17n:sr:kbd, "fcitx-keyboard-rs" m17n:sv:post, "m17n_sv_post" m17n:t:latn-post, "m17n_t_latn-post" m17n:t:latn-pre, "m17n_t_latn-pre" m17n:t:math-latex, "m17n_t_math-latex" m17n:t:rfc1345, "m17n_t_rfc1345" m17n:t:syrc-phonetic, "m17n_t_syrc-phonetic" m17n:t:unicode, "m17n_t_unicode" m17n:ta:inscript, "m17n_ta_inscript" m17n:ta:itrans, "m17n_ta_itrans" m17n:ta:lk-renganathan, "m17n_ta_lk-renganathan" m17n:ta:phonetic, "m17n_ta_phonetic" m17n:ta:tamil99, "m17n_ta_tamil99" m17n:ta:typewriter, "m17n_ta_typewriter" m17n:ta:vutam, "m17n_ta_vutam" m17n:tai:sonla-kbd, "m17n_tai_sonla-kbd" m17n:te:apple, "m17n_te_apple" m17n:te:inscript, "m17n_te_inscript" m17n:te:itrans, "m17n_te_itrans" m17n:te:pothana, "m17n_te_pothana" m17n:te:rts, "m17n_te_rts" m17n:te:sarala, "m17n_te_sarala" m17n:th:kesmanee, "m17n_th_kesmanee" m17n:th:pattachote, "m17n_th_pattachote" m17n:th:tis820, "m17n_th_tis820" m17n:ua:kbd, "fcitx-keyboard-ua" m17n:ug:kbd, "fcitx-keyboard-cn-ug" m17n:ur:phonetic, "m17n_ur_phonetic" m17n:uz:kbd, "fcitx-keyboard-uz" m17n:vi:han, "m17n_vi_han" m17n:vi:nomtelex, "m17n_vi_nomtelex" m17n:vi:nomvni, "m17n_vi_nomvni" m17n:vi:tcvn, "m17n_vi_tcvn" m17n:vi:telex, "m17n_vi_telex" m17n:vi:viqr, "m17n_vi_viqr" m17n:vi:vni, "m17n_vi_vni" m17n:yi:yivo, "m17n_yi_yivo" m17n:zh:bopomofo, "m17n_zh_bopomofo" m17n:zh:cangjie, "cangjie3" m17n:zh:pinyin, "m17n_zh_pinyin" m17n:zh:pinyin-vi, "m17n_zh_pinyin-vi" # m17n:zh:py, NULL m17n:zh:quick, "quick3" # m17n:zh:tonepy, NULL mozc-jp, "mozc" pinyin, "pinyin" quick, "quick3" quick-classic, "quick-classic" quick3, "quick3" quick5, "quick5" rime, "rime" rustrad, "rustrad" scj6, "scj6" skk, "skk" stroke5, "stroke5" sunpinyin, "sunpinyin" # tegaki, NULL thai, "thai" translit, "translit" translit-ua, "translit-ua" viqr, "viqr" wu, "wu" wubi-haifeng86, "wubi" wubi-jidian86, "wubi" # xkbc, NULL yawerty, "yawerty" # yong, NULL %% unity-settings-daemon/plugins/keyboard/kbd-capslock-off.png0000664000000000000000000000316215172222611021312 0ustar PNG  IHDR@@iqsBIT|d pHYsnNtEXtSoftwarewww.inkscape.org<IDATxME5|.DM#H(W<9p OzGA=iL< D$ Q? +]I0ay蚥fv&;dW .iْf>m(6d x vUD`p t- ǁ;%P@еpor\NIPPX*NKz?N~3 SC xhvC fފ,Gqh?o~`A9IY00@"ۀ]uO+g嬅]@[,6`w v"*Y5|%bK'5YY`Nrc} !ۜ@2ۇ&n`jrj}1Hڧs>;یa!IN ȹLݾp 5,|&z:M|P~|GS{dJ*5)Z,m0 (D_ᑬx qP>>)Q듂B{!n_D=Bөwd^ 8Tkq[al[b])8_I:KRC6zf`s% ,I9cΔ/1IrE@gf?g 6@c$7p0 ޛ"ic~ ج$gzewdIUdD?zXH6S[=Ƙ}9{ 6#r+qPn69U2֑-d(Iz(FP 9sՓpD'8'x$-l6 6 K|џ>N6 >u^!H4@G޵0WңL-cNCյ}! IY4)IE3+po*e,t*+9$̃9m5/d; }Ǟ,ǵ1r7&I ȗ3hwo3">H "I LkqK޳|r;w:v.f)f maO,d^4͹,1U4fmg JbvWVJlt``#?< ຣ30.ӎ=|ػ j{ܙB7t4vXKaM@a.]D@iJDc'Ocz5ֺer΀rOh@-],mZ\#_hWfd|i*ksK%)in ͝1:qAZCx+]zIzgJOBYjۦI1V ! W[PrO$%|/P@ٞsh$JҼ>NajjLjLIENDB`unity-settings-daemon/plugins/keyboard/kbd-capslock-on.png0000664000000000000000000000272015172222611021153 0ustar PNG  IHDR@@iqsRGBbKGD pHYsnNtIME:=PIDATxKhE{#4YSZ|!u!nJk(iDtck] ҅(E4ޒB >jF%!M VHLdr{M3g93"#P 40q`0ӬGN`iR`!/_ԅ^+pH\ڜa$xZKr{IO%8۴3q|Bu \S0PQo1Rw 䁻y9+P,[`h@[`z 4+WD9 fC#۪p,/ tq vQ)|_z|xWÃ[%dZK`n5ckGJ(i2Ljʥ5n=hD͒<R^E綃d f ; @WsGآ 04Lv<&Sc)- `*ףɴ YL0,+0nIrd=Ydei!n1Y[@ 8qSmeN#Cn'dnP <2f. VY@1ǜ(T>W4h1`SfmZ῱yt ,w ~_F`tx둟eӽ2\9*8^ *!bs&00Č,uIh:ogMJ' ][bÚGVk r}Pw! ";*1iUIG U Io WQT7J0r\{,ֹ@( |ؙ$p\8y @ҍ/P@)}1qh#jvI^1 -q'HL r,62er_ 9Smj<"Id{L.K<^>%-{Tv!/Җ„:'N(KSB/M%6 l絹 3)\R&/ stTSO8`*K598C[{vT ql/SU_BcoN|H0IENDB`unity-settings-daemon/plugins/keyboard/kbd-numlock-off.png0000664000000000000000000000331615172222611021164 0ustar PNG  IHDR@@iqsBIT|d pHYsnNtEXtSoftwarewww.inkscape.org<KIDATx[VU6b7g}g{8笵ko}Y{*4GdI㍟$&I{scte6lnt\E VAg 8 Fx(*b36H^%|ץcBM%QN~%S`0 ]щD=]lBj[;̎c1g)>fVf‘CEщYpfa#0$`sU` F *$W3|mon0|)$>YlLր9$?[SɁ|7FzY'`/rRB:XcžR c*p0k&!#Jw1KVZ8Gɐ|ׇ#iNr&3W38x0]o~8(a:6z%{ -F|(>*A!~,/RISTg@-ToԙJs+]?J9uGzm]́L4[ p9O0K{XҨ޴$1fUԳ{alUm- Bވ8.c8$OݺM[@q~ PM|"r9I`uoJPS3b**YBEp}̓Խv48-wNh|AE7bIUm+Z SoVU 2ދHd$e܋VH:4Jz_~ 3DR)2{@5Hkkpm % HIw/sIpOJ]wyGa4Is$z)ԭSι'Z G ss0]+m+>1{4G; 'D*tZ mi+e;%؞E0Ob- l>^-@:Ou/c'>XIq~b0[ ` ?l 0Ep lbhV Ֆ୉!r/b]~Qkr.PX$ IKLhs/pJ߈J:;v_Aұ/Wse: lr<@_y`xH,]]$er)0`^Q(2>xKe], rDd&@hj7n~67O] R 1?k9 oaof|Yo>V3Ktrщ/\ >Ǹ؂] Z*T)K]cn+Tg?|wU&IENDB`unity-settings-daemon/plugins/keyboard/kbd-numlock-on.png0000664000000000000000000000306715172222611021031 0ustar PNG  IHDR@@iqsRGBbKGD pHYsnNtIMEPLIDATxmhUu9 m±ޖl}^VNiїJCQ"(KA&RӈF\&Wr,Zlmm>ܳ|8?><׻<ߞso<"n%@(W:@\#qYlM`@!IɰO .PL]A}VN\b<&*p)e-f`Pƴqkc鄒4`^'R7ğ%^4R3v;1l1_/p%A=meX=)p^ZkɬFk M@K`D^e._n8CmhhDI50Íu%aE MPxV'Ц)tU\dpLPo&ǛN8ھEҌbԬaLˏEw+|Mj prb+$A`uD~,m P(0LhqDPKG.PHܩ p*d?(C!hNmw:4 L(\ P6Zi=8c .3*^ƍ H=+)Rj x0`Jϭ:@vJ&́;oI}Gs7O%U~xc m` cNXr $Fb5K8﷞`6ļAaGhU#<r0{qt.)up<r5km(4S&qrfwJi<U9޽ʻ[ϦXIyr KoxMl 0{~B;xxW"H.T\3&FGHT4oG*vGk'sʆbھpɽS< t,'.o%:EqDԑ/>`FQ%}poX BxpD"Vn+[ǀ ʇfn\k~Gp5F" 3\j WApd |Ϣ#ZBPQ#S%B<7%tSbv*yR7 <#P&*S)W]k:QZ[Ui紫4Q(HG:`KhLy~ (JkGcė [O-8C@mȄfREg<8E[c}zi`Լ@.h `)$ -BI-5X',WtB]PC~^\4՛i ksM;;k. =8z#͐'% L>df"`zsvJ'5j끀Jа}dE bhUw}GI8n. !IENDB`unity-settings-daemon/plugins/keyboard/kbd-scrolllock-off.png0000664000000000000000000000267315172222611021670 0ustar PNG  IHDR@@iqsBIT|d pHYsnNtEXtSoftwarewww.inkscape.org<8IDATxkUGǿ"F4"RЊJK6BnSM?@hiu!Db? آ.]"j(i\(qc]SlJtq癛s_˛y/ 9sΝ;wZ$O^IIssm pX`X_ۯq` <.{[t^}@Z]wIN ]֏ -蚐snFxR+0н߷+ewM Zz]ÛpBXʘ^J@GDϑ7qp8ߞnϙ@S(&`(h h {9Ƕ A(gTk_ *Qh CڼM6&ր8؇e@_{/ 3T2OڰDŽ*^&€{:|`xb40w{>gDIؓxCW=Yh 3<`/k EznßWXx4QZF6 jzmuw$?X*I˙]Js'#Ӓv4YTF'Ӵa?g"BdFAOK m{śͱx^"Kb|T42< @KAɦEv&S`fIӒJA#_J()tz+S|+ȜgAkSiL4Fnbd)a+sι#l\7&)hԀB=AQoz޾`CZ(cJ<ާlI:gkcp70i45v=m[cF $)7)=Gh~ wC(8I%(к~k{8g/ . +fxuȌT-K)5{P2qKe=AcK{-҈&2F4Q[<4Usab!=t9K2aA:)zmnI>Ifn[)VH9/m_lLWyROI%K%iv@?rIENDB`unity-settings-daemon/plugins/keyboard/kbd-scrolllock-on.png0000664000000000000000000000247115172222611021526 0ustar PNG  IHDR@@iqsRGBbKGD pHYsnNtIME)zIDATxkTW?o#qDPl ĝBlڐvZB$[Хk.ϡJ"EQ$Cmi)͹3o2<<;sν{~G>( `Iiy_ x% ln |#p0B8#0+ }}y PX48)PhMG~[Nu6^J L NA{;-ЛCϚ0TR'^UnL`ZR!hk, \lX`4%80}\RiКdkg6D FpaNj:By@_"}'Fy =9,&NKc6Q>I T&]'"xxQо, E$jANe[IpO jOe8(`Uk3Z.ĔPsin-5F |Erԅ_0 %GK߳HJPa4æ)p" W]Dఁ2) }q4}%2Vtv#ֹer1[(#޹cJry&tޅ ew+3sB.MU6ziks'Z-䵹~m(r^|'\Yo<.pEjB\1i+:sW[)!VڊX:JT.+>OY>% -u"IENDB`unity-settings-daemon/plugins/keyboard/keyboard.gnome-settings-plugin.in0000664000000000000000000000022415172222611024061 0ustar [GNOME Settings Plugin] Module=keyboard IAge=0 Priority=6 _Name=Keyboard _Description=Keyboard plugin Authors= Copyright=Copyright © 2007 Website= unity-settings-daemon/plugins/keyboard/test-keyboard-ibus-utils.c0000664000000000000000000000566215172222611022525 0ustar #include "gsd-xkb-utils.c" #include "gsd-keyboard-manager.c" static void test_layout_from_ibus_layout (void) { gint i; const gchar *test_strings[][2] = { /* input output */ { "", "" }, { "a", "a" }, { "a(", "a" }, { "a[", "a" }, }; for (i = 0; i < G_N_ELEMENTS (test_strings); ++i) g_assert_cmpstr (layout_from_ibus_layout (test_strings[i][0]), ==, test_strings[i][1]); } static void test_variant_from_ibus_layout (void) { gint i; const gchar *test_strings[][2] = { /* input output */ { "", NULL }, { "a", NULL }, { "(", NULL }, { "()", "" }, { "(b)", "b" }, { "a(", NULL }, { "a()", "" }, { "a(b)", "b" }, }; for (i = 0; i < G_N_ELEMENTS (test_strings); ++i) g_assert_cmpstr (variant_from_ibus_layout (test_strings[i][0]), ==, test_strings[i][1]); } static void test_options_from_ibus_layout (void) { gint i, j; gchar *output_0[] = { NULL }; gchar *output_1[] = { "", NULL }; gchar *output_2[] = { "b", NULL }; gchar *output_3[] = { "b", "", NULL }; gchar *output_4[] = { "b", "c", NULL }; const gpointer tests[][2] = { /* input output */ { "", NULL }, { "a", NULL }, { "a[", output_0 }, { "a[]", output_1 }, { "a[b]", output_2 }, { "a[b,]", output_3 }, { "a[b,c]", output_4 }, }; for (i = 0; i < G_N_ELEMENTS (tests); ++i) { if (tests[i][1] == NULL) { g_assert (options_from_ibus_layout (tests[i][0]) == NULL); } else { gchar **strv_a = options_from_ibus_layout (tests[i][0]); gchar **strv_b = tests[i][1]; g_assert (g_strv_length (strv_a) == g_strv_length (strv_b)); for (j = 0; j < g_strv_length (strv_a); ++j) g_assert_cmpstr (strv_a[j], ==, strv_b[j]); } } } int main (void) { test_layout_from_ibus_layout (); test_variant_from_ibus_layout (); test_options_from_ibus_layout (); return 0; } unity-settings-daemon/plugins/keyboard/test-keyboard.c0000664000000000000000000000032415172222611020415 0ustar #define NEW gsd_keyboard_manager_new #define START gsd_keyboard_manager_start #define STOP gsd_keyboard_manager_stop #define MANAGER GsdKeyboardManager #include "gsd-keyboard-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/media-keys/0000775000000000000000000000000015172222611015725 5ustar unity-settings-daemon/plugins/media-keys/Makefile.am0000664000000000000000000000673615172222611017775 0ustar icondir = $(datadir)/icons/hicolor context = actions plugin_name = media-keys NULL = SUBDIRS = gvc plugin_LTLIBRARIES = libmedia-keys.la BUILT_SOURCES = \ gsd-marshal.h \ gsd-marshal.c \ shell-key-grabber.c \ shell-key-grabber.h \ $(NULL) gsd-marshal.c: gsd-marshal.list $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=gsd_marshal $< --header --body --internal > $@ gsd-marshal.h: gsd-marshal.list $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=gsd_marshal $< --header --internal > $@ shell-key-grabber.c: shell-key-grabber.h shell-key-grabber.h: Makefile.am org.gnome.ShellKeyGrabber.xml gdbus-codegen --interface-prefix org.gnome. \ --generate-c-code shell-key-grabber \ --c-namespace Shell \ $(srcdir)/org.gnome.ShellKeyGrabber.xml libmedia_keys_la_SOURCES = \ what-did-you-plug-in/pa-backend.c \ what-did-you-plug-in/dialog-window.c \ gsd-media-keys-plugin.c \ gsd-media-keys-manager.h \ gsd-media-keys-manager.c \ gsd-screenshot-utils.h \ gsd-screenshot-utils.c \ shortcuts-list.h \ shell-keybinding-modes.h \ $(BUILT_SOURCES) \ $(NULL) libmedia_keys_la_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -I$(top_srcdir)/plugins/media-keys/gvc \ -I$(top_srcdir)/plugins/media-keys/what-did-you-plug-in \ -DBINDIR=\"$(bindir)\" \ -DPIXMAPDIR=\""$(pkgdatadir)"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libmedia_keys_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(MEDIA_KEYS_CFLAGS) \ $(AM_CFLAGS) libmedia_keys_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libmedia_keys_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/plugins/media-keys/gvc/libgvc.la \ $(MEDIA_KEYS_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ -lm plugin_in_files = \ media-keys.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) libexec_PROGRAMS = usd-test-media-keys usd_test_media_keys_SOURCES = \ gsd-media-keys-manager.c \ gsd-media-keys-manager.h \ gsd-screenshot-utils.h \ gsd-screenshot-utils.c \ test-media-keys.c \ what-did-you-plug-in/pa-backend.c \ what-did-you-plug-in/dialog-window.c \ $(BUILT_SOURCES) \ $(NULL) usd_test_media_keys_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -I$(top_srcdir)/plugins/media-keys/gvc \ -I$(top_srcdir)/plugins/media-keys/what-did-you-plug-in \ -DBINDIR=\"$(bindir)\" \ -DPIXMAPDIR=\""$(pkgdatadir)"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) usd_test_media_keys_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(MEDIA_KEYS_CFLAGS) \ $(AM_CFLAGS) usd_test_media_keys_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/plugins/media-keys/gvc/libgvc.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(MEDIA_KEYS_LIBS) \ -lm EXTRA_DIST = \ gsd-marshal.list \ README.media-keys-API \ org.gnome.ShellKeyGrabber.xml \ $(plugin_in_files) CLEANFILES = \ $(BUILT_SOURCES) \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/media-keys/README.media-keys-API0000664000000000000000000000345215172222611021247 0ustar This is very simple documentation to gnome-settings-daemon's D-Bus API for media players. gnome-settings-daemon will send key press events from multimedia keys to applications that register their interest in those events. This allows the play/pause button to control an audio player that's not focused for example. The D-Bus API is described in gsd-media-keys-manager.c (look for introspection_xml), but a small explanation follows here. 1. Create yourself a proxy object for the remote interface: Object path: /org/gnome/SettingsDaemon/MediaKeys D-Bus name: org.gnome.SettingsDaemon.MediaKeys Interface name: org.gnome.SettingsDaemon.MediaKeys 2. Register your application with gnome-settings-daemon GrabMediaPlayerKeys ("my-application", 0) with the second argument being the current time (usually 0, or the time passed to you from an event, such as a mouse click) 3. Listen to the MediaPlayerKeyPressed() signal 4. When receiving a MediaPlayerKeyPressed() signal, check whether the first argument (application) matches the value you passed to GrabMediaPlayerKeys() and apply the action depending on the key (2nd argument) Possible values of key are: - Play - Pause - Stop - Previous - Next - Rewind - FastForward - Repeat - Shuffle 5. Every time your application is focused, you should call GrabMediaPlayerKeys() again, so that gnome-settings-daemon knows which one was last used. This allows switching between a movie player and a music player, for example, and have the buttons control the last used application. 6. When your application wants to stop using the functionality it can call ReleaseMediaPlayerKeys(). If your application does not call ReleaseMediaPlayerKeys() and releases its D-Bus connection then the application will be automatically removed from the list of applications held by gnome-settings-daemon. unity-settings-daemon/plugins/media-keys/gsd-marshal.list0000664000000000000000000000002315172222611021017 0ustar VOID:STRING,STRING unity-settings-daemon/plugins/media-keys/gsd-media-keys-manager.c0000664000000000000000000036220115172222611022310 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2001-2003 Bastien Nocera * Copyright (C) 2006-2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GUDEV #include #endif #include "gnome-settings-plugin.h" #include "gnome-settings-bus.h" #include "gnome-settings-profile.h" #include "gsd-marshal.h" #include "gsd-media-keys-manager.h" #include "shortcuts-list.h" #include "shell-key-grabber.h" #include "gsd-screenshot-utils.h" #include "gsd-input-helper.h" #include "gsd-enums.h" #include #include #include "gvc-mixer-control.h" #include "gvc-mixer-control-private.h" #include "gvc-mixer-sink.h" #include "pa-backend.h" #include "dialog-window.h" #include #ifdef HAVE_FCITX #include #endif #define GSD_MEDIA_KEYS_DBUS_PATH GSD_DBUS_PATH "/MediaKeys" #define GSD_MEDIA_KEYS_DBUS_NAME GSD_DBUS_NAME ".MediaKeys" #define GNOME_KEYRING_DBUS_NAME "org.gnome.keyring" #define GNOME_KEYRING_DBUS_PATH "/org/gnome/keyring/daemon" #define GNOME_KEYRING_DBUS_INTERFACE "org.gnome.keyring.Daemon" #define SHELL_DBUS_NAME "org.gnome.Shell" #define SHELL_DBUS_PATH "/org/gnome/Shell" #define PANEL_DBUS_NAME "org.gnome.Panel" #define UNITY_DBUS_NAME "com.canonical.Unity" #define CUSTOM_BINDING_SCHEMA SETTINGS_BINDING_DIR ".custom-keybinding" #define SHELL_GRABBER_RETRY_INTERVAL 1 static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; #define SETTINGS_INTERFACE_DIR "org.gnome.desktop.interface" #define SETTINGS_POWER_DIR "com.canonical.unity.settings-daemon.plugins.power" #define SETTINGS_XSETTINGS_DIR "com.canonical.unity.settings-daemon.plugins.xsettings" #define SETTINGS_TOUCHPAD_DIR "org.gnome.desktop.peripherals.touchpad" #define UNITY_SETTINGS_INTERFACE_DIR "com.canonical.Unity.Interface" #define TOUCHPAD_ENABLED_KEY "send-events" #define HIGH_CONTRAST "HighContrast" #define TEXT_SCALING_FACTOR_KEY (in_desktop ("Unity") ? \ "text-scale-factor" : "text-scaling-factor") #define VOLUME_STEP 6 /* percents for one volume button press */ #define ENV_GTK_IM_MODULE "GTK_IM_MODULE" #define GTK_IM_MODULE_IBUS "ibus" #define GTK_IM_MODULE_FCITX "fcitx" #define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources" #define KEY_CURRENT_INPUT_SOURCE "current" #define KEY_INPUT_SOURCES "sources" #define INPUT_SOURCE_TYPE_XKB "xkb" #define INPUT_SOURCE_TYPE_IBUS "ibus" #define INPUT_SOURCE_TYPE_FCITX "fcitx" #define FCITX_XKB_PREFIX "fcitx-keyboard-" #define SYSTEMD_DBUS_NAME "org.freedesktop.login1" #define SYSTEMD_DBUS_PATH "/org/freedesktop/login1" #define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager" #define GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerPrivate)) typedef struct { char *application; char *dbus_name; guint32 time; guint watch_id; } MediaPlayer; typedef struct { MediaKeyType key_type; ShellKeyBindingMode modes; const char *settings_key; const char *hard_coded; char *custom_path; char *custom_command; Key *key; guint accel_id; } MediaKey; typedef struct { GsdMediaKeysManager *manager; MediaKey *key; } GrabData; struct GsdMediaKeysManagerPrivate { /* Volume bits */ GvcMixerControl *volume; GvcMixerStream *sink; GvcMixerStream *source; ca_context *ca; GtkSettings *gtksettings; #ifdef HAVE_GUDEV GHashTable *streams; /* key = X device ID, value = stream id */ GUdevClient *udev_client; #endif /* HAVE_GUDEV */ GSettings *settings; GSettings *input_settings; GHashTable *custom_settings; GSettings *sound_settings; GPtrArray *keys; /* HighContrast theme settings */ GSettings *interface_settings; char *icon_theme; char *gtk_theme; /* Power stuff */ GSettings *power_settings; GDBusProxy *power_proxy; GDBusProxy *power_screen_proxy; GDBusProxy *power_keyboard_proxy; /* Shell stuff */ guint name_owner_id; GDBusProxy *shell_proxy; ShellKeyGrabber *key_grabber; GCancellable *shell_cancellable; GCancellable *grab_cancellable; /* ScreenSaver stuff */ GsdScreenSaver *screen_saver_proxy; /* systemd stuff */ GDBusProxy *logind_proxy; gint inhibit_keys_fd; /* Multihead stuff */ GdkScreen *current_screen; GSList *screens; GdkScreen *screen; int opcode; GList *media_players; GDBusNodeInfo *introspection_data; GDBusConnection *connection; GCancellable *bus_cancellable; GDBusProxy *xrandr_proxy; GCancellable *cancellable; /* Only used for XRandR operations */ guint start_idle_id; /* Ubuntu notifications */ NotifyNotification *volume_notification; NotifyNotification *brightness_notification; NotifyNotification *kb_backlight_notification; /* Legacy keygrabber stuff */ guint unity_name_owner_id; guint panel_name_owner_id; guint have_legacy_keygrabber; #ifdef HAVE_FCITX FcitxInputMethod *fcitx; #endif gboolean is_ibus_active; gboolean is_fcitx_active; /* What did you plug in dialog */ pa_backend *wdypi_pa_backend; }; static void gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass); static void gsd_media_keys_manager_init (GsdMediaKeysManager *media_keys_manager); static void gsd_media_keys_manager_finalize (GObject *object); static void register_manager (GsdMediaKeysManager *manager); static void custom_binding_changed (GSettings *settings, const char *settings_key, GsdMediaKeysManager *manager); static void grab_media_keys (GsdMediaKeysManager *manager); static void grab_media_key (MediaKey *key, GsdMediaKeysManager *manager); static void ungrab_media_key (MediaKey *key, GsdMediaKeysManager *manager); G_DEFINE_TYPE (GsdMediaKeysManager, gsd_media_keys_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; #define NOTIFY_CAP_PRIVATE_SYNCHRONOUS "x-canonical-private-synchronous" #define NOTIFY_CAP_PRIVATE_ICON_ONLY "x-canonical-private-icon-only" #define NOTIFY_HINT_TRUE "true" typedef struct { GsdMediaKeysManager *manager; MediaKeyType type; guint old_percentage; } GsdBrightnessActionData; static const char *volume_icons[] = { "notification-audio-volume-muted", "notification-audio-volume-low", "notification-audio-volume-medium", "notification-audio-volume-high", NULL }; static const char *audio_volume_icons[] = { "audio-volume-muted-symbolic", "audio-volume-low-symbolic", "audio-volume-medium-symbolic", "audio-volume-high-symbolic", NULL }; static const char *mic_volume_icons[] = { "microphone-sensitivity-muted-symbolic", "microphone-sensitivity-low-symbolic", "microphone-sensitivity-medium-symbolic", "microphone-sensitivity-high-symbolic", NULL }; static const char *brightness_icons[] = { "notification-display-brightness-off", "notification-display-brightness-low", "notification-display-brightness-medium", "notification-display-brightness-high", "notification-display-brightness-full", NULL }; static const char *kb_backlight_icons[] = { "notification-keyboard-brightness-off", "notification-keyboard-brightness-low", "notification-keyboard-brightness-medium", "notification-keyboard-brightness-high", "notification-keyboard-brightness-full", NULL }; static gboolean in_desktop (const gchar *name) { const gchar *desktop_name_list; gchar **names; gboolean in_list = FALSE; gint i; desktop_name_list = g_getenv ("XDG_CURRENT_DESKTOP"); if (!desktop_name_list) return FALSE; names = g_strsplit (desktop_name_list, ":", -1); for (i = 0; names[i] && !in_list; i++) if (strcmp (names[i], name) == 0) { in_list = TRUE; break; } g_strfreev (names); return in_list; } static const char * calculate_icon_name (gint value, const char **icon_names) { value = CLAMP (value, 0, 100); gint length = g_strv_length ((gchar**) icon_names); gint s = (length - 1) * value / 100 + 1; s = CLAMP (s, 1, length - 1); return icon_names[s]; } static gboolean ubuntu_osd_notification_is_supported (void) { GList *caps; gboolean has_cap; caps = notify_get_server_caps (); has_cap = (g_list_find_custom (caps, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, (GCompareFunc) g_strcmp0) != NULL); g_list_foreach (caps, (GFunc) g_free, NULL); g_list_free (caps); return has_cap; } static gboolean ubuntu_osd_notification_show_icon (const char *icon, const char *hint) { if (!ubuntu_osd_notification_is_supported ()) return FALSE; NotifyNotification *notification = notify_notification_new (" ", "", icon); notify_notification_set_hint_string (notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint); notify_notification_set_hint_string (notification, NOTIFY_CAP_PRIVATE_ICON_ONLY, NOTIFY_HINT_TRUE); gboolean res = notify_notification_show (notification, NULL); g_object_unref (notification); return res; } static gboolean ubuntu_osd_do_notification (NotifyNotification **notification, const char *hint, gint value, gboolean muted, const char **icon_names) { if (!ubuntu_osd_notification_is_supported ()) return FALSE; if (!*notification) { *notification = notify_notification_new (" ", "", NULL); notify_notification_set_hint_string (*notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint); } value = CLAMP (value, -1, 101); const char *icon = muted ? icon_names[0] : calculate_icon_name (value, icon_names); notify_notification_set_hint_int32 (*notification, "value", value); notify_notification_update (*notification, " ", "", icon); return notify_notification_show (*notification, NULL); } static gboolean ubuntu_osd_notification_show_volume (GsdMediaKeysManager *manager, gint value, gboolean muted, gboolean is_mic) { const char **icons_name = is_mic ? mic_volume_icons : volume_icons; return ubuntu_osd_do_notification (&manager->priv->volume_notification, "volume", value, muted, icons_name); } static gboolean ubuntu_osd_notification_show_brightness (GsdMediaKeysManager *manager, gint value) { return ubuntu_osd_do_notification (&manager->priv->brightness_notification, "brightness", value, value <= 0, brightness_icons); } static gboolean ubuntu_osd_notification_show_kb_backlight (GsdMediaKeysManager *manager, gint value) { return ubuntu_osd_do_notification (&manager->priv->kb_backlight_notification, "keyboard", value, value <= 0, kb_backlight_icons); } static void init_screens (GsdMediaKeysManager *manager) { GdkDisplay *display; int i; display = gdk_display_get_default (); for (i = 0; i < gdk_display_get_n_screens (display); i++) { GdkScreen *screen; screen = gdk_display_get_screen (display, i); if (screen == NULL) { continue; } manager->priv->screens = g_slist_append (manager->priv->screens, screen); } manager->priv->current_screen = manager->priv->screens->data; } static void media_key_free (MediaKey *key) { if (key == NULL) return; g_free (key->custom_path); g_free (key->custom_command); if (key->key) free_key (key->key); g_free (key); } static char * get_term_command (GsdMediaKeysManager *manager) { char *cmd_term, *cmd_args;; char *cmd = NULL; GSettings *settings; settings = g_settings_new ("org.gnome.desktop.default-applications.terminal"); cmd_term = g_settings_get_string (settings, "exec"); if (cmd_term[0] == '\0') cmd_term = g_strdup ("gnome-terminal"); cmd_args = g_settings_get_string (settings, "exec-arg"); if (strcmp (cmd_term, "") != 0) { cmd = g_strdup_printf ("%s %s -e", cmd_term, cmd_args); } else { cmd = g_strdup_printf ("%s -e", cmd_term); } g_free (cmd_args); g_free (cmd_term); g_object_unref (settings); return cmd; } static char ** get_keyring_env (GsdMediaKeysManager *manager) { GError *error = NULL; GVariant *variant, *item; GVariantIter *iter; char **envp; variant = g_dbus_connection_call_sync (manager->priv->connection, GNOME_KEYRING_DBUS_NAME, GNOME_KEYRING_DBUS_PATH, GNOME_KEYRING_DBUS_INTERFACE, "GetEnvironment", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_warning ("Failed to call GetEnvironment on keyring daemon: %s", error->message); g_error_free (error); return NULL; } envp = g_get_environ (); envp = g_environ_unsetenv (envp, "DESKTOP_AUTOSTART_ID"); g_variant_get (variant, "(a{ss})", &iter); while ((item = g_variant_iter_next_value (iter))) { char *key; char *value; g_variant_get (item, "{ss}", &key, &value); envp = g_environ_setenv (envp, key, value, TRUE); g_variant_unref (item); g_free (key); g_free (value); } g_variant_iter_free (iter); g_variant_unref (variant); return envp; } static void execute (GsdMediaKeysManager *manager, char *cmd, gboolean need_term) { gboolean retval; char **argv; int argc; char *exec; char *term = NULL; GError *error = NULL; retval = FALSE; if (need_term) term = get_term_command (manager); if (term) { exec = g_strdup_printf ("%s %s", term, cmd); g_free (term); } else { exec = g_strdup (cmd); } if (g_shell_parse_argv (exec, &argc, &argv, NULL)) { char **envp; envp = get_keyring_env (manager); retval = g_spawn_async (g_get_home_dir (), argv, envp, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error); g_strfreev (argv); g_strfreev (envp); } if (retval == FALSE) { g_warning ("Couldn't execute command: %s: %s", exec, error->message); g_error_free (error); } g_free (exec); } static void print_key_parse_error (MediaKey *key, const char *str) { if (str == NULL || *str == '\0') return; if (key->settings_key != NULL) g_debug ("Unable to parse key '%s' for GSettings entry '%s'", str, key->settings_key); else g_debug ("Unable to parse hard-coded key '%s'", key->hard_coded); } static char * get_key_string (GsdMediaKeysManager *manager, MediaKey *key) { if (key->settings_key == "switch-input-source" || key->settings_key == "switch-input-source-backward") return g_settings_get_strv (manager->priv->input_settings, key->settings_key)[0]; else if (key->settings_key != NULL) return g_settings_get_string (manager->priv->settings, key->settings_key); else if (key->hard_coded != NULL) return g_strdup (key->hard_coded); else if (key->custom_path != NULL) { GSettings *settings; settings = g_hash_table_lookup (manager->priv->custom_settings, key->custom_path); return g_settings_get_string (settings, "binding"); } else g_assert_not_reached (); } static void ensure_cancellable (GCancellable **cancellable) { if (*cancellable == NULL) { *cancellable = g_cancellable_new (); g_object_add_weak_pointer (G_OBJECT (*cancellable), (gpointer *)cancellable); } else { g_object_ref (*cancellable); } } static void show_osd (GsdMediaKeysManager *manager, const char *icon, const char *label, int level) { GVariantBuilder builder; if (manager->priv->shell_proxy == NULL) return; g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE); g_variant_builder_open (&builder, G_VARIANT_TYPE_VARDICT); if (icon) g_variant_builder_add (&builder, "{sv}", "icon", g_variant_new_string (icon)); if (label) g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (label)); if (level >= 0) g_variant_builder_add (&builder, "{sv}", "level", g_variant_new_int32 (level)); g_variant_builder_close (&builder); g_dbus_proxy_call (manager->priv->shell_proxy, "ShowOSD", g_variant_builder_end (&builder), G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, manager->priv->shell_cancellable, NULL, NULL); } static const char * get_icon_name_for_volume (gboolean is_mic, gboolean muted, int volume) { int n; if (muted) { n = 0; } else { /* select image */ n = 3 * volume / 100 + 1; if (n < 1) { n = 1; } else if (n > 3) { n = 3; } } if (is_mic) return mic_volume_icons[n]; else return audio_volume_icons[n]; } static gboolean retry_grabs (gpointer data) { GsdMediaKeysManager *manager = data; g_debug ("Retrying to grab accelerators"); grab_media_keys (manager); return FALSE; } static void grab_accelerators_complete (GObject *object, GAsyncResult *result, gpointer user_data) { GVariant *actions; gboolean retry = FALSE; GError *error = NULL; GsdMediaKeysManager *manager = user_data; shell_key_grabber_call_grab_accelerators_finish (SHELL_KEY_GRABBER (object), &actions, result, &error); if (error) { retry = (error->code == G_DBUS_ERROR_UNKNOWN_METHOD); if (!retry && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to grab accelerators: %s (%d)", error->message, error->code); else if (retry) g_debug ("Failed to grab accelerators, will retry: %s (%d)", error->message, error->code); g_error_free (error); } else { int i; for (i = 0; i < manager->priv->keys->len; i++) { MediaKey *key; key = g_ptr_array_index (manager->priv->keys, i); g_variant_get_child (actions, i, "u", &key->accel_id); } } if (retry) g_timeout_add_seconds (SHELL_GRABBER_RETRY_INTERVAL, retry_grabs, manager); } static void grab_media_keys (GsdMediaKeysManager *manager) { GVariantBuilder builder; int i; g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(su)")); for (i = 0; i < manager->priv->keys->len; i++) { MediaKey *key; char *tmp; key = g_ptr_array_index (manager->priv->keys, i); tmp = get_key_string (manager, key); g_variant_builder_add (&builder, "(su)", tmp, key->modes); g_free (tmp); } shell_key_grabber_call_grab_accelerators (manager->priv->key_grabber, g_variant_builder_end (&builder), manager->priv->grab_cancellable, grab_accelerators_complete, manager); } static void grab_accelerator_complete (GObject *object, GAsyncResult *result, gpointer user_data) { GrabData *data = user_data; MediaKey *key = data->key; GError *error = NULL; if (!shell_key_grabber_call_grab_accelerator_finish (SHELL_KEY_GRABBER (object), &key->accel_id, result, &error)) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to grab accelerator: %s", error->message); g_error_free (error); } g_slice_free (GrabData, data); } static void grab_media_key (MediaKey *key, GsdMediaKeysManager *manager) { GrabData *data; char *tmp; ungrab_media_key (key, manager); tmp = get_key_string (manager, key); data = g_slice_new0 (GrabData); data->manager = manager; data->key = key; shell_key_grabber_call_grab_accelerator (manager->priv->key_grabber, tmp, key->modes, manager->priv->grab_cancellable, grab_accelerator_complete, data); g_free (tmp); } static gboolean grab_media_key_legacy (MediaKey *key, GsdMediaKeysManager *manager) { char *tmp; gboolean need_flush; need_flush = FALSE; if (key->key != NULL) { need_flush = TRUE; ungrab_key_unsafe (key->key, manager->priv->screens); } free_key (key->key); key->key = NULL; tmp = get_key_string (manager, key); key->key = parse_key (tmp); if (key->key == NULL) { print_key_parse_error (key, tmp); g_free (tmp); return need_flush; } grab_key_unsafe (key->key, GSD_KEYGRAB_NORMAL, manager->priv->screens); g_free (tmp); return TRUE; } static void ungrab_accelerator_complete (GObject *object, GAsyncResult *result, gpointer user_data) { GsdMediaKeysManager *manager = user_data; GError *error = NULL; if (!shell_key_grabber_call_ungrab_accelerator_finish (SHELL_KEY_GRABBER (object), NULL, result, &error)) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to ungrab accelerator: %s", error->message); g_error_free (error); } } static void ungrab_media_key (MediaKey *key, GsdMediaKeysManager *manager) { if (key->accel_id == 0) return; shell_key_grabber_call_ungrab_accelerator (manager->priv->key_grabber, key->accel_id, manager->priv->grab_cancellable, ungrab_accelerator_complete, manager); key->accel_id = 0; } static void gsettings_changed_cb (GSettings *settings, const gchar *settings_key, GsdMediaKeysManager *manager) { int i; gboolean need_flush = FALSE; if (manager->priv->have_legacy_keygrabber) need_flush = TRUE; /* Give up if we don't have proxy to the shell */ else if (!manager->priv->key_grabber) return; /* handled in gsettings_custom_changed_cb() */ if (g_str_equal (settings_key, "custom-keybindings")) return; if (manager->priv->have_legacy_keygrabber) gdk_error_trap_push (); /* Find the key that was modified */ for (i = 0; i < manager->priv->keys->len; i++) { MediaKey *key; key = g_ptr_array_index (manager->priv->keys, i); /* Skip over hard-coded and GConf keys */ if (key->settings_key == NULL) continue; if (strcmp (settings_key, key->settings_key) == 0) { if (!manager->priv->have_legacy_keygrabber) grab_media_key (key, manager); else { if (grab_media_key_legacy (key, manager)) need_flush = TRUE; } break; } } if (manager->priv->have_legacy_keygrabber) { if (need_flush) gdk_flush (); if (gdk_error_trap_pop ()) g_warning ("Grab failed for some keys, another application may already have access the them."); } } static MediaKey * media_key_new_for_path (GsdMediaKeysManager *manager, char *path) { GSettings *settings; char *command, *binding; MediaKey *key; g_debug ("media_key_new_for_path: %s", path); settings = g_hash_table_lookup (manager->priv->custom_settings, path); if (settings == NULL) { settings = g_settings_new_with_path (CUSTOM_BINDING_SCHEMA, path); g_signal_connect (settings, "changed", G_CALLBACK (custom_binding_changed), manager); g_hash_table_insert (manager->priv->custom_settings, g_strdup (path), settings); } command = g_settings_get_string (settings, "command"); binding = g_settings_get_string (settings, "binding"); if (*command == '\0' && *binding == '\0') { g_debug ("Key binding (%s) is incomplete", path); g_free (command); g_free (binding); return NULL; } g_free (binding); key = g_new0 (MediaKey, 1); key->key_type = CUSTOM_KEY; key->modes = GSD_KEYBINDING_MODE_LAUNCHER; key->custom_path = g_strdup (path); key->custom_command = command; return key; } static void update_custom_binding (GsdMediaKeysManager *manager, char *path) { MediaKey *key; int i; /* Remove the existing key */ for (i = 0; i < manager->priv->keys->len; i++) { key = g_ptr_array_index (manager->priv->keys, i); if (key->custom_path == NULL) continue; if (strcmp (key->custom_path, path) == 0) { g_debug ("Removing custom key binding %s", path); ungrab_media_key (key, manager); g_ptr_array_remove_index_fast (manager->priv->keys, i); break; } } /* And create a new one! */ key = media_key_new_for_path (manager, path); if (key) { g_debug ("Adding new custom key binding %s", path); g_ptr_array_add (manager->priv->keys, key); grab_media_key (key, manager); } } static void custom_binding_changed (GSettings *settings, const char *settings_key, GsdMediaKeysManager *manager) { char *path; if (strcmp (settings_key, "name") == 0) return; /* we don't care */ g_object_get (settings, "path", &path, NULL); update_custom_binding (manager, path); g_free (path); } static void gsettings_custom_changed_cb (GSettings *settings, const char *settings_key, GsdMediaKeysManager *manager) { char **bindings; int i, j, n_bindings; bindings = g_settings_get_strv (settings, settings_key); n_bindings = g_strv_length (bindings); /* Handle additions */ for (i = 0; i < n_bindings; i++) { if (g_hash_table_lookup (manager->priv->custom_settings, bindings[i])) continue; update_custom_binding (manager, bindings[i]); } /* Handle removals */ for (i = 0; i < manager->priv->keys->len; i++) { gboolean found = FALSE; MediaKey *key = g_ptr_array_index (manager->priv->keys, i); if (key->key_type != CUSTOM_KEY) continue; for (j = 0; j < n_bindings && !found; j++) found = strcmp (bindings[j], key->custom_path) == 0; if (found) continue; if (manager->priv->have_legacy_keygrabber && key->key) { gdk_error_trap_push (); ungrab_key_unsafe (key->key, manager->priv->screens); gdk_flush (); if (gdk_error_trap_pop ()) g_warning ("Ungrab failed for custom key '%s'", key->custom_path); } else ungrab_media_key (key, manager); g_hash_table_remove (manager->priv->custom_settings, key->custom_path); g_ptr_array_remove_index_fast (manager->priv->keys, i); --i; /* make up for the removed key */ } g_strfreev (bindings); } static void add_key (GsdMediaKeysManager *manager, guint i) { MediaKey *key; key = g_new0 (MediaKey, 1); key->key_type = media_keys[i].key_type; key->settings_key = media_keys[i].settings_key; key->hard_coded = media_keys[i].hard_coded; key->modes = media_keys[i].modes; g_ptr_array_add (manager->priv->keys, key); if (manager->priv->have_legacy_keygrabber) grab_media_key_legacy (key, manager); } static void init_kbd (GsdMediaKeysManager *manager) { char **custom_paths; int i; gnome_settings_profile_start (NULL); if (manager->priv->have_legacy_keygrabber) gdk_error_trap_push (); /* Media keys * Add hard-coded shortcuts first so that they can't be preempted */ for (i = 0; i < G_N_ELEMENTS (media_keys); i++) { if (media_keys[i].hard_coded) add_key (manager, i); } for (i = 0; i < G_N_ELEMENTS (media_keys); i++) { if (media_keys[i].hard_coded == NULL) add_key (manager, i); } /* Custom shortcuts */ custom_paths = g_settings_get_strv (manager->priv->settings, "custom-keybindings"); for (i = 0; i < g_strv_length (custom_paths); i++) { MediaKey *key; g_debug ("Setting up custom keybinding %s", custom_paths[i]); key = media_key_new_for_path (manager, custom_paths[i]); if (!key) { continue; } g_ptr_array_add (manager->priv->keys, key); if (manager->priv->have_legacy_keygrabber) grab_media_key_legacy (key, manager); } g_strfreev (custom_paths); if (!manager->priv->have_legacy_keygrabber) grab_media_keys (manager); else { gdk_flush (); if (gdk_error_trap_pop ()) g_warning ("Grab failed for some keys, another application may already have access the them."); } gnome_settings_profile_end (NULL); } static void launch_app (GAppInfo *app_info, gint64 timestamp) { GError *error = NULL; GdkAppLaunchContext *launch_context; /* setup the launch context so the startup notification is correct */ launch_context = gdk_display_get_app_launch_context (gdk_display_get_default ()); gdk_app_launch_context_set_timestamp (launch_context, timestamp); if (!g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error)) { g_warning ("Could not launch '%s': %s", g_app_info_get_commandline (app_info), error->message); g_error_free (error); } g_object_unref (launch_context); } static void do_url_action (GsdMediaKeysManager *manager, const char *scheme, gint64 timestamp) { GAppInfo *app_info; app_info = g_app_info_get_default_for_uri_scheme (scheme); if (app_info != NULL) { launch_app (app_info, timestamp); g_object_unref (app_info); } else { g_warning ("Could not find default application for '%s' scheme", scheme); } } static void do_media_action (GsdMediaKeysManager *manager, gint64 timestamp) { GAppInfo *app_info; app_info = g_app_info_get_default_for_type ("audio/x-vorbis+ogg", FALSE); if (app_info != NULL) { launch_app (app_info, timestamp); g_object_unref (app_info); } else { g_warning ("Could not find default application for '%s' mime-type", "audio/x-vorbis+ogg"); } } static void do_terminal_action (GsdMediaKeysManager *manager) { GSettings *settings; char *term; settings = g_settings_new ("org.gnome.desktop.default-applications.terminal"); term = g_settings_get_string (settings, "exec"); if (term) execute (manager, term, FALSE); g_free (term); g_object_unref (settings); } static void gnome_session_shutdown (GsdMediaKeysManager *manager) { GError *error = NULL; GVariant *variant; GDBusProxy *proxy; proxy = G_DBUS_PROXY (gnome_settings_bus_get_session_proxy ()); variant = g_dbus_proxy_call_sync (proxy, "Shutdown", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_warning ("Failed to call Shutdown on session manager: %s", error->message); g_error_free (error); return; } g_variant_unref (variant); g_object_unref (proxy); } static void do_logout_action (GsdMediaKeysManager *manager) { execute (manager, "gnome-session-quit --logout", FALSE); } static void do_eject_action_cb (GDrive *drive, GAsyncResult *res, GsdMediaKeysManager *manager) { g_drive_eject_with_operation_finish (drive, res, NULL); } #define NO_SCORE 0 #define SCORE_CAN_EJECT 50 #define SCORE_HAS_MEDIA 100 static void do_eject_action (GsdMediaKeysManager *manager) { GList *drives, *l; GDrive *fav_drive; guint score; GVolumeMonitor *volume_monitor; volume_monitor = g_volume_monitor_get (); /* Find the best drive to eject */ fav_drive = NULL; score = NO_SCORE; drives = g_volume_monitor_get_connected_drives (volume_monitor); for (l = drives; l != NULL; l = l->next) { GDrive *drive = l->data; if (g_drive_can_eject (drive) == FALSE) continue; if (g_drive_is_media_removable (drive) == FALSE) continue; if (score < SCORE_CAN_EJECT) { fav_drive = drive; score = SCORE_CAN_EJECT; } if (g_drive_has_media (drive) == FALSE) continue; if (score < SCORE_HAS_MEDIA) { fav_drive = drive; score = SCORE_HAS_MEDIA; break; } } /* Show OSD */ if (!ubuntu_osd_notification_show_icon ("notification-device-eject", "Eject")) { show_osd (manager, "media-eject-symbolic", NULL, -1); } /* Clean up the drive selection and exit if no suitable * drives are found */ if (fav_drive != NULL) fav_drive = g_object_ref (fav_drive); g_list_foreach (drives, (GFunc) g_object_unref, NULL); if (fav_drive == NULL) return; /* Eject! */ g_drive_eject_with_operation (fav_drive, G_MOUNT_UNMOUNT_FORCE, NULL, NULL, (GAsyncReadyCallback) do_eject_action_cb, manager); g_object_unref (fav_drive); g_object_unref (volume_monitor); } static void do_home_key_action (GsdMediaKeysManager *manager, gint64 timestamp) { GFile *file; GError *error = NULL; char *uri; file = g_file_new_for_path (g_get_home_dir ()); uri = g_file_get_uri (file); g_object_unref (file); if (gtk_show_uri (NULL, uri, timestamp, &error) == FALSE) { g_warning ("Failed to launch '%s': %s", uri, error->message); g_error_free (error); } g_free (uri); } static void do_search_action (GsdMediaKeysManager *manager, gint64 timestamp) { g_dbus_proxy_call (manager->priv->shell_proxy, "FocusSearch", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, manager->priv->shell_cancellable, NULL, NULL); } static void do_execute_desktop_or_desktop (GsdMediaKeysManager *manager, const char *desktop, const char *alt_desktop, gint64 timestamp) { GDesktopAppInfo *app_info; app_info = g_desktop_app_info_new (desktop); if (app_info == NULL) app_info = g_desktop_app_info_new (alt_desktop); if (app_info != NULL) { launch_app (G_APP_INFO (app_info), timestamp); g_object_unref (app_info); return; } g_warning ("Could not find application '%s' or '%s'", desktop, alt_desktop); } static void do_touchpad_osd_action (GsdMediaKeysManager *manager, gboolean state) { if (!ubuntu_osd_notification_show_icon ((!state) ? "touchpad-disabled-symbolic" : "input-touchpad-symbolic", "Touchpad")) { show_osd (manager, state ? "input-touchpad-symbolic" : "touchpad-disabled-symbolic", NULL, -1); } } static void do_touchpad_action (GsdMediaKeysManager *manager) { GSettings *settings; gboolean state; if (touchpad_is_present () == FALSE) { do_touchpad_osd_action (manager, FALSE); return; } settings = g_settings_new (SETTINGS_TOUCHPAD_DIR); state = (g_settings_get_enum (settings, TOUCHPAD_ENABLED_KEY) == G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED); do_touchpad_osd_action (manager, !state); g_settings_set_enum (settings, TOUCHPAD_ENABLED_KEY, !state ? G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED : G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED); g_object_unref (settings); } static void on_screen_locked (GsdScreenSaver *screen_saver, GAsyncResult *result, GsdMediaKeysManager *manager) { gboolean is_locked; GError *error = NULL; is_locked = gsd_screen_saver_call_lock_finish (screen_saver, result, &error); if (!is_locked) { g_warning ("Couldn't lock screen: %s", error->message); g_error_free (error); return; } } static void do_lock_screensaver (GsdMediaKeysManager *manager) { GsdMediaKeysManagerPrivate *priv = manager->priv; if (priv->screen_saver_proxy == NULL) priv->screen_saver_proxy = gnome_settings_bus_get_screen_saver_proxy (); gsd_screen_saver_call_lock (priv->screen_saver_proxy, priv->bus_cancellable, (GAsyncReadyCallback) on_screen_locked, manager); } static void sound_theme_changed (GtkSettings *settings, GParamSpec *pspec, GsdMediaKeysManager *manager) { char *theme_name; g_object_get (G_OBJECT (manager->priv->gtksettings), "gtk-sound-theme-name", &theme_name, NULL); if (theme_name) ca_context_change_props (manager->priv->ca, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL); g_free (theme_name); } static void ensure_canberra (GsdMediaKeysManager *manager) { char *theme_name; if (manager->priv->ca != NULL) return; ca_context_create (&manager->priv->ca); ca_context_set_driver (manager->priv->ca, "pulse"); ca_context_change_props (manager->priv->ca, 0, CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl", NULL); manager->priv->gtksettings = gtk_settings_get_for_screen (gdk_screen_get_default ()); g_object_get (G_OBJECT (manager->priv->gtksettings), "gtk-sound-theme-name", &theme_name, NULL); if (theme_name) ca_context_change_props (manager->priv->ca, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL); g_free (theme_name); g_signal_connect (manager->priv->gtksettings, "notify::gtk-sound-theme-name", G_CALLBACK (sound_theme_changed), manager); } static void update_dialog (GsdMediaKeysManager *manager, GvcMixerStream *stream, guint vol, gboolean muted, gboolean sound_changed, gboolean quiet) { GvcMixerUIDevice *device; const GvcMixerStreamPort *port; const char *icon; if (ubuntu_osd_notification_show_volume (manager, vol, muted, !GVC_IS_MIXER_SINK (stream))) goto done; vol = CLAMP (vol, 0, 100); icon = get_icon_name_for_volume (!GVC_IS_MIXER_SINK (stream), muted, vol); port = gvc_mixer_stream_get_port (stream); if (g_strcmp0 (gvc_mixer_stream_get_form_factor (stream), "internal") != 0 || (port != NULL && g_strcmp0 (port->port, "analog-output-speaker") != 0 && g_strcmp0 (port->port, "analog-output") != 0)) { device = gvc_mixer_control_lookup_device_from_stream (manager->priv->volume, stream); show_osd (manager, icon, gvc_mixer_ui_device_get_description (device), vol); } else { show_osd (manager, icon, NULL, vol); } done: if (quiet == FALSE && sound_changed != FALSE && muted == FALSE) { ensure_canberra (manager); ca_context_change_device (manager->priv->ca, gvc_mixer_stream_get_name (stream)); ca_context_play (manager->priv->ca, 1, CA_PROP_EVENT_ID, "audio-volume-change", CA_PROP_EVENT_DESCRIPTION, "volume changed through key press", CA_PROP_CANBERRA_CACHE_CONTROL, "permanent", NULL); } } #ifdef HAVE_GUDEV /* PulseAudio gives us /devices/... paths, when udev * expects /sys/devices/... paths. */ static GUdevDevice * get_udev_device_for_sysfs_path (GsdMediaKeysManager *manager, const char *sysfs_path) { char *path; GUdevDevice *dev; path = g_strdup_printf ("/sys%s", sysfs_path); dev = g_udev_client_query_by_sysfs_path (manager->priv->udev_client, path); g_free (path); return dev; } static GvcMixerStream * get_stream_for_device_id (GsdMediaKeysManager *manager, gboolean is_output, guint deviceid) { char *devnode; gpointer id_ptr; GvcMixerStream *res; GUdevDevice *dev, *parent; GSList *streams, *l; id_ptr = g_hash_table_lookup (manager->priv->streams, GUINT_TO_POINTER (deviceid)); if (id_ptr != NULL) { if (GPOINTER_TO_UINT (id_ptr) == (guint) -1) return NULL; else return gvc_mixer_control_lookup_stream_id (manager->priv->volume, GPOINTER_TO_UINT (id_ptr)); } devnode = xdevice_get_device_node (deviceid); if (devnode == NULL) { g_debug ("Could not find device node for XInput device %d", deviceid); return NULL; } dev = g_udev_client_query_by_device_file (manager->priv->udev_client, devnode); if (dev == NULL) { g_debug ("Could not find udev device for device path '%s'", devnode); g_free (devnode); return NULL; } g_free (devnode); if (g_strcmp0 (g_udev_device_get_property (dev, "ID_BUS"), "usb") != 0) { g_debug ("Not handling XInput device %d, not USB", deviceid); g_hash_table_insert (manager->priv->streams, GUINT_TO_POINTER (deviceid), GUINT_TO_POINTER ((guint) -1)); g_object_unref (dev); return NULL; } parent = g_udev_device_get_parent_with_subsystem (dev, "usb", "usb_device"); if (parent == NULL) { g_warning ("No USB device parent for XInput device %d even though it's USB", deviceid); g_object_unref (dev); return NULL; } res = NULL; if (is_output) streams = gvc_mixer_control_get_sinks (manager->priv->volume); else streams = gvc_mixer_control_get_sources (manager->priv->volume); for (l = streams; l; l = l->next) { GvcMixerStream *stream = l->data; const char *sysfs_path; GUdevDevice *stream_dev, *stream_parent; sysfs_path = gvc_mixer_stream_get_sysfs_path (stream); stream_dev = get_udev_device_for_sysfs_path (manager, sysfs_path); if (stream_dev == NULL) continue; stream_parent = g_udev_device_get_parent_with_subsystem (stream_dev, "usb", "usb_device"); g_object_unref (stream_dev); if (stream_parent == NULL) continue; if (g_strcmp0 (g_udev_device_get_sysfs_path (stream_parent), g_udev_device_get_sysfs_path (parent)) == 0) { res = stream; } g_object_unref (stream_parent); if (res != NULL) break; } g_slist_free (streams); if (res) g_hash_table_insert (manager->priv->streams, GUINT_TO_POINTER (deviceid), GUINT_TO_POINTER (gvc_mixer_stream_get_id (res))); else g_hash_table_insert (manager->priv->streams, GUINT_TO_POINTER (deviceid), GUINT_TO_POINTER ((guint) -1)); return res; } #endif /* HAVE_GUDEV */ static void do_sound_action (GsdMediaKeysManager *manager, guint deviceid, int type, gboolean is_output, gboolean quiet) { GvcMixerStream *stream; gboolean old_muted, new_muted; guint old_vol, new_vol, norm_vol_step, osd_vol; gboolean sound_changed; pa_volume_t max_volume; /* Find the stream that corresponds to the device, if any */ stream = NULL; #ifdef HAVE_GUDEV stream = get_stream_for_device_id (manager, is_output, deviceid); #endif /* HAVE_GUDEV */ if (stream == NULL) { if (is_output) stream = manager->priv->sink; else stream = manager->priv->source; } if (stream == NULL) return; if (g_settings_get_boolean (manager->priv->sound_settings, "allow-amplified-volume")) max_volume = PA_VOLUME_UI_MAX; else max_volume = PA_VOLUME_NORM; norm_vol_step = PA_VOLUME_NORM * VOLUME_STEP / 100; /* FIXME: this is racy */ new_vol = old_vol = gvc_mixer_stream_get_volume (stream); new_muted = old_muted = gvc_mixer_stream_get_is_muted (stream); sound_changed = FALSE; switch (type) { case MUTE_KEY: new_muted = !old_muted; break; case VOLUME_DOWN_KEY: if (old_vol <= norm_vol_step) { new_vol = 0; new_muted = TRUE; } else { new_vol = old_vol - norm_vol_step; } break; case VOLUME_UP_KEY: new_muted = FALSE; /* When coming out of mute only increase the volume if it was 0 */ if (!old_muted || old_vol == 0) new_vol = MIN (old_vol + norm_vol_step, max_volume); break; } if (old_muted != new_muted) { gvc_mixer_stream_change_is_muted (stream, new_muted); sound_changed = TRUE; } if (old_vol != new_vol) { if (gvc_mixer_stream_set_volume (stream, new_vol) != FALSE) { gvc_mixer_stream_push_volume (stream); sound_changed = TRUE; } } if (type == VOLUME_DOWN_KEY && old_vol == 0 && old_muted) osd_vol = -1; else if (type == VOLUME_UP_KEY && old_vol == max_volume && !old_muted) osd_vol = 101; else if (!new_muted) osd_vol = (int) (100 * (double) new_vol / max_volume); else osd_vol = 0; update_dialog (manager, stream, osd_vol, new_muted, sound_changed, quiet); } static void update_default_sink (GsdMediaKeysManager *manager) { GvcMixerStream *stream; stream = gvc_mixer_control_get_default_sink (manager->priv->volume); if (stream == manager->priv->sink) return; g_clear_object (&manager->priv->sink); if (stream != NULL) { manager->priv->sink = g_object_ref (stream); } else { g_warning ("Unable to get default sink"); } } static void update_default_source (GsdMediaKeysManager *manager) { GvcMixerStream *stream; stream = gvc_mixer_control_get_default_source (manager->priv->volume); if (stream == manager->priv->source) return; g_clear_object (&manager->priv->source); if (stream != NULL) { manager->priv->source = g_object_ref (stream); } else { g_warning ("Unable to get default source"); } } static void on_control_state_changed (GvcMixerControl *control, GvcMixerControlState new_state, GsdMediaKeysManager *manager) { update_default_sink (manager); update_default_source (manager); } static void on_control_default_sink_changed (GvcMixerControl *control, guint id, GsdMediaKeysManager *manager) { update_default_sink (manager); } static void on_control_default_source_changed (GvcMixerControl *control, guint id, GsdMediaKeysManager *manager) { update_default_source (manager); } #ifdef HAVE_GUDEV static gboolean remove_stream (gpointer key, gpointer value, gpointer id) { if (GPOINTER_TO_UINT (value) == GPOINTER_TO_UINT (id)) return TRUE; return FALSE; } #endif /* HAVE_GUDEV */ static void on_control_stream_removed (GvcMixerControl *control, guint id, GsdMediaKeysManager *manager) { if (manager->priv->sink != NULL) { if (gvc_mixer_stream_get_id (manager->priv->sink) == id) g_clear_object (&manager->priv->sink); } if (manager->priv->source != NULL) { if (gvc_mixer_stream_get_id (manager->priv->source) == id) g_clear_object (&manager->priv->source); } #ifdef HAVE_GUDEV g_hash_table_foreach_remove (manager->priv->streams, (GHRFunc) remove_stream, GUINT_TO_POINTER (id)); #endif } static void free_media_player (MediaPlayer *player) { if (player->watch_id > 0) { g_bus_unwatch_name (player->watch_id); player->watch_id = 0; } g_free (player->application); g_free (player->dbus_name); g_free (player); } static gint find_by_application (gconstpointer a, gconstpointer b) { return strcmp (((MediaPlayer *)a)->application, b); } static gint find_by_name (gconstpointer a, gconstpointer b) { return strcmp (((MediaPlayer *)a)->dbus_name, b); } static gint find_by_time (gconstpointer a, gconstpointer b) { return ((MediaPlayer *)a)->time < ((MediaPlayer *)b)->time; } static void name_vanished_handler (GDBusConnection *connection, const gchar *name, GsdMediaKeysManager *manager) { GList *iter; iter = g_list_find_custom (manager->priv->media_players, name, find_by_name); if (iter != NULL) { MediaPlayer *player; player = iter->data; g_debug ("Deregistering vanished %s (dbus_name: %s)", player->application, player->dbus_name); free_media_player (player); manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); } } /* * Register a new media player. Most applications will want to call * this with time = GDK_CURRENT_TIME. This way, the last registered * player will receive media events. In some cases, applications * may want to register with a lower priority (usually 1), to grab * events only nobody is interested. */ static void gsd_media_keys_manager_grab_media_player_keys (GsdMediaKeysManager *manager, const char *application, const char *dbus_name, guint32 time) { GList *iter; MediaPlayer *media_player; guint watch_id; if (time == GDK_CURRENT_TIME) { GTimeVal tv; g_get_current_time (&tv); time = tv.tv_sec * 1000 + tv.tv_usec / 1000; } iter = g_list_find_custom (manager->priv->media_players, application, find_by_application); if (iter != NULL) { if (((MediaPlayer *)iter->data)->time < time) { MediaPlayer *player = iter->data; free_media_player (player); manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); } else { return; } } watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, dbus_name, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, (GBusNameVanishedCallback) name_vanished_handler, manager, NULL); g_debug ("Registering %s at %u", application, time); media_player = g_new0 (MediaPlayer, 1); media_player->application = g_strdup (application); media_player->dbus_name = g_strdup (dbus_name); media_player->time = time; media_player->watch_id = watch_id; manager->priv->media_players = g_list_insert_sorted (manager->priv->media_players, media_player, find_by_time); } static void gsd_media_keys_manager_release_media_player_keys (GsdMediaKeysManager *manager, const char *application, const char *name) { GList *iter = NULL; g_return_if_fail (application != NULL || name != NULL); if (application != NULL) { iter = g_list_find_custom (manager->priv->media_players, application, find_by_application); } if (iter == NULL && name != NULL) { iter = g_list_find_custom (manager->priv->media_players, name, find_by_name); } if (iter != NULL) { MediaPlayer *player; player = iter->data; g_debug ("Deregistering %s (dbus_name: %s)", application, player->dbus_name); free_media_player (player); manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); } } static gboolean gsd_media_player_key_pressed (GsdMediaKeysManager *manager, const char *key) { const char *application; gboolean have_listeners; GError *error = NULL; MediaPlayer *player; g_return_val_if_fail (key != NULL, FALSE); g_debug ("Media key '%s' pressed", key); have_listeners = (manager->priv->media_players != NULL); if (!have_listeners) { /* Popup a dialog with an (/) icon */ show_osd (manager, "action-unavailable-symbolic", NULL, -1); return TRUE; } player = manager->priv->media_players->data; application = player->application; if (g_dbus_connection_emit_signal (manager->priv->connection, player->dbus_name, GSD_MEDIA_KEYS_DBUS_PATH, GSD_MEDIA_KEYS_DBUS_NAME, "MediaPlayerKeyPressed", g_variant_new ("(ss)", application ? application : "", key), &error) == FALSE) { g_debug ("Error emitting signal: %s", error->message); g_error_free (error); } return !have_listeners; } static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GsdMediaKeysManager *manager = (GsdMediaKeysManager *) user_data; g_debug ("Calling method '%s' for media-keys", method_name); if (g_strcmp0 (method_name, "ReleaseMediaPlayerKeys") == 0) { const char *app_name; g_variant_get (parameters, "(&s)", &app_name); gsd_media_keys_manager_release_media_player_keys (manager, app_name, sender); g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_strcmp0 (method_name, "GrabMediaPlayerKeys") == 0) { const char *app_name; guint32 time; g_variant_get (parameters, "(&su)", &app_name, &time); gsd_media_keys_manager_grab_media_player_keys (manager, app_name, sender, time); g_dbus_method_invocation_return_value (invocation, NULL); } } static const GDBusInterfaceVTable interface_vtable = { handle_method_call, NULL, /* Get Property */ NULL, /* Set Property */ }; static gboolean do_multimedia_player_action (GsdMediaKeysManager *manager, const char *icon, const char *key) { if (icon != NULL) ubuntu_osd_notification_show_icon (icon, key); return gsd_media_player_key_pressed (manager, key); } static void on_xrandr_action_call_finished (GObject *source_object, GAsyncResult *res, GsdMediaKeysManager *manager) { GError *error = NULL; GVariant *variant; char *action; action = g_object_get_data (G_OBJECT (source_object), "gsd-media-keys-manager-xrandr-action"); variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); g_object_unref (manager->priv->cancellable); manager->priv->cancellable = NULL; if (error != NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to complete XRandR action: %s", error->message); g_error_free (error); } else { g_variant_unref (variant); } g_free (action); } static void do_xrandr_action (GsdMediaKeysManager *manager, const char *action, gint64 timestamp) { GsdMediaKeysManagerPrivate *priv = manager->priv; if (priv->connection == NULL || priv->xrandr_proxy == NULL) { g_warning ("No existing D-Bus connection trying to handle XRANDR keys"); return; } if (priv->cancellable != NULL) { g_debug ("xrandr action already in flight"); return; } priv->cancellable = g_cancellable_new (); g_object_set_data (G_OBJECT (priv->xrandr_proxy), "gsd-media-keys-manager-xrandr-action", g_strdup (action)); g_dbus_proxy_call (priv->xrandr_proxy, action, g_variant_new ("(x)", timestamp), G_DBUS_CALL_FLAGS_NONE, -1, priv->cancellable, (GAsyncReadyCallback) on_xrandr_action_call_finished, manager); } static gboolean do_video_out_action (GsdMediaKeysManager *manager, gint64 timestamp) { do_xrandr_action (manager, "VideoModeSwitch", timestamp); return FALSE; } static gboolean do_video_rotate_action (GsdMediaKeysManager *manager, gint64 timestamp) { do_xrandr_action (manager, "Rotate", timestamp); return FALSE; } static void do_toggle_accessibility_key (const char *key) { GSettings *settings; gboolean state; settings = g_settings_new ("org.gnome.desktop.a11y.applications"); state = g_settings_get_boolean (settings, key); g_settings_set_boolean (settings, key, !state); g_object_unref (settings); } static void do_magnifier_action (GsdMediaKeysManager *manager) { do_toggle_accessibility_key ("screen-magnifier-enabled"); } static void do_screenreader_action (GsdMediaKeysManager *manager) { do_toggle_accessibility_key ("screen-reader-enabled"); } static void do_on_screen_keyboard_action (GsdMediaKeysManager *manager) { do_toggle_accessibility_key ("screen-keyboard-enabled"); } static void do_text_size_action (GsdMediaKeysManager *manager, MediaKeyType type) { GSettings *settings; gdouble factor, best, distance; guint i; /* Same values used in the Seeing tab of the Universal Access panel */ static gdouble factors[] = { 0.75, 1.0, 1.25, 1.5 }; const gchar *text_scaling_key = TEXT_SCALING_FACTOR_KEY; if (in_desktop ("Unity")) { settings = g_settings_new (UNITY_SETTINGS_INTERFACE_DIR); } else { settings = g_object_ref (manager->priv->interface_settings); } /* Figure out the current DPI scaling factor */ factor = g_settings_get_double (settings, text_scaling_key); factor += (type == INCREASE_TEXT_KEY ? 0.25 : -0.25); /* Try to find a matching value */ distance = 1e6; best = 1.0; for (i = 0; i < G_N_ELEMENTS(factors); i++) { gdouble d; d = fabs (factor - factors[i]); if (d < distance) { best = factors[i]; distance = d; } } if (best == 1.0) g_settings_reset (settings, text_scaling_key); else g_settings_set_double (settings, text_scaling_key, best); g_object_unref (settings); } static void do_magnifier_zoom_action (GsdMediaKeysManager *manager, MediaKeyType type) { GSettings *settings; gdouble offset, value; if (type == MAGNIFIER_ZOOM_IN_KEY) offset = 1.0; else offset = -1.0; settings = g_settings_new ("org.gnome.desktop.a11y.magnifier"); value = g_settings_get_double (settings, "mag-factor"); value += offset; value = roundl (value); g_settings_set_double (settings, "mag-factor", value); g_object_unref (settings); } static void do_toggle_contrast_action (GsdMediaKeysManager *manager) { gboolean high_contrast; char *theme; /* Are we using HighContrast now? */ theme = g_settings_get_string (manager->priv->interface_settings, "gtk-theme"); high_contrast = g_str_equal (theme, HIGH_CONTRAST); g_free (theme); if (high_contrast != FALSE) { if (manager->priv->gtk_theme == NULL) g_settings_reset (manager->priv->interface_settings, "gtk-theme"); else g_settings_set (manager->priv->interface_settings, "gtk-theme", manager->priv->gtk_theme); g_settings_set (manager->priv->interface_settings, "icon-theme", manager->priv->icon_theme); } else { g_settings_set (manager->priv->interface_settings, "gtk-theme", HIGH_CONTRAST); g_settings_set (manager->priv->interface_settings, "icon-theme", HIGH_CONTRAST); } } static void power_action (GsdMediaKeysManager *manager, const char *action, gboolean allow_interaction) { g_dbus_proxy_call (manager->priv->logind_proxy, action, g_variant_new ("(b)", allow_interaction), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, manager->priv->bus_cancellable, NULL, NULL); } static void do_config_power_action (GsdMediaKeysManager *manager, const gchar *config_key, gboolean in_lock_screen) { GsdPowerActionType action_type; action_type = g_settings_get_enum (manager->priv->power_settings, config_key); switch (action_type) { case GSD_POWER_ACTION_SUSPEND: power_action (manager, "Suspend", !in_lock_screen); break; case GSD_POWER_ACTION_INTERACTIVE: if (!in_lock_screen) gnome_session_shutdown (manager); break; case GSD_POWER_ACTION_SHUTDOWN: power_action (manager, "PowerOff", !in_lock_screen); break; case GSD_POWER_ACTION_HIBERNATE: power_action (manager, "Hibernate", !in_lock_screen); break; case GSD_POWER_ACTION_BLANK: case GSD_POWER_ACTION_NOTHING: /* these actions cannot be handled by media-keys and * are not used in this context */ break; } } #ifdef HAVE_FCITX static gchar * get_fcitx_name (const gchar *name) { gchar *fcitx_name = g_strdup (name); gchar *separator = strchr (fcitx_name, '+'); if (separator) *separator = '-'; return fcitx_name; } static gboolean input_source_is_fcitx_engine (const gchar *type, const gchar *name, const gchar *engine) { if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { if (g_str_has_prefix (engine, FCITX_XKB_PREFIX)) { gboolean equal; gchar *fcitx_name = get_fcitx_name (name); equal = g_str_equal (fcitx_name, engine + strlen (FCITX_XKB_PREFIX)); g_free (fcitx_name); return equal; } } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { return g_str_equal (name, engine); } return FALSE; } #endif static void do_switch_input_source_action (GsdMediaKeysManager *manager, MediaKeyType type) { GsdMediaKeysManagerPrivate *priv = manager->priv; GSettings *settings; GVariant *sources; const gchar *source_type; guint first; gint i, n; if (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "unity") != 0) if (!priv->have_legacy_keygrabber) return; settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR); sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); n = g_variant_n_children (sources); if (n < 2) goto out; i = -1; #ifdef HAVE_FCITX if (priv->is_fcitx_active && priv->fcitx) { gchar *engine = fcitx_input_method_get_current_im (priv->fcitx); if (engine) { GVariantIter iter; const gchar *source_name; g_variant_iter_init (&iter, sources); for (i = 0; g_variant_iter_next (&iter, "(&s&s)", &source_type, &source_name); i++) { if (input_source_is_fcitx_engine (source_type, source_name, engine)) { break; } } if (i >= g_variant_n_children (sources)) i = -1; g_free (engine); } } #endif if (i < 0) i = g_settings_get_uint (settings, KEY_CURRENT_INPUT_SOURCE); first = i; if (type == SWITCH_INPUT_SOURCE_KEY) { do { i = (i + 1) % n; g_variant_get_child (sources, i, "(&s&s)", &source_type, NULL); } while (i != first && ((g_str_equal (source_type, INPUT_SOURCE_TYPE_IBUS) && !priv->is_ibus_active) || (g_str_equal (source_type, INPUT_SOURCE_TYPE_FCITX) && !priv->is_fcitx_active))); } else { do { i = (i + n - 1) % n; g_variant_get_child (sources, i, "(&s&s)", &source_type, NULL); } while (i != first && ((g_str_equal (source_type, INPUT_SOURCE_TYPE_IBUS) && !priv->is_ibus_active) || (g_str_equal (source_type, INPUT_SOURCE_TYPE_FCITX) && !priv->is_fcitx_active))); } if (i != first) g_settings_set_uint (settings, KEY_CURRENT_INPUT_SOURCE, i); out: g_variant_unref (sources); g_object_unref (settings); } static void update_screen_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; guint percentage; GVariant *new_percentage; GsdBrightnessActionData *data = (GsdBrightnessActionData *) user_data; GsdMediaKeysManager *manager = data->manager; new_percentage = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (new_percentage == NULL) { g_warning ("Failed to set new screen percentage: %s", error->message); g_error_free (error); g_free (data); return; } /* update the dialog with the new value */ g_variant_get (new_percentage, "(u)", &percentage); guint osd_percentage; if (data->old_percentage == 100 && data->type == SCREEN_BRIGHTNESS_UP_KEY) osd_percentage = 101; else if (data->old_percentage == 0 && data->type == SCREEN_BRIGHTNESS_DOWN_KEY) osd_percentage = -1; else osd_percentage = CLAMP (percentage, 0, 100); if (!ubuntu_osd_notification_show_brightness (manager, osd_percentage)) { show_osd (manager, "display-brightness-symbolic", NULL, percentage); } g_free (data); g_variant_unref (new_percentage); } static void do_screen_brightness_action_real (GObject *source_object, GAsyncResult *res, gpointer user_data) { GsdBrightnessActionData *data = (GsdBrightnessActionData *) user_data; GsdMediaKeysManager *manager = data->manager; GError *error = NULL; GVariant *old_percentage = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (old_percentage == NULL) { g_warning ("Failed to get old screen percentage: %s", error->message); g_error_free (error); g_free (data); return; } g_variant_get (old_percentage, "(u)", &data->old_percentage); /* call into the power plugin */ g_dbus_proxy_call (manager->priv->power_screen_proxy, data->type == SCREEN_BRIGHTNESS_UP_KEY ? "StepUp" : "StepDown", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, update_screen_cb, data); g_variant_unref (old_percentage); } static void do_screen_brightness_action (GsdMediaKeysManager *manager, MediaKeyType type) { if (manager->priv->connection == NULL || manager->priv->power_screen_proxy == NULL) { g_warning ("No existing D-Bus connection trying to handle power keys"); return; } GsdBrightnessActionData *data = g_new0 (GsdBrightnessActionData, 1); data->manager = manager; data->type = type; g_dbus_proxy_call (manager->priv->power_screen_proxy, "GetPercentage", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, do_screen_brightness_action_real, data); } static void update_keyboard_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; guint percentage; GVariant *new_percentage; GsdMediaKeysManager *manager = GSD_MEDIA_KEYS_MANAGER (user_data); new_percentage = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (new_percentage == NULL) { g_warning ("Failed to set new keyboard percentage: %s", error->message); g_error_free (error); return; } /* update the dialog with the new value */ g_variant_get (new_percentage, "(u)", &percentage); /* FIXME: No overshoot effect for keyboard, as the power plugin has no interface * to get the old brightness */ if (!ubuntu_osd_notification_show_kb_backlight (manager, CLAMP (percentage, 0, 100))) { show_osd (manager, "keyboard-brightness-symbolic", NULL, percentage); } g_variant_unref (new_percentage); } static void do_keyboard_brightness_action (GsdMediaKeysManager *manager, MediaKeyType type) { const char *cmd; if (manager->priv->connection == NULL || manager->priv->power_keyboard_proxy == NULL) { g_warning ("No existing D-Bus connection trying to handle power keys"); return; } switch (type) { case KEYBOARD_BRIGHTNESS_UP_KEY: cmd = "StepUp"; break; case KEYBOARD_BRIGHTNESS_DOWN_KEY: cmd = "StepDown"; break; case KEYBOARD_BRIGHTNESS_TOGGLE_KEY: cmd = "Toggle"; break; default: g_assert_not_reached (); } /* call into the power plugin */ g_dbus_proxy_call (manager->priv->power_keyboard_proxy, cmd, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, update_keyboard_cb, manager); } static void do_screenshot_action (GsdMediaKeysManager *manager, MediaKeyType type) { switch (type){ case SCREENSHOT_KEY: execute (manager, "gnome-screenshot", FALSE); break; case WINDOW_SCREENSHOT_KEY: execute (manager, "gnome-screenshot --window", FALSE); break; case AREA_SCREENSHOT_KEY: execute (manager, "gnome-screenshot --area", FALSE); break; case SCREENSHOT_CLIP_KEY: execute (manager, "gnome-screenshot --clipboard", FALSE); break; case WINDOW_SCREENSHOT_CLIP_KEY: execute (manager, "gnome-screenshot --window --clipboard", FALSE); break; case AREA_SCREENSHOT_CLIP_KEY: execute (manager, "gnome-screenshot --area --clipboard", FALSE); } } static void do_custom_action (GsdMediaKeysManager *manager, guint deviceid, MediaKey *key, gint64 timestamp) { g_debug ("Launching custom action for key (on device id %d)", deviceid); execute (manager, key->custom_command, FALSE); } static gboolean do_action (GsdMediaKeysManager *manager, guint deviceid, MediaKeyType type, gint64 timestamp) { g_debug ("Launching action for key type '%d' (on device id %d)", type, deviceid); switch (type) { case TOUCHPAD_KEY: do_touchpad_action (manager); break; case TOUCHPAD_ON_KEY: do_touchpad_osd_action (manager, TRUE); break; case TOUCHPAD_OFF_KEY: do_touchpad_osd_action (manager, FALSE); break; case MUTE_KEY: case VOLUME_DOWN_KEY: case VOLUME_UP_KEY: do_sound_action (manager, deviceid, type, TRUE, FALSE); break; case MIC_MUTE_KEY: do_sound_action (manager, deviceid, MUTE_KEY, FALSE, TRUE); break; case MUTE_QUIET_KEY: do_sound_action (manager, deviceid, MUTE_KEY, TRUE, TRUE); break; case VOLUME_DOWN_QUIET_KEY: do_sound_action (manager, deviceid, VOLUME_DOWN_KEY, TRUE, TRUE); break; case VOLUME_UP_QUIET_KEY: do_sound_action (manager, deviceid, VOLUME_UP_KEY, TRUE, TRUE); break; case LOGOUT_KEY: do_logout_action (manager); break; case EJECT_KEY: do_eject_action (manager); break; case HOME_KEY: do_home_key_action (manager, timestamp); break; case SEARCH_KEY: do_search_action (manager, timestamp); break; case EMAIL_KEY: do_url_action (manager, "mailto", timestamp); break; case SCREENSAVER_KEY: do_lock_screensaver (manager); break; case HELP_KEY: do_url_action (manager, "ghelp", timestamp); break; case SCREENSHOT_KEY: case SCREENSHOT_CLIP_KEY: case WINDOW_SCREENSHOT_KEY: case WINDOW_SCREENSHOT_CLIP_KEY: case AREA_SCREENSHOT_KEY: case AREA_SCREENSHOT_CLIP_KEY: do_screenshot_action (manager, type); break; case TERMINAL_KEY: do_terminal_action (manager); break; case WWW_KEY: do_url_action (manager, "http", timestamp); break; case MEDIA_KEY: do_media_action (manager, timestamp); break; case CALCULATOR_KEY: do_execute_desktop_or_desktop (manager, "org.gnome.Calculator.desktop", "gnome-calculator.desktop", timestamp); break; case PLAY_KEY: return do_multimedia_player_action (manager, NULL, "Play"); case PAUSE_KEY: return do_multimedia_player_action (manager, NULL, "Pause"); case STOP_KEY: return do_multimedia_player_action (manager, NULL, "Stop"); case PREVIOUS_KEY: return do_multimedia_player_action (manager, NULL, "Previous"); case NEXT_KEY: return do_multimedia_player_action (manager, NULL, "Next"); case REWIND_KEY: return do_multimedia_player_action (manager, NULL, "Rewind"); case FORWARD_KEY: return do_multimedia_player_action (manager, NULL, "FastForward"); case REPEAT_KEY: return do_multimedia_player_action (manager, NULL, "Repeat"); case RANDOM_KEY: return do_multimedia_player_action (manager, NULL, "Shuffle"); case VIDEO_OUT_KEY: do_video_out_action (manager, timestamp); break; case ROTATE_VIDEO_KEY: do_video_rotate_action (manager, timestamp); break; case MAGNIFIER_KEY: do_magnifier_action (manager); break; case SCREENREADER_KEY: do_screenreader_action (manager); break; case ON_SCREEN_KEYBOARD_KEY: do_on_screen_keyboard_action (manager); break; case INCREASE_TEXT_KEY: case DECREASE_TEXT_KEY: do_text_size_action (manager, type); break; case MAGNIFIER_ZOOM_IN_KEY: case MAGNIFIER_ZOOM_OUT_KEY: do_magnifier_zoom_action (manager, type); break; case TOGGLE_CONTRAST_KEY: do_toggle_contrast_action (manager); break; case POWER_KEY: do_config_power_action (manager, "button-power", FALSE); break; case SLEEP_KEY: do_config_power_action (manager, "button-sleep", FALSE); break; case SUSPEND_KEY: do_config_power_action (manager, "button-suspend", FALSE); break; case HIBERNATE_KEY: do_config_power_action (manager, "button-hibernate", FALSE); break; case POWER_KEY_NO_DIALOG: do_config_power_action (manager, "button-power", TRUE); break; case SLEEP_KEY_NO_DIALOG: do_config_power_action (manager, "button-sleep", TRUE); break; case SUSPEND_KEY_NO_DIALOG: do_config_power_action (manager, "button-suspend", TRUE); break; case HIBERNATE_KEY_NO_DIALOG: do_config_power_action (manager, "button-hibernate", TRUE); break; case SCREEN_BRIGHTNESS_UP_KEY: case SCREEN_BRIGHTNESS_DOWN_KEY: do_screen_brightness_action (manager, type); break; case KEYBOARD_BRIGHTNESS_UP_KEY: case KEYBOARD_BRIGHTNESS_DOWN_KEY: case KEYBOARD_BRIGHTNESS_TOGGLE_KEY: do_keyboard_brightness_action (manager, type); break; case BATTERY_KEY: do_execute_desktop_or_desktop (manager, "gnome-power-statistics.desktop", "", timestamp); break; case SWITCH_INPUT_SOURCE_KEY: case SWITCH_INPUT_SOURCE_BACKWARD_KEY: do_switch_input_source_action (manager, type); break; /* Note, no default so compiler catches missing keys */ case CUSTOM_KEY: g_assert_not_reached (); } return FALSE; } static GdkScreen * get_screen_from_root (GsdMediaKeysManager *manager, Window root) { GSList *l; /* Look for which screen we're receiving events */ for (l = manager->priv->screens; l != NULL; l = l->next) { GdkScreen *screen = (GdkScreen *) l->data; GdkWindow *window = gdk_screen_get_root_window (screen); if (GDK_WINDOW_XID (window) == root) return screen; } return NULL; } static GdkFilterReturn filter_key_events (XEvent *xevent, GdkEvent *event, GsdMediaKeysManager *manager) { static gboolean ok_to_switch = TRUE; XIEvent *xiev; XIDeviceEvent *xev; XGenericEventCookie *cookie; guint i; guint deviceid; /* verify we have a key event */ if (xevent->type != GenericEvent) return GDK_FILTER_CONTINUE; cookie = &xevent->xcookie; if (cookie->extension != manager->priv->opcode) return GDK_FILTER_CONTINUE; xiev = (XIEvent *) xevent->xcookie.data; if (xiev->evtype != XI_KeyPress && xiev->evtype != XI_KeyRelease) return GDK_FILTER_CONTINUE; xev = (XIDeviceEvent *) xiev; deviceid = xev->sourceid; if (xiev->evtype == XI_KeyPress) ok_to_switch = TRUE; for (i = 0; i < manager->priv->keys->len; i++) { MediaKey *key; key = g_ptr_array_index (manager->priv->keys, i); if (match_xi2_key (key->key, xev)) { switch (key->key_type) { case VOLUME_DOWN_KEY: case VOLUME_UP_KEY: case VOLUME_DOWN_QUIET_KEY: case VOLUME_UP_QUIET_KEY: case SCREEN_BRIGHTNESS_UP_KEY: case SCREEN_BRIGHTNESS_DOWN_KEY: case KEYBOARD_BRIGHTNESS_UP_KEY: case KEYBOARD_BRIGHTNESS_DOWN_KEY: /* auto-repeatable keys */ if (xiev->evtype != XI_KeyPress) return GDK_FILTER_CONTINUE; break; default: if (xiev->evtype != XI_KeyRelease) { return GDK_FILTER_CONTINUE; } } manager->priv->current_screen = get_screen_from_root (manager, xev->root); if (key->key_type == CUSTOM_KEY) { do_custom_action (manager, deviceid, key, xev->time); return GDK_FILTER_REMOVE; } if (key->key_type == SWITCH_INPUT_SOURCE_KEY || key->key_type == SWITCH_INPUT_SOURCE_BACKWARD_KEY) { if (ok_to_switch) { do_action (manager, deviceid, key->key_type, xev->time); ok_to_switch = FALSE; } return GDK_FILTER_CONTINUE; } if (do_action (manager, deviceid, key->key_type, xev->time) == FALSE) { return GDK_FILTER_REMOVE; } else { return GDK_FILTER_CONTINUE; } } } return GDK_FILTER_CONTINUE; } static void on_accelerator_activated (ShellKeyGrabber *grabber, guint accel_id, guint deviceid, guint timestamp, GsdMediaKeysManager *manager) { guint i; g_debug ("Received accel id %u (device-id: %u, timestamp: %u", accel_id, deviceid, timestamp); for (i = 0; i < manager->priv->keys->len; i++) { MediaKey *key; key = g_ptr_array_index (manager->priv->keys, i); if (key->accel_id != accel_id) continue; if (key->key_type == CUSTOM_KEY) do_custom_action (manager, deviceid, key, timestamp); else do_action (manager, deviceid, key->key_type, timestamp); return; } g_warning ("Could not find accelerator for accel id %u", accel_id); } static void update_theme_settings (GSettings *settings, const char *key, GsdMediaKeysManager *manager) { char *theme; theme = g_settings_get_string (manager->priv->interface_settings, key); if (g_str_equal (theme, HIGH_CONTRAST)) { g_free (theme); } else { if (g_str_equal (key, "gtk-theme")) { g_free (manager->priv->gtk_theme); manager->priv->gtk_theme = theme; } else { g_free (manager->priv->icon_theme); manager->priv->icon_theme = theme; } } } static void on_wdypi_action (int action, void *userdata) { GsdMediaKeysManager *manager = userdata; pa_backend *pb = manager->priv->wdypi_pa_backend; pa_backend_set_context(pb, gvc_mixer_control_get_pa_context(manager->priv->volume)); switch (action) { case WDYPI_DIALOG_SOUND_SETTINGS: execute(manager, "unity-control-center sound", FALSE); break; case WDYPI_DIALOG_HEADPHONES: pa_backend_set_port(pb, "analog-output-headphones", true); pa_backend_set_port(pb, "analog-input-internal-mic", false); break; case WDYPI_DIALOG_HEADSET: pa_backend_set_port(pb, "analog-output-headphones", true); pa_backend_set_port(pb, "analog-input-headset-mic", false); break; case WDYPI_DIALOG_MICROPHONE: pa_backend_set_port(pb, "analog-output-speaker", true); pa_backend_set_port(pb, "analog-input-headphone-mic", false); break; default: break; } } static void on_wdypi_popup (bool hsmic, bool hpmic, void *userdata) { if (!hpmic && !hsmic) wdypi_dialog_kill(); else wdypi_dialog_run(hsmic, hpmic, on_wdypi_action, userdata); } static void on_control_card_info_updated (GvcMixerControl *control, gpointer card_info, GsdMediaKeysManager *manager) { pa_backend_card_changed (manager->priv->wdypi_pa_backend, card_info); #ifdef TEST_WDYPI_DIALOG /* Just a simple way to test the dialog on all types of hardware (pops up dialog on program start, and on every plug in) */ on_wdypi_popup (true, true, manager); #endif } static void initialize_volume_handler (GsdMediaKeysManager *manager) { /* initialise Volume handler * * We do this one here to force checking gstreamer cache, etc. * The rest (grabbing and setting the keys) can happen in an * idle. */ gnome_settings_profile_start ("gvc_mixer_control_new"); manager->priv->volume = gvc_mixer_control_new ("GNOME Volume Control Media Keys"); manager->priv->wdypi_pa_backend = pa_backend_new(on_wdypi_popup, manager); g_signal_connect (manager->priv->volume, "state-changed", G_CALLBACK (on_control_state_changed), manager); g_signal_connect (manager->priv->volume, "default-sink-changed", G_CALLBACK (on_control_default_sink_changed), manager); g_signal_connect (manager->priv->volume, "default-source-changed", G_CALLBACK (on_control_default_source_changed), manager); g_signal_connect (manager->priv->volume, "stream-removed", G_CALLBACK (on_control_stream_removed), manager); g_signal_connect (manager->priv->volume, "card-info", G_CALLBACK (on_control_card_info_updated), manager); gvc_mixer_control_open (manager->priv->volume); gnome_settings_profile_end ("gvc_mixer_control_new"); } static void on_shell_proxy_ready (GObject *source, GAsyncResult *result, gpointer data) { GsdMediaKeysManager *manager = data; manager->priv->shell_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL); } static void on_key_grabber_ready (GObject *source, GAsyncResult *result, gpointer data) { GsdMediaKeysManager *manager = data; GError *error = NULL; manager->priv->key_grabber = shell_key_grabber_proxy_new_for_bus_finish (result, &error); if (!manager->priv->key_grabber) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to create proxy for key grabber: %s", error->message); g_error_free (error); return; } g_signal_connect (manager->priv->key_grabber, "accelerator-activated", G_CALLBACK (on_accelerator_activated), manager); init_kbd (manager); } static gboolean session_has_key_grabber (void) { const gchar *session = g_getenv ("DESKTOP_SESSION"); return g_strcmp0 (session, "gnome") == 0 || g_strcmp0 (session, "unity") == 0; } static void on_shell_appeared (GDBusConnection *connection, const char *name, const char *name_owner, gpointer user_data) { if (!session_has_key_grabber ()) return; GsdMediaKeysManager *manager = user_data; shell_key_grabber_proxy_new_for_bus (G_BUS_TYPE_SESSION, 0, name_owner, SHELL_DBUS_PATH, manager->priv->grab_cancellable, on_key_grabber_ready, manager); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, 0, NULL, name_owner, SHELL_DBUS_PATH, SHELL_DBUS_NAME, manager->priv->shell_cancellable, on_shell_proxy_ready, manager); } static void on_shell_vanished (GDBusConnection *connection, const char *name, gpointer user_data) { if (!session_has_key_grabber ()) return; GsdMediaKeysManager *manager = user_data; g_ptr_array_set_size (manager->priv->keys, 0); g_clear_object (&manager->priv->key_grabber); g_clear_object (&manager->priv->shell_proxy); } static void start_legacy_grabber (GDBusConnection *connection, const char *name, const char *name_owner, gpointer user_data) { GsdMediaKeysManager *manager = user_data; GSList *l; if (session_has_key_grabber ()) return; manager->priv->have_legacy_keygrabber = TRUE; g_debug ("start_legacy_grabber"); if (manager->priv->keys == NULL) return; if (!name_owner) return; init_screens (manager); init_kbd (manager); /* Start filtering the events */ for (l = manager->priv->screens; l != NULL; l = l->next) { gnome_settings_profile_start ("gdk_window_add_filter"); g_debug ("adding key filter for screen: %d", gdk_screen_get_number (l->data)); gdk_window_add_filter (gdk_screen_get_root_window (l->data), (GdkFilterFunc) filter_key_events, manager); gnome_settings_profile_end ("gdk_window_add_filter"); } } static void stop_legacy_grabber (GDBusConnection *connection, const char *name, gpointer user_data) { GsdMediaKeysManager *manager = user_data; if (session_has_key_grabber ()) return; manager->priv->have_legacy_keygrabber = FALSE; g_ptr_array_set_size (manager->priv->keys, 0); } static gboolean start_media_keys_idle_cb (GsdMediaKeysManager *manager) { const gchar *module; g_debug ("Starting media_keys manager"); gnome_settings_profile_start (NULL); module = g_getenv (ENV_GTK_IM_MODULE); #ifdef HAVE_IBUS manager->priv->is_ibus_active = g_strcmp0 (module, GTK_IM_MODULE_IBUS) == 0; #endif #ifdef HAVE_FCITX manager->priv->is_fcitx_active = g_strcmp0 (module, GTK_IM_MODULE_FCITX) == 0; if (manager->priv->is_fcitx_active) { GError *error = NULL; manager->priv->fcitx = fcitx_input_method_new (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, 0, NULL, &error); if (!manager->priv->fcitx) { g_warning ("Fcitx connection unavailable: %s", error->message); g_error_free (error); } } #endif manager->priv->keys = g_ptr_array_new_with_free_func ((GDestroyNotify) media_key_free); initialize_volume_handler (manager); manager->priv->settings = g_settings_new (SETTINGS_BINDING_DIR); g_signal_connect (G_OBJECT (manager->priv->settings), "changed", G_CALLBACK (gsettings_changed_cb), manager); g_signal_connect (G_OBJECT (manager->priv->settings), "changed::custom-keybindings", G_CALLBACK (gsettings_custom_changed_cb), manager); manager->priv->input_settings = g_settings_new (INPUT_SETTINGS_BINDING_DIR); g_signal_connect (G_OBJECT (manager->priv->input_settings), "changed", G_CALLBACK (gsettings_changed_cb), manager); g_signal_connect (G_OBJECT (manager->priv->input_settings), "changed::custom-keybindings", G_CALLBACK (gsettings_custom_changed_cb), manager); manager->priv->custom_settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); manager->priv->sound_settings = g_settings_new ("com.ubuntu.sound"); /* for the power plugin interface code */ manager->priv->power_settings = g_settings_new (SETTINGS_POWER_DIR); /* Logic from http://git.gnome.org/browse/gnome-shell/tree/js/ui/status/accessibility.js#n163 */ manager->priv->interface_settings = g_settings_new (SETTINGS_INTERFACE_DIR); g_signal_connect (G_OBJECT (manager->priv->interface_settings), "changed::gtk-theme", G_CALLBACK (update_theme_settings), manager); g_signal_connect (G_OBJECT (manager->priv->interface_settings), "changed::icon-theme", G_CALLBACK (update_theme_settings), manager); manager->priv->gtk_theme = g_settings_get_string (manager->priv->interface_settings, "gtk-theme"); if (g_str_equal (manager->priv->gtk_theme, HIGH_CONTRAST)) { g_free (manager->priv->gtk_theme); manager->priv->gtk_theme = NULL; } manager->priv->icon_theme = g_settings_get_string (manager->priv->interface_settings, "icon-theme"); ensure_cancellable (&manager->priv->grab_cancellable); ensure_cancellable (&manager->priv->shell_cancellable); manager->priv->name_owner_id = g_bus_watch_name (G_BUS_TYPE_SESSION, SHELL_DBUS_NAME, 0, on_shell_appeared, on_shell_vanished, manager, NULL); manager->priv->unity_name_owner_id = g_bus_watch_name (G_BUS_TYPE_SESSION, UNITY_DBUS_NAME, 0, start_legacy_grabber, stop_legacy_grabber, manager, NULL); manager->priv->panel_name_owner_id = g_bus_watch_name (G_BUS_TYPE_SESSION, PANEL_DBUS_NAME, 0, start_legacy_grabber, stop_legacy_grabber, manager, NULL); gnome_settings_profile_end (NULL); manager->priv->start_idle_id = 0; return FALSE; } gboolean gsd_media_keys_manager_start (GsdMediaKeysManager *manager, GError **error) { const char * const subsystems[] = { "input", "usb", "sound", NULL }; gnome_settings_profile_start (NULL); if (supports_xinput2_devices (&manager->priv->opcode) == FALSE) { g_debug ("No Xinput2 support, disabling plugin"); return TRUE; } #ifdef HAVE_GUDEV manager->priv->streams = g_hash_table_new (g_direct_hash, g_direct_equal); manager->priv->udev_client = g_udev_client_new (subsystems); #endif manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); register_manager (manager_object); gnome_settings_profile_end (NULL); return TRUE; } void gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) { GsdMediaKeysManagerPrivate *priv = manager->priv; GSList *ls; int i; g_debug ("Stopping media_keys manager"); if (priv->bus_cancellable != NULL) { g_cancellable_cancel (priv->bus_cancellable); g_object_unref (priv->bus_cancellable); priv->bus_cancellable = NULL; } if (manager->priv->have_legacy_keygrabber){ for (ls = priv->screens; ls != NULL; ls = ls->next) { gdk_window_remove_filter (gdk_screen_get_root_window (ls->data), (GdkFilterFunc) filter_key_events, manager); } } if (manager->priv->gtksettings != NULL) { g_signal_handlers_disconnect_by_func (manager->priv->gtksettings, sound_theme_changed, manager); manager->priv->gtksettings = NULL; } g_clear_pointer (&manager->priv->ca, ca_context_destroy); #ifdef HAVE_GUDEV g_clear_pointer (&priv->streams, g_hash_table_destroy); g_clear_object (&priv->udev_client); #endif /* HAVE_GUDEV */ g_clear_object (&priv->logind_proxy); g_clear_object (&priv->settings); g_clear_object (&priv->input_settings); g_clear_object (&priv->power_settings); g_clear_object (&priv->power_proxy); g_clear_object (&priv->power_screen_proxy); g_clear_object (&priv->power_keyboard_proxy); g_clear_object (&priv->sound_settings); if (manager->priv->name_owner_id) { g_bus_unwatch_name (manager->priv->name_owner_id); manager->priv->name_owner_id = 0; } if (manager->priv->unity_name_owner_id) { g_bus_unwatch_name (manager->priv->unity_name_owner_id); manager->priv->unity_name_owner_id = 0; } if (manager->priv->panel_name_owner_id) { g_bus_unwatch_name (manager->priv->panel_name_owner_id); manager->priv->panel_name_owner_id = 0; } if (priv->cancellable != NULL) { g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); } g_clear_pointer (&priv->introspection_data, g_dbus_node_info_unref); g_clear_object (&priv->connection); if (priv->volume_notification != NULL) { notify_notification_close (priv->volume_notification, NULL); g_object_unref (priv->volume_notification); priv->volume_notification = NULL; } if (priv->brightness_notification != NULL) { notify_notification_close (priv->brightness_notification, NULL); g_object_unref (priv->brightness_notification); priv->brightness_notification = NULL; } if (priv->kb_backlight_notification != NULL) { notify_notification_close (priv->kb_backlight_notification, NULL); g_object_unref (priv->kb_backlight_notification); priv->kb_backlight_notification = NULL; } if (priv->keys != NULL) { if (manager->priv->have_legacy_keygrabber) gdk_error_trap_push (); for (i = 0; i < priv->keys->len; ++i) { MediaKey *key; key = g_ptr_array_index (manager->priv->keys, i); if (manager->priv->have_legacy_keygrabber && key->key) ungrab_key_unsafe (key->key, priv->screens); else ungrab_media_key (key, manager); } g_ptr_array_free (priv->keys, TRUE); priv->keys = NULL; } if (manager->priv->have_legacy_keygrabber){ gdk_flush (); gdk_error_trap_pop_ignored (); } if (manager->priv->wdypi_pa_backend) { pa_backend_free (manager->priv->wdypi_pa_backend); manager->priv->wdypi_pa_backend = NULL; } wdypi_dialog_kill(); if (priv->grab_cancellable != NULL) { g_cancellable_cancel (priv->grab_cancellable); g_clear_object (&priv->grab_cancellable); } if (priv->shell_cancellable != NULL) { g_cancellable_cancel (priv->shell_cancellable); g_clear_object (&priv->shell_cancellable); } g_clear_pointer (&priv->screens, g_slist_free); g_clear_object (&priv->sink); g_clear_object (&priv->source); g_clear_object (&priv->volume); if (priv->media_players != NULL) { g_list_free_full (priv->media_players, (GDestroyNotify) free_media_player); priv->media_players = NULL; } } static GObject * gsd_media_keys_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdMediaKeysManager *media_keys_manager; media_keys_manager = GSD_MEDIA_KEYS_MANAGER (G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (media_keys_manager); } static void gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_media_keys_manager_constructor; object_class->finalize = gsd_media_keys_manager_finalize; g_type_class_add_private (klass, sizeof (GsdMediaKeysManagerPrivate)); } static void inhibit_done (GObject *source, GAsyncResult *result, gpointer user_data) { GDBusProxy *proxy = G_DBUS_PROXY (source); GsdMediaKeysManager *manager = GSD_MEDIA_KEYS_MANAGER (user_data); GError *error = NULL; GVariant *res; GUnixFDList *fd_list = NULL; gint idx; res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error); if (res == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Unable to inhibit keypresses: %s", error->message); g_error_free (error); } else { g_variant_get (res, "(h)", &idx); manager->priv->inhibit_keys_fd = g_unix_fd_list_get (fd_list, idx, &error); if (manager->priv->inhibit_keys_fd == -1) { g_warning ("Failed to receive system inhibitor fd: %s", error->message); g_error_free (error); } g_debug ("System inhibitor fd is %d", manager->priv->inhibit_keys_fd); g_object_unref (fd_list); g_variant_unref (res); } } static void gsd_media_keys_manager_init (GsdMediaKeysManager *manager) { GError *error; GDBusConnection *bus; error = NULL; manager->priv = GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager); bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (bus == NULL) { g_warning ("Failed to connect to system bus: %s", error->message); g_error_free (error); return; } manager->priv->logind_proxy = g_dbus_proxy_new_sync (bus, 0, NULL, SYSTEMD_DBUS_NAME, SYSTEMD_DBUS_PATH, SYSTEMD_DBUS_INTERFACE, NULL, &error); if (manager->priv->logind_proxy == NULL) { g_warning ("Failed to connect to systemd: %s", error->message); g_error_free (error); } g_object_unref (bus); g_debug ("Adding system inhibitors for power keys"); manager->priv->inhibit_keys_fd = -1; g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy, "Inhibit", g_variant_new ("(ssss)", "handle-power-key:handle-suspend-key:handle-hibernate-key", g_get_user_name (), "GNOME handling keypresses", "block"), 0, G_MAXINT, NULL, NULL, inhibit_done, manager); } static void gsd_media_keys_manager_finalize (GObject *object) { GsdMediaKeysManager *media_keys_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_MEDIA_KEYS_MANAGER (object)); media_keys_manager = GSD_MEDIA_KEYS_MANAGER (object); g_return_if_fail (media_keys_manager->priv != NULL); if (media_keys_manager->priv->start_idle_id != 0) g_source_remove (media_keys_manager->priv->start_idle_id); if (media_keys_manager->priv->inhibit_keys_fd != -1) close (media_keys_manager->priv->inhibit_keys_fd); g_clear_object (&media_keys_manager->priv->screen_saver_proxy); G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->finalize (object); } static void xrandr_ready_cb (GObject *source_object, GAsyncResult *res, GsdMediaKeysManager *manager) { GError *error = NULL; manager->priv->xrandr_proxy = g_dbus_proxy_new_finish (res, &error); if (manager->priv->xrandr_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to get proxy for XRandR operations: %s", error->message); g_error_free (error); } } static void power_ready_cb (GObject *source_object, GAsyncResult *res, GsdMediaKeysManager *manager) { GError *error = NULL; manager->priv->power_proxy = g_dbus_proxy_new_finish (res, &error); if (manager->priv->power_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to get proxy for power: %s", error->message); g_error_free (error); } } static void power_screen_ready_cb (GObject *source_object, GAsyncResult *res, GsdMediaKeysManager *manager) { GError *error = NULL; manager->priv->power_screen_proxy = g_dbus_proxy_new_finish (res, &error); if (manager->priv->power_screen_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to get proxy for power (screen): %s", error->message); g_error_free (error); } } static void power_keyboard_ready_cb (GObject *source_object, GAsyncResult *res, GsdMediaKeysManager *manager) { GError *error = NULL; manager->priv->power_keyboard_proxy = g_dbus_proxy_new_finish (res, &error); if (manager->priv->power_keyboard_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to get proxy for power (keyboard): %s", error->message); g_error_free (error); } } static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdMediaKeysManager *manager) { GDBusConnection *connection; GError *error = NULL; connection = g_bus_get_finish (res, &error); if (connection == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; g_dbus_connection_register_object (connection, GSD_MEDIA_KEYS_DBUS_PATH, manager->priv->introspection_data->interfaces[0], &interface_vtable, manager, NULL, NULL); g_dbus_proxy_new (manager->priv->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, GSD_DBUS_NAME ".XRANDR", GSD_DBUS_PATH "/XRANDR", GSD_DBUS_BASE_INTERFACE ".XRANDR_2", NULL, (GAsyncReadyCallback) xrandr_ready_cb, manager); g_dbus_proxy_new (manager->priv->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, GSD_DBUS_NAME ".Power", GSD_DBUS_PATH "/Power", GSD_DBUS_BASE_INTERFACE ".Power", NULL, (GAsyncReadyCallback) power_ready_cb, manager); g_dbus_proxy_new (manager->priv->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, GSD_DBUS_NAME ".Power", GSD_DBUS_PATH "/Power", GSD_DBUS_BASE_INTERFACE ".Power.Screen", NULL, (GAsyncReadyCallback) power_screen_ready_cb, manager); g_dbus_proxy_new (manager->priv->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, GSD_DBUS_NAME ".Power", GSD_DBUS_PATH "/Power", GSD_DBUS_BASE_INTERFACE ".Power.Keyboard", NULL, (GAsyncReadyCallback) power_keyboard_ready_cb, manager); } static void register_manager (GsdMediaKeysManager *manager) { manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); manager->priv->bus_cancellable = g_cancellable_new (); g_assert (manager->priv->introspection_data != NULL); g_bus_get (G_BUS_TYPE_SESSION, manager->priv->bus_cancellable, (GAsyncReadyCallback) on_bus_gotten, manager); } GsdMediaKeysManager * gsd_media_keys_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_MEDIA_KEYS_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_MEDIA_KEYS_MANAGER (manager_object); } unity-settings-daemon/plugins/media-keys/gsd-media-keys-manager.h0000664000000000000000000000522415172222611022314 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_MEDIA_KEYS_MANAGER_H #define __GSD_MEDIA_KEYS_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_MEDIA_KEYS_MANAGER (gsd_media_keys_manager_get_type ()) #define GSD_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManager)) #define GSD_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerClass)) #define GSD_IS_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_MEDIA_KEYS_MANAGER)) #define GSD_IS_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_MEDIA_KEYS_MANAGER)) #define GSD_MEDIA_KEYS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerClass)) typedef struct GsdMediaKeysManagerPrivate GsdMediaKeysManagerPrivate; typedef struct { GObject parent; GsdMediaKeysManagerPrivate *priv; } GsdMediaKeysManager; typedef struct { GObjectClass parent_class; void (* media_player_key_pressed) (GsdMediaKeysManager *manager, const char *application, const char *key); } GsdMediaKeysManagerClass; GType gsd_media_keys_manager_get_type (void); GsdMediaKeysManager * gsd_media_keys_manager_new (void); gboolean gsd_media_keys_manager_start (GsdMediaKeysManager *manager, GError **error); void gsd_media_keys_manager_stop (GsdMediaKeysManager *manager); G_END_DECLS #endif /* __GSD_MEDIA_KEYS_MANAGER_H */ unity-settings-daemon/plugins/media-keys/gsd-media-keys-plugin.c0000664000000000000000000000203315172222611022166 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-media-keys-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdMediaKeys, gsd_media_keys) unity-settings-daemon/plugins/media-keys/gsd-screenshot-utils.c0000664000000000000000000002314515172222611022164 0ustar /* gsd-screenshot-utils.c - utilities to take screenshots * * Copyright (C) 2012 Red Hat, Inc. * * Adapted from gnome-screenshot code, which is * Copyright (C) 2001-2006 Jonathan Blandford * Copyright (C) 2006 Emmanuele Bassi * Copyright (C) 2008-2012 Cosimo Cecchi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ #include #include #include #include #include #include #include #include "gsd-screenshot-utils.h" #define SHELL_SCREENSHOT_BUS_NAME "org.gnome.Shell" #define SHELL_SCREENSHOT_BUS_PATH "/org/gnome/Shell/Screenshot" #define SHELL_SCREENSHOT_BUS_IFACE "org.gnome.Shell.Screenshot" typedef enum { SCREENSHOT_TYPE_SCREEN, SCREENSHOT_TYPE_WINDOW, SCREENSHOT_TYPE_AREA } ScreenshotType; typedef struct { ScreenshotType type; gboolean copy_to_clipboard; GdkRectangle area_selection; gchar *save_filename; gchar *used_filename; GDBusConnection *connection; } ScreenshotContext; static void screenshot_play_sound_effect (const gchar *event_id, const gchar *event_desc) { ca_context *c; c = ca_gtk_context_get (); ca_context_play (c, 0, CA_PROP_EVENT_ID, event_id, CA_PROP_EVENT_DESCRIPTION, event_desc, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent", NULL); } static void screenshot_context_free (ScreenshotContext *ctx) { g_free (ctx->save_filename); g_free (ctx->used_filename); g_clear_object (&ctx->connection); g_slice_free (ScreenshotContext, ctx); } static void screenshot_context_error (ScreenshotContext *ctx, GError *error, const gchar *warning_format) { screenshot_play_sound_effect ("dialog-error", _("Unable to capture a screenshot")); g_warning (warning_format, error->message); g_error_free (error); } static void screenshot_save_to_recent (ScreenshotContext *ctx) { GFile *file = g_file_new_for_path (ctx->used_filename); gchar *uri = g_file_get_uri (file); gtk_recent_manager_add_item (gtk_recent_manager_get_default (), uri); g_free (uri); g_object_unref (file); } static void screenshot_save_to_clipboard (ScreenshotContext *ctx) { GdkPixbuf *screenshot; GtkClipboard *clipboard; GError *error = NULL; screenshot = gdk_pixbuf_new_from_file (ctx->used_filename, &error); if (error != NULL) { screenshot_context_error (ctx, error, "Failed to save a screenshot to clipboard: %s\n"); return; } screenshot_play_sound_effect ("screen-capture", _("Screenshot taken")); clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (), GDK_SELECTION_CLIPBOARD); gtk_clipboard_set_image (clipboard, screenshot); /* remove the temporary file created by the shell */ g_unlink (ctx->used_filename); g_object_unref (screenshot); } static void bus_call_ready_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GError *error = NULL; ScreenshotContext *ctx = user_data; GVariant *variant; gboolean success; variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error); if (error != NULL) { screenshot_context_error (ctx, error, "Failed to save a screenshot: %s\n"); screenshot_context_free (ctx); return; } g_variant_get (variant, "(bs)", &success, &ctx->used_filename); if (success) { if (ctx->copy_to_clipboard) { screenshot_save_to_clipboard (ctx); } else { screenshot_play_sound_effect ("screen-capture", _("Screenshot taken")); screenshot_save_to_recent (ctx); } } screenshot_context_free (ctx); g_variant_unref (variant); } static void screenshot_call_shell (ScreenshotContext *ctx) { const gchar *method_name; GVariant *method_params; if (ctx->type == SCREENSHOT_TYPE_SCREEN) { method_name = "Screenshot"; method_params = g_variant_new ("(bbs)", FALSE, /* include pointer */ TRUE, /* flash */ ctx->save_filename); } else if (ctx->type == SCREENSHOT_TYPE_WINDOW) { method_name = "ScreenshotWindow"; method_params = g_variant_new ("(bbbs)", TRUE, /* include border */ FALSE, /* include pointer */ TRUE, /* flash */ ctx->save_filename); } else { method_name = "ScreenshotArea"; method_params = g_variant_new ("(iiiibs)", ctx->area_selection.x, ctx->area_selection.y, ctx->area_selection.width, ctx->area_selection.height, TRUE, /* flash */ ctx->save_filename); } g_dbus_connection_call (ctx->connection, SHELL_SCREENSHOT_BUS_NAME, SHELL_SCREENSHOT_BUS_PATH, SHELL_SCREENSHOT_BUS_IFACE, method_name, method_params, NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, bus_call_ready_cb, ctx); } static void area_selection_ready_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GdkRectangle rectangle; ScreenshotContext *ctx = user_data; GVariant *geometry; geometry = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, NULL); /* cancelled by the user */ if (!geometry) { screenshot_context_free (ctx); return; } g_variant_get (geometry, "(iiii)", &rectangle.x, &rectangle.y, &rectangle.width, &rectangle.height); ctx->area_selection = rectangle; screenshot_call_shell (ctx); g_variant_unref (geometry); } static void bus_connection_ready_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GError *error = NULL; ScreenshotContext *ctx = user_data; ctx->connection = g_bus_get_finish (res, &error); if (error != NULL) { screenshot_context_error (ctx, error, "Failed to save a screenshot: %s\n"); screenshot_context_free (ctx); return; } if (ctx->type == SCREENSHOT_TYPE_AREA) g_dbus_connection_call (ctx->connection, SHELL_SCREENSHOT_BUS_NAME, SHELL_SCREENSHOT_BUS_PATH, SHELL_SCREENSHOT_BUS_IFACE, "SelectArea", NULL, NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, area_selection_ready_cb, ctx); else screenshot_call_shell (ctx); } static void screenshot_take (ScreenshotContext *ctx) { g_bus_get (G_BUS_TYPE_SESSION, NULL, bus_connection_ready_cb, ctx); } static gchar * screenshot_build_tmp_path (void) { gchar *path; gint fd; fd = g_file_open_tmp ("gnome-settings-daemon-screenshot-XXXXXX", &path, NULL); close (fd); return path; } static gchar * screenshot_build_filename (void) { char *file_name, *origin; GDateTime *d; d = g_date_time_new_now_local (); origin = g_date_time_format (d, "%Y-%m-%d %H:%M:%S"); g_date_time_unref (d); /* translators: this is the name of the file that gets made up * with the screenshot */ file_name = g_strdup_printf (_("Screenshot from %s"), origin); g_free (origin); return file_name; } static void screenshot_check_name_ready (ScreenshotContext *ctx) { if (ctx->copy_to_clipboard) ctx->save_filename = screenshot_build_tmp_path (); else ctx->save_filename = screenshot_build_filename (); screenshot_take (ctx); } void gsd_screenshot_take (MediaKeyType key_type) { ScreenshotContext *ctx = g_slice_new0 (ScreenshotContext); ctx->copy_to_clipboard = (key_type == SCREENSHOT_CLIP_KEY || key_type == WINDOW_SCREENSHOT_CLIP_KEY || key_type == AREA_SCREENSHOT_CLIP_KEY); switch (key_type) { case SCREENSHOT_KEY: case SCREENSHOT_CLIP_KEY: ctx->type = SCREENSHOT_TYPE_SCREEN; break; case WINDOW_SCREENSHOT_KEY: case WINDOW_SCREENSHOT_CLIP_KEY: ctx->type = SCREENSHOT_TYPE_WINDOW; break; case AREA_SCREENSHOT_KEY: case AREA_SCREENSHOT_CLIP_KEY: ctx->type = SCREENSHOT_TYPE_AREA; break; default: g_assert_not_reached (); break; } screenshot_check_name_ready (ctx); } unity-settings-daemon/plugins/media-keys/gsd-screenshot-utils.h0000664000000000000000000000234315172222611022166 0ustar /* gsd-screenshot-utils.h - utilities to take screenshots * * Copyright (C) 2012 Red Hat, Inc. * * Adapted from gnome-screenshot code, which is * Copyright (C) 2001-2006 Jonathan Blandford * Copyright (C) 2006 Emmanuele Bassi * Copyright (C) 2008-2012 Cosimo Cecchi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ #ifndef __GSD_SCREENSHOT_UTILS_H__ #define __GSD_SCREENSHOT_UTILS_H__ #include "shortcuts-list.h" G_BEGIN_DECLS void gsd_screenshot_take (MediaKeyType key_type); G_END_DECLS #endif /* __GSD_SCREENSHOT_UTILS_H__ */ unity-settings-daemon/plugins/media-keys/gvc/0000775000000000000000000000000015172222611016504 5ustar unity-settings-daemon/plugins/media-keys/gvc/Makefile.am0000664000000000000000000000266315172222611020547 0ustar noinst_LTLIBRARIES = libgvc.la INTROSPECTION_SCANNER_ARGS = --warn-all libgvc_la_CPPFLAGS = \ $(WARN_CFLAGS) \ $(GVC_CFLAGS) \ -I$(srcdir) \ -DWITH_INTROSPECTION \ -DG_LOG_DOMAIN="\"Gvc\"" libgvc_la_gir_sources = \ gvc-mixer-card.h \ gvc-mixer-card.c \ gvc-mixer-stream.h \ gvc-mixer-stream.c \ gvc-channel-map.h \ gvc-channel-map.c \ gvc-mixer-ui-device.h \ gvc-mixer-ui-device.c \ gvc-mixer-sink.h \ gvc-mixer-sink.c \ gvc-mixer-source.h \ gvc-mixer-source.c \ gvc-mixer-sink-input.h \ gvc-mixer-sink-input.c \ gvc-mixer-source-output.h \ gvc-mixer-source-output.c \ gvc-mixer-event-role.h \ gvc-mixer-event-role.c \ gvc-mixer-control.h \ gvc-mixer-control.c \ $(NULL) libgvc_la_SOURCES = \ $(libgvc_la_gir_sources) \ gvc-mixer-card-private.h \ gvc-mixer-stream-private.h \ gvc-channel-map-private.h \ gvc-mixer-control-private.h \ gvc-pulseaudio-fake.h \ $(NULL) libgvc_la_LIBADD = \ $(GVC_LIBS) \ $(NULL) if HAVE_INTROSPECTION include $(INTROSPECTION_MAKEFILE) Gvc-1.0.gir: libgvc.la Gvc_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0 Gvc_1_0_gir_CFLAGS = $(INCLUDES) -I$(srcdir) -DWITH_INTROSPECTION Gvc_1_0_gir_LIBS = libgvc.la Gvc_1_0_gir_FILES = $(addprefix $(srcdir)/,$(libgvc_la_gir_sources)) INTROSPECTION_GIRS = Gvc-1.0.gir typelibdir = $(pkglibdir) typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES = Gvc-1.0.gir $(typelib_DATA) endif unity-settings-daemon/plugins/media-keys/gvc/gvc-channel-map-private.h0000664000000000000000000000305615172222611023271 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_CHANNEL_MAP_PRIVATE_H #define __GVC_CHANNEL_MAP_PRIVATE_H #include #include G_BEGIN_DECLS GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *map); const pa_channel_map * gvc_channel_map_get_pa_channel_map (const GvcChannelMap *map); void gvc_channel_map_volume_changed (GvcChannelMap *map, const pa_cvolume *cv, gboolean set); const pa_cvolume * gvc_channel_map_get_cvolume (const GvcChannelMap *map); G_END_DECLS #endif /* __GVC_CHANNEL_MAP_PRIVATE_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-channel-map.c0000664000000000000000000001661415172222611021620 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-channel-map.h" #include "gvc-channel-map-private.h" #define GVC_CHANNEL_MAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapPrivate)) struct GvcChannelMapPrivate { pa_channel_map pa_map; gboolean pa_volume_is_set; pa_cvolume pa_volume; gdouble extern_volume[NUM_TYPES]; /* volume, balance, fade, lfe */ gboolean can_balance; gboolean can_fade; }; enum { VOLUME_CHANGED, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0, }; static void gvc_channel_map_class_init (GvcChannelMapClass *klass); static void gvc_channel_map_init (GvcChannelMap *channel_map); static void gvc_channel_map_finalize (GObject *object); G_DEFINE_TYPE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT) guint gvc_channel_map_get_num_channels (const GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), 0); if (!pa_channel_map_valid(&map->priv->pa_map)) return 0; return map->priv->pa_map.channels; } const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); if (!pa_channel_map_valid(&map->priv->pa_map)) return NULL; map->priv->extern_volume[VOLUME] = (gdouble) pa_cvolume_max (&map->priv->pa_volume); if (gvc_channel_map_can_balance (map)) map->priv->extern_volume[BALANCE] = (gdouble) pa_cvolume_get_balance (&map->priv->pa_volume, &map->priv->pa_map); else map->priv->extern_volume[BALANCE] = 0; if (gvc_channel_map_can_fade (map)) map->priv->extern_volume[FADE] = (gdouble) pa_cvolume_get_fade (&map->priv->pa_volume, &map->priv->pa_map); else map->priv->extern_volume[FADE] = 0; if (gvc_channel_map_has_lfe (map)) map->priv->extern_volume[LFE] = (gdouble) pa_cvolume_get_position (&map->priv->pa_volume, &map->priv->pa_map, PA_CHANNEL_POSITION_LFE); else map->priv->extern_volume[LFE] = 0; return map->priv->extern_volume; } gboolean gvc_channel_map_can_balance (const GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE); return map->priv->can_balance; } gboolean gvc_channel_map_can_fade (const GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE); return map->priv->can_fade; } const char * gvc_channel_map_get_mapping (const GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); if (!pa_channel_map_valid(&map->priv->pa_map)) return NULL; return pa_channel_map_to_pretty_name (&map->priv->pa_map); } /** * gvc_channel_map_has_position: (skip) * @map: * @position: * * Returns: */ gboolean gvc_channel_map_has_position (const GvcChannelMap *map, pa_channel_position_t position) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE); return pa_channel_map_has_position (&(map->priv->pa_map), position); } const pa_channel_map * gvc_channel_map_get_pa_channel_map (const GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); if (!pa_channel_map_valid(&map->priv->pa_map)) return NULL; return &map->priv->pa_map; } const pa_cvolume * gvc_channel_map_get_cvolume (const GvcChannelMap *map) { g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); if (!pa_channel_map_valid(&map->priv->pa_map)) return NULL; return &map->priv->pa_volume; } static void gvc_channel_map_class_init (GvcChannelMapClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = gvc_channel_map_finalize; signals [VOLUME_CHANGED] = g_signal_new ("volume-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); g_type_class_add_private (klass, sizeof (GvcChannelMapPrivate)); } void gvc_channel_map_volume_changed (GvcChannelMap *map, const pa_cvolume *cv, gboolean set) { g_return_if_fail (GVC_IS_CHANNEL_MAP (map)); g_return_if_fail (cv != NULL); g_return_if_fail (pa_cvolume_compatible_with_channel_map(cv, &map->priv->pa_map)); if (pa_cvolume_equal(cv, &map->priv->pa_volume)) return; map->priv->pa_volume = *cv; if (map->priv->pa_volume_is_set == FALSE) { map->priv->pa_volume_is_set = TRUE; return; } g_signal_emit (map, signals[VOLUME_CHANGED], 0, set); } static void gvc_channel_map_init (GvcChannelMap *map) { map->priv = GVC_CHANNEL_MAP_GET_PRIVATE (map); map->priv->pa_volume_is_set = FALSE; } static void gvc_channel_map_finalize (GObject *object) { GvcChannelMap *channel_map; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_CHANNEL_MAP (object)); channel_map = GVC_CHANNEL_MAP (object); g_return_if_fail (channel_map->priv != NULL); G_OBJECT_CLASS (gvc_channel_map_parent_class)->finalize (object); } GvcChannelMap * gvc_channel_map_new (void) { GObject *map; map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL); return GVC_CHANNEL_MAP (map); } static void set_from_pa_map (GvcChannelMap *map, const pa_channel_map *pa_map) { g_assert (pa_channel_map_valid(pa_map)); map->priv->can_balance = pa_channel_map_can_balance (pa_map); map->priv->can_fade = pa_channel_map_can_fade (pa_map); map->priv->pa_map = *pa_map; pa_cvolume_set(&map->priv->pa_volume, pa_map->channels, PA_VOLUME_NORM); } GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *pa_map) { GObject *map; map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL); set_from_pa_map (GVC_CHANNEL_MAP (map), pa_map); return GVC_CHANNEL_MAP (map); } unity-settings-daemon/plugins/media-keys/gvc/gvc-channel-map.h0000664000000000000000000000557015172222611021624 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_CHANNEL_MAP_H #define __GVC_CHANNEL_MAP_H #include #include G_BEGIN_DECLS #define GVC_TYPE_CHANNEL_MAP (gvc_channel_map_get_type ()) #define GVC_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMap)) #define GVC_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass)) #define GVC_IS_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_CHANNEL_MAP)) #define GVC_IS_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_CHANNEL_MAP)) #define GVC_CHANNEL_MAP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass)) typedef struct GvcChannelMapPrivate GvcChannelMapPrivate; typedef struct { GObject parent; GvcChannelMapPrivate *priv; } GvcChannelMap; typedef struct { GObjectClass parent_class; void (*volume_changed) (GvcChannelMap *channel_map, gboolean set); } GvcChannelMapClass; enum { VOLUME, BALANCE, FADE, LFE, NUM_TYPES }; GType gvc_channel_map_get_type (void); GvcChannelMap * gvc_channel_map_new (void); guint gvc_channel_map_get_num_channels (const GvcChannelMap *map); const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map); gboolean gvc_channel_map_can_balance (const GvcChannelMap *map); gboolean gvc_channel_map_can_fade (const GvcChannelMap *map); gboolean gvc_channel_map_has_position (const GvcChannelMap *map, pa_channel_position_t position); #define gvc_channel_map_has_lfe(x) gvc_channel_map_has_position (x, PA_CHANNEL_POSITION_LFE) const char * gvc_channel_map_get_mapping (const GvcChannelMap *map); G_END_DECLS #endif /* __GVC_CHANNEL_MAP_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-card-private.h0000664000000000000000000000237515172222611023144 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008-2009 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_CARD_PRIVATE_H #define __GVC_MIXER_CARD_PRIVATE_H #include #include "gvc-mixer-card.h" G_BEGIN_DECLS GvcMixerCard * gvc_mixer_card_new (pa_context *context, guint index); pa_context * gvc_mixer_card_get_pa_context (GvcMixerCard *card); G_END_DECLS #endif /* __GVC_MIXER_CARD_PRIVATE_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-card.c0000664000000000000000000004463015172222611021467 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * Copyright (C) 2009 Bastien Nocera * Copyright (C) Conor Curran 2011 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-mixer-card.h" #include "gvc-mixer-card-private.h" #define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate)) static guint32 card_serial = 1; struct GvcMixerCardPrivate { pa_context *pa_context; guint id; guint index; char *name; char *icon_name; char *profile; char *target_profile; char *human_profile; GList *profiles; pa_operation *profile_op; GList *ports; }; enum { PROP_0, PROP_ID, PROP_PA_CONTEXT, PROP_INDEX, PROP_NAME, PROP_ICON_NAME, PROP_PROFILE, PROP_HUMAN_PROFILE, }; static void gvc_mixer_card_class_init (GvcMixerCardClass *klass); static void gvc_mixer_card_init (GvcMixerCard *mixer_card); static void gvc_mixer_card_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT) static guint32 get_next_card_serial (void) { guint32 serial; serial = card_serial++; if ((gint32)card_serial < 0) { card_serial = 1; } return serial; } pa_context * gvc_mixer_card_get_pa_context (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0); return card->priv->pa_context; } guint gvc_mixer_card_get_index (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0); return card->priv->index; } guint gvc_mixer_card_get_id (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0); return card->priv->id; } const char * gvc_mixer_card_get_name (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); return card->priv->name; } gboolean gvc_mixer_card_set_name (GvcMixerCard *card, const char *name) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); g_free (card->priv->name); card->priv->name = g_strdup (name); g_object_notify (G_OBJECT (card), "name"); return TRUE; } const char * gvc_mixer_card_get_icon_name (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); return card->priv->icon_name; } gboolean gvc_mixer_card_set_icon_name (GvcMixerCard *card, const char *icon_name) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); g_free (card->priv->icon_name); card->priv->icon_name = g_strdup (icon_name); g_object_notify (G_OBJECT (card), "icon-name"); return TRUE; } /** * gvc_mixer_card_get_profile: (skip) * @card: * * Returns: */ GvcMixerCardProfile * gvc_mixer_card_get_profile (GvcMixerCard *card) { GList *l; g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); g_return_val_if_fail (card->priv->profiles != NULL, NULL); for (l = card->priv->profiles; l != NULL; l = l->next) { GvcMixerCardProfile *p = l->data; if (g_str_equal (card->priv->profile, p->profile)) { return p; } } g_assert_not_reached (); return NULL; } gboolean gvc_mixer_card_set_profile (GvcMixerCard *card, const char *profile) { GList *l; g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); g_return_val_if_fail (card->priv->profiles != NULL, FALSE); g_free (card->priv->profile); card->priv->profile = g_strdup (profile); g_free (card->priv->human_profile); card->priv->human_profile = NULL; for (l = card->priv->profiles; l != NULL; l = l->next) { GvcMixerCardProfile *p = l->data; if (g_str_equal (card->priv->profile, p->profile)) { card->priv->human_profile = g_strdup (p->human_profile); break; } } g_object_notify (G_OBJECT (card), "profile"); return TRUE; } static void _pa_context_set_card_profile_by_index_cb (pa_context *context, int success, void *userdata) { GvcMixerCard *card = GVC_MIXER_CARD (userdata); g_assert (card->priv->target_profile); if (success > 0) { gvc_mixer_card_set_profile (card, card->priv->target_profile); } else { g_debug ("Failed to switch profile on '%s' from '%s' to '%s'", card->priv->name, card->priv->profile, card->priv->target_profile); } g_free (card->priv->target_profile); card->priv->target_profile = NULL; pa_operation_unref (card->priv->profile_op); card->priv->profile_op = NULL; } gboolean gvc_mixer_card_change_profile (GvcMixerCard *card, const char *profile) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); g_return_val_if_fail (card->priv->profiles != NULL, FALSE); /* Same profile, or already requested? */ if (g_strcmp0 (card->priv->profile, profile) == 0) return TRUE; if (g_strcmp0 (profile, card->priv->target_profile) == 0) return TRUE; if (card->priv->profile_op != NULL) { pa_operation_cancel (card->priv->profile_op); pa_operation_unref (card->priv->profile_op); card->priv->profile_op = NULL; } if (card->priv->profile != NULL) { g_free (card->priv->target_profile); card->priv->target_profile = g_strdup (profile); card->priv->profile_op = pa_context_set_card_profile_by_index (card->priv->pa_context, card->priv->index, card->priv->target_profile, _pa_context_set_card_profile_by_index_cb, card); if (card->priv->profile_op == NULL) { g_warning ("pa_context_set_card_profile_by_index() failed"); return FALSE; } } else { g_assert (card->priv->human_profile == NULL); card->priv->profile = g_strdup (profile); } return TRUE; } /** * gvc_mixer_card_get_profiles: * * Return value: (transfer none) (element-type GvcMixerCardProfile): */ const GList * gvc_mixer_card_get_profiles (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); return card->priv->profiles; } /** * gvc_mixer_card_get_ports: * * Return value: (transfer none) (element-type GvcMixerCardPort): */ const GList * gvc_mixer_card_get_ports (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); return card->priv->ports; } /** * gvc_mixer_card_profile_compare: * * Return value: 1 if @a has a higher priority, -1 if @b has a higher * priority, 0 if @a and @b have the same priority. */ int gvc_mixer_card_profile_compare (GvcMixerCardProfile *a, GvcMixerCardProfile *b) { if (a->priority == b->priority) return 0; if (a->priority > b->priority) return 1; return -1; } /** * gvc_mixer_card_set_profiles: * @profiles: (transfer full) (element-type GvcMixerCardProfile): */ gboolean gvc_mixer_card_set_profiles (GvcMixerCard *card, GList *profiles) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); g_return_val_if_fail (card->priv->profiles == NULL, FALSE); card->priv->profiles = g_list_sort (profiles, (GCompareFunc) gvc_mixer_card_profile_compare); return TRUE; } /** * gvc_mixer_card_get_gicon: * @card: * * Return value: (transfer full): */ GIcon * gvc_mixer_card_get_gicon (GvcMixerCard *card) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); if (card->priv->icon_name == NULL) return NULL; return g_themed_icon_new_with_default_fallbacks (card->priv->icon_name); } /** * gvc_mixer_card_set_ports: * @ports: (transfer full) (element-type GvcMixerCardPort): */ gboolean gvc_mixer_card_set_ports (GvcMixerCard *card, GList *ports) { g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); g_return_val_if_fail (card->priv->ports == NULL, FALSE); card->priv->ports = ports; return TRUE; } static void gvc_mixer_card_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GvcMixerCard *self = GVC_MIXER_CARD (object); switch (prop_id) { case PROP_PA_CONTEXT: self->priv->pa_context = g_value_get_pointer (value); break; case PROP_INDEX: self->priv->index = g_value_get_ulong (value); break; case PROP_ID: self->priv->id = g_value_get_ulong (value); break; case PROP_NAME: gvc_mixer_card_set_name (self, g_value_get_string (value)); break; case PROP_ICON_NAME: gvc_mixer_card_set_icon_name (self, g_value_get_string (value)); break; case PROP_PROFILE: gvc_mixer_card_set_profile (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gvc_mixer_card_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GvcMixerCard *self = GVC_MIXER_CARD (object); switch (prop_id) { case PROP_PA_CONTEXT: g_value_set_pointer (value, self->priv->pa_context); break; case PROP_INDEX: g_value_set_ulong (value, self->priv->index); break; case PROP_ID: g_value_set_ulong (value, self->priv->id); break; case PROP_NAME: g_value_set_string (value, self->priv->name); break; case PROP_ICON_NAME: g_value_set_string (value, self->priv->icon_name); break; case PROP_PROFILE: g_value_set_string (value, self->priv->profile); break; case PROP_HUMAN_PROFILE: g_value_set_string (value, self->priv->human_profile); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GObject * gvc_mixer_card_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; GvcMixerCard *self; object = G_OBJECT_CLASS (gvc_mixer_card_parent_class)->constructor (type, n_construct_properties, construct_params); self = GVC_MIXER_CARD (object); self->priv->id = get_next_card_serial (); return object; } static void gvc_mixer_card_class_init (GvcMixerCardClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->constructor = gvc_mixer_card_constructor; gobject_class->finalize = gvc_mixer_card_finalize; gobject_class->set_property = gvc_mixer_card_set_property; gobject_class->get_property = gvc_mixer_card_get_property; g_object_class_install_property (gobject_class, PROP_INDEX, g_param_spec_ulong ("index", "Index", "The index for this card", 0, G_MAXULONG, 0, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_ID, g_param_spec_ulong ("id", "id", "The id for this card", 0, G_MAXULONG, 0, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_PA_CONTEXT, g_param_spec_pointer ("pa-context", "PulseAudio context", "The PulseAudio context for this card", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_NAME, g_param_spec_string ("name", "Name", "Name to display for this card", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_ICON_NAME, g_param_spec_string ("icon-name", "Icon Name", "Name of icon to display for this card", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_PROFILE, g_param_spec_string ("profile", "Profile", "Name of current profile for this card", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_HUMAN_PROFILE, g_param_spec_string ("human-profile", "Profile (Human readable)", "Name of current profile for this card in human readable form", NULL, G_PARAM_READABLE)); g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate)); } static void gvc_mixer_card_init (GvcMixerCard *card) { card->priv = GVC_MIXER_CARD_GET_PRIVATE (card); } GvcMixerCard * gvc_mixer_card_new (pa_context *context, guint index) { GObject *object; object = g_object_new (GVC_TYPE_MIXER_CARD, "index", index, "pa-context", context, NULL); return GVC_MIXER_CARD (object); } static void free_profile (GvcMixerCardProfile *p) { g_free (p->profile); g_free (p->human_profile); g_free (p->status); g_free (p); } static void gvc_mixer_card_finalize (GObject *object) { GvcMixerCard *mixer_card; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_CARD (object)); mixer_card = GVC_MIXER_CARD (object); g_return_if_fail (mixer_card->priv != NULL); g_free (mixer_card->priv->name); mixer_card->priv->name = NULL; g_free (mixer_card->priv->icon_name); mixer_card->priv->icon_name = NULL; g_free (mixer_card->priv->target_profile); mixer_card->priv->target_profile = NULL; g_free (mixer_card->priv->profile); mixer_card->priv->profile = NULL; g_free (mixer_card->priv->human_profile); mixer_card->priv->human_profile = NULL; g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL); g_list_free (mixer_card->priv->profiles); mixer_card->priv->profiles = NULL; G_OBJECT_CLASS (gvc_mixer_card_parent_class)->finalize (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-card.h0000664000000000000000000000774215172222611021477 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008-2009 Red Hat, Inc. * Copyright (C) Conor Curran 2011 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_CARD_H #define __GVC_MIXER_CARD_H #include #include G_BEGIN_DECLS #define GVC_TYPE_MIXER_CARD (gvc_mixer_card_get_type ()) #define GVC_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CARD, GvcMixerCard)) #define GVC_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CARD, GvcMixerCardClass)) #define GVC_IS_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CARD)) #define GVC_IS_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CARD)) #define GVC_MIXER_CARD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardClass)) typedef struct GvcMixerCardPrivate GvcMixerCardPrivate; typedef struct { GObject parent; GvcMixerCardPrivate *priv; } GvcMixerCard; typedef struct { GObjectClass parent_class; /* vtable */ } GvcMixerCardClass; typedef struct { char *profile; char *human_profile; char *status; guint priority; guint n_sinks, n_sources; } GvcMixerCardProfile; typedef struct { char *port; char *human_port; guint priority; gint available; gint direction; GList *profiles; } GvcMixerCardPort; GType gvc_mixer_card_get_type (void); guint gvc_mixer_card_get_id (GvcMixerCard *card); guint gvc_mixer_card_get_index (GvcMixerCard *card); const char * gvc_mixer_card_get_name (GvcMixerCard *card); const char * gvc_mixer_card_get_icon_name (GvcMixerCard *card); GvcMixerCardProfile * gvc_mixer_card_get_profile (GvcMixerCard *card); const GList * gvc_mixer_card_get_profiles (GvcMixerCard *card); const GList * gvc_mixer_card_get_ports (GvcMixerCard *card); gboolean gvc_mixer_card_change_profile (GvcMixerCard *card, const char *profile); GIcon * gvc_mixer_card_get_gicon (GvcMixerCard *card); int gvc_mixer_card_profile_compare (GvcMixerCardProfile *a, GvcMixerCardProfile *b); /* private */ gboolean gvc_mixer_card_set_name (GvcMixerCard *card, const char *name); gboolean gvc_mixer_card_set_icon_name (GvcMixerCard *card, const char *name); gboolean gvc_mixer_card_set_profile (GvcMixerCard *card, const char *profile); gboolean gvc_mixer_card_set_profiles (GvcMixerCard *card, GList *profiles); gboolean gvc_mixer_card_set_ports (GvcMixerCard *stream, GList *ports); G_END_DECLS #endif /* __GVC_MIXER_CARD_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-control-private.h0000664000000000000000000000224415172222611023706 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_CONTROL_PRIVATE_H #define __GVC_MIXER_CONTROL_PRIVATE_H #include #include #include "gvc-mixer-stream.h" #include "gvc-mixer-card.h" G_BEGIN_DECLS pa_context * gvc_mixer_control_get_pa_context (GvcMixerControl *control); G_END_DECLS #endif /* __GVC_MIXER_CONTROL_PRIVATE_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-control.c0000664000000000000000000037413515172222611022244 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2008 Lennart Poettering * Copyright (C) 2008 Sjoerd Simons * Copyright (C) 2008 William Jon McCann * Copyright (C) 2012 Conor Curran * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "gvc-mixer-control.h" #include "gvc-mixer-sink.h" #include "gvc-mixer-source.h" #include "gvc-mixer-sink-input.h" #include "gvc-mixer-source-output.h" #include "gvc-mixer-event-role.h" #include "gvc-mixer-card.h" #include "gvc-mixer-card-private.h" #include "gvc-channel-map-private.h" #include "gvc-mixer-control-private.h" #include "gvc-mixer-ui-device.h" #define GVC_MIXER_CONTROL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlPrivate)) #define RECONNECT_DELAY 5 enum { PROP_0, PROP_NAME }; struct GvcMixerControlPrivate { pa_glib_mainloop *pa_mainloop; pa_mainloop_api *pa_api; pa_context *pa_context; int n_outstanding; guint reconnect_id; char *name; gboolean default_sink_is_set; guint default_sink_id; char *default_sink_name; gboolean default_source_is_set; guint default_source_id; char *default_source_name; gboolean event_sink_input_is_set; guint event_sink_input_id; GHashTable *all_streams; GHashTable *sinks; /* fixed outputs */ GHashTable *sources; /* fixed inputs */ GHashTable *sink_inputs; /* routable output streams */ GHashTable *source_outputs; /* routable input streams */ GHashTable *clients; GHashTable *cards; GvcMixerStream *new_default_sink_stream; /* new default sink stream, used in gvc_mixer_control_set_default_sink () */ GvcMixerStream *new_default_source_stream; /* new default source stream, used in gvc_mixer_control_set_default_source () */ GHashTable *ui_outputs; /* UI visible outputs */ GHashTable *ui_inputs; /* UI visible inputs */ /* When we change profile on a device that is not the server default sink, * it will jump back to the default sink set by the server to prevent the * audio setup from being 'outputless'. * * All well and good but then when we get the new stream created for the * new profile how do we know that this is the intended default or selected * device the user wishes to use. */ guint profile_swapping_device_id; GvcMixerControlState state; }; enum { STATE_CHANGED, STREAM_ADDED, STREAM_REMOVED, CARD_ADDED, CARD_REMOVED, DEFAULT_SINK_CHANGED, DEFAULT_SOURCE_CHANGED, ACTIVE_OUTPUT_UPDATE, ACTIVE_INPUT_UPDATE, OUTPUT_ADDED, INPUT_ADDED, OUTPUT_REMOVED, INPUT_REMOVED, CARD_INFO, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0, }; static void gvc_mixer_control_class_init (GvcMixerControlClass *klass); static void gvc_mixer_control_init (GvcMixerControl *mixer_control); static void gvc_mixer_control_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerControl, gvc_mixer_control, G_TYPE_OBJECT) pa_context * gvc_mixer_control_get_pa_context (GvcMixerControl *control) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); return control->priv->pa_context; } /** * gvc_mixer_control_get_event_sink_input: * @control: * * Returns: (transfer none): */ GvcMixerStream * gvc_mixer_control_get_event_sink_input (GvcMixerControl *control) { GvcMixerStream *stream; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); stream = g_hash_table_lookup (control->priv->all_streams, GUINT_TO_POINTER (control->priv->event_sink_input_id)); return stream; } static void gvc_mixer_control_stream_restore_cb (pa_context *c, GvcMixerStream *new_stream, const pa_ext_stream_restore_info *info, GvcMixerControl *control) { pa_operation *o; pa_ext_stream_restore_info new_info; if (new_stream == NULL) return; new_info.name = info->name; new_info.channel_map = info->channel_map; new_info.volume = info->volume; new_info.mute = info->mute; new_info.device = gvc_mixer_stream_get_name (new_stream); o = pa_ext_stream_restore_write (control->priv->pa_context, PA_UPDATE_REPLACE, &new_info, 1, TRUE, NULL, NULL); if (o == NULL) { g_warning ("pa_ext_stream_restore_write() failed: %s", pa_strerror (pa_context_errno (control->priv->pa_context))); return; } g_debug ("Changed default device for %s to %s", info->name, new_info.device); pa_operation_unref (o); } static void gvc_mixer_control_stream_restore_sink_cb (pa_context *c, const pa_ext_stream_restore_info *info, int eol, void *userdata) { GvcMixerControl *control = (GvcMixerControl *) userdata; if (eol || info == NULL || !g_str_has_prefix(info->name, "sink-input-by")) return; gvc_mixer_control_stream_restore_cb (c, control->priv->new_default_sink_stream, info, control); } static void gvc_mixer_control_stream_restore_source_cb (pa_context *c, const pa_ext_stream_restore_info *info, int eol, void *userdata) { GvcMixerControl *control = (GvcMixerControl *) userdata; if (eol || info == NULL || !g_str_has_prefix(info->name, "source-output-by")) return; gvc_mixer_control_stream_restore_cb (c, control->priv->new_default_source_stream, info, control); } /** * gvc_mixer_control_lookup_device_from_stream: * @control: * @stream: * * Returns: (transfer none): a #GvcUIDevice or %NULL */ GvcMixerUIDevice * gvc_mixer_control_lookup_device_from_stream (GvcMixerControl *control, GvcMixerStream *stream) { GList *devices, *d; gboolean is_network_stream; const GList *ports; GvcMixerUIDevice *ret; if (GVC_IS_MIXER_SOURCE (stream)) devices = g_hash_table_get_values (control->priv->ui_inputs); else devices = g_hash_table_get_values (control->priv->ui_outputs); ret = NULL; ports = gvc_mixer_stream_get_ports (stream); is_network_stream = (ports == NULL); for (d = devices; d != NULL; d = d->next) { GvcMixerUIDevice *device = d->data; gint stream_id = G_MAXINT; g_object_get (G_OBJECT (device), "stream-id", &stream_id, NULL); if (is_network_stream && stream_id == gvc_mixer_stream_get_id (stream)) { g_debug ("lookup device from stream - %s - it is a network_stream ", gvc_mixer_ui_device_get_description (device)); ret = device; break; } else if (!is_network_stream) { const GvcMixerStreamPort *port; port = gvc_mixer_stream_get_port (stream); if (stream_id == gvc_mixer_stream_get_id (stream) && g_strcmp0 (gvc_mixer_ui_device_get_port (device), port->port) == 0) { g_debug ("lookup-device-from-stream found device: device description '%s', device port = '%s', device stream id %i AND stream port = '%s' stream id '%u' and stream description '%s'", gvc_mixer_ui_device_get_description (device), gvc_mixer_ui_device_get_port (device), stream_id, port->port, gvc_mixer_stream_get_id (stream), gvc_mixer_stream_get_description (stream)); ret = device; break; } } } g_debug ("gvc_mixer_control_lookup_device_from_stream - Could not find a device for stream '%s'",gvc_mixer_stream_get_description (stream)); g_list_free (devices); return ret; } gboolean gvc_mixer_control_set_default_sink (GvcMixerControl *control, GvcMixerStream *stream) { pa_operation *o; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_debug ("about to set default sink on server"); o = pa_context_set_default_sink (control->priv->pa_context, gvc_mixer_stream_get_name (stream), NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_default_sink() failed: %s", pa_strerror (pa_context_errno (control->priv->pa_context))); return FALSE; } pa_operation_unref (o); control->priv->new_default_sink_stream = stream; g_object_add_weak_pointer (G_OBJECT (stream), (gpointer *) &control->priv->new_default_sink_stream); o = pa_ext_stream_restore_read (control->priv->pa_context, gvc_mixer_control_stream_restore_sink_cb, control); if (o == NULL) { g_warning ("pa_ext_stream_restore_read() failed: %s", pa_strerror (pa_context_errno (control->priv->pa_context))); return FALSE; } pa_operation_unref (o); return TRUE; } gboolean gvc_mixer_control_set_default_source (GvcMixerControl *control, GvcMixerStream *stream) { GvcMixerUIDevice* input; pa_operation *o; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); o = pa_context_set_default_source (control->priv->pa_context, gvc_mixer_stream_get_name (stream), NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_default_source() failed"); return FALSE; } pa_operation_unref (o); control->priv->new_default_source_stream = stream; g_object_add_weak_pointer (G_OBJECT (stream), (gpointer *) &control->priv->new_default_source_stream); o = pa_ext_stream_restore_read (control->priv->pa_context, gvc_mixer_control_stream_restore_source_cb, control); if (o == NULL) { g_warning ("pa_ext_stream_restore_read() failed: %s", pa_strerror (pa_context_errno (control->priv->pa_context))); return FALSE; } pa_operation_unref (o); /* source change successful, update the UI. */ input = gvc_mixer_control_lookup_device_from_stream (control, stream); g_signal_emit (G_OBJECT (control), signals[ACTIVE_INPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (input)); return TRUE; } /** * gvc_mixer_control_get_default_sink: * @control: * * Returns: (transfer none): */ GvcMixerStream * gvc_mixer_control_get_default_sink (GvcMixerControl *control) { GvcMixerStream *stream; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); if (control->priv->default_sink_is_set) { stream = g_hash_table_lookup (control->priv->all_streams, GUINT_TO_POINTER (control->priv->default_sink_id)); } else { stream = NULL; } return stream; } /** * gvc_mixer_control_get_default_source: * @control: * * Returns: (transfer none): */ GvcMixerStream * gvc_mixer_control_get_default_source (GvcMixerControl *control) { GvcMixerStream *stream; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); if (control->priv->default_source_is_set) { stream = g_hash_table_lookup (control->priv->all_streams, GUINT_TO_POINTER (control->priv->default_source_id)); } else { stream = NULL; } return stream; } static gpointer gvc_mixer_control_lookup_id (GHashTable *hash_table, guint id) { return g_hash_table_lookup (hash_table, GUINT_TO_POINTER (id)); } /** * gvc_mixer_control_lookup_stream_id: * @control: * @id: * * Returns: (transfer none): */ GvcMixerStream * gvc_mixer_control_lookup_stream_id (GvcMixerControl *control, guint id) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); return gvc_mixer_control_lookup_id (control->priv->all_streams, id); } /** * gvc_mixer_control_lookup_card_id: * @control: * @id: * * Returns: (transfer none): */ GvcMixerCard * gvc_mixer_control_lookup_card_id (GvcMixerControl *control, guint id) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); return gvc_mixer_control_lookup_id (control->priv->cards, id); } /** * gvc_mixer_control_lookup_output_id: * @control: * @id: * * Returns: (transfer none): */ GvcMixerUIDevice * gvc_mixer_control_lookup_output_id (GvcMixerControl *control, guint id) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); return gvc_mixer_control_lookup_id (control->priv->ui_outputs, id); } /** * gvc_mixer_control_lookup_input_id: * @control: * @id: * * Returns: (transfer none): */ GvcMixerUIDevice * gvc_mixer_control_lookup_input_id (GvcMixerControl *control, guint id) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); return gvc_mixer_control_lookup_id (control->priv->ui_inputs, id); } /** * gvc_mixer_control_get_stream_from_device: * @control: * @device: * * Returns: (transfer none): */ GvcMixerStream * gvc_mixer_control_get_stream_from_device (GvcMixerControl *control, GvcMixerUIDevice *device) { gint stream_id; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); stream_id = gvc_mixer_ui_device_get_stream_id (device); if (stream_id == GVC_MIXER_UI_DEVICE_INVALID) { g_debug ("gvc_mixer_control_get_stream_from_device - device has a null stream"); return NULL; } return gvc_mixer_control_lookup_stream_id (control, stream_id); } /** * gvc_mixer_control_change_profile_on_selected_device: * @control: * @device: * @profile: Can be null if any profile present on this port is okay * * Returns: This method will attempt to swap the profile on the card of * the device with given profile name. If successfull it will set the * preferred profile on that device so as we know the next time the user * moves to that device it should have this profile active. */ gboolean gvc_mixer_control_change_profile_on_selected_device (GvcMixerControl *control, GvcMixerUIDevice *device, const gchar *profile) { const gchar *best_profile; GvcMixerCardProfile *current_profile; GvcMixerCard *card; g_object_get (G_OBJECT (device), "card", &card, NULL); current_profile = gvc_mixer_card_get_profile (card); if (current_profile) best_profile = gvc_mixer_ui_device_get_best_profile (device, profile, current_profile->profile); else best_profile = profile; g_assert (best_profile); g_debug ("Selected '%s', moving to profile '%s' on card '%s' on stream id %i", profile ? profile : "(any)", best_profile, gvc_mixer_card_get_name (card), gvc_mixer_ui_device_get_stream_id (device)); g_debug ("default sink name = %s and default sink id %u", control->priv->default_sink_name, control->priv->default_sink_id); control->priv->profile_swapping_device_id = gvc_mixer_ui_device_get_id (device); if (gvc_mixer_card_change_profile (card, best_profile)) { gvc_mixer_ui_device_set_user_preferred_profile (device, best_profile); return TRUE; } return FALSE; } /** * gvc_mixer_control_change_output: * @control: * @output: * This method is called from the UI when the user selects a previously unselected device. * - Firstly it queries the stream from the device. * - It assumes that if the stream is null that it cannot be a bluetooth or network stream (they never show unless they have valid sinks and sources) * In the scenario of a NULL stream on the device * - It fetches the device's preferred profile or if NUll the profile with the highest priority on that device. * - It then caches this device in control->priv->cached_desired_output_id so that when the update_sink triggered * from when we attempt to change profile we will know exactly what device to highlight on that stream. * - It attempts to swap the profile on the card from that device and returns. * - Next, it handles network or bluetooth streams that only require their stream to be made the default. * - Next it deals with port changes so if the stream's active port is not the same as the port on the device * it will attempt to change the port on that stream to be same as the device. If this fails it will return. * - Finally it will set this new stream to be the default stream and emit a signal for the UI confirming the active output device. */ void gvc_mixer_control_change_output (GvcMixerControl *control, GvcMixerUIDevice* output) { GvcMixerStream *stream; GvcMixerStream *default_stream; const GvcMixerStreamPort *active_port; const gchar *output_port; g_debug ("control change output"); stream = gvc_mixer_control_get_stream_from_device (control, output); if (stream == NULL) { gvc_mixer_control_change_profile_on_selected_device (control, output, NULL); return; } /* Handle a network sink as a portless or cardless device */ if (!gvc_mixer_ui_device_has_ports (output)) { g_debug ("Did we try to move to a software/bluetooth sink ?"); if (gvc_mixer_control_set_default_sink (control, stream)) { /* sink change was successful, update the UI.*/ g_signal_emit (G_OBJECT (control), signals[ACTIVE_OUTPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (output)); } else { g_warning ("Failed to set default sink with stream from output %s", gvc_mixer_ui_device_get_description (output)); } return; } active_port = gvc_mixer_stream_get_port (stream); output_port = gvc_mixer_ui_device_get_port (output); /* First ensure the correct port is active on the sink */ if (g_strcmp0 (active_port->port, output_port) != 0) { g_debug ("Port change, switch to = %s", output_port); if (gvc_mixer_stream_change_port (stream, output_port) == FALSE) { g_warning ("Could not change port !"); return; } } default_stream = gvc_mixer_control_get_default_sink (control); /* Finally if we are not on the correct stream, swap over. */ if (stream != default_stream) { GvcMixerUIDevice* output; g_debug ("Attempting to swap over to stream %s ", gvc_mixer_stream_get_description (stream)); if (gvc_mixer_control_set_default_sink (control, stream)) { output = gvc_mixer_control_lookup_device_from_stream (control, stream); g_signal_emit (G_OBJECT (control), signals[ACTIVE_OUTPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (output)); } else { /* If the move failed for some reason reset the UI. */ output = gvc_mixer_control_lookup_device_from_stream (control, default_stream); g_signal_emit (G_OBJECT (control), signals[ACTIVE_OUTPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (output)); } } } /** * gvc_mixer_control_change_input: * @control: * @input: * This method is called from the UI when the user selects a previously unselected device. * - Firstly it queries the stream from the device. * - It assumes that if the stream is null that it cannot be a bluetooth or network stream (they never show unless they have valid sinks and sources) * In the scenario of a NULL stream on the device * - It fetches the device's preferred profile or if NUll the profile with the highest priority on that device. * - It then caches this device in control->priv->cached_desired_input_id so that when the update_source triggered * from when we attempt to change profile we will know exactly what device to highlight on that stream. * - It attempts to swap the profile on the card from that device and returns. * - Next, it handles network or bluetooth streams that only require their stream to be made the default. * - Next it deals with port changes so if the stream's active port is not the same as the port on the device * it will attempt to change the port on that stream to be same as the device. If this fails it will return. * - Finally it will set this new stream to be the default stream and emit a signal for the UI confirming the active input device. */ void gvc_mixer_control_change_input (GvcMixerControl *control, GvcMixerUIDevice* input) { GvcMixerStream *stream; GvcMixerStream *default_stream; const GvcMixerStreamPort *active_port; const gchar *input_port; stream = gvc_mixer_control_get_stream_from_device (control, input); if (stream == NULL) { gvc_mixer_control_change_profile_on_selected_device (control, input, NULL); return; } /* Handle a network sink as a portless/cardless device */ if (!gvc_mixer_ui_device_has_ports (input)) { g_debug ("Did we try to move to a software/bluetooth source ?"); if (! gvc_mixer_control_set_default_source (control, stream)) { g_warning ("Failed to set default source with stream from input %s", gvc_mixer_ui_device_get_description (input)); } return; } active_port = gvc_mixer_stream_get_port (stream); input_port = gvc_mixer_ui_device_get_port (input); /* First ensure the correct port is active on the sink */ if (g_strcmp0 (active_port->port, input_port) != 0) { g_debug ("Port change, switch to = %s", input_port); if (gvc_mixer_stream_change_port (stream, input_port) == FALSE) { g_warning ("Could not change port!"); return; } } default_stream = gvc_mixer_control_get_default_source (control); /* Finally if we are not on the correct stream, swap over. */ if (stream != default_stream) { g_debug ("change-input - attempting to swap over to stream %s", gvc_mixer_stream_get_description (stream)); gvc_mixer_control_set_default_source (control, stream); } } static void listify_hash_values_hfunc (gpointer key, gpointer value, gpointer user_data) { GSList **list = user_data; *list = g_slist_prepend (*list, value); } static int gvc_name_collate (const char *namea, const char *nameb) { if (nameb == NULL && namea == NULL) return 0; if (nameb == NULL) return 1; if (namea == NULL) return -1; return g_utf8_collate (namea, nameb); } static int gvc_card_collate (GvcMixerCard *a, GvcMixerCard *b) { const char *namea; const char *nameb; g_return_val_if_fail (a == NULL || GVC_IS_MIXER_CARD (a), 0); g_return_val_if_fail (b == NULL || GVC_IS_MIXER_CARD (b), 0); namea = gvc_mixer_card_get_name (a); nameb = gvc_mixer_card_get_name (b); return gvc_name_collate (namea, nameb); } /** * gvc_mixer_control_get_cards: * @control: * * Returns: (transfer container) (element-type Gvc.MixerCard): */ GSList * gvc_mixer_control_get_cards (GvcMixerControl *control) { GSList *retval; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); retval = NULL; g_hash_table_foreach (control->priv->cards, listify_hash_values_hfunc, &retval); return g_slist_sort (retval, (GCompareFunc) gvc_card_collate); } static int gvc_stream_collate (GvcMixerStream *a, GvcMixerStream *b) { const char *namea; const char *nameb; g_return_val_if_fail (a == NULL || GVC_IS_MIXER_STREAM (a), 0); g_return_val_if_fail (b == NULL || GVC_IS_MIXER_STREAM (b), 0); namea = gvc_mixer_stream_get_name (a); nameb = gvc_mixer_stream_get_name (b); return gvc_name_collate (namea, nameb); } /** * gvc_mixer_control_get_streams: * @control: * * Returns: (transfer container) (element-type Gvc.MixerStream): */ GSList * gvc_mixer_control_get_streams (GvcMixerControl *control) { GSList *retval; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); retval = NULL; g_hash_table_foreach (control->priv->all_streams, listify_hash_values_hfunc, &retval); return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); } /** * gvc_mixer_control_get_sinks: * @control: * * Returns: (transfer container) (element-type Gvc.MixerSink): */ GSList * gvc_mixer_control_get_sinks (GvcMixerControl *control) { GSList *retval; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); retval = NULL; g_hash_table_foreach (control->priv->sinks, listify_hash_values_hfunc, &retval); return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); } /** * gvc_mixer_control_get_sources: * @control: * * Returns: (transfer container) (element-type Gvc.MixerSource): */ GSList * gvc_mixer_control_get_sources (GvcMixerControl *control) { GSList *retval; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); retval = NULL; g_hash_table_foreach (control->priv->sources, listify_hash_values_hfunc, &retval); return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); } /** * gvc_mixer_control_get_sink_inputs: * @control: * * Returns: (transfer container) (element-type Gvc.MixerSinkInput): */ GSList * gvc_mixer_control_get_sink_inputs (GvcMixerControl *control) { GSList *retval; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); retval = NULL; g_hash_table_foreach (control->priv->sink_inputs, listify_hash_values_hfunc, &retval); return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); } /** * gvc_mixer_control_get_source_outputs: * @control: * * Returns: (transfer container) (element-type Gvc.MixerSourceOutput): */ GSList * gvc_mixer_control_get_source_outputs (GvcMixerControl *control) { GSList *retval; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); retval = NULL; g_hash_table_foreach (control->priv->source_outputs, listify_hash_values_hfunc, &retval); return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); } static void dec_outstanding (GvcMixerControl *control) { if (control->priv->n_outstanding <= 0) { return; } if (--control->priv->n_outstanding <= 0) { control->priv->state = GVC_STATE_READY; g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_READY); } } GvcMixerControlState gvc_mixer_control_get_state (GvcMixerControl *control) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); return control->priv->state; } static void on_default_source_port_notify (GObject *object, GParamSpec *pspec, GvcMixerControl *control) { char *port; GvcMixerUIDevice *input; g_object_get (object, "port", &port, NULL); input = gvc_mixer_control_lookup_device_from_stream (control, GVC_MIXER_STREAM (object)); g_debug ("on_default_source_port_notify - moved to port '%s' which SHOULD ?? correspond to output '%s'", port, gvc_mixer_ui_device_get_description (input)); g_signal_emit (G_OBJECT (control), signals[ACTIVE_INPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (input)); g_free (port); } static void _set_default_source (GvcMixerControl *control, GvcMixerStream *stream) { guint new_id; if (stream == NULL) { control->priv->default_source_id = 0; control->priv->default_source_is_set = FALSE; g_signal_emit (control, signals[DEFAULT_SOURCE_CHANGED], 0, PA_INVALID_INDEX); return; } new_id = gvc_mixer_stream_get_id (stream); if (control->priv->default_source_id != new_id) { GvcMixerUIDevice *input; control->priv->default_source_id = new_id; control->priv->default_source_is_set = TRUE; g_signal_emit (control, signals[DEFAULT_SOURCE_CHANGED], 0, new_id); if (control->priv->default_source_is_set) { g_signal_handlers_disconnect_by_func (gvc_mixer_control_get_default_source (control), on_default_source_port_notify, control); } g_signal_connect (stream, "notify::port", G_CALLBACK (on_default_source_port_notify), control); input = gvc_mixer_control_lookup_device_from_stream (control, stream); g_signal_emit (G_OBJECT (control), signals[ACTIVE_INPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (input)); } } static void on_default_sink_port_notify (GObject *object, GParamSpec *pspec, GvcMixerControl *control) { char *port; GvcMixerUIDevice *output; g_object_get (object, "port", &port, NULL); output = gvc_mixer_control_lookup_device_from_stream (control, GVC_MIXER_STREAM (object)); if (output != NULL) { g_debug ("on_default_sink_port_notify - moved to port %s - which SHOULD correspond to output %s", port, gvc_mixer_ui_device_get_description (output)); g_signal_emit (G_OBJECT (control), signals[ACTIVE_OUTPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (output)); } g_free (port); } static void _set_default_sink (GvcMixerControl *control, GvcMixerStream *stream) { guint new_id; if (stream == NULL) { /* Don't tell front-ends about an unset default * sink if it's already unset */ if (control->priv->default_sink_is_set == FALSE) return; control->priv->default_sink_id = 0; control->priv->default_sink_is_set = FALSE; g_signal_emit (control, signals[DEFAULT_SINK_CHANGED], 0, PA_INVALID_INDEX); return; } new_id = gvc_mixer_stream_get_id (stream); if (control->priv->default_sink_id != new_id) { GvcMixerUIDevice *output; if (control->priv->default_sink_is_set) { g_signal_handlers_disconnect_by_func (gvc_mixer_control_get_default_sink (control), on_default_sink_port_notify, control); } control->priv->default_sink_id = new_id; control->priv->default_sink_is_set = TRUE; g_signal_emit (control, signals[DEFAULT_SINK_CHANGED], 0, new_id); g_signal_connect (stream, "notify::port", G_CALLBACK (on_default_sink_port_notify), control); output = gvc_mixer_control_lookup_device_from_stream (control, stream); g_debug ("active_sink change"); g_signal_emit (G_OBJECT (control), signals[ACTIVE_OUTPUT_UPDATE], 0, gvc_mixer_ui_device_get_id (output)); } } static gboolean _stream_has_name (gpointer key, GvcMixerStream *stream, const char *name) { const char *t_name; t_name = gvc_mixer_stream_get_name (stream); if (t_name != NULL && name != NULL && strcmp (t_name, name) == 0) { return TRUE; } return FALSE; } static GvcMixerStream * find_stream_for_name (GvcMixerControl *control, const char *name) { GvcMixerStream *stream; stream = g_hash_table_find (control->priv->all_streams, (GHRFunc)_stream_has_name, (char *)name); return stream; } static void update_default_source_from_name (GvcMixerControl *control, const char *name) { gboolean changed = FALSE; if ((control->priv->default_source_name == NULL && name != NULL) || (control->priv->default_source_name != NULL && name == NULL) || (name != NULL && strcmp (control->priv->default_source_name, name) != 0)) { changed = TRUE; } if (changed) { GvcMixerStream *stream; g_free (control->priv->default_source_name); control->priv->default_source_name = g_strdup (name); stream = find_stream_for_name (control, name); _set_default_source (control, stream); } } static void update_default_sink_from_name (GvcMixerControl *control, const char *name) { gboolean changed = FALSE; if ((control->priv->default_sink_name == NULL && name != NULL) || (control->priv->default_sink_name != NULL && name == NULL) || (name != NULL && strcmp (control->priv->default_sink_name, name) != 0)) { changed = TRUE; } if (changed) { GvcMixerStream *stream; g_free (control->priv->default_sink_name); control->priv->default_sink_name = g_strdup (name); stream = find_stream_for_name (control, name); _set_default_sink (control, stream); } } static void update_server (GvcMixerControl *control, const pa_server_info *info) { if (info->default_source_name != NULL) { update_default_source_from_name (control, info->default_source_name); } if (info->default_sink_name != NULL) { g_debug ("update server"); update_default_sink_from_name (control, info->default_sink_name); } } static void remove_stream (GvcMixerControl *control, GvcMixerStream *stream) { guint id; g_object_ref (stream); id = gvc_mixer_stream_get_id (stream); if (id == control->priv->default_sink_id) { _set_default_sink (control, NULL); } else if (id == control->priv->default_source_id) { _set_default_source (control, NULL); } g_hash_table_remove (control->priv->all_streams, GUINT_TO_POINTER (id)); g_signal_emit (G_OBJECT (control), signals[STREAM_REMOVED], 0, gvc_mixer_stream_get_id (stream)); g_object_unref (stream); } static void add_stream (GvcMixerControl *control, GvcMixerStream *stream) { g_hash_table_insert (control->priv->all_streams, GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)), stream); g_signal_emit (G_OBJECT (control), signals[STREAM_ADDED], 0, gvc_mixer_stream_get_id (stream)); } /* This method will match individual stream ports against its corresponding device * It does this by: * - iterates through our devices and finds the one where the card-id on the device is the same as the card-id on the stream * and the port-name on the device is the same as the streamport-name. * This should always find a match and is used exclusively by sync_devices(). */ static gboolean match_stream_with_devices (GvcMixerControl *control, GvcMixerStreamPort *stream_port, GvcMixerStream *stream) { GList *devices, *d; guint stream_card_id; guint stream_id; gboolean in_possession = FALSE; stream_id = gvc_mixer_stream_get_id (stream); stream_card_id = gvc_mixer_stream_get_card_index (stream); devices = g_hash_table_get_values (GVC_IS_MIXER_SOURCE (stream) ? control->priv->ui_inputs : control->priv->ui_outputs); for (d = devices; d != NULL; d = d->next) { GvcMixerUIDevice *device; gint device_stream_id; gchar *device_port_name; gchar *origin; gchar *description; GvcMixerCard *card; gint card_id; device = d->data; g_object_get (G_OBJECT (device), "stream-id", &device_stream_id, "card", &card, "origin", &origin, "description", &description, "port-name", &device_port_name, NULL); card_id = gvc_mixer_card_get_index (card); g_debug ("Attempt to match_stream update_with_existing_outputs - Try description : '%s', origin : '%s', device port name : '%s', card : %p, AGAINST stream port: '%s', sink card id %i", description, origin, device_port_name, card, stream_port->port, stream_card_id); if (stream_card_id == card_id && g_strcmp0 (device_port_name, stream_port->port) == 0) { g_debug ("Match device with stream: We have a match with description: '%s', origin: '%s', cached already with device id %u, so set stream id to %i", description, origin, gvc_mixer_ui_device_get_id (device), stream_id); g_object_set (G_OBJECT (device), "stream-id", (gint)stream_id, NULL); in_possession = TRUE; } g_free (device_port_name); g_free (origin); g_free (description); if (in_possession == TRUE) break; } g_list_free (devices); return in_possession; } /* * This method attempts to match a sink or source with its relevant UI device. * GvcMixerStream can represent both a sink or source. * Using static card port introspection implies that we know beforehand what * outputs and inputs are available to the user. * But that does not mean that all of these inputs and outputs are available to be used. * For instance we might be able to see that there is a HDMI port available but if * we are on the default analog stereo output profile there is no valid sink for * that HDMI device. We first need to change profile and when update_sink() is called * only then can we match the new hdmi sink with its corresponding device. * * Firstly it checks to see if the incoming stream has no ports. * - If a stream has no ports but has a valid card ID (bluetooth), it will attempt * to match the device with the stream using the card id. * - If a stream has no ports and no valid card id, it goes ahead and makes a new * device (software/network devices are only detectable at the sink/source level) * If the stream has ports it will match each port against the stream using match_stream_with_devices(). * * This method should always find a match. */ static void sync_devices (GvcMixerControl *control, GvcMixerStream* stream) { /* Go through ports to see what outputs can be created. */ const GList *stream_ports; const GList *n = NULL; gboolean is_output = !GVC_IS_MIXER_SOURCE (stream); gint stream_port_count = 0; stream_ports = gvc_mixer_stream_get_ports (stream); if (stream_ports == NULL) { GvcMixerUIDevice *device; /* Bluetooth, no ports but a valid card */ if (gvc_mixer_stream_get_card_index (stream) != PA_INVALID_INDEX) { GList *devices, *d; gboolean in_possession = FALSE; devices = g_hash_table_get_values (is_output ? control->priv->ui_outputs : control->priv->ui_inputs); for (d = devices; d != NULL; d = d->next) { GvcMixerCard *card; gint card_id; device = d->data; g_object_get (G_OBJECT (device), "card", &card, NULL); card_id = gvc_mixer_card_get_index (card); g_debug ("sync devices, device description - '%s', device card id - %i, stream description - %s, stream card id - %i", gvc_mixer_ui_device_get_description (device), card_id, gvc_mixer_stream_get_description (stream), gvc_mixer_stream_get_card_index (stream)); if (card_id == gvc_mixer_stream_get_card_index (stream)) { in_possession = TRUE; break; } } g_list_free (devices); if (!in_possession) { g_warning ("Couldn't match the portless stream (with card) - '%s' is it an input ? -> %i, streams card id -> %i", gvc_mixer_stream_get_description (stream), GVC_IS_MIXER_SOURCE (stream), gvc_mixer_stream_get_card_index (stream)); return; } g_object_set (G_OBJECT (device), "stream-id", (gint)gvc_mixer_stream_get_id (stream), "description", gvc_mixer_stream_get_description (stream), "origin", "", /*Leave it empty for these special cases*/ "port-name", NULL, "port-available", TRUE, NULL); } else { /* Network sink/source has no ports and no card. */ GObject *object; object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, "stream-id", (gint)gvc_mixer_stream_get_id (stream), "description", gvc_mixer_stream_get_description (stream), "origin", "", /* Leave it empty for these special cases */ "port-name", NULL, "port-available", TRUE, NULL); device = GVC_MIXER_UI_DEVICE (object); g_hash_table_insert (is_output ? control->priv->ui_outputs : control->priv->ui_inputs, GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (device)), g_object_ref (device)); } g_signal_emit (G_OBJECT (control), signals[is_output ? OUTPUT_ADDED : INPUT_ADDED], 0, gvc_mixer_ui_device_get_id (device)); return; } /* Go ahead and make sure to match each port against a previously created device */ for (n = stream_ports; n != NULL; n = n->next) { GvcMixerStreamPort *stream_port; stream_port = n->data; stream_port_count ++; if (match_stream_with_devices (control, stream_port, stream)) continue; g_warning ("Sync_devices: Failed to match stream id: %u, description: '%s', origin: '%s'", gvc_mixer_stream_get_id (stream), stream_port->human_port, gvc_mixer_stream_get_description (stream)); } } static void set_icon_name_from_proplist (GvcMixerStream *stream, pa_proplist *l, const char *default_icon_name) { const char *t; if ((t = pa_proplist_gets (l, PA_PROP_DEVICE_ICON_NAME))) { goto finish; } if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ICON_NAME))) { goto finish; } if ((t = pa_proplist_gets (l, PA_PROP_WINDOW_ICON_NAME))) { goto finish; } if ((t = pa_proplist_gets (l, PA_PROP_APPLICATION_ICON_NAME))) { goto finish; } if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ROLE))) { if (strcmp (t, "video") == 0 || strcmp (t, "phone") == 0) { goto finish; } if (strcmp (t, "music") == 0) { t = "audio"; goto finish; } if (strcmp (t, "game") == 0) { t = "applications-games"; goto finish; } if (strcmp (t, "event") == 0) { t = "dialog-information"; goto finish; } } t = default_icon_name; finish: gvc_mixer_stream_set_icon_name (stream, t); } /* * Called when anything changes with a sink. */ static void update_sink (GvcMixerControl *control, const pa_sink_info *info) { GvcMixerStream *stream; gboolean is_new; pa_volume_t max_volume; GvcChannelMap *map; char map_buff[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_channel_map_snprint (map_buff, PA_CHANNEL_MAP_SNPRINT_MAX, &info->channel_map); #if 1 g_debug ("Updating sink: index=%u name='%s' description='%s' map='%s'", info->index, info->name, info->description, map_buff); #endif map = NULL; is_new = FALSE; stream = g_hash_table_lookup (control->priv->sinks, GUINT_TO_POINTER (info->index)); if (stream == NULL) { GList *list = NULL; guint i; map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); stream = gvc_mixer_sink_new (control->priv->pa_context, info->index, map); for (i = 0; i < info->n_ports; i++) { GvcMixerStreamPort *port; port = g_slice_new0 (GvcMixerStreamPort); port->port = g_strdup (info->ports[i]->name); port->human_port = g_strdup (info->ports[i]->description); port->priority = info->ports[i]->priority; port->available = info->ports[i]->available != PA_PORT_AVAILABLE_NO; list = g_list_prepend (list, port); } gvc_mixer_stream_set_ports (stream, list); g_object_unref (map); is_new = TRUE; } else if (gvc_mixer_stream_is_running (stream)) { /* Ignore events if volume changes are outstanding */ g_debug ("Ignoring event, volume changes are outstanding"); return; } max_volume = pa_cvolume_max (&info->volume); gvc_mixer_stream_set_name (stream, info->name); gvc_mixer_stream_set_card_index (stream, info->card); gvc_mixer_stream_set_description (stream, info->description); set_icon_name_from_proplist (stream, info->proplist, "audio-card"); gvc_mixer_stream_set_form_factor (stream, pa_proplist_gets (info->proplist, PA_PROP_DEVICE_FORM_FACTOR)); gvc_mixer_stream_set_sysfs_path (stream, pa_proplist_gets (info->proplist, "sysfs.path")); gvc_mixer_stream_set_volume (stream, (guint)max_volume); gvc_mixer_stream_set_is_muted (stream, info->mute); gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SINK_DECIBEL_VOLUME)); gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume); /* Messy I know but to set the port everytime regardless of whether it has changed will cost us a * port change notify signal which causes the frontend to resync. * Only update the UI when something has changed. */ if (info->active_port != NULL) { if (is_new) gvc_mixer_stream_set_port (stream, info->active_port->name); else { const GvcMixerStreamPort *active_port; active_port = gvc_mixer_stream_get_port (stream); if (active_port == NULL || g_strcmp0 (active_port->port, info->active_port->name) != 0) { g_debug ("update sink - apparently a port update"); gvc_mixer_stream_set_port (stream, info->active_port->name); } } } if (is_new) { g_debug ("update sink - is new"); g_hash_table_insert (control->priv->sinks, GUINT_TO_POINTER (info->index), g_object_ref (stream)); add_stream (control, stream); /* Always sink on a new stream to able to assign the right stream id * to the appropriate outputs (multiple potential outputs per stream). */ sync_devices (control, stream); } /* * When we change profile on a device that is not the server default sink, * it will jump back to the default sink set by the server to prevent the audio setup from being 'outputless'. * All well and good but then when we get the new stream created for the new profile how do we know * that this is the intended default or selected device the user wishes to use. * This is messy but it's the only reliable way that it can be done without ripping the whole thing apart. */ if (control->priv->profile_swapping_device_id != GVC_MIXER_UI_DEVICE_INVALID) { GvcMixerUIDevice *dev = NULL; dev = gvc_mixer_control_lookup_output_id (control, control->priv->profile_swapping_device_id); if (dev != NULL) { /* now check to make sure this new stream is the same stream just matched and set on the device object */ if (gvc_mixer_ui_device_get_stream_id (dev) == gvc_mixer_stream_get_id (stream)) { g_debug ("Looks like we profile swapped on a non server default sink"); gvc_mixer_control_set_default_sink (control, stream); } } control->priv->profile_swapping_device_id = GVC_MIXER_UI_DEVICE_INVALID; } if (control->priv->default_sink_name != NULL && info->name != NULL && strcmp (control->priv->default_sink_name, info->name) == 0) { _set_default_sink (control, stream); } if (map == NULL) map = (GvcChannelMap *) gvc_mixer_stream_get_channel_map (stream); gvc_channel_map_volume_changed (map, &info->volume, FALSE); } static void update_source (GvcMixerControl *control, const pa_source_info *info) { GvcMixerStream *stream; gboolean is_new; pa_volume_t max_volume; #if 1 g_debug ("Updating source: index=%u name='%s' description='%s'", info->index, info->name, info->description); #endif /* completely ignore monitors, they're not real sources */ if (info->monitor_of_sink != PA_INVALID_INDEX) { return; } is_new = FALSE; stream = g_hash_table_lookup (control->priv->sources, GUINT_TO_POINTER (info->index)); if (stream == NULL) { GList *list = NULL; guint i; GvcChannelMap *map; map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); stream = gvc_mixer_source_new (control->priv->pa_context, info->index, map); for (i = 0; i < info->n_ports; i++) { GvcMixerStreamPort *port; port = g_slice_new0 (GvcMixerStreamPort); port->port = g_strdup (info->ports[i]->name); port->human_port = g_strdup (info->ports[i]->description); port->priority = info->ports[i]->priority; list = g_list_prepend (list, port); } gvc_mixer_stream_set_ports (stream, list); g_object_unref (map); is_new = TRUE; } else if (gvc_mixer_stream_is_running (stream)) { /* Ignore events if volume changes are outstanding */ g_debug ("Ignoring event, volume changes are outstanding"); return; } max_volume = pa_cvolume_max (&info->volume); gvc_mixer_stream_set_name (stream, info->name); gvc_mixer_stream_set_card_index (stream, info->card); gvc_mixer_stream_set_description (stream, info->description); set_icon_name_from_proplist (stream, info->proplist, "audio-input-microphone"); gvc_mixer_stream_set_form_factor (stream, pa_proplist_gets (info->proplist, PA_PROP_DEVICE_FORM_FACTOR)); gvc_mixer_stream_set_volume (stream, (guint)max_volume); gvc_mixer_stream_set_is_muted (stream, info->mute); gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SOURCE_DECIBEL_VOLUME)); gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume); g_debug ("update source"); if (info->active_port != NULL) { if (is_new) gvc_mixer_stream_set_port (stream, info->active_port->name); else { const GvcMixerStreamPort *active_port; active_port = gvc_mixer_stream_get_port (stream); if (active_port == NULL || g_strcmp0 (active_port->port, info->active_port->name) != 0) { g_debug ("update source - apparently a port update"); gvc_mixer_stream_set_port (stream, info->active_port->name); } } } if (is_new) { g_hash_table_insert (control->priv->sources, GUINT_TO_POINTER (info->index), g_object_ref (stream)); add_stream (control, stream); sync_devices (control, stream); } if (control->priv->profile_swapping_device_id != GVC_MIXER_UI_DEVICE_INVALID) { GvcMixerUIDevice *dev = NULL; dev = gvc_mixer_control_lookup_input_id (control, control->priv->profile_swapping_device_id); if (dev != NULL) { /* now check to make sure this new stream is the same stream just matched and set on the device object */ if (gvc_mixer_ui_device_get_stream_id (dev) == gvc_mixer_stream_get_id (stream)) { g_debug ("Looks like we profile swapped on a non server default sink"); gvc_mixer_control_set_default_source (control, stream); } } control->priv->profile_swapping_device_id = GVC_MIXER_UI_DEVICE_INVALID; } if (control->priv->default_source_name != NULL && info->name != NULL && strcmp (control->priv->default_source_name, info->name) == 0) { _set_default_source (control, stream); } } static void set_is_event_stream_from_proplist (GvcMixerStream *stream, pa_proplist *l) { const char *t; gboolean is_event_stream; is_event_stream = FALSE; if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ROLE))) { if (g_str_equal (t, "event")) is_event_stream = TRUE; } gvc_mixer_stream_set_is_event_stream (stream, is_event_stream); } static void set_application_id_from_proplist (GvcMixerStream *stream, pa_proplist *l) { const char *t; if ((t = pa_proplist_gets (l, PA_PROP_APPLICATION_ID))) { gvc_mixer_stream_set_application_id (stream, t); } } static void update_sink_input (GvcMixerControl *control, const pa_sink_input_info *info) { GvcMixerStream *stream; gboolean is_new; pa_volume_t max_volume; const char *name; #if 0 g_debug ("Updating sink input: index=%u name='%s' client=%u sink=%u", info->index, info->name, info->client, info->sink); #endif is_new = FALSE; stream = g_hash_table_lookup (control->priv->sink_inputs, GUINT_TO_POINTER (info->index)); if (stream == NULL) { GvcChannelMap *map; map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); stream = gvc_mixer_sink_input_new (control->priv->pa_context, info->index, map); g_object_unref (map); is_new = TRUE; } else if (gvc_mixer_stream_is_running (stream)) { /* Ignore events if volume changes are outstanding */ g_debug ("Ignoring event, volume changes are outstanding"); return; } max_volume = pa_cvolume_max (&info->volume); name = (const char *)g_hash_table_lookup (control->priv->clients, GUINT_TO_POINTER (info->client)); gvc_mixer_stream_set_name (stream, name); gvc_mixer_stream_set_description (stream, info->name); set_application_id_from_proplist (stream, info->proplist); set_is_event_stream_from_proplist (stream, info->proplist); set_icon_name_from_proplist (stream, info->proplist, "applications-multimedia"); gvc_mixer_stream_set_volume (stream, (guint)max_volume); gvc_mixer_stream_set_is_muted (stream, info->mute); gvc_mixer_stream_set_is_virtual (stream, info->client == PA_INVALID_INDEX); if (is_new) { g_hash_table_insert (control->priv->sink_inputs, GUINT_TO_POINTER (info->index), g_object_ref (stream)); add_stream (control, stream); } } static void update_source_output (GvcMixerControl *control, const pa_source_output_info *info) { GvcMixerStream *stream; gboolean is_new; const char *name; #if 1 g_debug ("Updating source output: index=%u name='%s' client=%u source=%u", info->index, info->name, info->client, info->source); #endif is_new = FALSE; stream = g_hash_table_lookup (control->priv->source_outputs, GUINT_TO_POINTER (info->index)); if (stream == NULL) { GvcChannelMap *map; map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); stream = gvc_mixer_source_output_new (control->priv->pa_context, info->index, map); g_object_unref (map); is_new = TRUE; } name = (const char *)g_hash_table_lookup (control->priv->clients, GUINT_TO_POINTER (info->client)); gvc_mixer_stream_set_name (stream, name); gvc_mixer_stream_set_description (stream, info->name); set_application_id_from_proplist (stream, info->proplist); set_is_event_stream_from_proplist (stream, info->proplist); set_icon_name_from_proplist (stream, info->proplist, "audio-input-microphone"); if (is_new) { g_hash_table_insert (control->priv->source_outputs, GUINT_TO_POINTER (info->index), g_object_ref (stream)); add_stream (control, stream); } } static void update_client (GvcMixerControl *control, const pa_client_info *info) { #if 1 g_debug ("Updating client: index=%u name='%s'", info->index, info->name); #endif g_hash_table_insert (control->priv->clients, GUINT_TO_POINTER (info->index), g_strdup (info->name)); } static char * card_num_streams_to_status (guint sinks, guint sources) { char *sinks_str; char *sources_str; char *ret; if (sinks == 0 && sources == 0) { /* translators: * The device has been disabled */ return g_strdup (_("Disabled")); } if (sinks == 0) { sinks_str = NULL; } else { /* translators: * The number of sound outputs on a particular device */ sinks_str = g_strdup_printf (ngettext ("%u Output", "%u Outputs", sinks), sinks); } if (sources == 0) { sources_str = NULL; } else { /* translators: * The number of sound inputs on a particular device */ sources_str = g_strdup_printf (ngettext ("%u Input", "%u Inputs", sources), sources); } if (sources_str == NULL) return sinks_str; if (sinks_str == NULL) return sources_str; ret = g_strdup_printf ("%s / %s", sinks_str, sources_str); g_free (sinks_str); g_free (sources_str); return ret; } /* * A utility method to gather which card profiles are relevant to the port . */ static GList * determine_profiles_for_port (pa_card_port_info *port, GList* card_profiles) { gint i; GList *supported_profiles = NULL; GList *p; for (i = 0; i < port->n_profiles; i++) { for (p = card_profiles; p != NULL; p = p->next) { GvcMixerCardProfile *prof; prof = p->data; if (g_strcmp0 (port->profiles[i]->name, prof->profile) == 0) supported_profiles = g_list_append (supported_profiles, prof); } } g_debug ("%i profiles supported on port %s", g_list_length (supported_profiles), port->description); return g_list_sort (supported_profiles, (GCompareFunc) gvc_mixer_card_profile_compare); } static gboolean is_card_port_an_output (GvcMixerCardPort* port) { return port->direction == PA_DIRECTION_OUTPUT ? TRUE : FALSE; } /* * This method will create a ui device for the given port. */ static void create_ui_device_from_port (GvcMixerControl* control, GvcMixerCardPort* port, GvcMixerCard* card) { GvcMixerUIDeviceDirection direction; GObject *object; GvcMixerUIDevice *uidevice; gboolean available = port->available != PA_PORT_AVAILABLE_NO; direction = (is_card_port_an_output (port) == TRUE) ? UIDeviceOutput : UIDeviceInput; object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, "type", (uint)direction, "card", card, "port-name", port->port, "description", port->human_port, "origin", gvc_mixer_card_get_name (card), "port-available", available, NULL); uidevice = GVC_MIXER_UI_DEVICE (object); gvc_mixer_ui_device_set_profiles (uidevice, port->profiles); g_hash_table_insert (is_card_port_an_output (port) ? control->priv->ui_outputs : control->priv->ui_inputs, GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (uidevice)), g_object_ref (uidevice)); if (available) { g_signal_emit (G_OBJECT (control), signals[is_card_port_an_output (port) ? OUTPUT_ADDED : INPUT_ADDED], 0, gvc_mixer_ui_device_get_id (uidevice)); } g_debug ("create_ui_device_from_port, direction %u, description '%s', origin '%s', port available %i", direction, port->human_port, gvc_mixer_card_get_name (card), available); } /* * This method will match up GvcMixerCardPorts with existing devices. * A match is achieved if the device's card-id and the port's card-id are the same * && the device's port-name and the card-port's port member are the same. * A signal is then sent adding or removing that device from the UI depending on the availability of the port. */ static void match_card_port_with_existing_device (GvcMixerControl *control, GvcMixerCardPort *card_port, GvcMixerCard *card, gboolean available) { GList *d; GList *devices; GvcMixerUIDevice *device; gboolean is_output = is_card_port_an_output (card_port); devices = g_hash_table_get_values (is_output ? control->priv->ui_outputs : control->priv->ui_inputs); for (d = devices; d != NULL; d = d->next) { GvcMixerCard *device_card; gchar *device_port_name; device = d->data; g_object_get (G_OBJECT (device), "card", &device_card, "port-name", &device_port_name, NULL); if (g_strcmp0 (card_port->port, device_port_name) == 0 && device_card == card) { g_debug ("Found the relevant device %s, update its port availability flag to %i, is_output %i", device_port_name, available, is_output); g_object_set (G_OBJECT (device), "port-available", available, NULL); g_signal_emit (G_OBJECT (control), is_output ? signals[available ? OUTPUT_ADDED : OUTPUT_REMOVED] : signals[available ? INPUT_ADDED : INPUT_REMOVED], 0, gvc_mixer_ui_device_get_id (device)); } g_free (device_port_name); } g_list_free (devices); } static void create_ui_device_from_card (GvcMixerControl *control, GvcMixerCard *card) { GObject *object; GvcMixerUIDevice *in; GvcMixerUIDevice *out; const GList *profiles; /* For now just create two devices and presume this device is multi directional * Ensure to remove both on card removal (available to false by default) */ profiles = gvc_mixer_card_get_profiles (card); g_debug ("Portless card just registered - %i", gvc_mixer_card_get_index (card)); object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, "type", UIDeviceInput, "description", gvc_mixer_card_get_name (card), "origin", "", /* Leave it empty for these special cases */ "port-name", NULL, "port-available", FALSE, "card", card, NULL); in = GVC_MIXER_UI_DEVICE (object); gvc_mixer_ui_device_set_profiles (in, profiles); g_hash_table_insert (control->priv->ui_inputs, GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (in)), g_object_ref (in)); object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, "type", UIDeviceOutput, "description", gvc_mixer_card_get_name (card), "origin", "", /* Leave it empty for these special cases */ "port-name", NULL, "port-available", FALSE, "card", card, NULL); out = GVC_MIXER_UI_DEVICE (object); gvc_mixer_ui_device_set_profiles (out, profiles); g_hash_table_insert (control->priv->ui_outputs, GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (out)), g_object_ref (out)); } /* * At this point we can determine all devices available to us (besides network 'ports') * This is done by the following: * * - gvc_mixer_card and gvc_mixer_card_ports are created and relevant setters are called. * - First it checks to see if it's a portless card. Bluetooth devices are portless AFAIHS. * If so it creates two devices, an input and an output. * - If it's a 'normal' card with ports it will create a new ui-device or * synchronise port availability with the existing device cached for that port on this card. */ static void update_card (GvcMixerControl *control, const pa_card_info *info) { const GList *card_ports = NULL; const GList *m = NULL; GvcMixerCard *card; gboolean is_new = FALSE; #if 1 guint i; const char *key; void *state; g_debug ("Udpating card %s (index: %u driver: %s):", info->name, info->index, info->driver); for (i = 0; i < info->n_profiles; i++) { struct pa_card_profile_info pi = info->profiles[i]; gboolean is_default; is_default = (g_strcmp0 (pi.name, info->active_profile->name) == 0); g_debug ("\tProfile '%s': %d sources %d sinks%s", pi.name, pi.n_sources, pi.n_sinks, is_default ? " (Current)" : ""); } state = NULL; key = pa_proplist_iterate (info->proplist, &state); while (key != NULL) { g_debug ("\tProperty: '%s' = '%s'", key, pa_proplist_gets (info->proplist, key)); key = pa_proplist_iterate (info->proplist, &state); } #endif card = g_hash_table_lookup (control->priv->cards, GUINT_TO_POINTER (info->index)); if (card == NULL) { GList *profile_list = NULL; GList *port_list = NULL; for (i = 0; i < info->n_profiles; i++) { GvcMixerCardProfile *profile; struct pa_card_profile_info pi = info->profiles[i]; profile = g_new0 (GvcMixerCardProfile, 1); profile->profile = g_strdup (pi.name); profile->human_profile = g_strdup (pi.description); profile->status = card_num_streams_to_status (pi.n_sinks, pi.n_sources); profile->n_sinks = pi.n_sinks; profile->n_sources = pi.n_sources; profile->priority = pi.priority; profile_list = g_list_prepend (profile_list, profile); } card = gvc_mixer_card_new (control->priv->pa_context, info->index); gvc_mixer_card_set_profiles (card, profile_list); for (i = 0; i < info->n_ports; i++) { GvcMixerCardPort *port; port = g_new0 (GvcMixerCardPort, 1); port->port = g_strdup (info->ports[i]->name); port->human_port = g_strdup (info->ports[i]->description); port->priority = info->ports[i]->priority; port->available = info->ports[i]->available; port->direction = info->ports[i]->direction; port->profiles = determine_profiles_for_port (info->ports[i], profile_list); port_list = g_list_prepend (port_list, port); } gvc_mixer_card_set_ports (card, port_list); is_new = TRUE; } gvc_mixer_card_set_name (card, pa_proplist_gets (info->proplist, "device.description")); gvc_mixer_card_set_icon_name (card, pa_proplist_gets (info->proplist, "device.icon_name")); gvc_mixer_card_set_profile (card, info->active_profile->name); if (is_new) { g_hash_table_insert (control->priv->cards, GUINT_TO_POINTER (info->index), g_object_ref (card)); } card_ports = gvc_mixer_card_get_ports (card); if (card_ports == NULL && is_new) { g_debug ("Portless card just registered - %s", gvc_mixer_card_get_name (card)); create_ui_device_from_card (control, card); } for (m = card_ports; m != NULL; m = m->next) { GvcMixerCardPort *card_port; card_port = m->data; if (is_new) create_ui_device_from_port (control, card_port, card); else { for (i = 0; i < info->n_ports; i++) { if (g_strcmp0 (card_port->port, info->ports[i]->name) == 0) { if (card_port->available != info->ports[i]->available) { card_port->available = info->ports[i]->available; g_debug ("sync port availability on card %i, card port name '%s', new available value %i", gvc_mixer_card_get_index (card), card_port->port, card_port->available); match_card_port_with_existing_device (control, card_port, card, card_port->available != PA_PORT_AVAILABLE_NO); } } } } } g_signal_emit (G_OBJECT (control), signals[CARD_INFO], 0, info); g_signal_emit (G_OBJECT (control), signals[CARD_ADDED], 0, info->index); } static void _pa_context_get_sink_info_cb (pa_context *context, const pa_sink_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { if (pa_context_errno (context) == PA_ERR_NOENTITY) { return; } g_warning ("Sink callback failure"); return; } if (eol > 0) { dec_outstanding (control); return; } update_sink (control, i); } static void _pa_context_get_source_info_cb (pa_context *context, const pa_source_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { if (pa_context_errno (context) == PA_ERR_NOENTITY) { return; } g_warning ("Source callback failure"); return; } if (eol > 0) { dec_outstanding (control); return; } update_source (control, i); } static void _pa_context_get_sink_input_info_cb (pa_context *context, const pa_sink_input_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { if (pa_context_errno (context) == PA_ERR_NOENTITY) { return; } g_warning ("Sink input callback failure"); return; } if (eol > 0) { dec_outstanding (control); return; } update_sink_input (control, i); } static void _pa_context_get_source_output_info_cb (pa_context *context, const pa_source_output_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { if (pa_context_errno (context) == PA_ERR_NOENTITY) { return; } g_warning ("Source output callback failure"); return; } if (eol > 0) { dec_outstanding (control); return; } update_source_output (control, i); } static void _pa_context_get_client_info_cb (pa_context *context, const pa_client_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { if (pa_context_errno (context) == PA_ERR_NOENTITY) { return; } g_warning ("Client callback failure"); return; } if (eol > 0) { dec_outstanding (control); return; } update_client (control, i); } static void _pa_context_get_card_info_by_index_cb (pa_context *context, const pa_card_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { if (pa_context_errno (context) == PA_ERR_NOENTITY) return; g_warning ("Card callback failure"); return; } if (eol > 0) { dec_outstanding (control); return; } update_card (control, i); } static void _pa_context_get_server_info_cb (pa_context *context, const pa_server_info *i, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (i == NULL) { g_warning ("Server info callback failure"); return; } g_debug ("get server info"); update_server (control, i); dec_outstanding (control); } static void remove_event_role_stream (GvcMixerControl *control) { g_debug ("Removing event role"); } static void update_event_role_stream (GvcMixerControl *control, const pa_ext_stream_restore_info *info) { GvcMixerStream *stream; gboolean is_new; pa_volume_t max_volume; if (strcmp (info->name, "sink-input-by-media-role:event") != 0) { return; } #if 0 g_debug ("Updating event role: name='%s' device='%s'", info->name, info->device); #endif is_new = FALSE; if (!control->priv->event_sink_input_is_set) { pa_channel_map pa_map; GvcChannelMap *map; pa_map.channels = 1; pa_map.map[0] = PA_CHANNEL_POSITION_MONO; map = gvc_channel_map_new_from_pa_channel_map (&pa_map); stream = gvc_mixer_event_role_new (control->priv->pa_context, info->device, map); control->priv->event_sink_input_id = gvc_mixer_stream_get_id (stream); control->priv->event_sink_input_is_set = TRUE; is_new = TRUE; } else { stream = g_hash_table_lookup (control->priv->all_streams, GUINT_TO_POINTER (control->priv->event_sink_input_id)); } max_volume = pa_cvolume_max (&info->volume); gvc_mixer_stream_set_name (stream, _("System Sounds")); gvc_mixer_stream_set_icon_name (stream, "multimedia-volume-control"); gvc_mixer_stream_set_volume (stream, (guint)max_volume); gvc_mixer_stream_set_is_muted (stream, info->mute); if (is_new) { add_stream (control, stream); } } static void _pa_ext_stream_restore_read_cb (pa_context *context, const pa_ext_stream_restore_info *i, int eol, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); if (eol < 0) { g_debug ("Failed to initialized stream_restore extension: %s", pa_strerror (pa_context_errno (context))); remove_event_role_stream (control); return; } if (eol > 0) { dec_outstanding (control); /* If we don't have an event stream to restore, then * set one up with a default 100% volume */ if (!control->priv->event_sink_input_is_set) { pa_ext_stream_restore_info info; memset (&info, 0, sizeof(info)); info.name = "sink-input-by-media-role:event"; info.volume.channels = 1; info.volume.values[0] = PA_VOLUME_NORM; update_event_role_stream (control, &info); } return; } update_event_role_stream (control, i); } static void _pa_ext_stream_restore_subscribe_cb (pa_context *context, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); pa_operation *o; o = pa_ext_stream_restore_read (context, _pa_ext_stream_restore_read_cb, control); if (o == NULL) { g_warning ("pa_ext_stream_restore_read() failed"); return; } pa_operation_unref (o); } static void req_update_server_info (GvcMixerControl *control, int index) { pa_operation *o; o = pa_context_get_server_info (control->priv->pa_context, _pa_context_get_server_info_cb, control); if (o == NULL) { g_warning ("pa_context_get_server_info() failed"); return; } pa_operation_unref (o); } static void req_update_client_info (GvcMixerControl *control, int index) { pa_operation *o; if (index < 0) { o = pa_context_get_client_info_list (control->priv->pa_context, _pa_context_get_client_info_cb, control); } else { o = pa_context_get_client_info (control->priv->pa_context, index, _pa_context_get_client_info_cb, control); } if (o == NULL) { g_warning ("pa_context_client_info_list() failed"); return; } pa_operation_unref (o); } static void req_update_card (GvcMixerControl *control, int index) { pa_operation *o; if (index < 0) { o = pa_context_get_card_info_list (control->priv->pa_context, _pa_context_get_card_info_by_index_cb, control); } else { o = pa_context_get_card_info_by_index (control->priv->pa_context, index, _pa_context_get_card_info_by_index_cb, control); } if (o == NULL) { g_warning ("pa_context_get_card_info_by_index() failed"); return; } pa_operation_unref (o); } static void req_update_sink_info (GvcMixerControl *control, int index) { pa_operation *o; if (index < 0) { o = pa_context_get_sink_info_list (control->priv->pa_context, _pa_context_get_sink_info_cb, control); } else { o = pa_context_get_sink_info_by_index (control->priv->pa_context, index, _pa_context_get_sink_info_cb, control); } if (o == NULL) { g_warning ("pa_context_get_sink_info_list() failed"); return; } pa_operation_unref (o); } static void req_update_source_info (GvcMixerControl *control, int index) { pa_operation *o; if (index < 0) { o = pa_context_get_source_info_list (control->priv->pa_context, _pa_context_get_source_info_cb, control); } else { o = pa_context_get_source_info_by_index(control->priv->pa_context, index, _pa_context_get_source_info_cb, control); } if (o == NULL) { g_warning ("pa_context_get_source_info_list() failed"); return; } pa_operation_unref (o); } static void req_update_sink_input_info (GvcMixerControl *control, int index) { pa_operation *o; if (index < 0) { o = pa_context_get_sink_input_info_list (control->priv->pa_context, _pa_context_get_sink_input_info_cb, control); } else { o = pa_context_get_sink_input_info (control->priv->pa_context, index, _pa_context_get_sink_input_info_cb, control); } if (o == NULL) { g_warning ("pa_context_get_sink_input_info_list() failed"); return; } pa_operation_unref (o); } static void req_update_source_output_info (GvcMixerControl *control, int index) { pa_operation *o; if (index < 0) { o = pa_context_get_source_output_info_list (control->priv->pa_context, _pa_context_get_source_output_info_cb, control); } else { o = pa_context_get_source_output_info (control->priv->pa_context, index, _pa_context_get_source_output_info_cb, control); } if (o == NULL) { g_warning ("pa_context_get_source_output_info_list() failed"); return; } pa_operation_unref (o); } static void remove_client (GvcMixerControl *control, guint index) { g_hash_table_remove (control->priv->clients, GUINT_TO_POINTER (index)); } static void remove_card (GvcMixerControl *control, guint index) { GList *devices, *d; devices = g_list_concat (g_hash_table_get_values (control->priv->ui_inputs), g_hash_table_get_values (control->priv->ui_outputs)); for (d = devices; d != NULL; d = d->next) { GvcMixerCard *card; GvcMixerUIDevice *device = d->data; g_object_get (G_OBJECT (device), "card", &card, NULL); if (gvc_mixer_card_get_index (card) == index) { g_signal_emit (G_OBJECT (control), signals[gvc_mixer_ui_device_is_output (device) ? OUTPUT_REMOVED : INPUT_REMOVED], 0, gvc_mixer_ui_device_get_id (device)); g_debug ("Card removal remove device %s", gvc_mixer_ui_device_get_description (device)); g_hash_table_remove (gvc_mixer_ui_device_is_output (device) ? control->priv->ui_outputs : control->priv->ui_inputs, GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (device))); } } g_list_free (devices); g_hash_table_remove (control->priv->cards, GUINT_TO_POINTER (index)); g_signal_emit (G_OBJECT (control), signals[CARD_REMOVED], 0, index); } static void remove_sink (GvcMixerControl *control, guint index) { GvcMixerStream *stream; GvcMixerUIDevice *device; g_debug ("Removing sink: index=%u", index); stream = g_hash_table_lookup (control->priv->sinks, GUINT_TO_POINTER (index)); if (stream == NULL) return; device = gvc_mixer_control_lookup_device_from_stream (control, stream); if (device != NULL) { gvc_mixer_ui_device_invalidate_stream (device); if (!gvc_mixer_ui_device_has_ports (device)) { g_signal_emit (G_OBJECT (control), signals[OUTPUT_REMOVED], 0, gvc_mixer_ui_device_get_id (device)); } else { GList *devices, *d; devices = g_hash_table_get_values (control->priv->ui_outputs); for (d = devices; d != NULL; d = d->next) { gint stream_id = GVC_MIXER_UI_DEVICE_INVALID; device = d->data; g_object_get (G_OBJECT (device), "stream-id", &stream_id, NULL); if (stream_id == gvc_mixer_stream_get_id (stream)) gvc_mixer_ui_device_invalidate_stream (device); } g_list_free (devices); } } g_hash_table_remove (control->priv->sinks, GUINT_TO_POINTER (index)); remove_stream (control, stream); } static void remove_source (GvcMixerControl *control, guint index) { GvcMixerStream *stream; GvcMixerUIDevice *device; g_debug ("Removing source: index=%u", index); stream = g_hash_table_lookup (control->priv->sources, GUINT_TO_POINTER (index)); if (stream == NULL) return; device = gvc_mixer_control_lookup_device_from_stream (control, stream); if (device != NULL) { gvc_mixer_ui_device_invalidate_stream (device); if (!gvc_mixer_ui_device_has_ports (device)) { g_signal_emit (G_OBJECT (control), signals[INPUT_REMOVED], 0, gvc_mixer_ui_device_get_id (device)); } else { GList *devices, *d; devices = g_hash_table_get_values (control->priv->ui_inputs); for (d = devices; d != NULL; d = d->next) { gint stream_id = GVC_MIXER_UI_DEVICE_INVALID; device = d->data; g_object_get (G_OBJECT (device), "stream-id", &stream_id, NULL); if (stream_id == gvc_mixer_stream_get_id (stream)) gvc_mixer_ui_device_invalidate_stream (device); } g_list_free (devices); } } g_hash_table_remove (control->priv->sources, GUINT_TO_POINTER (index)); remove_stream (control, stream); } static void remove_sink_input (GvcMixerControl *control, guint index) { GvcMixerStream *stream; g_debug ("Removing sink input: index=%u", index); stream = g_hash_table_lookup (control->priv->sink_inputs, GUINT_TO_POINTER (index)); if (stream == NULL) { return; } g_hash_table_remove (control->priv->sink_inputs, GUINT_TO_POINTER (index)); remove_stream (control, stream); } static void remove_source_output (GvcMixerControl *control, guint index) { GvcMixerStream *stream; g_debug ("Removing source output: index=%u", index); stream = g_hash_table_lookup (control->priv->source_outputs, GUINT_TO_POINTER (index)); if (stream == NULL) { return; } g_hash_table_remove (control->priv->source_outputs, GUINT_TO_POINTER (index)); remove_stream (control, stream); } static void _pa_context_subscribe_cb (pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { remove_sink (control, index); } else { req_update_sink_info (control, index); } break; case PA_SUBSCRIPTION_EVENT_SOURCE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { remove_source (control, index); } else { req_update_source_info (control, index); } break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { remove_sink_input (control, index); } else { req_update_sink_input_info (control, index); } break; case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { remove_source_output (control, index); } else { req_update_source_output_info (control, index); } break; case PA_SUBSCRIPTION_EVENT_CLIENT: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { remove_client (control, index); } else { req_update_client_info (control, index); } break; case PA_SUBSCRIPTION_EVENT_SERVER: req_update_server_info (control, index); break; case PA_SUBSCRIPTION_EVENT_CARD: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { remove_card (control, index); } else { req_update_card (control, index); } break; } } static void gvc_mixer_control_ready (GvcMixerControl *control) { pa_operation *o; pa_context_set_subscribe_callback (control->priv->pa_context, _pa_context_subscribe_cb, control); o = pa_context_subscribe (control->priv->pa_context, (pa_subscription_mask_t) (PA_SUBSCRIPTION_MASK_SINK| PA_SUBSCRIPTION_MASK_SOURCE| PA_SUBSCRIPTION_MASK_SINK_INPUT| PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| PA_SUBSCRIPTION_MASK_CLIENT| PA_SUBSCRIPTION_MASK_SERVER| PA_SUBSCRIPTION_MASK_CARD), NULL, NULL); if (o == NULL) { g_warning ("pa_context_subscribe() failed"); return; } pa_operation_unref (o); req_update_server_info (control, -1); req_update_card (control, -1); req_update_client_info (control, -1); req_update_sink_info (control, -1); req_update_source_info (control, -1); req_update_sink_input_info (control, -1); req_update_source_output_info (control, -1); control->priv->n_outstanding = 6; /* This call is not always supported */ o = pa_ext_stream_restore_read (control->priv->pa_context, _pa_ext_stream_restore_read_cb, control); if (o != NULL) { pa_operation_unref (o); control->priv->n_outstanding++; pa_ext_stream_restore_set_subscribe_cb (control->priv->pa_context, _pa_ext_stream_restore_subscribe_cb, control); o = pa_ext_stream_restore_subscribe (control->priv->pa_context, 1, NULL, NULL); if (o != NULL) { pa_operation_unref (o); } } else { g_debug ("Failed to initialized stream_restore extension: %s", pa_strerror (pa_context_errno (control->priv->pa_context))); } } static void gvc_mixer_new_pa_context (GvcMixerControl *self) { pa_proplist *proplist; g_return_if_fail (self); g_return_if_fail (!self->priv->pa_context); proplist = pa_proplist_new (); pa_proplist_sets (proplist, PA_PROP_APPLICATION_NAME, self->priv->name); pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, "org.gnome.VolumeControl"); pa_proplist_sets (proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control"); pa_proplist_sets (proplist, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION); self->priv->pa_context = pa_context_new_with_proplist (self->priv->pa_api, NULL, proplist); pa_proplist_free (proplist); g_assert (self->priv->pa_context); } static void remove_all_streams (GvcMixerControl *control, GHashTable *hash_table) { GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, hash_table); while (g_hash_table_iter_next (&iter, &key, &value)) { remove_stream (control, value); g_hash_table_iter_remove (&iter); } } static gboolean idle_reconnect (gpointer data) { GvcMixerControl *control = GVC_MIXER_CONTROL (data); GHashTableIter iter; gpointer key, value; g_return_val_if_fail (control, FALSE); if (control->priv->pa_context) { pa_context_unref (control->priv->pa_context); control->priv->pa_context = NULL; gvc_mixer_new_pa_context (control); } remove_all_streams (control, control->priv->sinks); remove_all_streams (control, control->priv->sources); remove_all_streams (control, control->priv->sink_inputs); remove_all_streams (control, control->priv->source_outputs); g_hash_table_iter_init (&iter, control->priv->clients); while (g_hash_table_iter_next (&iter, &key, &value)) g_hash_table_iter_remove (&iter); gvc_mixer_control_open (control); /* cannot fail */ control->priv->reconnect_id = 0; return FALSE; } static void _pa_context_state_cb (pa_context *context, void *userdata) { GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); switch (pa_context_get_state (context)) { case PA_CONTEXT_UNCONNECTED: case PA_CONTEXT_CONNECTING: case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: gvc_mixer_control_ready (control); break; case PA_CONTEXT_FAILED: control->priv->state = GVC_STATE_FAILED; g_signal_emit (control, signals[STATE_CHANGED], 0, GVC_STATE_FAILED); if (control->priv->reconnect_id == 0) control->priv->reconnect_id = g_timeout_add_seconds (RECONNECT_DELAY, idle_reconnect, control); break; case PA_CONTEXT_TERMINATED: default: /* FIXME: */ break; } } gboolean gvc_mixer_control_open (GvcMixerControl *control) { int res; g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); g_return_val_if_fail (control->priv->pa_context != NULL, FALSE); g_return_val_if_fail (pa_context_get_state (control->priv->pa_context) == PA_CONTEXT_UNCONNECTED, FALSE); pa_context_set_state_callback (control->priv->pa_context, _pa_context_state_cb, control); control->priv->state = GVC_STATE_CONNECTING; g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_CONNECTING); res = pa_context_connect (control->priv->pa_context, NULL, (pa_context_flags_t) PA_CONTEXT_NOFAIL, NULL); if (res < 0) { g_warning ("Failed to connect context: %s", pa_strerror (pa_context_errno (control->priv->pa_context))); } return res; } gboolean gvc_mixer_control_close (GvcMixerControl *control) { g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); g_return_val_if_fail (control->priv->pa_context != NULL, FALSE); pa_context_disconnect (control->priv->pa_context); control->priv->state = GVC_STATE_CLOSED; g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_CLOSED); return TRUE; } static void gvc_mixer_control_dispose (GObject *object) { GvcMixerControl *control = GVC_MIXER_CONTROL (object); if (control->priv->reconnect_id != 0) { g_source_remove (control->priv->reconnect_id); control->priv->reconnect_id = 0; } if (control->priv->pa_context != NULL) { pa_context_unref (control->priv->pa_context); control->priv->pa_context = NULL; } if (control->priv->default_source_name != NULL) { g_free (control->priv->default_source_name); control->priv->default_source_name = NULL; } if (control->priv->default_sink_name != NULL) { g_free (control->priv->default_sink_name); control->priv->default_sink_name = NULL; } if (control->priv->pa_mainloop != NULL) { pa_glib_mainloop_free (control->priv->pa_mainloop); control->priv->pa_mainloop = NULL; } if (control->priv->all_streams != NULL) { g_hash_table_destroy (control->priv->all_streams); control->priv->all_streams = NULL; } if (control->priv->sinks != NULL) { g_hash_table_destroy (control->priv->sinks); control->priv->sinks = NULL; } if (control->priv->sources != NULL) { g_hash_table_destroy (control->priv->sources); control->priv->sources = NULL; } if (control->priv->sink_inputs != NULL) { g_hash_table_destroy (control->priv->sink_inputs); control->priv->sink_inputs = NULL; } if (control->priv->source_outputs != NULL) { g_hash_table_destroy (control->priv->source_outputs); control->priv->source_outputs = NULL; } if (control->priv->clients != NULL) { g_hash_table_destroy (control->priv->clients); control->priv->clients = NULL; } if (control->priv->cards != NULL) { g_hash_table_destroy (control->priv->cards); control->priv->cards = NULL; } if (control->priv->ui_outputs != NULL) { g_hash_table_destroy (control->priv->ui_outputs); control->priv->ui_outputs = NULL; } if (control->priv->ui_inputs != NULL) { g_hash_table_destroy (control->priv->ui_inputs); control->priv->ui_inputs = NULL; } G_OBJECT_CLASS (gvc_mixer_control_parent_class)->dispose (object); } static void gvc_mixer_control_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GvcMixerControl *self = GVC_MIXER_CONTROL (object); switch (prop_id) { case PROP_NAME: g_free (self->priv->name); self->priv->name = g_value_dup_string (value); g_object_notify (G_OBJECT (self), "name"); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gvc_mixer_control_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GvcMixerControl *self = GVC_MIXER_CONTROL (object); switch (prop_id) { case PROP_NAME: g_value_set_string (value, self->priv->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GObject * gvc_mixer_control_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; GvcMixerControl *self; object = G_OBJECT_CLASS (gvc_mixer_control_parent_class)->constructor (type, n_construct_properties, construct_params); self = GVC_MIXER_CONTROL (object); gvc_mixer_new_pa_context (self); self->priv->profile_swapping_device_id = GVC_MIXER_UI_DEVICE_INVALID; return object; } static void gvc_mixer_control_class_init (GvcMixerControlClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gvc_mixer_control_constructor; object_class->dispose = gvc_mixer_control_dispose; object_class->finalize = gvc_mixer_control_finalize; object_class->set_property = gvc_mixer_control_set_property; object_class->get_property = gvc_mixer_control_get_property; g_object_class_install_property (object_class, PROP_NAME, g_param_spec_string ("name", "Name", "Name to display for this mixer control", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); signals [STATE_CHANGED] = g_signal_new ("state-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, state_changed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [STREAM_ADDED] = g_signal_new ("stream-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, stream_added), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [STREAM_REMOVED] = g_signal_new ("stream-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, stream_removed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [CARD_INFO] = g_signal_new ("card-info", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals [CARD_ADDED] = g_signal_new ("card-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, card_added), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [CARD_REMOVED] = g_signal_new ("card-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, card_removed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [DEFAULT_SINK_CHANGED] = g_signal_new ("default-sink-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, default_sink_changed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [DEFAULT_SOURCE_CHANGED] = g_signal_new ("default-source-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, default_source_changed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [ACTIVE_OUTPUT_UPDATE] = g_signal_new ("active-output-update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, active_output_update), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [ACTIVE_INPUT_UPDATE] = g_signal_new ("active-input-update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, active_input_update), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [OUTPUT_ADDED] = g_signal_new ("output-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, output_added), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [INPUT_ADDED] = g_signal_new ("input-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, input_added), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [OUTPUT_REMOVED] = g_signal_new ("output-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, output_removed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals [INPUT_REMOVED] = g_signal_new ("input-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GvcMixerControlClass, input_removed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); g_type_class_add_private (klass, sizeof (GvcMixerControlPrivate)); } static void gvc_mixer_control_init (GvcMixerControl *control) { control->priv = GVC_MIXER_CONTROL_GET_PRIVATE (control); control->priv->pa_mainloop = pa_glib_mainloop_new (g_main_context_default ()); g_assert (control->priv->pa_mainloop); control->priv->pa_api = pa_glib_mainloop_get_api (control->priv->pa_mainloop); g_assert (control->priv->pa_api); control->priv->all_streams = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->sinks = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->sources = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->sink_inputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->source_outputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->cards = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->ui_outputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->ui_inputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); control->priv->clients = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_free); control->priv->state = GVC_STATE_CLOSED; } static void gvc_mixer_control_finalize (GObject *object) { GvcMixerControl *mixer_control; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_CONTROL (object)); mixer_control = GVC_MIXER_CONTROL (object); g_free (mixer_control->priv->name); mixer_control->priv->name = NULL; g_return_if_fail (mixer_control->priv != NULL); G_OBJECT_CLASS (gvc_mixer_control_parent_class)->finalize (object); } GvcMixerControl * gvc_mixer_control_new (const char *name) { GObject *control; control = g_object_new (GVC_TYPE_MIXER_CONTROL, "name", name, NULL); return GVC_MIXER_CONTROL (control); } gdouble gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control) { return (gdouble) PA_VOLUME_NORM; } gdouble gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control) { return (gdouble) PA_VOLUME_UI_MAX; } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-control.h0000664000000000000000000001637215172222611022245 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_CONTROL_H #define __GVC_MIXER_CONTROL_H #include #include "gvc-mixer-stream.h" #include "gvc-mixer-card.h" #include "gvc-mixer-ui-device.h" G_BEGIN_DECLS typedef enum { GVC_STATE_CLOSED, GVC_STATE_READY, GVC_STATE_CONNECTING, GVC_STATE_FAILED } GvcMixerControlState; #define GVC_TYPE_MIXER_CONTROL (gvc_mixer_control_get_type ()) #define GVC_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControl)) #define GVC_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass)) #define GVC_IS_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CONTROL)) #define GVC_IS_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CONTROL)) #define GVC_MIXER_CONTROL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass)) typedef struct GvcMixerControlPrivate GvcMixerControlPrivate; typedef struct { GObject parent; GvcMixerControlPrivate *priv; } GvcMixerControl; typedef struct { GObjectClass parent_class; void (*state_changed) (GvcMixerControl *control, GvcMixerControlState new_state); void (*stream_added) (GvcMixerControl *control, guint id); void (*stream_removed) (GvcMixerControl *control, guint id); void (*card_added) (GvcMixerControl *control, guint id); void (*card_removed) (GvcMixerControl *control, guint id); void (*default_sink_changed) (GvcMixerControl *control, guint id); void (*default_source_changed) (GvcMixerControl *control, guint id); void (*active_output_update) (GvcMixerControl *control, guint id); void (*active_input_update) (GvcMixerControl *control, guint id); void (*output_added) (GvcMixerControl *control, guint id); void (*input_added) (GvcMixerControl *control, guint id); void (*output_removed) (GvcMixerControl *control, guint id); void (*input_removed) (GvcMixerControl *control, guint id); } GvcMixerControlClass; GType gvc_mixer_control_get_type (void); GvcMixerControl * gvc_mixer_control_new (const char *name); gboolean gvc_mixer_control_open (GvcMixerControl *control); gboolean gvc_mixer_control_close (GvcMixerControl *control); GSList * gvc_mixer_control_get_cards (GvcMixerControl *control); GSList * gvc_mixer_control_get_streams (GvcMixerControl *control); GSList * gvc_mixer_control_get_sinks (GvcMixerControl *control); GSList * gvc_mixer_control_get_sources (GvcMixerControl *control); GSList * gvc_mixer_control_get_sink_inputs (GvcMixerControl *control); GSList * gvc_mixer_control_get_source_outputs (GvcMixerControl *control); GvcMixerStream * gvc_mixer_control_lookup_stream_id (GvcMixerControl *control, guint id); GvcMixerCard * gvc_mixer_control_lookup_card_id (GvcMixerControl *control, guint id); GvcMixerUIDevice * gvc_mixer_control_lookup_output_id (GvcMixerControl *control, guint id); GvcMixerUIDevice * gvc_mixer_control_lookup_input_id (GvcMixerControl *control, guint id); GvcMixerUIDevice * gvc_mixer_control_lookup_device_from_stream (GvcMixerControl *control, GvcMixerStream *stream); GvcMixerStream * gvc_mixer_control_get_default_sink (GvcMixerControl *control); GvcMixerStream * gvc_mixer_control_get_default_source (GvcMixerControl *control); GvcMixerStream * gvc_mixer_control_get_event_sink_input (GvcMixerControl *control); gboolean gvc_mixer_control_set_default_sink (GvcMixerControl *control, GvcMixerStream *stream); gboolean gvc_mixer_control_set_default_source (GvcMixerControl *control, GvcMixerStream *stream); gdouble gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control); gdouble gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control); void gvc_mixer_control_change_output (GvcMixerControl *control, GvcMixerUIDevice* output); void gvc_mixer_control_change_input (GvcMixerControl *control, GvcMixerUIDevice* input); GvcMixerStream* gvc_mixer_control_get_stream_from_device (GvcMixerControl *control, GvcMixerUIDevice *device); gboolean gvc_mixer_control_change_profile_on_selected_device (GvcMixerControl *control, GvcMixerUIDevice *device, const gchar* profile); GvcMixerControlState gvc_mixer_control_get_state (GvcMixerControl *control); G_END_DECLS #endif /* __GVC_MIXER_CONTROL_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-event-role.c0000664000000000000000000001701115172222611022627 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include "gvc-mixer-event-role.h" #include "gvc-mixer-stream-private.h" #include "gvc-channel-map-private.h" #define GVC_MIXER_EVENT_ROLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRolePrivate)) struct GvcMixerEventRolePrivate { char *device; }; enum { PROP_0, PROP_DEVICE }; static void gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass); static void gvc_mixer_event_role_init (GvcMixerEventRole *mixer_event_role); static void gvc_mixer_event_role_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM) static gboolean update_settings (GvcMixerEventRole *role, gboolean is_muted, gpointer *op) { pa_operation *o; const GvcChannelMap *map; pa_context *context; pa_ext_stream_restore_info info; map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role)); info.volume = *gvc_channel_map_get_cvolume(map); info.name = "sink-input-by-media-role:event"; info.channel_map = *gvc_channel_map_get_pa_channel_map(map); info.device = role->priv->device; info.mute = is_muted; context = gvc_mixer_stream_get_pa_context (GVC_MIXER_STREAM (role)); o = pa_ext_stream_restore_write (context, PA_UPDATE_REPLACE, &info, 1, TRUE, NULL, NULL); if (o == NULL) { g_warning ("pa_ext_stream_restore_write() failed"); return FALSE; } if (op != NULL) *op = o; return TRUE; } static gboolean gvc_mixer_event_role_push_volume (GvcMixerStream *stream, gpointer *op) { return update_settings (GVC_MIXER_EVENT_ROLE (stream), gvc_mixer_stream_get_is_muted (stream), op); } static gboolean gvc_mixer_event_role_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { /* Apply change straight away so that we don't get a race with * gvc_mixer_event_role_push_volume(). * See https://bugs.freedesktop.org/show_bug.cgi?id=51413 */ gvc_mixer_stream_set_is_muted (stream, is_muted); return update_settings (GVC_MIXER_EVENT_ROLE (stream), is_muted, NULL); } static gboolean gvc_mixer_event_role_set_device (GvcMixerEventRole *role, const char *device) { g_return_val_if_fail (GVC_IS_MIXER_EVENT_ROLE (role), FALSE); g_free (role->priv->device); role->priv->device = g_strdup (device); g_object_notify (G_OBJECT (role), "device"); return TRUE; } static void gvc_mixer_event_role_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object); switch (prop_id) { case PROP_DEVICE: gvc_mixer_event_role_set_device (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gvc_mixer_event_role_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object); switch (prop_id) { case PROP_DEVICE: g_value_set_string (value, self->priv->device); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); object_class->finalize = gvc_mixer_event_role_finalize; object_class->set_property = gvc_mixer_event_role_set_property; object_class->get_property = gvc_mixer_event_role_get_property; stream_class->push_volume = gvc_mixer_event_role_push_volume; stream_class->change_is_muted = gvc_mixer_event_role_change_is_muted; g_object_class_install_property (object_class, PROP_DEVICE, g_param_spec_string ("device", "Device", "Device", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_type_class_add_private (klass, sizeof (GvcMixerEventRolePrivate)); } static void gvc_mixer_event_role_init (GvcMixerEventRole *event_role) { event_role->priv = GVC_MIXER_EVENT_ROLE_GET_PRIVATE (event_role); } static void gvc_mixer_event_role_finalize (GObject *object) { GvcMixerEventRole *mixer_event_role; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_EVENT_ROLE (object)); mixer_event_role = GVC_MIXER_EVENT_ROLE (object); g_return_if_fail (mixer_event_role->priv != NULL); g_free (mixer_event_role->priv->device); G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->finalize (object); } /** * gvc_mixer_event_role_new: (skip) * @context: * @device: * @channel_map: * * Returns: */ GvcMixerStream * gvc_mixer_event_role_new (pa_context *context, const char *device, GvcChannelMap *channel_map) { GObject *object; object = g_object_new (GVC_TYPE_MIXER_EVENT_ROLE, "pa-context", context, "index", 0, "device", device, "channel-map", channel_map, NULL); return GVC_MIXER_STREAM (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-event-role.h0000664000000000000000000000433415172222611022640 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_EVENT_ROLE_H #define __GVC_MIXER_EVENT_ROLE_H #include #include "gvc-mixer-stream.h" G_BEGIN_DECLS #define GVC_TYPE_MIXER_EVENT_ROLE (gvc_mixer_event_role_get_type ()) #define GVC_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRole)) #define GVC_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass)) #define GVC_IS_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_EVENT_ROLE)) #define GVC_IS_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_EVENT_ROLE)) #define GVC_MIXER_EVENT_ROLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass)) typedef struct GvcMixerEventRolePrivate GvcMixerEventRolePrivate; typedef struct { GvcMixerStream parent; GvcMixerEventRolePrivate *priv; } GvcMixerEventRole; typedef struct { GvcMixerStreamClass parent_class; } GvcMixerEventRoleClass; GType gvc_mixer_event_role_get_type (void); GvcMixerStream * gvc_mixer_event_role_new (pa_context *context, const char *device, GvcChannelMap *channel_map); G_END_DECLS #endif /* __GVC_MIXER_EVENT_ROLE_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-sink-input.c0000664000000000000000000001170215172222611022651 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-mixer-sink-input.h" #include "gvc-mixer-stream-private.h" #include "gvc-channel-map-private.h" #define GVC_MIXER_SINK_INPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputPrivate)) struct GvcMixerSinkInputPrivate { gpointer dummy; }; static void gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass); static void gvc_mixer_sink_input_init (GvcMixerSinkInput *mixer_sink_input); static void gvc_mixer_sink_input_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM) static gboolean gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op) { pa_operation *o; guint index; const GvcChannelMap *map; pa_context *context; const pa_cvolume *cv; index = gvc_mixer_stream_get_index (stream); map = gvc_mixer_stream_get_channel_map (stream); cv = gvc_channel_map_get_cvolume(map); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_sink_input_volume (context, index, cv, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_sink_input_volume() failed"); return FALSE; } *op = o; return TRUE; } static gboolean gvc_mixer_sink_input_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { pa_operation *o; guint index; pa_context *context; index = gvc_mixer_stream_get_index (stream); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_sink_input_mute (context, index, is_muted, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_sink_input_mute_by_index() failed"); return FALSE; } pa_operation_unref(o); return TRUE; } static void gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); object_class->finalize = gvc_mixer_sink_input_finalize; stream_class->push_volume = gvc_mixer_sink_input_push_volume; stream_class->change_is_muted = gvc_mixer_sink_input_change_is_muted; g_type_class_add_private (klass, sizeof (GvcMixerSinkInputPrivate)); } static void gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input) { sink_input->priv = GVC_MIXER_SINK_INPUT_GET_PRIVATE (sink_input); } static void gvc_mixer_sink_input_finalize (GObject *object) { GvcMixerSinkInput *mixer_sink_input; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object)); mixer_sink_input = GVC_MIXER_SINK_INPUT (object); g_return_if_fail (mixer_sink_input->priv != NULL); G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->finalize (object); } /** * gvc_mixer_sink_input_new: (skip) * @context: * @index: * @channel_map: * * Returns: */ GvcMixerStream * gvc_mixer_sink_input_new (pa_context *context, guint index, GvcChannelMap *channel_map) { GObject *object; object = g_object_new (GVC_TYPE_MIXER_SINK_INPUT, "pa-context", context, "index", index, "channel-map", channel_map, NULL); return GVC_MIXER_STREAM (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-sink-input.h0000664000000000000000000000433315172222611022660 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_SINK_INPUT_H #define __GVC_MIXER_SINK_INPUT_H #include #include "gvc-mixer-stream.h" G_BEGIN_DECLS #define GVC_TYPE_MIXER_SINK_INPUT (gvc_mixer_sink_input_get_type ()) #define GVC_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInput)) #define GVC_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass)) #define GVC_IS_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK_INPUT)) #define GVC_IS_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK_INPUT)) #define GVC_MIXER_SINK_INPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass)) typedef struct GvcMixerSinkInputPrivate GvcMixerSinkInputPrivate; typedef struct { GvcMixerStream parent; GvcMixerSinkInputPrivate *priv; } GvcMixerSinkInput; typedef struct { GvcMixerStreamClass parent_class; } GvcMixerSinkInputClass; GType gvc_mixer_sink_input_get_type (void); GvcMixerStream * gvc_mixer_sink_input_new (pa_context *context, guint index, GvcChannelMap *channel_map); G_END_DECLS #endif /* __GVC_MIXER_SINK_INPUT_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-sink.c0000664000000000000000000001334015172222611021514 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-mixer-sink.h" #include "gvc-mixer-stream-private.h" #include "gvc-channel-map-private.h" #define GVC_MIXER_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkPrivate)) struct GvcMixerSinkPrivate { gpointer dummy; }; static void gvc_mixer_sink_class_init (GvcMixerSinkClass *klass); static void gvc_mixer_sink_init (GvcMixerSink *mixer_sink); static void gvc_mixer_sink_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM) static gboolean gvc_mixer_sink_push_volume (GvcMixerStream *stream, gpointer *op) { pa_operation *o; guint index; const GvcChannelMap *map; pa_context *context; const pa_cvolume *cv; index = gvc_mixer_stream_get_index (stream); map = gvc_mixer_stream_get_channel_map (stream); /* set the volume */ cv = gvc_channel_map_get_cvolume(map); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_sink_volume_by_index (context, index, cv, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_sink_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context))); return FALSE; } *op = o; return TRUE; } static gboolean gvc_mixer_sink_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { pa_operation *o; guint index; pa_context *context; index = gvc_mixer_stream_get_index (stream); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_sink_mute_by_index (context, index, is_muted, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_sink_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context))); return FALSE; } pa_operation_unref(o); return TRUE; } static gboolean gvc_mixer_sink_change_port (GvcMixerStream *stream, const char *port) { pa_operation *o; guint index; pa_context *context; index = gvc_mixer_stream_get_index (stream); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_sink_port_by_index (context, index, port, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_sink_port_by_index() failed: %s", pa_strerror(pa_context_errno(context))); return FALSE; } pa_operation_unref(o); return TRUE; } static void gvc_mixer_sink_class_init (GvcMixerSinkClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); object_class->finalize = gvc_mixer_sink_finalize; stream_class->push_volume = gvc_mixer_sink_push_volume; stream_class->change_port = gvc_mixer_sink_change_port; stream_class->change_is_muted = gvc_mixer_sink_change_is_muted; g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate)); } static void gvc_mixer_sink_init (GvcMixerSink *sink) { sink->priv = GVC_MIXER_SINK_GET_PRIVATE (sink); } static void gvc_mixer_sink_finalize (GObject *object) { GvcMixerSink *mixer_sink; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_SINK (object)); mixer_sink = GVC_MIXER_SINK (object); g_return_if_fail (mixer_sink->priv != NULL); G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->finalize (object); } /** * gvc_mixer_sink_new: (skip) * @context: * @index: * @channel_map: * * Returns: */ GvcMixerStream * gvc_mixer_sink_new (pa_context *context, guint index, GvcChannelMap *channel_map) { GObject *object; object = g_object_new (GVC_TYPE_MIXER_SINK, "pa-context", context, "index", index, "channel-map", channel_map, NULL); return GVC_MIXER_STREAM (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-sink.h0000664000000000000000000000412415172222611021521 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_SINK_H #define __GVC_MIXER_SINK_H #include #include "gvc-mixer-stream.h" G_BEGIN_DECLS #define GVC_TYPE_MIXER_SINK (gvc_mixer_sink_get_type ()) #define GVC_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK, GvcMixerSink)) #define GVC_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass)) #define GVC_IS_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK)) #define GVC_IS_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK)) #define GVC_MIXER_SINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass)) typedef struct GvcMixerSinkPrivate GvcMixerSinkPrivate; typedef struct { GvcMixerStream parent; GvcMixerSinkPrivate *priv; } GvcMixerSink; typedef struct { GvcMixerStreamClass parent_class; } GvcMixerSinkClass; GType gvc_mixer_sink_get_type (void); GvcMixerStream * gvc_mixer_sink_new (pa_context *context, guint index, GvcChannelMap *channel_map); G_END_DECLS #endif /* __GVC_MIXER_SINK_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-source-output.c0000664000000000000000000000717415172222611023416 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-mixer-source-output.h" #define GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputPrivate)) struct GvcMixerSourceOutputPrivate { gpointer dummy; }; static void gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass); static void gvc_mixer_source_output_init (GvcMixerSourceOutput *mixer_source_output); static void gvc_mixer_source_output_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerSourceOutput, gvc_mixer_source_output, GVC_TYPE_MIXER_STREAM) static gboolean gvc_mixer_source_output_push_volume (GvcMixerStream *stream, gpointer *op) { /* FIXME: */ *op = NULL; return TRUE; } static gboolean gvc_mixer_source_output_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { /* FIXME: */ return TRUE; } static void gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); object_class->finalize = gvc_mixer_source_output_finalize; stream_class->push_volume = gvc_mixer_source_output_push_volume; stream_class->change_is_muted = gvc_mixer_source_output_change_is_muted; g_type_class_add_private (klass, sizeof (GvcMixerSourceOutputPrivate)); } static void gvc_mixer_source_output_init (GvcMixerSourceOutput *source_output) { source_output->priv = GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE (source_output); } static void gvc_mixer_source_output_finalize (GObject *object) { GvcMixerSourceOutput *mixer_source_output; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_SOURCE_OUTPUT (object)); mixer_source_output = GVC_MIXER_SOURCE_OUTPUT (object); g_return_if_fail (mixer_source_output->priv != NULL); G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->finalize (object); } /** * gvc_mixer_source_output_new: (skip) * @context: * @index: * @channel_map: * * Returns: */ GvcMixerStream * gvc_mixer_source_output_new (pa_context *context, guint index, GvcChannelMap *channel_map) { GObject *object; object = g_object_new (GVC_TYPE_MIXER_SOURCE_OUTPUT, "pa-context", context, "index", index, "channel-map", channel_map, NULL); return GVC_MIXER_STREAM (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-source-output.h0000664000000000000000000000445715172222611023424 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_SOURCE_OUTPUT_H #define __GVC_MIXER_SOURCE_OUTPUT_H #include #include "gvc-mixer-stream.h" G_BEGIN_DECLS #define GVC_TYPE_MIXER_SOURCE_OUTPUT (gvc_mixer_source_output_get_type ()) #define GVC_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutput)) #define GVC_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass)) #define GVC_IS_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT)) #define GVC_IS_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE_OUTPUT)) #define GVC_MIXER_SOURCE_OUTPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass)) typedef struct GvcMixerSourceOutputPrivate GvcMixerSourceOutputPrivate; typedef struct { GvcMixerStream parent; GvcMixerSourceOutputPrivate *priv; } GvcMixerSourceOutput; typedef struct { GvcMixerStreamClass parent_class; } GvcMixerSourceOutputClass; GType gvc_mixer_source_output_get_type (void); GvcMixerStream * gvc_mixer_source_output_new (pa_context *context, guint index, GvcChannelMap *channel_map); G_END_DECLS #endif /* __GVC_MIXER_SOURCE_OUTPUT_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-source.c0000664000000000000000000001353415172222611022055 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-mixer-source.h" #include "gvc-mixer-stream-private.h" #include "gvc-channel-map-private.h" #define GVC_MIXER_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourcePrivate)) struct GvcMixerSourcePrivate { gpointer dummy; }; static void gvc_mixer_source_class_init (GvcMixerSourceClass *klass); static void gvc_mixer_source_init (GvcMixerSource *mixer_source); static void gvc_mixer_source_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM) static gboolean gvc_mixer_source_push_volume (GvcMixerStream *stream, gpointer *op) { pa_operation *o; guint index; const GvcChannelMap *map; pa_context *context; const pa_cvolume *cv; index = gvc_mixer_stream_get_index (stream); map = gvc_mixer_stream_get_channel_map (stream); /* set the volume */ cv = gvc_channel_map_get_cvolume (map); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_source_volume_by_index (context, index, cv, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_source_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context))); return FALSE; } *op = o; return TRUE; } static gboolean gvc_mixer_source_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { pa_operation *o; guint index; pa_context *context; index = gvc_mixer_stream_get_index (stream); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_source_mute_by_index (context, index, is_muted, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_source_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context))); return FALSE; } pa_operation_unref(o); return TRUE; } static gboolean gvc_mixer_source_change_port (GvcMixerStream *stream, const char *port) { pa_operation *o; guint index; pa_context *context; index = gvc_mixer_stream_get_index (stream); context = gvc_mixer_stream_get_pa_context (stream); o = pa_context_set_source_port_by_index (context, index, port, NULL, NULL); if (o == NULL) { g_warning ("pa_context_set_source_port_by_index() failed: %s", pa_strerror(pa_context_errno(context))); return FALSE; } pa_operation_unref(o); return TRUE; } static void gvc_mixer_source_class_init (GvcMixerSourceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); object_class->finalize = gvc_mixer_source_finalize; stream_class->push_volume = gvc_mixer_source_push_volume; stream_class->change_is_muted = gvc_mixer_source_change_is_muted; stream_class->change_port = gvc_mixer_source_change_port; g_type_class_add_private (klass, sizeof (GvcMixerSourcePrivate)); } static void gvc_mixer_source_init (GvcMixerSource *source) { source->priv = GVC_MIXER_SOURCE_GET_PRIVATE (source); } static void gvc_mixer_source_finalize (GObject *object) { GvcMixerSource *mixer_source; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_SOURCE (object)); mixer_source = GVC_MIXER_SOURCE (object); g_return_if_fail (mixer_source->priv != NULL); G_OBJECT_CLASS (gvc_mixer_source_parent_class)->finalize (object); } /** * gvc_mixer_source_new: (skip) * @context: * @index: * @channel_map: * * Returns: */ GvcMixerStream * gvc_mixer_source_new (pa_context *context, guint index, GvcChannelMap *channel_map) { GObject *object; object = g_object_new (GVC_TYPE_MIXER_SOURCE, "pa-context", context, "index", index, "channel-map", channel_map, NULL); return GVC_MIXER_STREAM (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-source.h0000664000000000000000000000420415172222611022054 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_SOURCE_H #define __GVC_MIXER_SOURCE_H #include #include "gvc-mixer-stream.h" G_BEGIN_DECLS #define GVC_TYPE_MIXER_SOURCE (gvc_mixer_source_get_type ()) #define GVC_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSource)) #define GVC_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass)) #define GVC_IS_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE)) #define GVC_IS_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE)) #define GVC_MIXER_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass)) typedef struct GvcMixerSourcePrivate GvcMixerSourcePrivate; typedef struct { GvcMixerStream parent; GvcMixerSourcePrivate *priv; } GvcMixerSource; typedef struct { GvcMixerStreamClass parent_class; } GvcMixerSourceClass; GType gvc_mixer_source_get_type (void); GvcMixerStream * gvc_mixer_source_new (pa_context *context, guint index, GvcChannelMap *channel_map); G_END_DECLS #endif /* __GVC_MIXER_SOURCE_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-stream-private.h0000664000000000000000000000214015172222611023514 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_STREAM_PRIVATE_H #define __GVC_MIXER_STREAM_PRIVATE_H #include #include "gvc-channel-map.h" G_BEGIN_DECLS pa_context * gvc_mixer_stream_get_pa_context (GvcMixerStream *stream); G_END_DECLS #endif /* __GVC_MIXER_STREAM_PRIVATE_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-stream.c0000664000000000000000000011071315172222611022045 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gvc-mixer-stream.h" #include "gvc-mixer-stream-private.h" #include "gvc-channel-map-private.h" #define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate)) static guint32 stream_serial = 1; struct GvcMixerStreamPrivate { pa_context *pa_context; guint id; guint index; gint card_index; GvcChannelMap *channel_map; char *name; char *description; char *application_id; char *icon_name; char *form_factor; char *sysfs_path; gboolean is_muted; gboolean can_decibel; gboolean is_event_stream; gboolean is_virtual; pa_volume_t base_volume; pa_operation *change_volume_op; char *port; char *human_port; GList *ports; }; enum { PROP_0, PROP_ID, PROP_PA_CONTEXT, PROP_CHANNEL_MAP, PROP_INDEX, PROP_NAME, PROP_DESCRIPTION, PROP_APPLICATION_ID, PROP_ICON_NAME, PROP_FORM_FACTOR, PROP_SYSFS_PATH, PROP_VOLUME, PROP_DECIBEL, PROP_IS_MUTED, PROP_CAN_DECIBEL, PROP_IS_EVENT_STREAM, PROP_IS_VIRTUAL, PROP_CARD_INDEX, PROP_PORT, }; static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass); static void gvc_mixer_stream_init (GvcMixerStream *mixer_stream); static void gvc_mixer_stream_finalize (GObject *object); G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT) static void free_port (GvcMixerStreamPort *p) { g_free (p->port); g_free (p->human_port); g_slice_free (GvcMixerStreamPort, p); } static GvcMixerStreamPort * dup_port (GvcMixerStreamPort *p) { GvcMixerStreamPort *m; m = g_slice_new (GvcMixerStreamPort); *m = *p; m->port = g_strdup (p->port); m->human_port = g_strdup (p->human_port); return m; } G_DEFINE_BOXED_TYPE (GvcMixerStreamPort, gvc_mixer_stream_port, dup_port, free_port) static guint32 get_next_stream_serial (void) { guint32 serial; serial = stream_serial++; if ((gint32)stream_serial < 0) { stream_serial = 1; } return serial; } pa_context * gvc_mixer_stream_get_pa_context (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); return stream->priv->pa_context; } guint gvc_mixer_stream_get_index (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); return stream->priv->index; } guint gvc_mixer_stream_get_id (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); return stream->priv->id; } const GvcChannelMap * gvc_mixer_stream_get_channel_map (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->channel_map; } /** * gvc_mixer_stream_get_volume: * @stream: * * Returns: (type guint32) (transfer none): */ pa_volume_t gvc_mixer_stream_get_volume (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]; } gdouble gvc_mixer_stream_get_decibel (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); return pa_sw_volume_to_dB( (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]); } /** * gvc_mixer_stream_set_volume: * @stream: * @volume: (type guint32): * * Returns: */ gboolean gvc_mixer_stream_set_volume (GvcMixerStream *stream, pa_volume_t volume) { pa_cvolume cv; g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map); pa_cvolume_scale(&cv, volume); if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) { gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE); g_object_notify (G_OBJECT (stream), "volume"); return TRUE; } return FALSE; } gboolean gvc_mixer_stream_set_decibel (GvcMixerStream *stream, gdouble db) { pa_cvolume cv; g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map); pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db)); if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) { gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE); g_object_notify (G_OBJECT (stream), "volume"); } return TRUE; } gboolean gvc_mixer_stream_get_is_muted (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); return stream->priv->is_muted; } gboolean gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); return stream->priv->can_decibel; } gboolean gvc_mixer_stream_set_is_muted (GvcMixerStream *stream, gboolean is_muted) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); if (is_muted != stream->priv->is_muted) { stream->priv->is_muted = is_muted; g_object_notify (G_OBJECT (stream), "is-muted"); } return TRUE; } gboolean gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream, gboolean can_decibel) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); if (can_decibel != stream->priv->can_decibel) { stream->priv->can_decibel = can_decibel; g_object_notify (G_OBJECT (stream), "can-decibel"); } return TRUE; } const char * gvc_mixer_stream_get_name (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->name; } const char * gvc_mixer_stream_get_description (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->description; } gboolean gvc_mixer_stream_set_name (GvcMixerStream *stream, const char *name) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_free (stream->priv->name); stream->priv->name = g_strdup (name); g_object_notify (G_OBJECT (stream), "name"); return TRUE; } gboolean gvc_mixer_stream_set_description (GvcMixerStream *stream, const char *description) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_free (stream->priv->description); stream->priv->description = g_strdup (description); g_object_notify (G_OBJECT (stream), "description"); return TRUE; } gboolean gvc_mixer_stream_is_event_stream (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); return stream->priv->is_event_stream; } gboolean gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream, gboolean is_event_stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); stream->priv->is_event_stream = is_event_stream; g_object_notify (G_OBJECT (stream), "is-event-stream"); return TRUE; } gboolean gvc_mixer_stream_is_virtual (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); return stream->priv->is_virtual; } gboolean gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream, gboolean is_virtual) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); stream->priv->is_virtual = is_virtual; g_object_notify (G_OBJECT (stream), "is-virtual"); return TRUE; } const char * gvc_mixer_stream_get_application_id (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->application_id; } gboolean gvc_mixer_stream_set_application_id (GvcMixerStream *stream, const char *application_id) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_free (stream->priv->application_id); stream->priv->application_id = g_strdup (application_id); g_object_notify (G_OBJECT (stream), "application-id"); return TRUE; } static void on_channel_map_volume_changed (GvcChannelMap *channel_map, gboolean set, GvcMixerStream *stream) { if (set == TRUE) gvc_mixer_stream_push_volume (stream); g_object_notify (G_OBJECT (stream), "volume"); } static gboolean gvc_mixer_stream_set_channel_map (GvcMixerStream *stream, GvcChannelMap *channel_map) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); if (channel_map != NULL) { g_object_ref (channel_map); } if (stream->priv->channel_map != NULL) { g_signal_handlers_disconnect_by_func (stream->priv->channel_map, on_channel_map_volume_changed, stream); g_object_unref (stream->priv->channel_map); } stream->priv->channel_map = channel_map; if (stream->priv->channel_map != NULL) { g_signal_connect (stream->priv->channel_map, "volume-changed", G_CALLBACK (on_channel_map_volume_changed), stream); g_object_notify (G_OBJECT (stream), "channel-map"); } return TRUE; } const char * gvc_mixer_stream_get_icon_name (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->icon_name; } const char * gvc_mixer_stream_get_form_factor (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->form_factor; } const char * gvc_mixer_stream_get_sysfs_path (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->sysfs_path; } /** * gvc_mixer_stream_get_gicon: * @stream: a #GvcMixerStream * * Returns: (transfer full): a new #GIcon */ GIcon * gvc_mixer_stream_get_gicon (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); if (stream->priv->icon_name == NULL) return NULL; return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name); } gboolean gvc_mixer_stream_set_icon_name (GvcMixerStream *stream, const char *icon_name) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_free (stream->priv->icon_name); stream->priv->icon_name = g_strdup (icon_name); g_object_notify (G_OBJECT (stream), "icon-name"); return TRUE; } gboolean gvc_mixer_stream_set_form_factor (GvcMixerStream *stream, const char *form_factor) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_free (stream->priv->form_factor); stream->priv->form_factor = g_strdup (form_factor); g_object_notify (G_OBJECT (stream), "form-factor"); return TRUE; } gboolean gvc_mixer_stream_set_sysfs_path (GvcMixerStream *stream, const char *sysfs_path) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_free (stream->priv->sysfs_path); stream->priv->sysfs_path = g_strdup (sysfs_path); g_object_notify (G_OBJECT (stream), "sysfs-path"); return TRUE; } /** * gvc_mixer_stream_get_base_volume: * @stream: * * Returns: (type guint32) (transfer none): */ pa_volume_t gvc_mixer_stream_get_base_volume (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); return stream->priv->base_volume; } /** * gvc_mixer_stream_set_base_volume: * @stream: * @base_volume: (type guint32): * * Returns: */ gboolean gvc_mixer_stream_set_base_volume (GvcMixerStream *stream, pa_volume_t base_volume) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); stream->priv->base_volume = base_volume; return TRUE; } const GvcMixerStreamPort * gvc_mixer_stream_get_port (GvcMixerStream *stream) { GList *l; g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); g_return_val_if_fail (stream->priv->ports != NULL, NULL); for (l = stream->priv->ports; l != NULL; l = l->next) { GvcMixerStreamPort *p = l->data; if (g_strcmp0 (stream->priv->port, p->port) == 0) { return p; } } g_assert_not_reached (); return NULL; } gboolean gvc_mixer_stream_set_port (GvcMixerStream *stream, const char *port) { GList *l; g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_return_val_if_fail (stream->priv->ports != NULL, FALSE); g_free (stream->priv->port); stream->priv->port = g_strdup (port); g_free (stream->priv->human_port); stream->priv->human_port = NULL; for (l = stream->priv->ports; l != NULL; l = l->next) { GvcMixerStreamPort *p = l->data; if (g_str_equal (stream->priv->port, p->port)) { stream->priv->human_port = g_strdup (p->human_port); break; } } g_object_notify (G_OBJECT (stream), "port"); return TRUE; } gboolean gvc_mixer_stream_change_port (GvcMixerStream *stream, const char *port) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port); } /** * gvc_mixer_stream_get_ports: * * Return value: (transfer none) (element-type GvcMixerStreamPort): */ const GList * gvc_mixer_stream_get_ports (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); return stream->priv->ports; } static int sort_ports (GvcMixerStreamPort *a, GvcMixerStreamPort *b) { if (a->priority == b->priority) return 0; if (a->priority > b->priority) return 1; return -1; } /** * gvc_mixer_stream_set_ports: * @ports: (transfer full) (element-type GvcMixerStreamPort): */ gboolean gvc_mixer_stream_set_ports (GvcMixerStream *stream, GList *ports) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); g_return_val_if_fail (stream->priv->ports == NULL, FALSE); stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports); return TRUE; } gint gvc_mixer_stream_get_card_index (GvcMixerStream *stream) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX); return stream->priv->card_index; } gboolean gvc_mixer_stream_set_card_index (GvcMixerStream *stream, gint card_index) { g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); stream->priv->card_index = card_index; g_object_notify (G_OBJECT (stream), "card-index"); return TRUE; } static void gvc_mixer_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GvcMixerStream *self = GVC_MIXER_STREAM (object); switch (prop_id) { case PROP_PA_CONTEXT: self->priv->pa_context = g_value_get_pointer (value); break; case PROP_INDEX: self->priv->index = g_value_get_ulong (value); break; case PROP_ID: self->priv->id = g_value_get_ulong (value); break; case PROP_CHANNEL_MAP: gvc_mixer_stream_set_channel_map (self, g_value_get_object (value)); break; case PROP_NAME: gvc_mixer_stream_set_name (self, g_value_get_string (value)); break; case PROP_DESCRIPTION: gvc_mixer_stream_set_description (self, g_value_get_string (value)); break; case PROP_APPLICATION_ID: gvc_mixer_stream_set_application_id (self, g_value_get_string (value)); break; case PROP_ICON_NAME: gvc_mixer_stream_set_icon_name (self, g_value_get_string (value)); break; case PROP_FORM_FACTOR: gvc_mixer_stream_set_form_factor (self, g_value_get_string (value)); break; case PROP_SYSFS_PATH: gvc_mixer_stream_set_sysfs_path (self, g_value_get_string (value)); break; case PROP_VOLUME: gvc_mixer_stream_set_volume (self, g_value_get_ulong (value)); break; case PROP_DECIBEL: gvc_mixer_stream_set_decibel (self, g_value_get_double (value)); break; case PROP_IS_MUTED: gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value)); break; case PROP_IS_EVENT_STREAM: gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value)); break; case PROP_IS_VIRTUAL: gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value)); break; case PROP_CAN_DECIBEL: gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value)); break; case PROP_PORT: gvc_mixer_stream_set_port (self, g_value_get_string (value)); break; case PROP_CARD_INDEX: self->priv->card_index = g_value_get_long (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gvc_mixer_stream_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GvcMixerStream *self = GVC_MIXER_STREAM (object); switch (prop_id) { case PROP_PA_CONTEXT: g_value_set_pointer (value, self->priv->pa_context); break; case PROP_INDEX: g_value_set_ulong (value, self->priv->index); break; case PROP_ID: g_value_set_ulong (value, self->priv->id); break; case PROP_CHANNEL_MAP: g_value_set_object (value, self->priv->channel_map); break; case PROP_NAME: g_value_set_string (value, self->priv->name); break; case PROP_DESCRIPTION: g_value_set_string (value, self->priv->description); break; case PROP_APPLICATION_ID: g_value_set_string (value, self->priv->application_id); break; case PROP_ICON_NAME: g_value_set_string (value, self->priv->icon_name); break; case PROP_FORM_FACTOR: g_value_set_string (value, self->priv->form_factor); break; case PROP_SYSFS_PATH: g_value_set_string (value, self->priv->sysfs_path); break; case PROP_VOLUME: g_value_set_ulong (value, pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))); break; case PROP_DECIBEL: g_value_set_double (value, pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)))); break; case PROP_IS_MUTED: g_value_set_boolean (value, self->priv->is_muted); break; case PROP_IS_EVENT_STREAM: g_value_set_boolean (value, self->priv->is_event_stream); break; case PROP_IS_VIRTUAL: g_value_set_boolean (value, self->priv->is_virtual); break; case PROP_CAN_DECIBEL: g_value_set_boolean (value, self->priv->can_decibel); break; case PROP_PORT: g_value_set_string (value, self->priv->port); break; case PROP_CARD_INDEX: g_value_set_long (value, self->priv->card_index); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GObject * gvc_mixer_stream_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; GvcMixerStream *self; object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params); self = GVC_MIXER_STREAM (object); self->priv->id = get_next_stream_serial (); return object; } static gboolean gvc_mixer_stream_real_change_port (GvcMixerStream *stream, const char *port) { return FALSE; } static gboolean gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op) { return FALSE; } static gboolean gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { return FALSE; } gboolean gvc_mixer_stream_push_volume (GvcMixerStream *stream) { pa_operation *op; gboolean ret; g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); if (stream->priv->is_event_stream != FALSE) return TRUE; g_debug ("Pushing new volume to stream '%s' (%s)", stream->priv->description, stream->priv->name); ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op); if (ret) { if (stream->priv->change_volume_op != NULL) pa_operation_unref (stream->priv->change_volume_op); stream->priv->change_volume_op = op; } return ret; } gboolean gvc_mixer_stream_change_is_muted (GvcMixerStream *stream, gboolean is_muted) { gboolean ret; g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted); return ret; } gboolean gvc_mixer_stream_is_running (GvcMixerStream *stream) { if (stream->priv->change_volume_op == NULL) return FALSE; if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING)) return TRUE; pa_operation_unref(stream->priv->change_volume_op); stream->priv->change_volume_op = NULL; return FALSE; } static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->constructor = gvc_mixer_stream_constructor; gobject_class->finalize = gvc_mixer_stream_finalize; gobject_class->set_property = gvc_mixer_stream_set_property; gobject_class->get_property = gvc_mixer_stream_get_property; klass->push_volume = gvc_mixer_stream_real_push_volume; klass->change_port = gvc_mixer_stream_real_change_port; klass->change_is_muted = gvc_mixer_stream_real_change_is_muted; g_object_class_install_property (gobject_class, PROP_INDEX, g_param_spec_ulong ("index", "Index", "The index for this stream", 0, G_MAXULONG, 0, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_ID, g_param_spec_ulong ("id", "id", "The id for this stream", 0, G_MAXULONG, 0, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_CHANNEL_MAP, g_param_spec_object ("channel-map", "channel map", "The channel map for this stream", GVC_TYPE_CHANNEL_MAP, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_PA_CONTEXT, g_param_spec_pointer ("pa-context", "PulseAudio context", "The PulseAudio context for this stream", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_VOLUME, g_param_spec_ulong ("volume", "Volume", "The volume for this stream", 0, G_MAXULONG, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_DECIBEL, g_param_spec_double ("decibel", "Decibel", "The decibel level for this stream", -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_NAME, g_param_spec_string ("name", "Name", "Name to display for this stream", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_DESCRIPTION, g_param_spec_string ("description", "Description", "Description to display for this stream", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_APPLICATION_ID, g_param_spec_string ("application-id", "Application identifier", "Application identifier for this stream", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_ICON_NAME, g_param_spec_string ("icon-name", "Icon Name", "Name of icon to display for this stream", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_FORM_FACTOR, g_param_spec_string ("form-factor", "Form Factor", "Device form factor for this stream, as reported by PulseAudio", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_SYSFS_PATH, g_param_spec_string ("sysfs-path", "Sysfs path", "Sysfs path for the device associated with this stream", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_IS_MUTED, g_param_spec_boolean ("is-muted", "is muted", "Whether stream is muted", FALSE, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_CAN_DECIBEL, g_param_spec_boolean ("can-decibel", "can decibel", "Whether stream volume can be converted to decibel units", FALSE, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_IS_EVENT_STREAM, g_param_spec_boolean ("is-event-stream", "is event stream", "Whether stream's role is to play an event", FALSE, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_IS_VIRTUAL, g_param_spec_boolean ("is-virtual", "is virtual stream", "Whether the stream is virtual", FALSE, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_PORT, g_param_spec_string ("port", "Port", "The name of the current port for this stream", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CARD_INDEX, g_param_spec_long ("card-index", "Card index", "The index of the card for this stream", PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate)); } static void gvc_mixer_stream_init (GvcMixerStream *stream) { stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream); } static void gvc_mixer_stream_finalize (GObject *object) { GvcMixerStream *mixer_stream; g_return_if_fail (object != NULL); g_return_if_fail (GVC_IS_MIXER_STREAM (object)); mixer_stream = GVC_MIXER_STREAM (object); g_return_if_fail (mixer_stream->priv != NULL); g_object_unref (mixer_stream->priv->channel_map); mixer_stream->priv->channel_map = NULL; g_free (mixer_stream->priv->name); mixer_stream->priv->name = NULL; g_free (mixer_stream->priv->description); mixer_stream->priv->description = NULL; g_free (mixer_stream->priv->application_id); mixer_stream->priv->application_id = NULL; g_free (mixer_stream->priv->icon_name); mixer_stream->priv->icon_name = NULL; g_free (mixer_stream->priv->form_factor); mixer_stream->priv->form_factor = NULL; g_free (mixer_stream->priv->sysfs_path); mixer_stream->priv->sysfs_path = NULL; g_free (mixer_stream->priv->port); mixer_stream->priv->port = NULL; g_free (mixer_stream->priv->human_port); mixer_stream->priv->human_port = NULL; g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL); g_list_free (mixer_stream->priv->ports); mixer_stream->priv->ports = NULL; if (mixer_stream->priv->change_volume_op) { pa_operation_unref(mixer_stream->priv->change_volume_op); mixer_stream->priv->change_volume_op = NULL; } G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-stream.h0000664000000000000000000001607515172222611022060 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_MIXER_STREAM_H #define __GVC_MIXER_STREAM_H #include #include "gvc-pulseaudio-fake.h" #include "gvc-channel-map.h" #include G_BEGIN_DECLS #define GVC_TYPE_MIXER_STREAM (gvc_mixer_stream_get_type ()) #define GVC_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStream)) #define GVC_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass)) #define GVC_IS_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_STREAM)) #define GVC_IS_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_STREAM)) #define GVC_MIXER_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass)) typedef struct GvcMixerStreamPrivate GvcMixerStreamPrivate; typedef struct { GObject parent; GvcMixerStreamPrivate *priv; } GvcMixerStream; typedef struct { GObjectClass parent_class; /* vtable */ gboolean (*push_volume) (GvcMixerStream *stream, gpointer *operation); gboolean (*change_is_muted) (GvcMixerStream *stream, gboolean is_muted); gboolean (*change_port) (GvcMixerStream *stream, const char *port); } GvcMixerStreamClass; typedef struct { char *port; char *human_port; guint priority; gboolean available; } GvcMixerStreamPort; GType gvc_mixer_stream_port_get_type (void) G_GNUC_CONST; GType gvc_mixer_stream_get_type (void) G_GNUC_CONST; guint gvc_mixer_stream_get_index (GvcMixerStream *stream); guint gvc_mixer_stream_get_id (GvcMixerStream *stream); const GvcChannelMap *gvc_mixer_stream_get_channel_map(GvcMixerStream *stream); const GvcMixerStreamPort *gvc_mixer_stream_get_port (GvcMixerStream *stream); const GList * gvc_mixer_stream_get_ports (GvcMixerStream *stream); gboolean gvc_mixer_stream_change_port (GvcMixerStream *stream, const char *port); pa_volume_t gvc_mixer_stream_get_volume (GvcMixerStream *stream); gdouble gvc_mixer_stream_get_decibel (GvcMixerStream *stream); gboolean gvc_mixer_stream_push_volume (GvcMixerStream *stream); pa_volume_t gvc_mixer_stream_get_base_volume (GvcMixerStream *stream); gboolean gvc_mixer_stream_get_is_muted (GvcMixerStream *stream); gboolean gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream); gboolean gvc_mixer_stream_change_is_muted (GvcMixerStream *stream, gboolean is_muted); gboolean gvc_mixer_stream_is_running (GvcMixerStream *stream); const char * gvc_mixer_stream_get_name (GvcMixerStream *stream); const char * gvc_mixer_stream_get_icon_name (GvcMixerStream *stream); const char * gvc_mixer_stream_get_form_factor (GvcMixerStream *stream); const char * gvc_mixer_stream_get_sysfs_path (GvcMixerStream *stream); GIcon * gvc_mixer_stream_get_gicon (GvcMixerStream *stream); const char * gvc_mixer_stream_get_description (GvcMixerStream *stream); const char * gvc_mixer_stream_get_application_id (GvcMixerStream *stream); gboolean gvc_mixer_stream_is_event_stream (GvcMixerStream *stream); gboolean gvc_mixer_stream_is_virtual (GvcMixerStream *stream); gint gvc_mixer_stream_get_card_index (GvcMixerStream *stream); /* private */ gboolean gvc_mixer_stream_set_volume (GvcMixerStream *stream, pa_volume_t volume); gboolean gvc_mixer_stream_set_decibel (GvcMixerStream *stream, gdouble db); gboolean gvc_mixer_stream_set_is_muted (GvcMixerStream *stream, gboolean is_muted); gboolean gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream, gboolean can_decibel); gboolean gvc_mixer_stream_set_name (GvcMixerStream *stream, const char *name); gboolean gvc_mixer_stream_set_description (GvcMixerStream *stream, const char *description); gboolean gvc_mixer_stream_set_icon_name (GvcMixerStream *stream, const char *name); gboolean gvc_mixer_stream_set_form_factor (GvcMixerStream *stream, const char *form_factor); gboolean gvc_mixer_stream_set_sysfs_path (GvcMixerStream *stream, const char *sysfs_path); gboolean gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream, gboolean is_event_stream); gboolean gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream, gboolean is_event_stream); gboolean gvc_mixer_stream_set_application_id (GvcMixerStream *stream, const char *application_id); gboolean gvc_mixer_stream_set_base_volume (GvcMixerStream *stream, pa_volume_t base_volume); gboolean gvc_mixer_stream_set_port (GvcMixerStream *stream, const char *port); gboolean gvc_mixer_stream_set_ports (GvcMixerStream *stream, GList *ports); gboolean gvc_mixer_stream_set_card_index (GvcMixerStream *stream, gint card_index); G_END_DECLS #endif /* __GVC_MIXER_STREAM_H */ unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-ui-device.c0000664000000000000000000006025615172222611022432 0ustar /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * gvc-mixer-ui-device.c * Copyright (C) Conor Curran 2011 * Copyright (C) 2012 David Henningsson, Canonical Ltd. * * gvc-mixer-ui-device.c is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * gvc-mixer-ui-device.c is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "gvc-mixer-ui-device.h" #include "gvc-mixer-card.h" #define GVC_MIXER_UI_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDevicePrivate)) struct GvcMixerUIDevicePrivate { gchar *first_line_desc; gchar *second_line_desc; GvcMixerCard *card; gchar *port_name; gint stream_id; guint id; gboolean port_available; /* These two lists contain pointers to GvcMixerCardProfile objects. Those objects are owned by GvcMixerCard. * * TODO: Do we want to add a weak reference to the GvcMixerCard for this reason? */ GList *supported_profiles; /* all profiles supported by this port.*/ GList *profiles; /* profiles to be added to combobox, subset of supported_profiles. */ GvcMixerUIDeviceDirection type; gboolean disable_profile_swapping; gchar *user_preferred_profile; }; enum { PROP_0, PROP_DESC_LINE_1, PROP_DESC_LINE_2, PROP_CARD, PROP_PORT_NAME, PROP_STREAM_ID, PROP_UI_DEVICE_TYPE, PROP_PORT_AVAILABLE, }; static void gvc_mixer_ui_device_class_init (GvcMixerUIDeviceClass *klass); static void gvc_mixer_ui_device_init (GvcMixerUIDevice *device); static void gvc_mixer_ui_device_finalize (GObject *object); G_DEFINE_TYPE (GvcMixerUIDevice, gvc_mixer_ui_device, G_TYPE_OBJECT); static guint32 get_next_output_serial (void) { static guint32 output_serial = 1; guint32 serial; serial = output_serial++; if ((gint32)output_serial < 0) output_serial = 1; return serial; } static void gvc_mixer_ui_device_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GvcMixerUIDevice *self = GVC_MIXER_UI_DEVICE (object); switch (property_id) { case PROP_DESC_LINE_1: g_value_set_string (value, self->priv->first_line_desc); break; case PROP_DESC_LINE_2: g_value_set_string (value, self->priv->second_line_desc); break; case PROP_CARD: g_value_set_pointer (value, self->priv->card); break; case PROP_PORT_NAME: g_value_set_string (value, self->priv->port_name); break; case PROP_STREAM_ID: g_value_set_int (value, self->priv->stream_id); break; case PROP_UI_DEVICE_TYPE: g_value_set_uint (value, (guint)self->priv->type); break; case PROP_PORT_AVAILABLE: g_value_set_boolean (value, self->priv->port_available); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gvc_mixer_ui_device_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GvcMixerUIDevice *self = GVC_MIXER_UI_DEVICE (object); switch (property_id) { case PROP_DESC_LINE_1: g_free (self->priv->first_line_desc); self->priv->first_line_desc = g_value_dup_string (value); g_debug ("gvc-mixer-output-set-property - 1st line: %s\n", self->priv->first_line_desc); break; case PROP_DESC_LINE_2: g_free (self->priv->second_line_desc); self->priv->second_line_desc = g_value_dup_string (value); g_debug ("gvc-mixer-output-set-property - 2nd line: %s\n", self->priv->second_line_desc); break; case PROP_CARD: self->priv->card = g_value_get_pointer (value); g_debug ("gvc-mixer-output-set-property - card: %p\n", self->priv->card); break; case PROP_PORT_NAME: g_free (self->priv->port_name); self->priv->port_name = g_value_dup_string (value); g_debug ("gvc-mixer-output-set-property - card port name: %s\n", self->priv->port_name); break; case PROP_STREAM_ID: self->priv->stream_id = g_value_get_int (value); g_debug ("gvc-mixer-output-set-property - sink/source id: %i\n", self->priv->stream_id); break; case PROP_UI_DEVICE_TYPE: self->priv->type = (GvcMixerUIDeviceDirection) g_value_get_uint (value); break; case PROP_PORT_AVAILABLE: self->priv->port_available = g_value_get_boolean (value); g_debug ("gvc-mixer-output-set-property - port available %i, value passed in %i \n", self->priv->port_available, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GObject * gvc_mixer_ui_device_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; GvcMixerUIDevice *self; object = G_OBJECT_CLASS (gvc_mixer_ui_device_parent_class)->constructor (type, n_construct_properties, construct_params); self = GVC_MIXER_UI_DEVICE (object); self->priv->id = get_next_output_serial (); self->priv->stream_id = GVC_MIXER_UI_DEVICE_INVALID; return object; } static void gvc_mixer_ui_device_init (GvcMixerUIDevice *device) { device->priv = GVC_MIXER_UI_DEVICE_GET_PRIVATE (device); } static void gvc_mixer_ui_device_dispose (GObject *object) { GvcMixerUIDevice *device; g_return_if_fail (object != NULL); g_return_if_fail (GVC_MIXER_UI_DEVICE (object)); device = GVC_MIXER_UI_DEVICE (object); g_clear_pointer (&device->priv->port_name, g_free); g_clear_pointer (&device->priv->first_line_desc, g_free); g_clear_pointer (&device->priv->second_line_desc, g_free); g_clear_pointer (&device->priv->profiles, g_list_free); g_clear_pointer (&device->priv->supported_profiles, g_list_free); g_clear_pointer (&device->priv->user_preferred_profile, g_free); G_OBJECT_CLASS (gvc_mixer_ui_device_parent_class)->dispose (object); } static void gvc_mixer_ui_device_finalize (GObject *object) { G_OBJECT_CLASS (gvc_mixer_ui_device_parent_class)->finalize (object); } static void gvc_mixer_ui_device_class_init (GvcMixerUIDeviceClass *klass) { GObjectClass* object_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; object_class->constructor = gvc_mixer_ui_device_constructor; object_class->dispose = gvc_mixer_ui_device_dispose; object_class->finalize = gvc_mixer_ui_device_finalize; object_class->set_property = gvc_mixer_ui_device_set_property; object_class->get_property = gvc_mixer_ui_device_get_property; pspec = g_param_spec_string ("description", "Description construct prop", "Set first line description", "no-name-set", G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_DESC_LINE_1, pspec); pspec = g_param_spec_string ("origin", "origin construct prop", "Set second line description name", "no-name-set", G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_DESC_LINE_2, pspec); pspec = g_param_spec_pointer ("card", "Card from pulse", "Set/Get card", G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_CARD, pspec); pspec = g_param_spec_string ("port-name", "port-name construct prop", "Set port-name", NULL, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_PORT_NAME, pspec); pspec = g_param_spec_int ("stream-id", "stream id assigned by gvc-stream", "Set/Get stream id", -1, G_MAXINT, GVC_MIXER_UI_DEVICE_INVALID, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_STREAM_ID, pspec); pspec = g_param_spec_uint ("type", "ui-device type", "determine whether its an input and output", 0, 1, 0, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_UI_DEVICE_TYPE, pspec); pspec = g_param_spec_boolean ("port-available", "available", "determine whether this port is available", FALSE, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_PORT_AVAILABLE, pspec); g_type_class_add_private (klass, sizeof (GvcMixerUIDevicePrivate)); } /* Removes the part of the string that starts with skip_prefix * ie. corresponding to the other direction. * Normally either "input:" or "output:" * * Example: if given the input string "output:hdmi-stereo+input:analog-stereo" and * skip_prefix "input:", the resulting string is "output:hdmi-stereo". * * The returned string must be freed with g_free(). */ static gchar * get_profile_canonical_name (const gchar *profile_name, const gchar *skip_prefix) { gchar *result = NULL; gchar **s; int i; /* optimisation for the simple case. */ if (strstr (profile_name, skip_prefix) == NULL) return g_strdup (profile_name); s = g_strsplit (profile_name, "+", 0); for (i = 0; i < g_strv_length (s); i++) { if (g_str_has_prefix (s[i], skip_prefix)) continue; if (result == NULL) result = g_strdup (s[i]); else { gchar *c = g_strdup_printf("%s+%s", result, s[i]); g_free(result); result = c; } } g_strfreev(s); if (!result) return g_strdup("off"); return result; } const gchar * gvc_mixer_ui_device_get_matching_profile (GvcMixerUIDevice *device, const gchar *profile) { gchar *skip_prefix = device->priv->type == UIDeviceInput ? "output:" : "input:"; gchar *target_cname = get_profile_canonical_name (profile, skip_prefix); GList *l; gchar *result = NULL; for (l = device->priv->profiles; l != NULL; l = l->next) { gchar *canonical_name; GvcMixerCardProfile* p = l->data; canonical_name = get_profile_canonical_name (p->profile, skip_prefix); if (strcmp (canonical_name, target_cname) == 0) result = p->profile; g_free (canonical_name); } g_free (target_cname); g_debug ("Matching profile for '%s' is '%s'", profile, result ? result : "(null)"); return result; } static void add_canonical_names_of_profiles (GvcMixerUIDevice *device, const GList *in_profiles, GHashTable *added_profiles, const gchar *skip_prefix, gboolean only_canonical) { const GList *l; for (l = in_profiles; l != NULL; l = l->next) { gchar *canonical_name; GvcMixerCardProfile* p = l->data; canonical_name = get_profile_canonical_name (p->profile, skip_prefix); g_debug ("The canonical name for '%s' is '%s'", p->profile, canonical_name); /* Have we already added the canonical version of this profile? */ if (g_hash_table_contains (added_profiles, canonical_name)) { g_free (canonical_name); continue; } if (only_canonical && strcmp (p->profile, canonical_name) != 0) { g_free (canonical_name); continue; } g_free (canonical_name); g_debug ("Adding profile to combobox: '%s' - '%s'", p->profile, p->human_profile); g_hash_table_insert (added_profiles, g_strdup (p->profile), p); device->priv->profiles = g_list_append (device->priv->profiles, p); } } /** * gvc_mixer_ui_device_set_profiles: * @in_profiles: (element-type Gvc.MixerCardProfile): a list of GvcMixerCardProfile * * Assigns value to * - device->priv->profiles (profiles to be added to combobox) * - device->priv->supported_profiles (all profiles of this port) * - device->priv->disable_profile_swapping (whether to show the combobox) * * This method attempts to reduce the list of profiles visible to the user by figuring out * from the context of that device (whether it's an input or an output) what profiles * actually provide an alternative. * * It does this by the following. * - It ignores off profiles. * - It takes the canonical name of the profile. That name is what you get when you * ignore the other direction. * - In the first iteration, it only adds the names of canonical profiles - i e * when the other side is turned off. * - Normally the first iteration covers all cases, but sometimes (e g bluetooth) * it doesn't, so add other profiles whose canonical name isn't already added * in a second iteration. */ void gvc_mixer_ui_device_set_profiles (GvcMixerUIDevice *device, const GList *in_profiles) { GHashTable *added_profiles; gchar *skip_prefix = device->priv->type == UIDeviceInput ? "output:" : "input:"; g_debug ("Set profiles for '%s'", gvc_mixer_ui_device_get_description(device)); if (in_profiles == NULL) return; device->priv->supported_profiles = g_list_copy ((GList*) in_profiles); added_profiles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* Run two iterations: First, add profiles which are canonical themselves, * Second, add profiles for which the canonical name is not added already. */ add_canonical_names_of_profiles(device, in_profiles, added_profiles, skip_prefix, TRUE); add_canonical_names_of_profiles(device, in_profiles, added_profiles, skip_prefix, FALSE); /* TODO: Consider adding the "Off" profile here */ device->priv->disable_profile_swapping = g_hash_table_size (added_profiles) <= 1; g_hash_table_destroy (added_profiles); } /** * gvc_mixer_ui_device_get_best_profile: * @selected: The selected profile or its canonical name or %NULL for any profile * @current: The currently selected profile * * Returns: (transfer none): a profile name, valid as long as the UI device profiles are. */ const gchar * gvc_mixer_ui_device_get_best_profile (GvcMixerUIDevice *device, const gchar *selected, const gchar *current) { GList *candidates, *l; const gchar *result; gchar *skip_prefix; gchar *canonical_name_selected; if (device->priv->type == UIDeviceInput) skip_prefix = "output:"; else skip_prefix = "input:"; /* First make a list of profiles acceptable to switch to */ canonical_name_selected = NULL; if (selected) canonical_name_selected = get_profile_canonical_name (selected, skip_prefix); candidates = NULL; for (l = device->priv->supported_profiles; l != NULL; l = l->next) { gchar *canonical_name; GvcMixerCardProfile* p = l->data; canonical_name = get_profile_canonical_name (p->profile, skip_prefix); if (!canonical_name_selected || strcmp (canonical_name, canonical_name_selected) == 0) { candidates = g_list_append (candidates, p); g_debug ("Candidate for profile switching: '%s'", p->profile); } } if (!candidates) { g_warning ("No suitable profile candidates for '%s'", selected ? selected : "(null)"); g_free (canonical_name_selected); return current; } /* 1) Maybe we can skip profile switching altogether? */ result = NULL; for (l = candidates; (result == NULL) && (l != NULL); l = l->next) { GvcMixerCardProfile* p = l->data; if (strcmp (current, p->profile) == 0) result = p->profile; } /* 2) Try to keep the other side unchanged if possible */ if (result == NULL) { guint prio = 0; gchar *skip_prefix_reverse = device->priv->type == UIDeviceInput ? "input:" : "output:"; gchar *current_reverse = get_profile_canonical_name (current, skip_prefix_reverse); for (l = candidates; l != NULL; l = l->next) { gchar *p_reverse; GvcMixerCardProfile* p = l->data; p_reverse = get_profile_canonical_name (p->profile, skip_prefix_reverse); g_debug ("Comparing '%s' (from '%s') with '%s', prio %d", p_reverse, p->profile, current_reverse, p->priority); if (strcmp (p_reverse, current_reverse) == 0 && (!result || p->priority > prio)) { result = p->profile; prio = p->priority; } g_free (p_reverse); } g_free (current_reverse); } /* 3) All right, let's just pick the profile with highest priority. * TODO: We could consider asking a GUI question if this stops streams * in the other direction */ if (result == NULL) { guint prio = 0; for (l = candidates; l != NULL; l = l->next) { GvcMixerCardProfile* p = l->data; if ((p->priority > prio) || !result) { result = p->profile; prio = p->priority; } } } g_list_free (candidates); g_free (canonical_name_selected); return result; } const gchar * gvc_mixer_ui_device_get_active_profile (GvcMixerUIDevice* device) { GvcMixerCardProfile *profile; g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); if (device->priv->card == NULL) { g_warning ("Device did not have an appropriate card"); return NULL; } profile = gvc_mixer_card_get_profile (device->priv->card); return gvc_mixer_ui_device_get_matching_profile (device, profile->profile); } gboolean gvc_mixer_ui_device_should_profiles_be_hidden (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE); return device->priv->disable_profile_swapping; } /** * gvc_mixer_ui_device_get_profiles: * @device: * * Returns: (transfer none) (element-type Gvc.MixerCardProfile): */ GList* gvc_mixer_ui_device_get_profiles (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); return device->priv->profiles; } /** * gvc_mixer_ui_device_get_supported_profiles: * @device: * * Returns: (transfer none) (element-type Gvc.MixerCardProfile): */ GList* gvc_mixer_ui_device_get_supported_profiles (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); return device->priv->supported_profiles; } guint gvc_mixer_ui_device_get_id (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), 0); return device->priv->id; } gint gvc_mixer_ui_device_get_stream_id (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), 0); return device->priv->stream_id; } void gvc_mixer_ui_device_invalidate_stream (GvcMixerUIDevice *self) { g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (self)); self->priv->stream_id = GVC_MIXER_UI_DEVICE_INVALID; } const gchar * gvc_mixer_ui_device_get_description (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); return device->priv->first_line_desc; } const gchar * gvc_mixer_ui_device_get_origin (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); return device->priv->second_line_desc; } const gchar* gvc_mixer_ui_device_get_user_preferred_profile (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); return device->priv->user_preferred_profile; } const gchar * gvc_mixer_ui_device_get_top_priority_profile (GvcMixerUIDevice *device) { GList *last; GvcMixerCardProfile *profile; g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); last = g_list_last (device->priv->supported_profiles); profile = last->data; return profile->profile; } void gvc_mixer_ui_device_set_user_preferred_profile (GvcMixerUIDevice *device, const gchar *profile) { g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (device)); g_free (device->priv->user_preferred_profile); device->priv->user_preferred_profile = g_strdup (profile); } const gchar * gvc_mixer_ui_device_get_port (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); return device->priv->port_name; } gboolean gvc_mixer_ui_device_has_ports (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE); return (device->priv->port_name != NULL); } gboolean gvc_mixer_ui_device_is_output (GvcMixerUIDevice *device) { g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE); return (device->priv->type == UIDeviceOutput); } unity-settings-daemon/plugins/media-keys/gvc/gvc-mixer-ui-device.h0000664000000000000000000001012715172222611022427 0ustar /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * Copyright (C) Conor Curran 2011 * * This is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * gvc-mixer-ui-device.h is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef _GVC_MIXER_UI_DEVICE_H_ #define _GVC_MIXER_UI_DEVICE_H_ #include G_BEGIN_DECLS #define GVC_TYPE_MIXER_UI_DEVICE (gvc_mixer_ui_device_get_type ()) #define GVC_MIXER_UI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDevice)) #define GVC_MIXER_UI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDeviceClass)) #define GVC_IS_MIXER_UI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVC_TYPE_MIXER_UI_DEVICE)) #define GVC_IS_MIXER_UI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVC_TYPE_MIXER_UI_DEVICE)) #define GVC_MIXER_UI_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDeviceClass)) #define GVC_MIXER_UI_DEVICE_INVALID -1 typedef struct GvcMixerUIDevicePrivate GvcMixerUIDevicePrivate; typedef struct { GObjectClass parent_class; } GvcMixerUIDeviceClass; typedef struct { GObject parent_instance; GvcMixerUIDevicePrivate *priv; } GvcMixerUIDevice; typedef enum { UIDeviceInput, UIDeviceOutput, } GvcMixerUIDeviceDirection; GType gvc_mixer_ui_device_get_type (void) G_GNUC_CONST; guint gvc_mixer_ui_device_get_id (GvcMixerUIDevice *device); gint gvc_mixer_ui_device_get_stream_id (GvcMixerUIDevice *device); const gchar * gvc_mixer_ui_device_get_description (GvcMixerUIDevice *device); const gchar * gvc_mixer_ui_device_get_origin (GvcMixerUIDevice *device); const gchar * gvc_mixer_ui_device_get_port (GvcMixerUIDevice *device); const gchar * gvc_mixer_ui_device_get_best_profile (GvcMixerUIDevice *device, const gchar *selected, const gchar *current); const gchar * gvc_mixer_ui_device_get_active_profile (GvcMixerUIDevice* device); const gchar * gvc_mixer_ui_device_get_matching_profile (GvcMixerUIDevice *device, const gchar *profile); const gchar * gvc_mixer_ui_device_get_user_preferred_profile (GvcMixerUIDevice *device); const gchar * gvc_mixer_ui_device_get_top_priority_profile (GvcMixerUIDevice *device); GList * gvc_mixer_ui_device_get_profiles (GvcMixerUIDevice *device); GList * gvc_mixer_ui_device_get_supported_profiles (GvcMixerUIDevice *device); gboolean gvc_mixer_ui_device_should_profiles_be_hidden (GvcMixerUIDevice *device); void gvc_mixer_ui_device_set_profiles (GvcMixerUIDevice *device, const GList *in_profiles); void gvc_mixer_ui_device_set_user_preferred_profile (GvcMixerUIDevice *device, const gchar *profile); void gvc_mixer_ui_device_invalidate_stream (GvcMixerUIDevice *device); gboolean gvc_mixer_ui_device_has_ports (GvcMixerUIDevice *device); gboolean gvc_mixer_ui_device_is_output (GvcMixerUIDevice *device); G_END_DECLS #endif /* _GVC_MIXER_UI_DEVICE_H_ */ unity-settings-daemon/plugins/media-keys/gvc/gvc-pulseaudio-fake.h0000664000000000000000000000216715172222611022516 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GVC_PULSEAUDIO_FAKE_H #define __GVC_PULSEAUDIO_FAKE_H #ifdef WITH_INTROSPECTION #ifndef PA_API_VERSION #define pa_channel_position_t int #define pa_volume_t guint32 #define pa_context gpointer #endif /* PA_API_VERSION */ #endif /* WITH_INTROSPECTION */ #endif /* __GVC_PULSEAUDIO_FAKE_H */ unity-settings-daemon/plugins/media-keys/media-keys.gnome-settings-plugin.in0000664000000000000000000000026115172222611024542 0ustar [GNOME Settings Plugin] Module=media-keys IAge=0 # Default Priority # Priority=100 _Name=Media keys _Description=Media keys plugin Authors= Copyright=Copyright © 2007 Website= unity-settings-daemon/plugins/media-keys/org.gnome.ShellKeyGrabber.xml0000664000000000000000000000147415172222611023354 0ustar unity-settings-daemon/plugins/media-keys/shell-keybinding-modes.h0000664000000000000000000000324315172222611022435 0ustar /** * ShellKeyBindingMode: * @SHELL_KEYBINDING_MODE_NONE: block keybinding * @SHELL_KEYBINDING_MODE_NORMAL: allow keybinding when in window mode, * e.g. when the focus is in an application window * @SHELL_KEYBINDING_MODE_OVERVIEW: allow keybinding while the overview * is active * @SHELL_KEYBINDING_MODE_LOCK_SCREEN: allow keybinding when the screen * is locked, e.g. when the screen shield is shown * @SHELL_KEYBINDING_MODE_UNLOCK_SCREEN: allow keybinding in the unlock * dialog * @SHELL_KEYBINDING_MODE_LOGIN_SCREEN: allow keybinding in the login screen * @SHELL_KEYBINDING_MODE_MESSAGE_TRAY: allow keybinding while the message * tray is popped up * @SHELL_KEYBINDING_MODE_SYSTEM_MODAL: allow keybinding when a system modal * dialog (e.g. authentification or session dialogs) is open * @SHELL_KEYBINDING_MODE_LOOKING_GLASS: allow keybinding in looking glass * @SHELL_KEYBINDING_MODE_TOPBAR_POPUP: allow keybinding while a top bar menu * is open * @SHELL_KEYBINDING_MODE_ALL: always allow keybinding * * Controls in which GNOME Shell states a keybinding should be handled. */ typedef enum { SHELL_KEYBINDING_MODE_NONE = 0, SHELL_KEYBINDING_MODE_NORMAL = 1 << 0, SHELL_KEYBINDING_MODE_OVERVIEW = 1 << 1, SHELL_KEYBINDING_MODE_LOCK_SCREEN = 1 << 2, SHELL_KEYBINDING_MODE_UNLOCK_SCREEN = 1 << 3, SHELL_KEYBINDING_MODE_LOGIN_SCREEN = 1 << 4, SHELL_KEYBINDING_MODE_MESSAGE_TRAY = 1 << 5, SHELL_KEYBINDING_MODE_SYSTEM_MODAL = 1 << 6, SHELL_KEYBINDING_MODE_LOOKING_GLASS = 1 << 7, SHELL_KEYBINDING_MODE_TOPBAR_POPUP = 1 << 8, SHELL_KEYBINDING_MODE_ALL = ~SHELL_KEYBINDING_MODE_NONE } ShellKeyBindingMode; unity-settings-daemon/plugins/media-keys/shortcuts-list.h0000664000000000000000000002340415172222611021110 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2001 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef __SHORTCUTS_LIST_H__ #define __SHORTCUTS_LIST_H__ #include "shell-keybinding-modes.h" #include "gsd-keygrab.h" #define SETTINGS_BINDING_DIR "com.canonical.unity.settings-daemon.plugins.media-keys" #define INPUT_SETTINGS_BINDING_DIR "org.gnome.desktop.wm.keybindings" typedef enum { TOUCHPAD_KEY, TOUCHPAD_ON_KEY, TOUCHPAD_OFF_KEY, MUTE_KEY, VOLUME_DOWN_KEY, VOLUME_UP_KEY, MUTE_QUIET_KEY, VOLUME_DOWN_QUIET_KEY, VOLUME_UP_QUIET_KEY, MIC_MUTE_KEY, LOGOUT_KEY, EJECT_KEY, HOME_KEY, MEDIA_KEY, CALCULATOR_KEY, SEARCH_KEY, EMAIL_KEY, SCREENSAVER_KEY, HELP_KEY, SCREENSHOT_KEY, WINDOW_SCREENSHOT_KEY, AREA_SCREENSHOT_KEY, SCREENSHOT_CLIP_KEY, WINDOW_SCREENSHOT_CLIP_KEY, AREA_SCREENSHOT_CLIP_KEY, TERMINAL_KEY, WWW_KEY, PLAY_KEY, PAUSE_KEY, STOP_KEY, PREVIOUS_KEY, NEXT_KEY, REWIND_KEY, FORWARD_KEY, REPEAT_KEY, RANDOM_KEY, VIDEO_OUT_KEY, ROTATE_VIDEO_KEY, MAGNIFIER_KEY, SCREENREADER_KEY, ON_SCREEN_KEYBOARD_KEY, INCREASE_TEXT_KEY, DECREASE_TEXT_KEY, TOGGLE_CONTRAST_KEY, MAGNIFIER_ZOOM_IN_KEY, MAGNIFIER_ZOOM_OUT_KEY, POWER_KEY, SLEEP_KEY, SUSPEND_KEY, HIBERNATE_KEY, POWER_KEY_NO_DIALOG, SLEEP_KEY_NO_DIALOG, SUSPEND_KEY_NO_DIALOG, HIBERNATE_KEY_NO_DIALOG, SCREEN_BRIGHTNESS_UP_KEY, SCREEN_BRIGHTNESS_DOWN_KEY, KEYBOARD_BRIGHTNESS_UP_KEY, KEYBOARD_BRIGHTNESS_DOWN_KEY, KEYBOARD_BRIGHTNESS_TOGGLE_KEY, BATTERY_KEY, SWITCH_INPUT_SOURCE_KEY, SWITCH_INPUT_SOURCE_BACKWARD_KEY, CUSTOM_KEY } MediaKeyType; #define GSD_KEYBINDING_MODE_LAUNCHER (SHELL_KEYBINDING_MODE_NORMAL | \ SHELL_KEYBINDING_MODE_OVERVIEW) #define SCREENSAVER_MODE SHELL_KEYBINDING_MODE_ALL & ~SHELL_KEYBINDING_MODE_UNLOCK_SCREEN #define POWER_KEYS_MODE (SHELL_KEYBINDING_MODE_NORMAL | \ SHELL_KEYBINDING_MODE_OVERVIEW | \ SHELL_KEYBINDING_MODE_LOGIN_SCREEN) #define POWER_KEYS_MODE_NO_DIALOG (SHELL_KEYBINDING_MODE_LOCK_SCREEN | \ SHELL_KEYBINDING_MODE_UNLOCK_SCREEN) static struct { MediaKeyType key_type; const char *settings_key; const char *key_name; const char *hard_coded; ShellKeyBindingMode modes; } media_keys[] = { { TOUCHPAD_KEY, NULL, N_("Touchpad toggle") ,"XF86TouchpadToggle", SHELL_KEYBINDING_MODE_ALL }, { TOUCHPAD_ON_KEY, NULL, N_("Touchpad On"), "XF86TouchpadOn", SHELL_KEYBINDING_MODE_ALL }, { TOUCHPAD_OFF_KEY, NULL, N_("Touchpad Off"), "XF86TouchpadOff", SHELL_KEYBINDING_MODE_ALL }, { MUTE_KEY, "volume-mute", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { VOLUME_DOWN_KEY, "volume-down", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { VOLUME_UP_KEY, "volume-up", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { MIC_MUTE_KEY, NULL, N_("Microphone Mute"), "F20", SHELL_KEYBINDING_MODE_ALL }, { MIC_MUTE_KEY, NULL, N_("Microphone Mute"), "XF86AudioMicMute", SHELL_KEYBINDING_MODE_ALL }, { MUTE_QUIET_KEY, NULL, N_("Quiet Volume Mute"), "XF86AudioMute", SHELL_KEYBINDING_MODE_ALL }, { VOLUME_DOWN_QUIET_KEY, NULL, N_("Quiet Volume Down"), "XF86AudioLowerVolume", SHELL_KEYBINDING_MODE_ALL }, { VOLUME_UP_QUIET_KEY, NULL, N_("Quiet Volume Up"), "XF86AudioRaiseVolume", SHELL_KEYBINDING_MODE_ALL }, { LOGOUT_KEY, "logout", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { EJECT_KEY, "eject", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { HOME_KEY, "home", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { MEDIA_KEY, "media", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { CALCULATOR_KEY, "calculator", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { SEARCH_KEY, "search", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { EMAIL_KEY, "email", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { SCREENSAVER_KEY, "screensaver", NULL, NULL, SCREENSAVER_MODE }, { SCREENSAVER_KEY, NULL, N_("Lock Screen"), "XF86ScreenSaver", SCREENSAVER_MODE }, { HELP_KEY, "help", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { SCREENSHOT_KEY, "screenshot", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { WINDOW_SCREENSHOT_KEY, "window-screenshot", NULL, NULL, SHELL_KEYBINDING_MODE_NORMAL }, { AREA_SCREENSHOT_KEY, "area-screenshot", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { SCREENSHOT_CLIP_KEY, "screenshot-clip", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { WINDOW_SCREENSHOT_CLIP_KEY, "window-screenshot-clip", NULL, NULL, SHELL_KEYBINDING_MODE_NORMAL }, { AREA_SCREENSHOT_CLIP_KEY, "area-screenshot-clip", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { TERMINAL_KEY, "terminal", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { WWW_KEY, "www", NULL, NULL, GSD_KEYBINDING_MODE_LAUNCHER }, { PLAY_KEY, "play", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { PAUSE_KEY, "pause", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { STOP_KEY, "stop", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { PREVIOUS_KEY, "previous", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { NEXT_KEY, "next", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { REWIND_KEY, NULL, N_("Rewind"), "XF86AudioRewind", SHELL_KEYBINDING_MODE_ALL }, { FORWARD_KEY, NULL, N_("Forward"), "XF86AudioForward", SHELL_KEYBINDING_MODE_ALL }, { REPEAT_KEY, NULL, N_("Repeat"), "XF86AudioRepeat", SHELL_KEYBINDING_MODE_ALL }, { RANDOM_KEY, NULL, N_("Random Play"), "XF86AudioRandomPlay", SHELL_KEYBINDING_MODE_ALL }, { VIDEO_OUT_KEY, NULL, N_("Video Out"), "p", SHELL_KEYBINDING_MODE_ALL }, /* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */ { VIDEO_OUT_KEY, NULL, N_("Video Out"), "XF86Display", SHELL_KEYBINDING_MODE_ALL }, /* Key code of the XF86RotateWindows key (present on some tablets) */ { ROTATE_VIDEO_KEY, NULL, N_("Rotate Screen"), "XF86RotateWindows", SHELL_KEYBINDING_MODE_NORMAL }, { MAGNIFIER_KEY, "magnifier", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { SCREENREADER_KEY, "screenreader", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { ON_SCREEN_KEYBOARD_KEY, "on-screen-keyboard", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { INCREASE_TEXT_KEY, "increase-text-size", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { DECREASE_TEXT_KEY, "decrease-text-size", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { TOGGLE_CONTRAST_KEY, "toggle-contrast", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { MAGNIFIER_ZOOM_IN_KEY, "magnifier-zoom-in", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { MAGNIFIER_ZOOM_OUT_KEY, "magnifier-zoom-out", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { POWER_KEY, NULL, N_("Power Off"), "XF86PowerOff", POWER_KEYS_MODE }, /* the kernel / Xorg names really are like this... */ /* translators: "Sleep" means putting the machine to sleep, either through hibernate or suspend */ { SLEEP_KEY, NULL, N_("Sleep"), "XF86Suspend", POWER_KEYS_MODE }, { SUSPEND_KEY, NULL, N_("Suspend"), "XF86Sleep", POWER_KEYS_MODE }, { HIBERNATE_KEY, NULL, N_("Hibernate"), "XF86Hibernate", POWER_KEYS_MODE }, { POWER_KEY_NO_DIALOG, NULL, N_("Power Off"), "XF86PowerOff", POWER_KEYS_MODE_NO_DIALOG }, /* the kernel / Xorg names really are like this... */ /* translators: "Sleep" means putting the machine to sleep, either through hibernate or suspend */ { SLEEP_KEY_NO_DIALOG, NULL, N_("Sleep"), "XF86Suspend", POWER_KEYS_MODE_NO_DIALOG }, { SUSPEND_KEY_NO_DIALOG, NULL, N_("Suspend"), "XF86Sleep", POWER_KEYS_MODE_NO_DIALOG }, { HIBERNATE_KEY_NO_DIALOG, NULL, N_("Hibernate"), "XF86Hibernate", POWER_KEYS_MODE_NO_DIALOG }, { SCREEN_BRIGHTNESS_UP_KEY, NULL, N_("Brightness Up"), "XF86MonBrightnessUp", SHELL_KEYBINDING_MODE_ALL }, { SCREEN_BRIGHTNESS_DOWN_KEY, NULL, N_("Brightness Down"), "XF86MonBrightnessDown", SHELL_KEYBINDING_MODE_ALL }, { KEYBOARD_BRIGHTNESS_UP_KEY, NULL, N_("Keyboard Brightness Up"), "XF86KbdBrightnessUp", SHELL_KEYBINDING_MODE_ALL }, { KEYBOARD_BRIGHTNESS_DOWN_KEY, NULL, N_("Keyboard Brightness Down"), "XF86KbdBrightnessDown", SHELL_KEYBINDING_MODE_ALL }, { KEYBOARD_BRIGHTNESS_TOGGLE_KEY, NULL, N_("Keyboard Brightness Toggle"), "XF86KbdLightOnOff", SHELL_KEYBINDING_MODE_ALL }, { BATTERY_KEY, NULL, N_("Battery Status"), "XF86Battery", GSD_KEYBINDING_MODE_LAUNCHER }, { SWITCH_INPUT_SOURCE_KEY, "switch-input-source", NULL, NULL, SHELL_KEYBINDING_MODE_ALL }, { SWITCH_INPUT_SOURCE_BACKWARD_KEY, "switch-input-source-backward", NULL, NULL, SHELL_KEYBINDING_MODE_ALL } }; #undef SCREENSAVER_MODE #endif /* __SHORTCUTS_LIST_H__ */ unity-settings-daemon/plugins/media-keys/test-media-keys.c0000664000000000000000000000033515172222611021077 0ustar #define NEW gsd_media_keys_manager_new #define START gsd_media_keys_manager_start #define STOP gsd_media_keys_manager_stop #define MANAGER GsdMediaKeysManager #include "gsd-media-keys-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/media-keys/what-did-you-plug-in/0000775000000000000000000000000015172222611021611 5ustar unity-settings-daemon/plugins/media-keys/what-did-you-plug-in/dialog-window.c0000664000000000000000000001130115172222611024515 0ustar #include #include #include #include #include #include "dialog-window.h" typedef struct dialog_window { GtkWidget *dialog; GtkWidget *ca_box; GtkWidget *v_box; GtkWidget *icon_box; GtkWidget *btn_box; GtkWidget *label; GtkWidget *cancel_btn; GtkWidget *settings_btn; GtkWidget *hp_btn; GtkWidget *hs_btn; GtkWidget *mic_btn; int button_response; wdypi_dialog_cb cb; void *cb_userdata; } dialog_window; /* It's okay to have a global here - we should never show more than one dialog */ dialog_window dlg; void wdypi_dialog_kill() { dialog_window *d = &dlg; if (d->dialog) { gtk_widget_destroy(d->dialog); d->dialog = NULL; } } static void on_iconbtn_clicked (GtkWidget *widget, gpointer data) { dialog_window *d = &dlg; d->button_response = (ssize_t) data; gtk_dialog_response(GTK_DIALOG(d->dialog), GTK_RESPONSE_OK); } static void on_response (GtkWidget *widget, gint response_id, gpointer data) { int resp; dialog_window *d = data; if (!d->cb) return; switch (response_id) { case GTK_RESPONSE_YES: resp = WDYPI_DIALOG_SOUND_SETTINGS; break; case GTK_RESPONSE_OK: resp = d->button_response; break; default: resp = WDYPI_DIALOG_CANCELLED; } d->cb(resp, d->cb_userdata); wdypi_dialog_kill(); } static GtkWidget * create_icon_button(int response, const char *name, const char *icon) { GtkWidget *btn = gtk_button_new(); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); GtkWidget *lbl = gtk_label_new(name); GtkWidget *img = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_DIALOG); gtk_box_pack_end(GTK_BOX(box), lbl, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(box), img, FALSE, FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(box), 6); gtk_container_add(GTK_CONTAINER(btn), box); g_signal_connect(btn, "clicked", G_CALLBACK(on_iconbtn_clicked), (void*) (ssize_t) response); return btn; } static void dialog_create(dialog_window *d, bool show_headset, bool show_mic) { guint32 timestamp; d->dialog = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(d->dialog), _("Unknown Audio Device")); gtk_container_set_border_width(GTK_CONTAINER(d->dialog), 6); gtk_window_set_icon_name(GTK_WINDOW(d->dialog), "audio-headphones"); gtk_window_set_resizable(GTK_WINDOW(d->dialog), FALSE); d->ca_box = gtk_dialog_get_content_area(GTK_DIALOG(d->dialog)); d->v_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_container_set_border_width(GTK_CONTAINER(d->v_box), 5); d->icon_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_set_homogeneous(GTK_BOX(d->icon_box), TRUE); d->label = gtk_label_new(_("What kind of device did you plug in?")); gtk_misc_set_alignment(GTK_MISC(d->label), 0.5, 0.5); gtk_box_pack_start(GTK_BOX(d->v_box), d->label, FALSE, FALSE, 6); d->hp_btn = create_icon_button(WDYPI_DIALOG_HEADPHONES, _("Headphones"), "audio-headphones"); gtk_box_pack_start(GTK_BOX(d->icon_box), d->hp_btn, FALSE, TRUE, 0); if (show_headset) { d->hs_btn = create_icon_button(WDYPI_DIALOG_HEADSET, _("Headset"), "audio-headset"); gtk_box_pack_start(GTK_BOX(d->icon_box), d->hs_btn, FALSE, TRUE, 0); } if (show_mic) { d->mic_btn = create_icon_button(WDYPI_DIALOG_MICROPHONE, _("Microphone"), "audio-input-microphone"); gtk_box_pack_start(GTK_BOX(d->icon_box), d->mic_btn, FALSE, TRUE, 0); } gtk_box_pack_start(GTK_BOX(d->v_box), d->icon_box, FALSE, FALSE, 6); d->cancel_btn = gtk_dialog_add_button(GTK_DIALOG(d->dialog), _("Cancel"), GTK_RESPONSE_CANCEL); d->settings_btn = gtk_dialog_add_button(GTK_DIALOG(d->dialog), _("Sound Settings…"), GTK_RESPONSE_YES); gtk_container_add(GTK_CONTAINER(d->ca_box), d->v_box); g_signal_connect(d->dialog, "response", G_CALLBACK(on_response), d); gtk_widget_show_all(d->dialog); /* This event did not originate from a pointer or key movement, so we can't use GDK_CURRENT_TIME (or just gtk_window_present) here. There is also no other source timestamp to rely on. Without a timestamp, the dialog would often show up behind other windows. */ timestamp = gdk_x11_get_server_time(gtk_widget_get_window(GTK_WIDGET(d->dialog))); gtk_window_present_with_time(GTK_WINDOW(d->dialog), timestamp); } void wdypi_dialog_run(bool show_headset, bool show_mic, wdypi_dialog_cb cb, void *cb_userdata) { dialog_window *d = &dlg; wdypi_dialog_kill(); d->cb = cb; d->cb_userdata = cb_userdata; dialog_create(d, show_headset, show_mic); } unity-settings-daemon/plugins/media-keys/what-did-you-plug-in/dialog-window.h0000664000000000000000000000067515172222611024536 0ustar #ifndef __DIALOG_WINDOW_H__ #define __DIALOG_WINDOW_H__ #include #define WDYPI_DIALOG_CANCELLED 0 #define WDYPI_DIALOG_HEADPHONES 1 #define WDYPI_DIALOG_HEADSET 2 #define WDYPI_DIALOG_MICROPHONE 3 #define WDYPI_DIALOG_SOUND_SETTINGS 4 typedef void (*wdypi_dialog_cb)(int response, void *userdata); void wdypi_dialog_run(bool show_headset, bool show_mic, wdypi_dialog_cb cb, void *cb_userdata); void wdypi_dialog_kill(); #endif unity-settings-daemon/plugins/media-keys/what-did-you-plug-in/pa-backend.c0000664000000000000000000001644615172222611023755 0ustar #include #include #include #include #include #include #include "pa-backend.h" struct pa_backend { const pa_context *context; pa_backend_cb dialog_cb; void *cb_userdata; int headset_card; bool headset_plugged_in; bool has_headsetmic; bool has_headphonemic; const char *sink_port_name_to_set; const char *source_port_name_to_set; }; void pa_backend_set_context(pa_backend *p, const pa_context *c) { p->context = c; } pa_backend *pa_backend_new(pa_backend_cb cb, void *cb_userdata) { pa_backend *p = calloc(1, sizeof(*p)); if (!p) return NULL; p->headset_card = -1; p->dialog_cb = cb; p->cb_userdata = cb_userdata; return p; } typedef struct headset_ports { const pa_card_port_info *headphones, *headsetmic, *headphonemic; } headset_ports; /* TODO: Check if we still need this with the changed PA port names In PulseAudio ports will show up with the following names: Headphones - analog-output-headphones Headset mic - analog-input-headset-mic (was: analog-input-microphone-headset) Jack in mic-in mode - analog-input-headphone-mic (was: analog-input-microphone) However, since regular mics also show up as analog-input-microphone, we need to check for certain controls on alsa mixer level too, to know if we deal with a separate mic jack, or a multi-function jack with a mic-in mode (also called "headphone mic"). We check for the following names: Headphone Mic Jack - indicates headphone and mic-in mode share the same jack, i e, not two separate jacks. Hardware cannot distinguish between a headphone and a mic. Headset Mic Phantom Jack - indicates headset jack where hardware can not distinguish between headphones and headsets Headset Mic Jack - indicates headset jack where hardware can distinguish between headphones and headsets. There is no use popping up a dialog in this case, unless we already need to do this for the mic-in mode. */ static headset_ports get_headset_ports(const pa_card_info *c) { headset_ports h = {NULL, NULL, NULL}; int i; for (i = 0; i < c->n_ports; i++) { pa_card_port_info *p = c->ports[i]; if (!strcmp(p->name, "analog-output-headphones")) h.headphones = p; else if (!strcmp(p->name, "analog-input-headset-mic")) h.headsetmic = p; else if (!strcmp(p->name, "analog-input-headphone-mic")) h.headphonemic = p; } return h; } static bool verify_alsa_card(int cardindex, bool *headsetmic, bool *headphonemic) { char ctlstr[20]; snd_hctl_t *hctl; snd_ctl_elem_id_t *id; int err; *headsetmic = false; *headphonemic = false; snprintf(ctlstr, sizeof(ctlstr), "hw:%i", cardindex); if ((err = snd_hctl_open(&hctl, ctlstr, 0)) < 0) { g_warning("snd_hctl_open failed: %s", snd_strerror(err)); return false; } if ((err = snd_hctl_load(hctl)) < 0) { g_warning("snd_hctl_load failed: %s", snd_strerror(err)); snd_hctl_close(hctl); return false; } snd_ctl_elem_id_alloca(&id); snd_ctl_elem_id_clear(id); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD); snd_ctl_elem_id_set_name(id, "Headphone Mic Jack"); if (snd_hctl_find_elem(hctl, id)) *headphonemic = true; snd_ctl_elem_id_clear(id); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD); snd_ctl_elem_id_set_name(id, "Headset Mic Phantom Jack"); if (snd_hctl_find_elem(hctl, id)) *headsetmic = true; if (*headphonemic) { snd_ctl_elem_id_clear(id); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD); snd_ctl_elem_id_set_name(id, "Headset Mic Jack"); if (snd_hctl_find_elem(hctl, id)) *headsetmic = true; } snd_hctl_close(hctl); return *headsetmic || *headphonemic; } void pa_backend_card_changed(pa_backend *p, const pa_card_info *i) { headset_ports h; bool start_dialog = false, stop_dialog = false; h = get_headset_ports(i); if (!h.headphones || (!h.headsetmic && !h.headphonemic)) return; /* Not a headset jack */ if (p->headset_card != (int) i->index) { int cardindex = 0; bool hsmic, hpmic; const char *s = pa_proplist_gets(i->proplist, "alsa.card"); if (!s) return; cardindex = strtol(s, NULL, 10); if (cardindex == 0 && strcmp(s, "0")) return; if (!verify_alsa_card(cardindex, &hsmic, &hpmic)) return; p->headset_card = (int) i->index; p->has_headsetmic = hsmic && h.headsetmic; p->has_headphonemic = hpmic && h.headphonemic; } else { start_dialog = p->dialog_cb && (h.headphones->available != PA_PORT_AVAILABLE_NO) && !p->headset_plugged_in; stop_dialog = p->dialog_cb && (h.headphones->available == PA_PORT_AVAILABLE_NO) && p->headset_plugged_in; } p->headset_plugged_in = h.headphones->available != PA_PORT_AVAILABLE_NO; if (start_dialog) p->dialog_cb(p->has_headsetmic, p->has_headphonemic, p->cb_userdata); else if (stop_dialog) p->dialog_cb(false, false, p->cb_userdata); } /* We need to re-enumerate sources and sinks every time the user makes a choice, because they can change due to use interaction in other software (or policy changes inside PulseAudio). Enumeration means PulseAudio will do a series of callbacks, one for every source/sink. Set the port when we find the correct source/sink. */ static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) { pa_backend *p = userdata; pa_operation *o; int j; const char *s = p->sink_port_name_to_set; if (eol) return; if (i->card != p->headset_card) return; if (i->active_port && !strcmp(i->active_port->name, s)) return; for (j = 0; j < i->n_ports; j++) if (!strcmp(i->ports[j]->name, s)) break; if (j >= i->n_ports) return; o = pa_context_set_sink_port_by_index(c, i->index, s, NULL, NULL); if (o) pa_operation_unref(o); } static void source_info_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata) { pa_backend *p = userdata; pa_operation *o; int j; const char *s = p->source_port_name_to_set; if (eol) return; if (i->card != p->headset_card) return; if (i->active_port && !strcmp(i->active_port->name, s)) return; for (j = 0; j < i->n_ports; j++) if (!strcmp(i->ports[j]->name, s)) break; if (j >= i->n_ports) return; o = pa_context_set_source_port_by_index(c, i->index, s, NULL, NULL); if (o) pa_operation_unref(o); } void pa_backend_set_port(pa_backend *p, const char *portname, bool is_output) { pa_operation *o; if (is_output) { p->sink_port_name_to_set = portname; o = pa_context_get_sink_info_list(p->context, sink_info_cb, p); } else { p->source_port_name_to_set = portname; o = pa_context_get_source_info_list(p->context, source_info_cb, p); } if (o) { pa_operation_unref(o); } } void pa_backend_free(pa_backend *p) { if (!p) return; free(p); } unity-settings-daemon/plugins/media-keys/what-did-you-plug-in/pa-backend.h0000664000000000000000000000105115172222611023744 0ustar #ifndef __PA_BACKEND_H__ #define __PA_BACKEND_H__ #include #include typedef struct pa_backend pa_backend; typedef void (*pa_backend_cb)(bool headsetmic, bool headphonemic, void *userdata); pa_backend *pa_backend_new(pa_backend_cb cb, void *cb_userdata); void pa_backend_free(pa_backend *p); void pa_backend_card_changed(pa_backend *p, const pa_card_info *i); void pa_backend_set_context(pa_backend *p, const pa_context *c); void pa_backend_set_port(pa_backend *p, const char *portname, bool is_output); #endif unity-settings-daemon/plugins/mouse/0000775000000000000000000000000015172222611015025 5ustar unity-settings-daemon/plugins/mouse/Makefile.am0000664000000000000000000000374115172222611017066 0ustar plugin_name = mouse plugin_LTLIBRARIES = libmouse.la libmouse_la_SOURCES = \ gsd-mouse-plugin.c \ gsd-mouse-manager.h \ gsd-mouse-manager.c libmouse_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common/ \ -I$(top_srcdir)/data/ \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) libmouse_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(MOUSE_CFLAGS) \ $(AM_CFLAGS) libmouse_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libmouse_la_LIBADD = \ $(MOUSE_LIBS) \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = mouse.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) libexec_PROGRAMS = usd-locate-pointer usd_locate_pointer_SOURCES = \ gsd-locate-pointer.h \ gsd-locate-pointer.c \ gsd-timeline.h \ gsd-timeline.c usd_locate_pointer_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(MOUSE_CFLAGS) \ $(AM_CFLAGS) usd_locate_pointer_LDADD = \ $(SETTINGS_PLUGIN_LIBS) \ $(MOUSE_LIBS) \ -lm libexec_PROGRAMS += usd-test-mouse usd_test_mouse_SOURCES = \ test-mouse.c \ gsd-mouse-manager.c \ gsd-mouse-manager.h usd_test_mouse_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) usd_test_mouse_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(MOUSE_CFLAGS) \ $(AM_CFLAGS) usd_test_mouse_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(MOUSE_LIBS) \ -lm EXTRA_DIST = $(plugin_in_files) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/mouse/gsd-locate-pointer.c0000664000000000000000000003572015172222611020700 0ustar /* gsd-locate-pointer.c * * Copyright (C) 2008 Carlos Garnacho * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include "gsd-timeline.h" #include "gsd-locate-pointer.h" #include #include #include #define ANIMATION_LENGTH 750 #define WINDOW_SIZE 101 #define N_CIRCLES 4 /* All circles are supposed to be moving when progress * reaches 0.5, and each of them are supposed to long * for half of the progress, hence the need of 0.5 to * get the circles interval, and the multiplication * by 2 to know a circle progress */ #define CIRCLES_PROGRESS_INTERVAL (0.5 / N_CIRCLES) #define CIRCLE_PROGRESS(p) (MIN (1., ((gdouble) (p) * 2.))) typedef struct GsdLocatePointerData GsdLocatePointerData; struct GsdLocatePointerData { GsdTimeline *timeline; GtkWidget *widget; GdkWindow *window; gdouble progress; }; static GsdLocatePointerData *data = NULL; static void locate_pointer_paint (GsdLocatePointerData *data, cairo_t *cr, gboolean composite) { GdkRGBA color; gdouble progress, circle_progress; gint width, height, i; GtkStyleContext *context; progress = data->progress; width = gdk_window_get_width (data->window); height = gdk_window_get_height (data->window); context = gtk_widget_get_style_context (data->widget); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED, &color); cairo_set_source_rgba (cr, 1., 1., 1., 0.); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); for (i = 0; i <= N_CIRCLES; i++) { if (progress < 0.) break; circle_progress = MIN (1., (progress * 2)); progress -= CIRCLES_PROGRESS_INTERVAL; if (circle_progress >= 1.) continue; if (composite) { cairo_set_source_rgba (cr, color.red, color.green, color.blue, 1 - circle_progress); cairo_arc (cr, width / 2, height / 2, circle_progress * width / 2, 0, 2 * G_PI); cairo_fill (cr); } else { cairo_set_source_rgb (cr, 0., 0., 0.); cairo_set_line_width (cr, 3.); cairo_arc (cr, width / 2, height / 2, circle_progress * width / 2, 0, 2 * G_PI); cairo_stroke (cr); cairo_set_source_rgb (cr, 1., 1., 1.); cairo_set_line_width (cr, 1.); cairo_arc (cr, width / 2, height / 2, circle_progress * width / 2, 0, 2 * G_PI); cairo_stroke (cr); } } } static gboolean locate_pointer_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data) { GsdLocatePointerData *data = (GsdLocatePointerData *) user_data; if (gtk_cairo_should_draw_window (cr, data->window)) locate_pointer_paint (data, cr, gtk_widget_is_composited (data->widget)); return TRUE; } static void update_shape (GsdLocatePointerData *data) { cairo_t *cr; cairo_region_t *region; cairo_surface_t *mask; mask = cairo_image_surface_create (CAIRO_FORMAT_A1, WINDOW_SIZE, WINDOW_SIZE); cr = cairo_create (mask); locate_pointer_paint (data, cr, FALSE); region = gdk_cairo_region_create_from_surface (mask); gdk_window_shape_combine_region (data->window, region, 0, 0); cairo_region_destroy (region); cairo_destroy (cr); cairo_surface_destroy (mask); } static void timeline_frame_cb (GsdTimeline *timeline, gdouble progress, gpointer user_data) { GsdLocatePointerData *data = (GsdLocatePointerData *) user_data; GdkScreen *screen; gint cursor_x, cursor_y; if (gtk_widget_is_composited (data->widget)) { gdk_window_invalidate_rect (data->window, NULL, FALSE); data->progress = progress; } else if (progress >= data->progress + CIRCLES_PROGRESS_INTERVAL) { /* only invalidate window each circle interval */ update_shape (data); gdk_window_invalidate_rect (data->window, NULL, FALSE); data->progress += CIRCLES_PROGRESS_INTERVAL; } screen = gdk_window_get_screen (data->window); gdk_window_get_pointer (gdk_screen_get_root_window (screen), &cursor_x, &cursor_y, NULL); gdk_window_move (data->window, cursor_x - WINDOW_SIZE / 2, cursor_y - WINDOW_SIZE / 2); } static void set_transparent_shape (GdkWindow *window) { cairo_region_t *region; region = cairo_region_create (); gdk_window_shape_combine_region (data->window, region, 0, 0); cairo_region_destroy (region); } static void unset_transparent_shape (GdkWindow *window) { gdk_window_shape_combine_region (data->window, NULL, 0, 0); } static void composited_changed (GtkWidget *widget, GsdLocatePointerData *data) { if (!gtk_widget_is_composited (widget)) set_transparent_shape (data->window); else unset_transparent_shape (data->window); } static void timeline_finished_cb (GsdTimeline *timeline, gpointer user_data) { GsdLocatePointerData *data = (GsdLocatePointerData *) user_data; /* set transparent shape and hide window */ if (!gtk_widget_is_composited (data->widget)) set_transparent_shape (data->window); gtk_widget_hide (data->widget); gdk_window_hide (data->window); } static void create_window (GsdLocatePointerData *data, GdkScreen *screen) { GdkVisual *visual; GdkWindowAttr attributes; gint attributes_mask; visual = gdk_screen_get_rgba_visual (screen); if (visual == NULL) visual = gdk_screen_get_system_visual (screen); attributes_mask = GDK_WA_X | GDK_WA_Y; if (visual != NULL) attributes_mask = attributes_mask | GDK_WA_VISUAL; attributes.window_type = GDK_WINDOW_TEMP; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = visual; attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK; attributes.width = 1; attributes.height = 1; data->window = gdk_window_new (gdk_screen_get_root_window (screen), &attributes, attributes_mask); gdk_window_set_user_data (data->window, data->widget); } static GsdLocatePointerData * gsd_locate_pointer_data_new (GdkScreen *screen) { GsdLocatePointerData *data; data = g_new0 (GsdLocatePointerData, 1); /* this widget will never be shown, it's * mainly used to get signals/events from */ data->widget = gtk_invisible_new (); gtk_widget_realize (data->widget); g_signal_connect (G_OBJECT (data->widget), "draw", G_CALLBACK (locate_pointer_draw), data); data->timeline = gsd_timeline_new (ANIMATION_LENGTH); g_signal_connect (data->timeline, "frame", G_CALLBACK (timeline_frame_cb), data); g_signal_connect (data->timeline, "finished", G_CALLBACK (timeline_finished_cb), data); create_window (data, screen); return data; } static void move_locate_pointer_window (GsdLocatePointerData *data, GdkScreen *screen) { cairo_region_t *region; gint cursor_x, cursor_y; gdk_window_get_pointer (gdk_screen_get_root_window (screen), &cursor_x, &cursor_y, NULL); gdk_window_move_resize (data->window, cursor_x - WINDOW_SIZE / 2, cursor_y - WINDOW_SIZE / 2, WINDOW_SIZE, WINDOW_SIZE); /* allow events to happen through the window */ region = cairo_region_create (); gdk_window_input_shape_combine_region (data->window, region, 0, 0); cairo_region_destroy (region); } void gsd_locate_pointer (GdkScreen *screen) { if (!data) data = gsd_locate_pointer_data_new (screen); gsd_timeline_pause (data->timeline); gsd_timeline_rewind (data->timeline); /* Create again the window if it is not for the current screen */ if (gdk_screen_get_number (screen) != gdk_screen_get_number (gdk_window_get_screen (data->window))) { gdk_window_set_user_data (data->window, NULL); gdk_window_destroy (data->window); create_window (data, screen); } data->progress = 0.; g_signal_connect (data->widget, "composited-changed", G_CALLBACK (composited_changed), data); move_locate_pointer_window (data, screen); composited_changed (data->widget, data); gdk_window_show (data->window); gtk_widget_show (data->widget); gsd_timeline_start (data->timeline); } #define KEYBOARD_GROUP_SHIFT 13 #define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14)) /* Owen magic */ static GdkFilterReturn filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) { XEvent *xev = (XEvent *) xevent; guint keyval; gint group; GdkScreen *screen = (GdkScreen *)data; if (xev->type == ButtonPress) { XAllowEvents (xev->xbutton.display, ReplayPointer, xev->xbutton.time); XUngrabButton (xev->xbutton.display, AnyButton, AnyModifier, xev->xbutton.window); XUngrabKeyboard (xev->xbutton.display, xev->xbutton.time); } if (xev->type == KeyPress || xev->type == KeyRelease) { /* get the keysym */ group = (xev->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT; gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), xev->xkey.keycode, xev->xkey.state, group, &keyval, NULL, NULL, NULL); if (keyval == GDK_KEY_Control_L || keyval == GDK_KEY_Control_R) { if (xev->type == KeyPress) { XAllowEvents (xev->xkey.display, SyncKeyboard, xev->xkey.time); XGrabButton (xev->xkey.display, AnyButton, AnyModifier, xev->xkey.window, False, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None); } else { XUngrabButton (xev->xkey.display, AnyButton, AnyModifier, xev->xkey.window); XAllowEvents (xev->xkey.display, AsyncKeyboard, xev->xkey.time); gsd_locate_pointer (screen); } } else { XAllowEvents (xev->xkey.display, ReplayKeyboard, xev->xkey.time); XUngrabButton (xev->xkey.display, AnyButton, AnyModifier, xev->xkey.window); XUngrabKeyboard (xev->xkey.display, xev->xkey.time); } } return GDK_FILTER_CONTINUE; } static void set_locate_pointer (void) { GdkKeymapKey *keys; GdkDisplay *display; int n_screens; int n_keys; gboolean has_entries; static const guint keyvals[] = { GDK_KEY_Control_L, GDK_KEY_Control_R }; unsigned j; display = gdk_display_get_default (); n_screens = gdk_display_get_n_screens (display); for (j = 0 ; j < G_N_ELEMENTS (keyvals) ; j++) { has_entries = gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), keyvals[j], &keys, &n_keys); if (has_entries) { gint i, j; for (i = 0; i < n_keys; i++) { for (j = 0; j < n_screens; j++) { GdkScreen *screen; Window xroot; screen = gdk_display_get_screen (display, j); xroot = gdk_x11_window_get_xid (gdk_screen_get_root_window (screen)); gdk_x11_display_error_trap_push (display); XGrabKey (GDK_DISPLAY_XDISPLAY (display), keys[i].keycode, 0, xroot, False, GrabModeAsync, GrabModeSync); XGrabKey (GDK_DISPLAY_XDISPLAY (display), keys[i].keycode, LockMask, xroot, False, GrabModeAsync, GrabModeSync); XGrabKey (GDK_DISPLAY_XDISPLAY (display), keys[i].keycode, Mod2Mask, xroot, False, GrabModeAsync, GrabModeSync); XGrabKey (GDK_DISPLAY_XDISPLAY (display), keys[i].keycode, Mod4Mask, xroot, False, GrabModeAsync, GrabModeSync); gdk_x11_display_error_trap_pop_ignored (display); } } g_free (keys); for (i = 0; i < n_screens; i++) { GdkScreen *screen; screen = gdk_display_get_screen (display, i); gdk_window_add_filter (gdk_screen_get_root_window (screen), filter, screen); } } } } int main (int argc, char *argv[]) { gdk_disable_multidevice (); gtk_init (&argc, &argv); set_locate_pointer (); gtk_main (); return 0; } unity-settings-daemon/plugins/mouse/gsd-locate-pointer.h0000664000000000000000000000153315172222611020700 0ustar /* * Copyright 2001 Jonathan Blandford * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Red Hat not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Red Hat makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * Authors: Jonathan Blandford */ #ifndef LOCATE_POINTER_H #define LOCATE_POINTER_H #include void gsd_locate_pointer (GdkScreen *screen); #endif unity-settings-daemon/plugins/mouse/gsd-mouse-manager.c0000664000000000000000000015230215172222611020507 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef __linux #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-profile.h" #include "gsd-mouse-manager.h" #include "gsd-input-helper.h" #include "gsd-enums.h" #include "gsd-settings-migrate.h" #define GSD_MOUSE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerPrivate)) #define GNOME_DESKTOP_INTERFACE_DIR "org.gnome.desktop.interface" #define GSETTINGS_MOUSE_SCHEMA "org.gnome.desktop.peripherals.mouse" #define GSETTINGS_TOUCHPAD_SCHEMA "org.gnome.desktop.peripherals.touchpad" #define USD_TOUCHPAD_SCHEMA "com.canonical.unity.settings-daemon.peripherals.touchpad" /* Keys for both touchpad and mouse */ #define KEY_LEFT_HANDED "left-handed" /* a boolean for mouse, an enum for touchpad */ #define KEY_SPEED "speed" /* Touchpad settings */ #define KEY_SCROLL_METHOD "scroll-method" #define KEY_TAP_TO_CLICK "tap-to-click" #define KEY_SEND_EVENTS "send-events" #define KEY_NATURAL_SCROLL_ENABLED "natural-scroll" /* Mouse settings */ #define KEY_LOCATE_POINTER "locate-pointer" #define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled" #define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled" struct GsdMouseManagerPrivate { guint start_idle_id; GSettings *touchpad_settings; GSettings *usd_touchpad_settings; GSettings *mouse_settings; GSettings *mouse_a11y_settings; GSettings *interface_settings; GdkDeviceManager *device_manager; guint device_added_id; guint device_removed_id; GHashTable *blacklist; gboolean mousetweaks_daemon_running; gboolean syndaemon_spawned; GPid syndaemon_pid; gboolean locate_pointer_spawned; GPid locate_pointer_pid; }; static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass); static void gsd_mouse_manager_init (GsdMouseManager *mouse_manager); static void gsd_mouse_manager_finalize (GObject *object); static void set_tap_to_click (GdkDevice *device, gboolean state, gboolean left_handed); static void set_natural_scroll (GsdMouseManager *manager, GdkDevice *device, gboolean natural_scroll); G_DEFINE_TYPE (GsdMouseManager, gsd_mouse_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static GObject * gsd_mouse_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdMouseManager *mouse_manager; mouse_manager = GSD_MOUSE_MANAGER (G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (mouse_manager); } static void gsd_mouse_manager_dispose (GObject *object) { G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->dispose (object); } static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_mouse_manager_constructor; object_class->dispose = gsd_mouse_manager_dispose; object_class->finalize = gsd_mouse_manager_finalize; g_type_class_add_private (klass, sizeof (GsdMouseManagerPrivate)); } static XDevice * open_gdk_device (GdkDevice *device) { XDevice *xdevice; int id; g_object_get (G_OBJECT (device), "device-id", &id, NULL); gdk_error_trap_push (); xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); if (gdk_error_trap_pop () != 0) return NULL; return xdevice; } static gboolean device_is_blacklisted (GsdMouseManager *manager, GdkDevice *device) { int id; g_object_get (G_OBJECT (device), "device-id", &id, NULL); if (g_hash_table_lookup (manager->priv->blacklist, GINT_TO_POINTER (id)) != NULL) { g_debug ("device %s (%d) is blacklisted", gdk_device_get_name (device), id); return TRUE; } return FALSE; } static gboolean device_is_ignored (GsdMouseManager *manager, GdkDevice *device) { GdkInputSource source; const char *name; if (device_is_blacklisted (manager, device)) return TRUE; source = gdk_device_get_source (device); if (source != GDK_SOURCE_MOUSE && source != GDK_SOURCE_TOUCHPAD && source != GDK_SOURCE_CURSOR) return TRUE; name = gdk_device_get_name (device); if (name != NULL && g_str_equal ("Virtual core XTEST pointer", name)) return TRUE; return FALSE; } static void configure_button_layout (guchar *buttons, gint n_buttons, gboolean left_handed) { const gint left_button = 1; gint right_button; gint i; /* if the button is higher than 2 (3rd button) then it's * probably one direction of a scroll wheel or something else * uninteresting */ right_button = MIN (n_buttons, 3); /* If we change things we need to make sure we only swap buttons. * If we end up with multiple physical buttons assigned to the same * logical button the server will complain. This code assumes physical * button 0 is the physical left mouse button, and that the physical * button other than 0 currently assigned left_button or right_button * is the physical right mouse button. */ /* check if the current mapping satisfies the above assumptions */ if (buttons[left_button - 1] != left_button && buttons[left_button - 1] != right_button) /* The current mapping is weird. Swapping buttons is probably not a * good idea. */ return; /* check if we are left_handed and currently not swapped */ if (left_handed && buttons[left_button - 1] == left_button) { /* find the right button */ for (i = 0; i < n_buttons; i++) { if (buttons[i] == right_button) { buttons[i] = left_button; break; } } /* swap the buttons */ buttons[left_button - 1] = right_button; } /* check if we are not left_handed but are swapped */ else if (!left_handed && buttons[left_button - 1] == right_button) { /* find the right button */ for (i = 0; i < n_buttons; i++) { if (buttons[i] == left_button) { buttons[i] = right_button; break; } } /* swap the buttons */ buttons[left_button - 1] = left_button; } } static gboolean xinput_device_has_buttons (GdkDevice *device) { int i; XAnyClassInfo *class_info; /* FIXME can we use the XDevice's classes here instead? */ XDeviceInfo *device_info, *info; gint n_devices; int id; /* Find the XDeviceInfo for the GdkDevice */ g_object_get (G_OBJECT (device), "device-id", &id, NULL); device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) return FALSE; info = NULL; for (i = 0; i < n_devices; i++) { if (device_info[i].id == id) { info = &device_info[i]; break; } } if (info == NULL) goto bail; class_info = info->inputclassinfo; for (i = 0; i < info->num_classes; i++) { if (class_info->class == ButtonClass) { XButtonInfo *button_info; button_info = (XButtonInfo *) class_info; if (button_info->num_buttons > 0) { XFreeDeviceList (device_info); return TRUE; } } class_info = (XAnyClassInfo *) (((guchar *) class_info) + class_info->length); } bail: XFreeDeviceList (device_info); return FALSE; } static gboolean touchpad_has_single_button (XDevice *device) { Atom type, prop; int format; unsigned long nitems, bytes_after; unsigned char *data; gboolean is_single_button = FALSE; int rc; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", False); if (!prop) return FALSE; gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, &data); if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 3) is_single_button = (data[0] == 1 && data[1] == 0 && data[2] == 0); if (rc == Success) XFree (data); gdk_error_trap_pop_ignored (); return is_single_button; } static void set_left_handed (GsdMouseManager *manager, GdkDevice *device, gboolean mouse_left_handed, gboolean touchpad_left_handed) { XDevice *xdevice; guchar *buttons; gsize buttons_capacity = 16; gboolean left_handed; gint n_buttons; if (!xinput_device_has_buttons (device)) return; xdevice = open_gdk_device (device); if (xdevice == NULL) return; g_debug ("setting handedness on %s", gdk_device_get_name (device)); buttons = g_new (guchar, buttons_capacity); /* If the device is a touchpad, swap tap buttons * around too, otherwise a tap would be a right-click */ if (device_is_touchpad (xdevice)) { gboolean tap = g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK); gboolean single_button = touchpad_has_single_button (xdevice); left_handed = touchpad_left_handed; if (tap && !single_button) set_tap_to_click (device, tap, left_handed); if (single_button) goto out; } else { left_handed = mouse_left_handed; } gdk_error_trap_push (); n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, buttons, buttons_capacity); while (n_buttons > buttons_capacity) { buttons_capacity = n_buttons; buttons = (guchar *) g_realloc (buttons, buttons_capacity * sizeof (guchar)); n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, buttons, buttons_capacity); } configure_button_layout (buttons, n_buttons, left_handed); XSetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, buttons, n_buttons); gdk_error_trap_pop_ignored (); out: xdevice_close (xdevice); g_free (buttons); } static void set_motion (GsdMouseManager *manager, GdkDevice *device) { XDevice *xdevice; XPtrFeedbackControl feedback; XFeedbackState *states, *state; int num_feedbacks; int numerator, denominator; gfloat motion_acceleration; int motion_threshold; GSettings *settings; gdouble speed; guint i; xdevice = open_gdk_device (device); if (xdevice == NULL) return; g_debug ("setting motion on %s", gdk_device_get_name (device)); if (device_is_touchpad (xdevice)) settings = manager->priv->touchpad_settings; else settings = manager->priv->mouse_settings; speed = g_settings_get_double (settings, KEY_SPEED); /* Calculate acceleration and threshold */ motion_acceleration = (speed + 1) * 5; /* speed is [-1..1], map to [0..10] */ motion_threshold = CLAMP (10 - floor (motion_acceleration), 1, 10); if (motion_acceleration >= 1.0) { /* we want to get the acceleration, with a resolution of 0.5 */ if ((motion_acceleration - floor (motion_acceleration)) < 0.25) { numerator = floor (motion_acceleration); denominator = 1; } else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) { numerator = ceil (2.0 * motion_acceleration); denominator = 2; } else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) { numerator = floor (2.0 *motion_acceleration); denominator = 2; } else { numerator = ceil (motion_acceleration); denominator = 1; } } else if (motion_acceleration < 1.0 && motion_acceleration > 0) { /* This we do to 1/10ths */ numerator = floor (motion_acceleration * 10) + 1; denominator= 10; } else { numerator = -1; denominator = -1; } gdk_error_trap_push (); /* Get the list of feedbacks for the device */ states = XGetFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, &num_feedbacks); if (states == NULL) goto out; state = (XFeedbackState *) states; for (i = 0; i < num_feedbacks; i++) { if (state->class == PtrFeedbackClass) { /* And tell the device */ feedback.class = PtrFeedbackClass; feedback.length = sizeof (XPtrFeedbackControl); feedback.id = state->id; feedback.threshold = motion_threshold; feedback.accelNum = numerator; feedback.accelDenom = denominator; g_debug ("Setting accel %d/%d, threshold %d for device '%s'", numerator, denominator, motion_threshold, gdk_device_get_name (device)); XChangeFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, DvAccelNum | DvAccelDenom | DvThreshold, (XFeedbackControl *) &feedback); break; } state = (XFeedbackState *) ((char *) state + state->length); } if (gdk_error_trap_pop ()) g_warning ("Error setting acceleration on \"%s\"", gdk_device_get_name (device)); XFreeFeedbackList (states); out: xdevice_close (xdevice); } /* Ensure that syndaemon dies together with us, to avoid running several of * them */ static void setup_syndaemon (gpointer user_data) { #ifdef __linux prctl (PR_SET_PDEATHSIG, SIGHUP); #endif } static gboolean have_program_in_path (const char *name) { gchar *path; gboolean result; path = g_find_program_in_path (name); result = (path != NULL); g_free (path); return result; } static void syndaemon_died (GPid pid, gint status, gpointer user_data) { GsdMouseManager *manager = GSD_MOUSE_MANAGER (user_data); g_debug ("syndaemon stopped with status %i", status); g_spawn_close_pid (pid); manager->priv->syndaemon_spawned = FALSE; } static int set_disable_w_typing (GsdMouseManager *manager, gboolean state) { if (state && touchpad_is_present ()) { GError *error = NULL; GPtrArray *args; if (manager->priv->syndaemon_spawned) return 0; if (!have_program_in_path ("syndaemon")) return 0; args = g_ptr_array_new (); g_ptr_array_add (args, "syndaemon"); g_ptr_array_add (args, "-i"); g_ptr_array_add (args, "1.0"); g_ptr_array_add (args, "-t"); g_ptr_array_add (args, "-K"); g_ptr_array_add (args, "-R"); g_ptr_array_add (args, NULL); /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid * double-forking, otherwise syndaemon will immediately get * killed again through (PR_SET_PDEATHSIG when the intermediate * process dies */ g_spawn_async (g_get_home_dir (), (char **) args->pdata, NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL, &manager->priv->syndaemon_pid, &error); manager->priv->syndaemon_spawned = (error == NULL); g_ptr_array_free (args, FALSE); if (error) { g_warning ("Failed to launch syndaemon: %s", error->message); g_error_free (error); } else { g_child_watch_add (manager->priv->syndaemon_pid, syndaemon_died, manager); g_debug ("Launched syndaemon"); } } else if (manager->priv->syndaemon_spawned) { kill (manager->priv->syndaemon_pid, SIGHUP); g_spawn_close_pid (manager->priv->syndaemon_pid); manager->priv->syndaemon_spawned = FALSE; g_debug ("Killed syndaemon"); } return 0; } static void set_tap_to_click (GdkDevice *device, gboolean state, gboolean left_handed) { int format, rc; unsigned long nitems, bytes_after; XDevice *xdevice; unsigned char* data; Atom prop, type; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Tap Action", False); if (!prop) return; xdevice = open_gdk_device (device); if (xdevice == NULL) return; if (!device_is_touchpad (xdevice)) { xdevice_close (xdevice); return; } g_debug ("setting tap to click on %s", gdk_device_get_name (device)); gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, &data); if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 7) { /* Set MR mapping for corner tapping on the right side*/ data[0] = (state) ? 2 : 0; data[1] = (state) ? 3 : 0; /* Set RLM mapping for 1/2/3 fingers*/ data[4] = (state) ? ((left_handed) ? 3 : 1) : 0; data[5] = (state) ? ((left_handed) ? 1 : 3) : 0; data[6] = 0; /* Disable three touch tap so gestures work */ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, XA_INTEGER, 8, PropModeReplace, data, nitems); } if (rc == Success) XFree (data); if (gdk_error_trap_pop ()) g_warning ("Error in setting tap to click on \"%s\"", gdk_device_get_name (device)); xdevice_close (xdevice); } static void set_horiz_scroll (GdkDevice *device, gboolean state) { int rc; XDevice *xdevice; Atom act_type, prop_edge, prop_twofinger; int act_format; unsigned long nitems, bytes_after; unsigned char *data; prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False); prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False); if (!prop_edge || !prop_twofinger) return; xdevice = open_gdk_device (device); if (xdevice == NULL) return; if (!device_is_touchpad (xdevice)) { xdevice_close (xdevice); return; } g_debug ("setting horiz scroll on %s", gdk_device_get_name (device)); gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_edge, 0, 1, False, XA_INTEGER, &act_type, &act_format, &nitems, &bytes_after, &data); if (rc == Success && act_type == XA_INTEGER && act_format == 8 && nitems >= 2) { data[1] = (state && data[0]); XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_edge, XA_INTEGER, 8, PropModeReplace, data, nitems); } XFree (data); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_twofinger, 0, 1, False, XA_INTEGER, &act_type, &act_format, &nitems, &bytes_after, &data); if (rc == Success && act_type == XA_INTEGER && act_format == 8 && nitems >= 2) { data[1] = (state && data[0]); XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_twofinger, XA_INTEGER, 8, PropModeReplace, data, nitems); } if (gdk_error_trap_pop ()) g_warning ("Error in setting horiz scroll on \"%s\"", gdk_device_get_name (device)); if (rc == Success) XFree (data); xdevice_close (xdevice); } static void set_scroll_method (GsdMouseManager *manager, GdkDevice *device, GsdTouchpadScrollMethod method) { int rc; XDevice *xdevice; Atom act_type, prop, prop_edge, prop_twofinger; int act_format; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", True); prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False); prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False); if (!prop_edge || !prop_twofinger || !prop) return; xdevice = open_gdk_device (device); if (xdevice == NULL) return; if (!device_is_touchpad (xdevice)) { xdevice_close (xdevice); return; } g_debug ("setting edge scroll on %s", gdk_device_get_name (device)); gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 2, False, XA_INTEGER, &act_type, &act_format, &nitems, &bytes_after, &data); if (rc == Success && act_type != None) { if (!(data[3]) && method == GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING) { g_warning ("Two finger scroll is not supported by %s", gdk_device_get_name (device)); method = GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING; g_settings_set_enum (manager->priv->usd_touchpad_settings, KEY_SCROLL_METHOD, method); } XFree (data); } rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_edge, 0, 1, False, XA_INTEGER, &act_type, &act_format, &nitems, &bytes_after, &data); if (rc == Success && act_type == XA_INTEGER && act_format == 8 && nitems >= 2) { data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING) ? 1 : 0; XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_edge, XA_INTEGER, 8, PropModeReplace, data, nitems); } XFree (data); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_twofinger, 0, 1, False, XA_INTEGER, &act_type, &act_format, &nitems, &bytes_after, &data); if (rc == Success && act_type == XA_INTEGER && act_format == 8 && nitems >= 2) { data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING) ? 1 : 0; XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_twofinger, XA_INTEGER, 8, PropModeReplace, data, nitems); } if (gdk_error_trap_pop ()) g_warning ("Error in setting edge scroll on \"%s\"", gdk_device_get_name (device)); if (rc == Success) XFree (data); xdevice_close (xdevice); } static void set_touchpad_disabled (GdkDevice *device) { int id; XDevice *xdevice; g_object_get (G_OBJECT (device), "device-id", &id, NULL); g_debug ("Trying to set device disabled for \"%s\" (%d)", gdk_device_get_name (device), id); xdevice = open_gdk_device (device); if (xdevice == NULL) return; if (!device_is_touchpad (xdevice)) { xdevice_close (xdevice); return; } if (set_device_enabled (id, FALSE) == FALSE) g_warning ("Error disabling device \"%s\" (%d)", gdk_device_get_name (device), id); else g_debug ("Disabled device \"%s\" (%d)", gdk_device_get_name (device), id); xdevice_close (xdevice); } static void set_touchpad_enabled (int id) { XDevice *xdevice; g_debug ("Trying to set device enabled for %d", id); gdk_error_trap_push (); xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); if (gdk_error_trap_pop () != 0) return; if (!device_is_touchpad (xdevice)) { xdevice_close (xdevice); return; } if (set_device_enabled (id, TRUE) == FALSE) g_warning ("Error enabling device \"%d\"", id); else g_debug ("Enabled device %d", id); xdevice_close (xdevice); } static void set_locate_pointer (GsdMouseManager *manager, gboolean state) { if (state) { GError *error = NULL; char *args[2]; if (manager->priv->locate_pointer_spawned) return; args[0] = LIBEXECDIR "/usd-locate-pointer"; args[1] = NULL; g_spawn_async (NULL, args, NULL, 0, NULL, NULL, &manager->priv->locate_pointer_pid, &error); manager->priv->locate_pointer_spawned = (error == NULL); if (error) { g_settings_set_boolean (manager->priv->interface_settings, KEY_LOCATE_POINTER, FALSE); g_error_free (error); } } else if (manager->priv->locate_pointer_spawned) { kill (manager->priv->locate_pointer_pid, SIGHUP); g_spawn_close_pid (manager->priv->locate_pointer_pid); manager->priv->locate_pointer_spawned = FALSE; } } static void set_mousetweaks_daemon (GsdMouseManager *manager, gboolean dwell_click_enabled, gboolean secondary_click_enabled) { GError *error = NULL; gchar *comm; gboolean run_daemon = dwell_click_enabled || secondary_click_enabled; if (run_daemon || manager->priv->mousetweaks_daemon_running) comm = g_strdup_printf ("mousetweaks %s", run_daemon ? "" : "-s"); else return; if (run_daemon) manager->priv->mousetweaks_daemon_running = TRUE; if (! g_spawn_command_line_async (comm, &error)) { if (error->code == G_SPAWN_ERROR_NOENT && run_daemon) { GtkWidget *dialog; if (dwell_click_enabled) { g_settings_set_boolean (manager->priv->mouse_a11y_settings, KEY_DWELL_CLICK_ENABLED, FALSE); } else if (secondary_click_enabled) { g_settings_set_boolean (manager->priv->mouse_a11y_settings, KEY_SECONDARY_CLICK_ENABLED, FALSE); } dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Could not enable mouse accessibility features")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("Mouse accessibility requires Mousetweaks " "to be installed on your system.")); gtk_window_set_title (GTK_WINDOW (dialog), _("Universal Access")); gtk_window_set_icon_name (GTK_WINDOW (dialog), "preferences-desktop-accessibility"); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } g_error_free (error); } g_free (comm); } static gboolean get_touchpad_handedness (GsdMouseManager *manager, gboolean mouse_left_handed) { switch (g_settings_get_enum (manager->priv->touchpad_settings, KEY_LEFT_HANDED)) { case GSD_TOUCHPAD_HANDEDNESS_RIGHT: return FALSE; case GSD_TOUCHPAD_HANDEDNESS_LEFT: return TRUE; case GSD_TOUCHPAD_HANDEDNESS_MOUSE: return mouse_left_handed; default: g_assert_not_reached (); } } static gboolean get_touchpad_enabled (GsdMouseManager *manager) { GDesktopDeviceSendEvents send_events; send_events = g_settings_get_enum (manager->priv->touchpad_settings, KEY_SEND_EVENTS); if (send_events == G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) { /* FIXME: mouse_is_present() also finds internal ones... */ return (!mouse_is_present () && !trackball_is_present ()); } return send_events == G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED ? TRUE : FALSE; } static void set_mouse_settings (GsdMouseManager *manager, GdkDevice *device) { gboolean mouse_left_handed, touchpad_left_handed; mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed); set_left_handed (manager, device, mouse_left_handed, touchpad_left_handed); set_motion (manager, device); set_tap_to_click (device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK), touchpad_left_handed); set_scroll_method (manager, device, g_settings_get_enum (manager->priv->usd_touchpad_settings, KEY_SCROLL_METHOD)); set_horiz_scroll (device, TRUE); set_natural_scroll (manager, device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_NATURAL_SCROLL_ENABLED)); if (!get_touchpad_enabled (manager)) set_touchpad_disabled (device); } static void set_natural_scroll (GsdMouseManager *manager, GdkDevice *device, gboolean natural_scroll) { XDevice *xdevice; Atom scrolling_distance, act_type; int rc, act_format; unsigned long nitems, bytes_after; unsigned char *data; glong *ptr; xdevice = open_gdk_device (device); if (xdevice == NULL) return; if (!device_is_touchpad (xdevice)) { xdevice_close (xdevice); return; } g_debug ("Trying to set %s for \"%s\"", natural_scroll ? "natural (reverse) scroll" : "normal scroll", gdk_device_get_name (device)); scrolling_distance = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Scrolling Distance", False); gdk_error_trap_push (); rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, scrolling_distance, 0, 2, False, XA_INTEGER, &act_type, &act_format, &nitems, &bytes_after, &data); if (rc == Success && act_type == XA_INTEGER && act_format == 32 && nitems >= 2) { ptr = (glong *) data; if (natural_scroll) { ptr[0] = -abs(ptr[0]); ptr[1] = -abs(ptr[1]); } else { ptr[0] = abs(ptr[0]); ptr[1] = abs(ptr[1]); } XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, scrolling_distance, XA_INTEGER, act_format, PropModeReplace, data, nitems); } if (gdk_error_trap_pop ()) g_warning ("Error setting %s for \"%s\"", natural_scroll ? "natural (reverse) scroll" : "normal scroll", gdk_device_get_name (device)); if (rc == Success) XFree (data); xdevice_close (xdevice); } static void mouse_callback (GSettings *settings, const gchar *key, GsdMouseManager *manager) { GList *devices, *l; if (g_str_equal (key, KEY_DWELL_CLICK_ENABLED) || g_str_equal (key, KEY_SECONDARY_CLICK_ENABLED)) { set_mousetweaks_daemon (manager, g_settings_get_boolean (settings, KEY_DWELL_CLICK_ENABLED), g_settings_get_boolean (settings, KEY_SECONDARY_CLICK_ENABLED)); return; } else if (g_str_equal (key, KEY_LOCATE_POINTER)) { set_locate_pointer (manager, g_settings_get_boolean (settings, KEY_LOCATE_POINTER)); return; } devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); for (l = devices; l != NULL; l = l->next) { GdkDevice *device = l->data; if (device_is_ignored (manager, device)) continue; if (g_str_equal (key, KEY_LEFT_HANDED)) { gboolean mouse_left_handed; mouse_left_handed = g_settings_get_boolean (settings, KEY_LEFT_HANDED); set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed)); } else if (g_str_equal (key, KEY_SPEED)) { set_motion (manager, device); } } g_list_free (devices); } static void touchpad_callback (GSettings *settings, const gchar *key, GsdMouseManager *manager) { GList *devices, *l; devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); for (l = devices; l != NULL; l = l->next) { GdkDevice *device = l->data; if (device_is_ignored (manager, device)) continue; if (g_str_equal (key, KEY_TAP_TO_CLICK)) { gboolean mouse_left_handed; mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); set_tap_to_click (device, g_settings_get_boolean (manager->priv->touchpad_settings, key), get_touchpad_handedness (manager, mouse_left_handed)); } else if (g_str_equal (key, KEY_SCROLL_METHOD)) { set_scroll_method (manager, device, g_settings_get_enum (manager->priv->usd_touchpad_settings, key)); set_horiz_scroll (device, TRUE); } else if (g_str_equal (key, KEY_SEND_EVENTS)) { if (!get_touchpad_enabled (manager)) set_touchpad_disabled (device); else set_touchpad_enabled (gdk_x11_device_get_id (device)); } else if (g_str_equal (key, KEY_SPEED)) { set_motion (manager, device); } else if (g_str_equal (key, KEY_LEFT_HANDED)) { gboolean mouse_left_handed; mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed)); } else if (g_str_equal (key, KEY_NATURAL_SCROLL_ENABLED)) { set_natural_scroll (manager, device, g_settings_get_boolean (manager->priv->touchpad_settings, key)); } } g_list_free (devices); if (g_str_equal (key, KEY_SEND_EVENTS) && get_touchpad_enabled (manager)) { devices = get_disabled_devices (manager->priv->device_manager); for (l = devices; l != NULL; l = l->next) { int device_id; device_id = GPOINTER_TO_INT (l->data); set_touchpad_enabled (device_id); } g_list_free (devices); } } /* Re-enable touchpad when any other pointing device isn't present. */ static void ensure_touchpad_active (GsdMouseManager *manager) { GList *devices, *l; if (get_touchpad_enabled (manager)) { devices = get_disabled_devices (manager->priv->device_manager); for (l = devices; l != NULL; l = l->next) { int device_id; device_id = GPOINTER_TO_INT (l->data); set_touchpad_enabled (device_id); } g_list_free (devices); } else { devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); for (l = devices; l != NULL; l = l->next) { GdkDevice *device = l->data; if (device_is_ignored (manager, device)) continue; if (gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD) continue; set_touchpad_disabled (device); } g_list_free (devices); } } static void device_added_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdMouseManager *manager) { if (device_is_ignored (manager, device) == FALSE) { if (run_custom_command (device, COMMAND_DEVICE_ADDED) == FALSE) { set_mouse_settings (manager, device); } else { int id; g_object_get (G_OBJECT (device), "device-id", &id, NULL); g_hash_table_insert (manager->priv->blacklist, GINT_TO_POINTER (id), GINT_TO_POINTER (1)); } /* If a touchpad was to appear... */ set_disable_w_typing (manager, TRUE); /* If a mouse was to appear... */ ensure_touchpad_active (manager); } } static void device_removed_cb (GdkDeviceManager *device_manager, GdkDevice *device, GsdMouseManager *manager) { int id; /* Remove the device from the hash table so that * device_is_ignored () doesn't check for blacklisted devices */ g_object_get (G_OBJECT (device), "device-id", &id, NULL); g_hash_table_remove (manager->priv->blacklist, GINT_TO_POINTER (id)); if (device_is_ignored (manager, device) == FALSE) { run_custom_command (device, COMMAND_DEVICE_REMOVED); /* If a touchpad was to disappear... */ set_disable_w_typing (manager, TRUE); if (gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD) ensure_touchpad_active (manager); } } static void set_devicepresence_handler (GsdMouseManager *manager) { GdkDeviceManager *device_manager; device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", G_CALLBACK (device_added_cb), manager); manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", G_CALLBACK (device_removed_cb), manager); manager->priv->device_manager = device_manager; } static void gsd_mouse_manager_init (GsdMouseManager *manager) { manager->priv = GSD_MOUSE_MANAGER_GET_PRIVATE (manager); manager->priv->blacklist = g_hash_table_new (g_direct_hash, g_direct_equal); } static gboolean gsd_mouse_manager_idle_cb (GsdMouseManager *manager) { GList *devices, *l; gnome_settings_profile_start (NULL); set_devicepresence_handler (manager); manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR); g_signal_connect (manager->priv->interface_settings, "changed", G_CALLBACK (mouse_callback), manager); manager->priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse"); g_signal_connect (manager->priv->mouse_a11y_settings, "changed", G_CALLBACK (mouse_callback), manager); manager->priv->mouse_settings = g_settings_new (GSETTINGS_MOUSE_SCHEMA); g_signal_connect (manager->priv->mouse_settings, "changed", G_CALLBACK (mouse_callback), manager); manager->priv->touchpad_settings = g_settings_new (GSETTINGS_TOUCHPAD_SCHEMA); g_signal_connect (manager->priv->touchpad_settings, "changed", G_CALLBACK (touchpad_callback), manager); manager->priv->usd_touchpad_settings = g_settings_new (USD_TOUCHPAD_SCHEMA); g_signal_connect (manager->priv->usd_touchpad_settings, "changed", G_CALLBACK (touchpad_callback), manager); manager->priv->syndaemon_spawned = FALSE; set_locate_pointer (manager, g_settings_get_boolean (manager->priv->interface_settings, KEY_LOCATE_POINTER)); set_mousetweaks_daemon (manager, g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_DWELL_CLICK_ENABLED), g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_SECONDARY_CLICK_ENABLED)); set_disable_w_typing (manager, TRUE); devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); for (l = devices; l != NULL; l = l->next) { GdkDevice *device = l->data; if (device_is_ignored (manager, device)) continue; if (run_custom_command (device, COMMAND_DEVICE_PRESENT) == FALSE) { set_mouse_settings (manager, device); } else { int id; g_object_get (G_OBJECT (device), "device-id", &id, NULL); g_hash_table_insert (manager->priv->blacklist, GINT_TO_POINTER (id), GINT_TO_POINTER (1)); } } g_list_free (devices); ensure_touchpad_active (manager); if (get_touchpad_enabled (manager)) { devices = get_disabled_devices (manager->priv->device_manager); for (l = devices; l != NULL; l = l->next) { int device_id; device_id = GPOINTER_TO_INT (l->data); set_touchpad_enabled (device_id); } g_list_free (devices); } gnome_settings_profile_end (NULL); manager->priv->start_idle_id = 0; return FALSE; } gboolean gsd_mouse_manager_start (GsdMouseManager *manager, GError **error) { gnome_settings_profile_start (NULL); if (!supports_xinput_devices ()) { g_debug ("XInput is not supported, not applying any settings"); return TRUE; } manager->priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_mouse_manager_idle_cb, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_mouse_manager_stop (GsdMouseManager *manager) { GsdMouseManagerPrivate *p = manager->priv; g_debug ("Stopping mouse manager"); if (manager->priv->start_idle_id != 0) { g_source_remove (manager->priv->start_idle_id); manager->priv->start_idle_id = 0; } if (p->device_manager != NULL) { g_signal_handler_disconnect (p->device_manager, p->device_added_id); g_signal_handler_disconnect (p->device_manager, p->device_removed_id); p->device_manager = NULL; } g_clear_object (&p->mouse_a11y_settings); g_clear_object (&p->mouse_settings); g_clear_object (&p->touchpad_settings); g_clear_object (&p->usd_touchpad_settings); set_locate_pointer (manager, FALSE); g_clear_object (&p->interface_settings); } static void gsd_mouse_manager_finalize (GObject *object) { GsdMouseManager *mouse_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_MOUSE_MANAGER (object)); mouse_manager = GSD_MOUSE_MANAGER (object); g_return_if_fail (mouse_manager->priv != NULL); gsd_mouse_manager_stop (mouse_manager); if (mouse_manager->priv->blacklist != NULL) g_hash_table_destroy (mouse_manager->priv->blacklist); G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->finalize (object); } static GVariant * map_speed (GVariant *variant) { gdouble value; value = g_variant_get_double (variant); /* Remap from [0..10] to [-1..1] */ value = (value / 5) - 1; return g_variant_new_double (value); } static GVariant * map_send_events (GVariant *variant) { gboolean enabled; enabled = g_variant_get_boolean (variant); if (enabled) { return g_variant_new_string ("enabled"); } else { return g_variant_new_string ("disabled"); } } static void migrate_mouse_settings (void) { GsdSettingsMigrateEntry trackball_entries[] = { { "scroll-wheel-emulation-button", "scroll-wheel-emulation-button", NULL } }; GsdSettingsMigrateEntry mouse_entries[] = { { "left-handed", "left-handed", NULL }, { "motion-acceleration", "speed", map_speed }, { "motion-threshold", NULL, NULL }, { "middle-button-enabled", NULL, NULL }, }; GsdSettingsMigrateEntry touchpad_entries[] = { { "disable-while-typing", NULL, NULL }, { "horiz-scroll-enabled", NULL, NULL }, { "tap-to-click", "tap-to-click", NULL }, { "touchpad-enabled", "send-events", map_send_events }, { "left-handed", "left-handed", NULL }, { "motion-acceleration", "speed", map_speed }, { "motion-threshold", NULL, NULL }, { "natural-scroll", "natural-scroll", NULL } }; gsd_settings_migrate_check ("com.canonical.unity.settings-daemon.peripherals.trackball.deprecated", "/com/canonical/unity/settings-daemon/peripherals/trackball/", "org.gnome.desktop.peripherals.trackball", "/org/gnome/desktop/peripherals/trackball/", trackball_entries, G_N_ELEMENTS (trackball_entries)); gsd_settings_migrate_check ("com.canonical.unity.settings-daemon.peripherals.mouse.deprecated", "/com/canonical/unity/settings-daemon/peripherals/mouse/", "org.gnome.desktop.peripherals.mouse", "/org/gnome/desktop/peripherals/mouse/", mouse_entries, G_N_ELEMENTS (mouse_entries)); gsd_settings_migrate_check ("com.canonical.unity.settings-daemon.peripherals.touchpad.deprecated", "/com/canonical/unity/settings-daemon/peripherals/touchpad/", "org.gnome.desktop.peripherals.touchpad", "/org/gnome/desktop/peripherals/touchpad/", touchpad_entries, G_N_ELEMENTS (touchpad_entries)); } GsdMouseManager * gsd_mouse_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { migrate_mouse_settings (); manager_object = g_object_new (GSD_TYPE_MOUSE_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_MOUSE_MANAGER (manager_object); } unity-settings-daemon/plugins/mouse/gsd-mouse-manager.h0000664000000000000000000000437015172222611020515 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_MOUSE_MANAGER_H #define __GSD_MOUSE_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_MOUSE_MANAGER (gsd_mouse_manager_get_type ()) #define GSD_MOUSE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManager)) #define GSD_MOUSE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerClass)) #define GSD_IS_MOUSE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_MOUSE_MANAGER)) #define GSD_IS_MOUSE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_MOUSE_MANAGER)) #define GSD_MOUSE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerClass)) typedef struct GsdMouseManagerPrivate GsdMouseManagerPrivate; typedef struct { GObject parent; GsdMouseManagerPrivate *priv; } GsdMouseManager; typedef struct { GObjectClass parent_class; } GsdMouseManagerClass; GType gsd_mouse_manager_get_type (void); GsdMouseManager * gsd_mouse_manager_new (void); gboolean gsd_mouse_manager_start (GsdMouseManager *manager, GError **error); void gsd_mouse_manager_stop (GsdMouseManager *manager); G_END_DECLS #endif /* __GSD_MOUSE_MANAGER_H */ unity-settings-daemon/plugins/mouse/gsd-mouse-plugin.c0000664000000000000000000000201515172222611020366 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-mouse-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdMouse, gsd_mouse) unity-settings-daemon/plugins/mouse/gsd-timeline.c0000664000000000000000000004730215172222611017560 0ustar /* gsd-timeline.c * * Copyright (C) 2008 Carlos Garnacho * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "gsd-timeline.h" #define GSD_TIMELINE_GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSD_TYPE_TIMELINE, GsdTimelinePriv)) #define MSECS_PER_SEC 1000 #define FRAME_INTERVAL(nframes) (MSECS_PER_SEC / nframes) #define DEFAULT_FPS 30 typedef struct GsdTimelinePriv GsdTimelinePriv; struct GsdTimelinePriv { guint duration; guint fps; guint source_id; GTimer *timer; GdkScreen *screen; GsdTimelineProgressType progress_type; GsdTimelineProgressFunc progress_func; guint loop : 1; guint direction : 1; }; enum { PROP_0, PROP_FPS, PROP_DURATION, PROP_LOOP, PROP_DIRECTION, PROP_SCREEN, PROP_PROGRESS_TYPE, }; enum { STARTED, PAUSED, FINISHED, FRAME, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0, }; static void gsd_timeline_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gsd_timeline_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gsd_timeline_finalize (GObject *object); G_DEFINE_TYPE (GsdTimeline, gsd_timeline, G_TYPE_OBJECT) GType gsd_timeline_direction_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GEnumValue values[] = { { GSD_TIMELINE_DIRECTION_FORWARD, "GSD_TIMELINE_DIRECTION_FORWARD", "forward" }, { GSD_TIMELINE_DIRECTION_BACKWARD, "GSD_TIMELINE_DIRECTION_BACKWARD", "backward" }, { 0, NULL, NULL } }; type = g_enum_register_static (g_intern_static_string ("GsdTimelineDirection"), values); } return type; } GType gsd_timeline_progress_type_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GEnumValue values[] = { { GSD_TIMELINE_PROGRESS_LINEAR, "GSD_TIMELINE_PROGRESS_LINEAR", "linear" }, { GSD_TIMELINE_PROGRESS_SINUSOIDAL, "GSD_TIMELINE_PROGRESS_SINUSOIDAL", "sinusoidal" }, { GSD_TIMELINE_PROGRESS_EXPONENTIAL, "GSD_TIMELINE_PROGRESS_EXPONENTIAL", "exponential" }, { 0, NULL, NULL } }; type = g_enum_register_static (g_intern_static_string ("GsdTimelineProgressType"), values); } return type; } static void gsd_timeline_class_init (GsdTimelineClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); object_class->set_property = gsd_timeline_set_property; object_class->get_property = gsd_timeline_get_property; object_class->finalize = gsd_timeline_finalize; g_object_class_install_property (object_class, PROP_FPS, g_param_spec_uint ("fps", "FPS", "Frames per second for the timeline", 1, G_MAXUINT, DEFAULT_FPS, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_DURATION, g_param_spec_uint ("duration", "Animation Duration", "Animation Duration", 0, G_MAXUINT, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_LOOP, g_param_spec_boolean ("loop", "Loop", "Whether the timeline loops or not", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_DIRECTION, g_param_spec_enum ("direction", "Direction", "Whether the timeline moves forward or backward in time", GSD_TYPE_TIMELINE_DIRECTION, GSD_TIMELINE_DIRECTION_FORWARD, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_DIRECTION, g_param_spec_enum ("progress-type", "Progress type", "Type of progress through the timeline", GSD_TYPE_TIMELINE_PROGRESS_TYPE, GSD_TIMELINE_PROGRESS_LINEAR, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SCREEN, g_param_spec_object ("screen", "Screen", "Screen to get the settings from", GDK_TYPE_SCREEN, G_PARAM_READWRITE)); signals[STARTED] = g_signal_new ("started", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdTimelineClass, started), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[PAUSED] = g_signal_new ("paused", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdTimelineClass, paused), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[FINISHED] = g_signal_new ("finished", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdTimelineClass, finished), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[FRAME] = g_signal_new ("frame", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdTimelineClass, frame), NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE); g_type_class_add_private (class, sizeof (GsdTimelinePriv)); } static void gsd_timeline_init (GsdTimeline *timeline) { GsdTimelinePriv *priv; priv = GSD_TIMELINE_GET_PRIV (timeline); priv->fps = DEFAULT_FPS; priv->duration = 0; priv->direction = GSD_TIMELINE_DIRECTION_FORWARD; priv->screen = gdk_screen_get_default (); } static void gsd_timeline_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GsdTimeline *timeline; timeline = GSD_TIMELINE (object); switch (prop_id) { case PROP_FPS: gsd_timeline_set_fps (timeline, g_value_get_uint (value)); break; case PROP_DURATION: gsd_timeline_set_duration (timeline, g_value_get_uint (value)); break; case PROP_LOOP: gsd_timeline_set_loop (timeline, g_value_get_boolean (value)); break; case PROP_DIRECTION: gsd_timeline_set_direction (timeline, g_value_get_enum (value)); break; case PROP_SCREEN: gsd_timeline_set_screen (timeline, GDK_SCREEN (g_value_get_object (value))); break; case PROP_PROGRESS_TYPE: gsd_timeline_set_progress_type (timeline, g_value_get_enum (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gsd_timeline_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GsdTimeline *timeline; GsdTimelinePriv *priv; timeline = GSD_TIMELINE (object); priv = GSD_TIMELINE_GET_PRIV (timeline); switch (prop_id) { case PROP_FPS: g_value_set_uint (value, priv->fps); break; case PROP_DURATION: g_value_set_uint (value, priv->duration); break; case PROP_LOOP: g_value_set_boolean (value, priv->loop); break; case PROP_DIRECTION: g_value_set_enum (value, priv->direction); break; case PROP_SCREEN: g_value_set_object (value, priv->screen); break; case PROP_PROGRESS_TYPE: g_value_set_enum (value, priv->progress_type); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gsd_timeline_finalize (GObject *object) { GsdTimelinePriv *priv; priv = GSD_TIMELINE_GET_PRIV (object); if (priv->source_id) { g_source_remove (priv->source_id); priv->source_id = 0; } if (priv->timer) g_timer_destroy (priv->timer); G_OBJECT_CLASS (gsd_timeline_parent_class)->finalize (object); } /* Sinusoidal progress */ static gdouble sinusoidal_progress (gdouble progress) { return (sinf ((progress * G_PI) / 2)); } static gdouble exponential_progress (gdouble progress) { return progress * progress; } static GsdTimelineProgressFunc progress_type_to_func (GsdTimelineProgressType type) { if (type == GSD_TIMELINE_PROGRESS_SINUSOIDAL) return sinusoidal_progress; else if (type == GSD_TIMELINE_PROGRESS_EXPONENTIAL) return exponential_progress; return NULL; } static gboolean gsd_timeline_run_frame (GsdTimeline *timeline, gboolean enable_animations) { GsdTimelinePriv *priv; gdouble linear_progress, progress; guint elapsed_time; GsdTimelineProgressFunc progress_func = NULL; priv = GSD_TIMELINE_GET_PRIV (timeline); if (enable_animations) { elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000); linear_progress = (gdouble) elapsed_time / priv->duration; if (priv->direction == GSD_TIMELINE_DIRECTION_BACKWARD) linear_progress = 1 - linear_progress; linear_progress = CLAMP (linear_progress, 0., 1.); if (priv->progress_func) progress_func = priv->progress_func; else if (priv->progress_type) progress_func = progress_type_to_func (priv->progress_type); if (progress_func) progress = (progress_func) (linear_progress); else progress = linear_progress; } else progress = (priv->direction == GSD_TIMELINE_DIRECTION_FORWARD) ? 1.0 : 0.0; g_signal_emit (timeline, signals [FRAME], 0, CLAMP (progress, 0.0, 1.0)); if ((priv->direction == GSD_TIMELINE_DIRECTION_FORWARD && progress >= 1.0) || (priv->direction == GSD_TIMELINE_DIRECTION_BACKWARD && progress <= 0.0)) { if (!priv->loop) { if (priv->source_id) { g_source_remove (priv->source_id); priv->source_id = 0; } g_signal_emit (timeline, signals [FINISHED], 0); return FALSE; } else gsd_timeline_rewind (timeline); } return TRUE; } static gboolean gsd_timeline_frame_idle_func (GsdTimeline *timeline) { return gsd_timeline_run_frame (timeline, TRUE); } /** * gsd_timeline_new: * @duration: duration in milliseconds for the timeline * * Creates a new #GsdTimeline with the specified number of frames. * * Return Value: the newly created #GsdTimeline **/ GsdTimeline * gsd_timeline_new (guint duration) { return g_object_new (GSD_TYPE_TIMELINE, "duration", duration, NULL); } GsdTimeline * gsd_timeline_new_for_screen (guint duration, GdkScreen *screen) { return g_object_new (GSD_TYPE_TIMELINE, "duration", duration, "screen", screen, NULL); } /** * gsd_timeline_start: * @timeline: A #GsdTimeline * * Runs the timeline from the current frame. **/ void gsd_timeline_start (GsdTimeline *timeline) { GsdTimelinePriv *priv; GtkSettings *settings; gboolean enable_animations = FALSE; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); if (priv->screen) { settings = gtk_settings_get_for_screen (priv->screen); g_object_get (settings, "gtk-enable-animations", &enable_animations, NULL); } if (enable_animations) { if (!priv->source_id) { if (priv->timer) g_timer_continue (priv->timer); else priv->timer = g_timer_new (); /* sanity check */ g_assert (priv->fps > 0); g_signal_emit (timeline, signals [STARTED], 0); priv->source_id = gdk_threads_add_timeout (FRAME_INTERVAL (priv->fps), (GSourceFunc) gsd_timeline_frame_idle_func, timeline); } } else { /* If animations are not enabled, only run the last frame, * it take us instantaneously to the last state of the animation. * The only potential flaw happens when people use the ::finished * signal to trigger another animation, or even worse, finally * loop into this animation again. */ g_signal_emit (timeline, signals [STARTED], 0); gsd_timeline_run_frame (timeline, FALSE); } } /** * gsd_timeline_pause: * @timeline: A #GsdTimeline * * Pauses the timeline. **/ void gsd_timeline_pause (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); if (priv->source_id) { g_source_remove (priv->source_id); priv->source_id = 0; g_timer_stop (priv->timer); g_signal_emit (timeline, signals [PAUSED], 0); } } /** * gsd_timeline_rewind: * @timeline: A #GsdTimeline * * Rewinds the timeline. **/ void gsd_timeline_rewind (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); /* destroy and re-create timer if neccesary */ if (priv->timer) { g_timer_destroy (priv->timer); if (gsd_timeline_is_running (timeline)) priv->timer = g_timer_new (); else priv->timer = NULL; } } /** * gsd_timeline_is_running: * @timeline: A #GsdTimeline * * Returns whether the timeline is running or not. * * Return Value: %TRUE if the timeline is running **/ gboolean gsd_timeline_is_running (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), FALSE); priv = GSD_TIMELINE_GET_PRIV (timeline); return (priv->source_id != 0); } /** * gsd_timeline_get_fps: * @timeline: A #GsdTimeline * * Returns the number of frames per second. * * Return Value: frames per second **/ guint gsd_timeline_get_fps (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), 1); priv = GSD_TIMELINE_GET_PRIV (timeline); return priv->fps; } /** * gsd_timeline_set_fps: * @timeline: A #GsdTimeline * @fps: frames per second * * Sets the number of frames per second that * the timeline will play. **/ void gsd_timeline_set_fps (GsdTimeline *timeline, guint fps) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); g_return_if_fail (fps > 0); priv = GSD_TIMELINE_GET_PRIV (timeline); priv->fps = fps; if (gsd_timeline_is_running (timeline)) { g_source_remove (priv->source_id); priv->source_id = gdk_threads_add_timeout (FRAME_INTERVAL (priv->fps), (GSourceFunc) gsd_timeline_run_frame, timeline); } g_object_notify (G_OBJECT (timeline), "fps"); } /** * gsd_timeline_get_loop: * @timeline: A #GsdTimeline * * Returns whether the timeline loops to the * beginning when it has reached the end. * * Return Value: %TRUE if the timeline loops **/ gboolean gsd_timeline_get_loop (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), FALSE); priv = GSD_TIMELINE_GET_PRIV (timeline); return priv->loop; } /** * gsd_timeline_set_loop: * @timeline: A #GsdTimeline * @loop: %TRUE to make the timeline loop * * Sets whether the timeline loops to the beginning * when it has reached the end. **/ void gsd_timeline_set_loop (GsdTimeline *timeline, gboolean loop) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); priv->loop = loop; g_object_notify (G_OBJECT (timeline), "loop"); } void gsd_timeline_set_duration (GsdTimeline *timeline, guint duration) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); priv->duration = duration; g_object_notify (G_OBJECT (timeline), "duration"); } guint gsd_timeline_get_duration (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), 0); priv = GSD_TIMELINE_GET_PRIV (timeline); return priv->duration; } /** * gsd_timeline_get_direction: * @timeline: A #GsdTimeline * * Returns the direction of the timeline. * * Return Value: direction **/ GsdTimelineDirection gsd_timeline_get_direction (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), GSD_TIMELINE_DIRECTION_FORWARD); priv = GSD_TIMELINE_GET_PRIV (timeline); return priv->direction; } /** * gsd_timeline_set_direction: * @timeline: A #GsdTimeline * @direction: direction * * Sets the direction of the timeline. **/ void gsd_timeline_set_direction (GsdTimeline *timeline, GsdTimelineDirection direction) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); priv->direction = direction; g_object_notify (G_OBJECT (timeline), "direction"); } GdkScreen * gsd_timeline_get_screen (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), NULL); priv = GSD_TIMELINE_GET_PRIV (timeline); return priv->screen; } void gsd_timeline_set_screen (GsdTimeline *timeline, GdkScreen *screen) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); g_return_if_fail (GDK_IS_SCREEN (screen)); priv = GSD_TIMELINE_GET_PRIV (timeline); if (priv->screen) g_object_unref (priv->screen); priv->screen = g_object_ref (screen); g_object_notify (G_OBJECT (timeline), "screen"); } void gsd_timeline_set_progress_type (GsdTimeline *timeline, GsdTimelineProgressType type) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); priv->progress_type = type; g_object_notify (G_OBJECT (timeline), "progress-type"); } GsdTimelineProgressType gsd_timeline_get_progress_type (GsdTimeline *timeline) { GsdTimelinePriv *priv; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), GSD_TIMELINE_PROGRESS_LINEAR); priv = GSD_TIMELINE_GET_PRIV (timeline); if (priv->progress_func) return GSD_TIMELINE_PROGRESS_LINEAR; return priv->progress_type; } /** * gsd_timeline_set_progress_func: * @timeline: A #GsdTimeline * @progress_func: progress function * * Sets the progress function. This function will be used to calculate * a different progress to pass to the ::frame signal based on the * linear progress through the timeline. Setting progress_func * to %NULL will make the timeline use the default function, * which is just a linear progress. * * All progresses are in the [0.0, 1.0] range. **/ void gsd_timeline_set_progress_func (GsdTimeline *timeline, GsdTimelineProgressFunc progress_func) { GsdTimelinePriv *priv; g_return_if_fail (GSD_IS_TIMELINE (timeline)); priv = GSD_TIMELINE_GET_PRIV (timeline); priv->progress_func = progress_func; } gdouble gsd_timeline_get_progress (GsdTimeline *timeline) { GsdTimelinePriv *priv; GsdTimelineProgressFunc progress_func = NULL; gdouble linear_progress, progress; guint elapsed_time; g_return_val_if_fail (GSD_IS_TIMELINE (timeline), 0.0); priv = GSD_TIMELINE_GET_PRIV (timeline); if (!priv->timer) return 0.; elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000); linear_progress = (gdouble) elapsed_time / priv->duration; if (priv->direction == GSD_TIMELINE_DIRECTION_BACKWARD) linear_progress = 1 - linear_progress; linear_progress = CLAMP (linear_progress, 0., 1.); if (priv->progress_func) progress_func = priv->progress_func; else if (priv->progress_type) progress_func = progress_type_to_func (priv->progress_type); if (progress_func) progress = (progress_func) (linear_progress); else progress = linear_progress; return CLAMP (progress, 0., 1.); } unity-settings-daemon/plugins/mouse/gsd-timeline.h0000664000000000000000000001210215172222611017553 0ustar /* gsdtimeline.c * * Copyright (C) 2008 Carlos Garnacho * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __GSD_TIMELINE_H__ #define __GSD_TIMELINE_H__ #include #include G_BEGIN_DECLS #define GSD_TYPE_TIMELINE_DIRECTION (gsd_timeline_direction_get_type ()) #define GSD_TYPE_TIMELINE_PROGRESS_TYPE (gsd_timeline_progress_type_get_type ()) #define GSD_TYPE_TIMELINE (gsd_timeline_get_type ()) #define GSD_TIMELINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_TIMELINE, GsdTimeline)) #define GSD_TIMELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_TIMELINE, GsdTimelineClass)) #define GSD_IS_TIMELINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_TIMELINE)) #define GSD_IS_TIMELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_TIMELINE)) #define GSD_TIMELINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_TIMELINE, GsdTimelineClass)) typedef enum { GSD_TIMELINE_DIRECTION_FORWARD, GSD_TIMELINE_DIRECTION_BACKWARD } GsdTimelineDirection; typedef enum { GSD_TIMELINE_PROGRESS_LINEAR, GSD_TIMELINE_PROGRESS_SINUSOIDAL, GSD_TIMELINE_PROGRESS_EXPONENTIAL } GsdTimelineProgressType; typedef struct GsdTimeline GsdTimeline; typedef struct GsdTimelineClass GsdTimelineClass; struct GsdTimeline { GObject parent_instance; }; struct GsdTimelineClass { GObjectClass parent_class; void (* started) (GsdTimeline *timeline); void (* finished) (GsdTimeline *timeline); void (* paused) (GsdTimeline *timeline); void (* frame) (GsdTimeline *timeline, gdouble progress); void (* __gsd_reserved1) (void); void (* __gsd_reserved2) (void); void (* __gsd_reserved3) (void); void (* __gsd_reserved4) (void); }; typedef gdouble (*GsdTimelineProgressFunc) (gdouble progress); GType gsd_timeline_get_type (void) G_GNUC_CONST; GType gsd_timeline_direction_get_type (void) G_GNUC_CONST; GType gsd_timeline_progress_type_get_type (void) G_GNUC_CONST; GsdTimeline *gsd_timeline_new (guint duration); GsdTimeline *gsd_timeline_new_for_screen (guint duration, GdkScreen *screen); void gsd_timeline_start (GsdTimeline *timeline); void gsd_timeline_pause (GsdTimeline *timeline); void gsd_timeline_rewind (GsdTimeline *timeline); gboolean gsd_timeline_is_running (GsdTimeline *timeline); guint gsd_timeline_get_fps (GsdTimeline *timeline); void gsd_timeline_set_fps (GsdTimeline *timeline, guint fps); gboolean gsd_timeline_get_loop (GsdTimeline *timeline); void gsd_timeline_set_loop (GsdTimeline *timeline, gboolean loop); guint gsd_timeline_get_duration (GsdTimeline *timeline); void gsd_timeline_set_duration (GsdTimeline *timeline, guint duration); GdkScreen *gsd_timeline_get_screen (GsdTimeline *timeline); void gsd_timeline_set_screen (GsdTimeline *timeline, GdkScreen *screen); GsdTimelineDirection gsd_timeline_get_direction (GsdTimeline *timeline); void gsd_timeline_set_direction (GsdTimeline *timeline, GsdTimelineDirection direction); GsdTimelineProgressType gsd_timeline_get_progress_type (GsdTimeline *timeline); void gsd_timeline_set_progress_type (GsdTimeline *timeline, GsdTimelineProgressType type); void gsd_timeline_get_progress_func (GsdTimeline *timeline); void gsd_timeline_set_progress_func (GsdTimeline *timeline, GsdTimelineProgressFunc progress_func); gdouble gsd_timeline_get_progress (GsdTimeline *timeline); G_END_DECLS #endif /* __GSD_TIMELINE_H__ */ unity-settings-daemon/plugins/mouse/mouse.gnome-settings-plugin.in0000664000000000000000000000021415172222611022740 0ustar [GNOME Settings Plugin] Module=mouse IAge=0 Priority=7 _Name=Mouse _Description=Mouse plugin Authors= Copyright=Copyright © 2007 Website= unity-settings-daemon/plugins/mouse/test-mouse.c0000664000000000000000000000030515172222611017274 0ustar #define NEW gsd_mouse_manager_new #define START gsd_mouse_manager_start #define STOP gsd_mouse_manager_stop #define MANAGER GsdMouseManager #include "gsd-mouse-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/orientation/0000775000000000000000000000000015172222611016230 5ustar unity-settings-daemon/plugins/orientation/Makefile.am0000664000000000000000000000320315172222611020262 0ustar plugin_name = orientation libexec_PROGRAMS = usd-test-orientation usd_test_orientation_SOURCES = \ gsd-orientation-manager.h \ gsd-orientation-manager.c \ test-orientation.c usd_test_orientation_CFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(ORIENTATION_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_orientation_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(ORIENTATION_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = liborientation.la liborientation_la_SOURCES = \ gsd-orientation-plugin.c \ gsd-orientation-manager.h \ gsd-orientation-manager.c liborientation_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common/ \ -I$(top_srcdir)/data/ \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) liborientation_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(ORIENTATION_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) liborientation_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) liborientation_la_LIBADD = \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(ORIENTATION_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = orientation.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = $(plugin_in_files) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/orientation/gsd-orientation-manager.c0000664000000000000000000004766715172222611023136 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2010,2011 Red Hat, Inc. * * Author: Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "gsd-input-helper.h" #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #include "gsd-orientation-manager.h" #include "gsd-rr.h" typedef enum { ORIENTATION_UNDEFINED, ORIENTATION_NORMAL, ORIENTATION_BOTTOM_UP, ORIENTATION_LEFT_UP, ORIENTATION_RIGHT_UP } OrientationUp; #define GSD_ORIENTATION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_ORIENTATION_MANAGER, GsdOrientationManagerPrivate)) struct GsdOrientationManagerPrivate { guint start_idle_id; guint name_id; /* Accelerometer */ char *sysfs_path; OrientationUp prev_orientation; /* DBus */ GDBusNodeInfo *introspection_data; GDBusConnection *connection; GDBusProxy *xrandr_proxy; GCancellable *cancellable; /* Notifications */ GUdevClient *client; GSettings *settings; gboolean orientation_lock; }; #define CONF_SCHEMA "com.canonical.unity.settings-daemon.peripherals.touchscreen" #define ORIENTATION_LOCK_KEY "orientation-lock" #define GSD_ORIENTATION_DBUS_NAME GSD_DBUS_NAME ".Orientation" #define GSD_ORIENTATION_DBUS_PATH GSD_DBUS_PATH "/Orientation" static const gchar introspection_xml[] = "" " " " " " " ""; static void gsd_orientation_manager_class_init (GsdOrientationManagerClass *klass); static void gsd_orientation_manager_init (GsdOrientationManager *orientation_manager); static void gsd_orientation_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdOrientationManager, gsd_orientation_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; #define MPU_THRESHOLD 12000 #define MPU_POLL_INTERVAL 1 static gboolean is_mpu6050 = FALSE; static char *mpu6050_accel_x = NULL; static char *mpu6050_accel_y = NULL; static gboolean mpu_timer(GsdOrientationManager *manager); static GObject * gsd_orientation_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdOrientationManager *orientation_manager; orientation_manager = GSD_ORIENTATION_MANAGER (G_OBJECT_CLASS (gsd_orientation_manager_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (orientation_manager); } static void gsd_orientation_manager_dispose (GObject *object) { G_OBJECT_CLASS (gsd_orientation_manager_parent_class)->dispose (object); } static void gsd_orientation_manager_class_init (GsdOrientationManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_orientation_manager_constructor; object_class->dispose = gsd_orientation_manager_dispose; object_class->finalize = gsd_orientation_manager_finalize; g_type_class_add_private (klass, sizeof (GsdOrientationManagerPrivate)); } static void gsd_orientation_manager_init (GsdOrientationManager *manager) { manager->priv = GSD_ORIENTATION_MANAGER_GET_PRIVATE (manager); manager->priv->prev_orientation = ORIENTATION_UNDEFINED; } static GsdRRRotation orientation_to_rotation (OrientationUp orientation) { switch (orientation) { case ORIENTATION_NORMAL: return GSD_RR_ROTATION_0; case ORIENTATION_BOTTOM_UP: return GSD_RR_ROTATION_180; case ORIENTATION_LEFT_UP: return GSD_RR_ROTATION_90; case ORIENTATION_RIGHT_UP: return GSD_RR_ROTATION_270; default: g_assert_not_reached (); } } static OrientationUp orientation_from_string (const char *orientation) { if (g_strcmp0 (orientation, "normal") == 0) return ORIENTATION_NORMAL; if (g_strcmp0 (orientation, "bottom-up") == 0) return ORIENTATION_BOTTOM_UP; if (g_strcmp0 (orientation, "left-up") == 0) return ORIENTATION_LEFT_UP; if (g_strcmp0 (orientation, "right-up") == 0) return ORIENTATION_RIGHT_UP; return ORIENTATION_UNDEFINED; } static const char * orientation_to_string (OrientationUp o) { switch (o) { case ORIENTATION_UNDEFINED: return "undefined"; case ORIENTATION_NORMAL: return "normal"; case ORIENTATION_BOTTOM_UP: return "bottom-up"; case ORIENTATION_LEFT_UP: return "left-up"; case ORIENTATION_RIGHT_UP: return "right-up"; default: g_assert_not_reached (); } } static OrientationUp get_orientation_from_device (GUdevDevice *dev) { const char *value; value = g_udev_device_get_property (dev, "ID_INPUT_ACCELEROMETER_ORIENTATION"); if (value == NULL) { g_debug ("Couldn't find orientation for accelerometer %s", g_udev_device_get_sysfs_path (dev)); return ORIENTATION_UNDEFINED; } g_debug ("Found orientation '%s' for accelerometer %s", value, g_udev_device_get_sysfs_path (dev)); return orientation_from_string (value); } static void on_xrandr_action_call_finished (GObject *source_object, GAsyncResult *res, GsdOrientationManager *manager) { GError *error = NULL; GVariant *variant; variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); g_object_unref (manager->priv->cancellable); manager->priv->cancellable = NULL; if (error != NULL) { g_warning ("Unable to call 'RotateTo': %s", error->message); g_error_free (error); } else { g_variant_unref (variant); } } static void do_xrandr_action (GsdOrientationManager *manager, GsdRRRotation rotation) { GsdOrientationManagerPrivate *priv = manager->priv; GTimeVal tv; gint64 timestamp; if (priv->connection == NULL || priv->xrandr_proxy == NULL) { g_warning ("No existing D-Bus connection trying to handle XRANDR keys"); return; } if (priv->cancellable != NULL) { g_debug ("xrandr action already in flight"); return; } g_get_current_time (&tv); timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000; priv->cancellable = g_cancellable_new (); g_dbus_proxy_call (priv->xrandr_proxy, "RotateTo", g_variant_new ("(ix)", rotation, timestamp), G_DBUS_CALL_FLAGS_NONE, -1, priv->cancellable, (GAsyncReadyCallback) on_xrandr_action_call_finished, manager); } static void do_rotation (GsdOrientationManager *manager) { GsdRRRotation rotation; if (manager->priv->orientation_lock) { g_debug ("Orientation changed, but we are locked"); return; } if (manager->priv->prev_orientation == ORIENTATION_UNDEFINED) { g_debug ("Not trying to rotate, orientation is undefined"); return; } rotation = orientation_to_rotation (manager->priv->prev_orientation); do_xrandr_action (manager, rotation); } static void client_uevent_cb (GUdevClient *client, gchar *action, GUdevDevice *device, GsdOrientationManager *manager) { const char *sysfs_path; OrientationUp orientation; sysfs_path = g_udev_device_get_sysfs_path (device); g_debug ("Received uevent '%s' from '%s'", action, sysfs_path); if (manager->priv->orientation_lock) return; if (g_str_equal (action, "change") == FALSE) return; if (g_strcmp0 (manager->priv->sysfs_path, sysfs_path) != 0) return; g_debug ("Received an event from the accelerometer"); orientation = get_orientation_from_device (device); if (orientation != manager->priv->prev_orientation) { manager->priv->prev_orientation = orientation; g_debug ("Orientation changed to '%s', switching screen rotation", orientation_to_string (manager->priv->prev_orientation)); do_rotation (manager); } } static void orientation_lock_changed_cb (GSettings *settings, gchar *key, GsdOrientationManager *manager) { gboolean new; new = g_settings_get_boolean (settings, key); if (new == manager->priv->orientation_lock) return; manager->priv->orientation_lock = new; if (new == FALSE) { if (is_mpu6050) { g_timeout_add_seconds(MPU_POLL_INTERVAL, (GSourceFunc) mpu_timer, manager); } /* Handle the rotations that could have occurred while * we were locked */ do_rotation (manager); } } static void xrandr_ready_cb (GObject *source_object, GAsyncResult *res, GsdOrientationManager *manager) { GError *error = NULL; manager->priv->xrandr_proxy = g_dbus_proxy_new_finish (res, &error); if (manager->priv->xrandr_proxy == NULL) { g_warning ("Failed to get proxy for XRandR operations: %s", error->message); g_error_free (error); } } static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdOrientationManager *manager) { GDBusConnection *connection; GError *error = NULL; connection = g_bus_get_finish (res, &error); if (connection == NULL) { g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; g_dbus_connection_register_object (connection, GSD_ORIENTATION_DBUS_PATH, manager->priv->introspection_data->interfaces[0], NULL, NULL, NULL, NULL); g_dbus_proxy_new (manager->priv->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, GSD_DBUS_NAME ".XRANDR", GSD_DBUS_PATH "/XRANDR", GSD_DBUS_BASE_INTERFACE ".XRANDR_2", NULL, (GAsyncReadyCallback) xrandr_ready_cb, manager); manager->priv->name_id = g_bus_own_name_on_connection (connection, GSD_ORIENTATION_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); } static GUdevDevice * get_accelerometer (GUdevClient *client) { GList *list, *listiio, *l; GUdevDevice *ret, *parent; /* Look for a device with the ID_INPUT_ACCELEROMETER=1 property */ ret = NULL; list = g_udev_client_query_by_subsystem (client, "input"); listiio = g_udev_client_query_by_subsystem (client, "iio"); list = g_list_concat(list, listiio); for (l = list; l != NULL; l = l->next) { GUdevDevice *dev; dev = l->data; if (g_udev_device_get_property_as_boolean (dev, "ID_INPUT_ACCELEROMETER")) { ret = dev; continue; } g_object_unref (dev); } g_list_free (list); if (ret == NULL) return NULL; /* Now walk up to the parent */ parent = g_udev_device_get_parent (ret); if (parent == NULL) return ret; if (g_udev_device_get_property_as_boolean (parent, "ID_INPUT_ACCELEROMETER")) { g_object_unref (ret); ret = parent; } else { g_object_unref (parent); } return ret; } static int read_sysfs_attr_as_int(const char *filename) { int i, c; char buf[40]; int fd = open(filename, O_RDONLY); if (fd < 0) return 0; c = read(fd, buf, 40); if (c < 0) return 0; close(fd); sscanf(buf, "%d", &i); return i; } static gboolean mpu_timer(GsdOrientationManager *manager) { int x, y; static gboolean first = TRUE; OrientationUp orientation = manager->priv->prev_orientation; if (manager->priv->xrandr_proxy == NULL) return TRUE; x = read_sysfs_attr_as_int(mpu6050_accel_x); y = read_sysfs_attr_as_int(mpu6050_accel_y); if (x > MPU_THRESHOLD) orientation = ORIENTATION_NORMAL; if (x < -MPU_THRESHOLD) orientation = ORIENTATION_BOTTOM_UP; if (y > MPU_THRESHOLD) orientation = ORIENTATION_RIGHT_UP; if (y < -MPU_THRESHOLD) orientation = ORIENTATION_LEFT_UP; if (orientation != manager->priv->prev_orientation || first) { first = FALSE; manager->priv->prev_orientation = orientation; g_debug ("Orientation changed to '%s', switching screen rotation", orientation_to_string (manager->priv->prev_orientation)); do_rotation (manager); } return !manager->priv->orientation_lock; } static gboolean gsd_orientation_manager_idle_cb (GsdOrientationManager *manager) { const char * const subsystems[] = { "input", NULL }; GUdevDevice *dev; gnome_settings_profile_start (NULL); manager->priv->start_idle_id = 0; manager->priv->settings = g_settings_new (CONF_SCHEMA); g_signal_connect (G_OBJECT (manager->priv->settings), "changed::orientation-lock", G_CALLBACK (orientation_lock_changed_cb), manager); manager->priv->orientation_lock = g_settings_get_boolean (manager->priv->settings, ORIENTATION_LOCK_KEY); manager->priv->client = g_udev_client_new (subsystems); dev = get_accelerometer (manager->priv->client); if (dev == NULL) { g_debug ("Did not find an accelerometer"); gnome_settings_profile_end (NULL); return FALSE; } manager->priv->sysfs_path = g_strdup (g_udev_device_get_sysfs_path (dev)); g_debug ("Found accelerometer at sysfs path '%s'", manager->priv->sysfs_path); manager->priv->prev_orientation = get_orientation_from_device (dev); /* Poll the sysfs attributes exposed by MPU6050 as it is not an uevent based input driver */ if (g_strcmp0 (g_udev_device_get_sysfs_attr (dev, "name"), "mpu6050") == 0) { manager->priv->prev_orientation = ORIENTATION_NORMAL; g_timeout_add_seconds(MPU_POLL_INTERVAL, (GSourceFunc) mpu_timer, manager); mpu6050_accel_x = g_build_filename(manager->priv->sysfs_path, "in_accel_x_raw", NULL); mpu6050_accel_y = g_build_filename(manager->priv->sysfs_path, "in_accel_y_raw", NULL); is_mpu6050 = TRUE; } g_object_unref (dev); /* Start process of owning a D-Bus name */ g_bus_get (G_BUS_TYPE_SESSION, NULL, (GAsyncReadyCallback) on_bus_gotten, manager); g_signal_connect (G_OBJECT (manager->priv->client), "uevent", G_CALLBACK (client_uevent_cb), manager); gnome_settings_profile_end (NULL); return FALSE; } gboolean gsd_orientation_manager_start (GsdOrientationManager *manager, GError **error) { gnome_settings_profile_start (NULL); manager->priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_orientation_manager_idle_cb, manager); manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (manager->priv->introspection_data != NULL); gnome_settings_profile_end (NULL); return TRUE; } void gsd_orientation_manager_stop (GsdOrientationManager *manager) { GsdOrientationManagerPrivate *p = manager->priv; g_debug ("Stopping orientation manager"); if (p->settings) { g_object_unref (p->settings); p->settings = NULL; } if (p->sysfs_path) { g_free (p->sysfs_path); p->sysfs_path = NULL; } if (p->introspection_data) { g_dbus_node_info_unref (p->introspection_data); p->introspection_data = NULL; } if (p->client) { g_object_unref (p->client); p->client = NULL; } } static void gsd_orientation_manager_finalize (GObject *object) { GsdOrientationManager *orientation_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_ORIENTATION_MANAGER (object)); orientation_manager = GSD_ORIENTATION_MANAGER (object); g_return_if_fail (orientation_manager->priv != NULL); if (orientation_manager->priv->start_idle_id != 0) g_source_remove (orientation_manager->priv->start_idle_id); if (orientation_manager->priv->name_id != 0) g_bus_unown_name (orientation_manager->priv->name_id); G_OBJECT_CLASS (gsd_orientation_manager_parent_class)->finalize (object); } GsdOrientationManager * gsd_orientation_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_ORIENTATION_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_ORIENTATION_MANAGER (manager_object); } unity-settings-daemon/plugins/orientation/gsd-orientation-manager.h0000664000000000000000000000472015172222611023122 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_ORIENTATION_MANAGER_H #define __GSD_ORIENTATION_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_ORIENTATION_MANAGER (gsd_orientation_manager_get_type ()) #define GSD_ORIENTATION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_ORIENTATION_MANAGER, GsdOrientationManager)) #define GSD_ORIENTATION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_ORIENTATION_MANAGER, GsdOrientationManagerClass)) #define GSD_IS_ORIENTATION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_ORIENTATION_MANAGER)) #define GSD_IS_ORIENTATION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_ORIENTATION_MANAGER)) #define GSD_ORIENTATION_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_ORIENTATION_MANAGER, GsdOrientationManagerClass)) typedef struct GsdOrientationManagerPrivate GsdOrientationManagerPrivate; typedef struct { GObject parent; GsdOrientationManagerPrivate *priv; } GsdOrientationManager; typedef struct { GObjectClass parent_class; } GsdOrientationManagerClass; GType gsd_orientation_manager_get_type (void); GsdOrientationManager * gsd_orientation_manager_new (void); gboolean gsd_orientation_manager_start (GsdOrientationManager *manager, GError **error); void gsd_orientation_manager_stop (GsdOrientationManager *manager); G_END_DECLS #endif /* __GSD_ORIENTATION_MANAGER_H */ unity-settings-daemon/plugins/orientation/gsd-orientation-plugin.c0000664000000000000000000000210315172222611022772 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-orientation-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdOrientation, gsd_orientation) unity-settings-daemon/plugins/orientation/orientation.gnome-settings-plugin.in0000664000000000000000000000030215172222611025344 0ustar [GNOME Settings Plugin] Module=orientation IAge=0 # Default Priority # Priority=100 _Name=Orientation _Description=Orientation plugin Authors=Peter Hutterer Copyright=Copyright © 2010 Website= unity-settings-daemon/plugins/orientation/test-orientation.c0000664000000000000000000000034315172222611021704 0ustar #define NEW gsd_orientation_manager_new #define START gsd_orientation_manager_start #define STOP gsd_orientation_manager_stop #define MANAGER GsdOrientationManager #include "gsd-orientation-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/power/0000775000000000000000000000000015172222611015031 5ustar unity-settings-daemon/plugins/power/Makefile.am0000664000000000000000000001266415172222611017076 0ustar BUILT_SOURCES = plugin_name = power plugin_LTLIBRARIES = \ libpower.la libpower_la_SOURCES = \ gpm-common.c \ gpm-common.h \ gsd-backlight-linux.c \ gsd-backlight-linux.h \ gsd-power-manager.c \ gsd-power-manager.h \ gsm-inhibitor-flag.h \ gsm-presence-flag.h \ gsm-manager-logout-mode.h \ gsd-power-constants.h \ gsd-power-plugin.c libpower_la_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ -DSBINDIR=\"$(sbindir)\" \ -DLIBEXECDIR=\"$(libexecdir)\" \ $(AM_CPPFLAGS) libpower_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(POWER_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libpower_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libpower_la_LIBADD = \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(POWER_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = \ power.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) com.ubuntu.unity-settings-daemon.plugins.power.policy.in: com.ubuntu.unity-settings-daemon.plugins.power.policy.in.in Makefile $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ @INTLTOOL_POLICY_RULE@ polkit_policydir = $(datadir)/polkit-1/actions polkit_policy_in_files = com.ubuntu.unity-settings-daemon.plugins.power.policy.in polkit_policy_DATA = $(polkit_policy_in_files:.policy.in=.policy) # so it always gets included in the tarball usd_backlight_helper_SOURCES = \ gsd-backlight-linux.c \ gsd-backlight-linux.h \ gsd-backlight-helper.c noinst_PROGRAMS = usd-test-power usd_test_power_SOURCES = \ gpm-common.c \ gpm-common.h \ gsd-backlight-linux.c \ gsd-backlight-linux.h \ gsd-power-manager.c \ gsd-power-manager.h \ gsm-inhibitor-flag.h \ gsm-presence-flag.h \ gsm-manager-logout-mode.h \ test-power.c usd_test_power_CFLAGS = $(libpower_la_CFLAGS) usd_test_power_CPPFLAGS = $(libpower_la_CPPFLAGS) -DGSD_MOCK=1 -DGSD_ACTION_DELAY=1 usd_test_power_LDADD = \ -lm \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(POWER_LIBS) \ $(SETTINGS_PLUGIN_LIBS) EXTRA_DIST = \ $(plugin_in_files) \ $(gsd_backlight_helper_SOURCES) \ $(NULL) if HAVE_GUDEV libexec_PROGRAMS = usd-backlight-helper usd_backlight_helper_LDFLAGS = \ $(BACKLIGHT_HELPER_LIBS) \ -lm usd_backlight_helper_CFLAGS = \ $(BACKLIGHT_HELPER_CFLAGS) EXTRA_DIST += \ com.ubuntu.unity-settings-daemon.plugins.power.policy.in.in endif # Enums GSD_POWER_ENUM_FILES = gsd-power-enums.c gsd-power-enums.h gsd-power-enums.h: gsm-inhibitor-flag.h gsm-presence-flag.h Makefile $(AM_V_GEN)($(GLIB_MKENUMS) \ --fhead "#ifndef GSD_POWER_ENUMS_H\n#define GSD_POWER_ENUMS_H\n\n#include \n\nG_BEGIN_DECLS\n" \ --fprod "/* enumerations from \"@filename@\" */\n" \ --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define GSD_POWER_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ --ftail "G_END_DECLS\n\n#endif /* !GSD_POWER_ENUMS_H */" $(srcdir)/gsm-inhibitor-flag.h $(srcdir)/gsm-presence-flag.h > $@) gsd-power-enums.c: gsd-power-constants.h gsm-inhibitor-flag.h gsm-presence-flag.h Makefile gsd-power-enums.h $(AM_V_GEN)($(GLIB_MKENUMS) \ --fhead "#include \"gsm-inhibitor-flag.h\"\n#include \"gsm-presence-flag.h\"\n#include \"gsd-power-enums.h\"" \ --fprod "\n/* enumerations from \"@filename@\" */" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $(srcdir)/gsm-inhibitor-flag.h $(srcdir)/gsm-presence-flag.h > $@) BUILT_SOURCES += $(GSD_POWER_ENUM_FILES) gsdpowerconstants.py: gsd-power-constants-update.pl gsd-power-constants.h $(AM_V_GEN) $(srcdir)/gsd-power-constants-update.pl gsdpowerenums.py: gsd-power-enums-update gsd-power-enums.h gsd-power-enums.c $(AM_V_GEN) $(builddir)/gsd-power-enums-update > $@ noinst_PROGRAMS += gsd-power-enums-update gsd_power_enums_update_SOURCES = \ gsd-power-enums-update.c \ gsd-power-enums.h \ gsd-power-enums.c gsd_power_enums_update_CFLAGS = $(libpower_la_CFLAGS) gsd_power_enums_update_CPPFLAGS = $(libpower_la_CPPFLAGS) -I$(top_builddir)/plugins/power gsd_power_enums_update_LDFLAGS = $(POWER_LIBS) EXTRA_DIST += gsd-power-constants-update.pl gsdpowerconstants.py gsdpowerenums.py test.py check-local: $(top_builddir)/tests/shiftkey usd-test-power test.py gsdpowerconstants.py gsdpowerenums.py # This is how you run a single test # BUILDDIR=$(builddir) TOP_BUILDDIR=$(top_builddir) ${PYTHON} $(srcdir)/test.py PowerPluginTest.test_sleep_inactive_blank BUILDDIR=$(builddir) TOP_BUILDDIR=$(top_builddir) ${PYTHON} $(srcdir)/test.py clean-local: rm -f *~ CLEANFILES = \ $(plugin_DATA) \ $(GSD_POWER_ENUM_FILES) \ gsdpowerenums.py \ com.ubuntu.unity-settings-daemon.plugins.power.policy \ com.ubuntu.unity-settings-daemon.plugins.power.policy.in @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/power/com.ubuntu.unity-settings-daemon.plugins.power.policy.in.in0000664000000000000000000000223015172222611030441 0ustar Unity Settings Daemon http://git.gnome.org/browse/gnome-settings-daemon battery <_description>Modify the laptop brightness <_message>Authentication is required to modify the laptop brightness no no yes @libexecdir@/usd-backlight-helper unity-settings-daemon/plugins/power/gpm-common.c0000664000000000000000000020245215172222611017253 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2005-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "gpm-common.h" #include "gsd-power-constants.h" #include "gsd-power-manager.h" #include "gsd-backlight-linux.h" #include "gsd-rr.h" #define XSCREENSAVER_WATCHDOG_TIMEOUT 120 /* seconds */ #define UPS_SOUND_LOOP_ID 99 #define GSD_POWER_MANAGER_CRITICAL_ALERT_TIMEOUT 5 /* seconds */ /* take a discrete value with offset and convert to percentage */ int gsd_power_backlight_abs_to_percentage (int min, int max, int value) { g_return_val_if_fail (max > min, -1); g_return_val_if_fail (value >= min, -1); g_return_val_if_fail (value <= max, -1); return (((value - min) * 100) / (max - min)); } #define GPM_UP_TIME_PRECISION 5*60 #define GPM_UP_TEXT_MIN_TIME 120 /** * Return value: The time string, e.g. "2 hours 3 minutes" **/ gchar * gpm_get_timestring (guint time_secs) { char* timestring = NULL; gint hours; gint minutes; /* Add 0.5 to do rounding */ minutes = (int) ( ( time_secs / 60.0 ) + 0.5 ); if (minutes == 0) { timestring = g_strdup (_("Unknown time")); return timestring; } if (minutes < 60) { timestring = g_strdup_printf (ngettext ("%i minute", "%i minutes", minutes), minutes); return timestring; } hours = minutes / 60; minutes = minutes % 60; if (minutes == 0) timestring = g_strdup_printf (ngettext ( "%i hour", "%i hours", hours), hours); else /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" * Swap order with "%2$s %2$i %1$s %1$i if needed */ timestring = g_strdup_printf (_("%i %s %i %s"), hours, ngettext ("hour", "hours", hours), minutes, ngettext ("minute", "minutes", minutes)); return timestring; } static const gchar * gpm_upower_get_device_icon_index (UpDevice *device) { gdouble percentage; /* get device properties */ g_object_get (device, "percentage", &percentage, NULL); if (percentage < 10) return "000"; else if (percentage < 30) return "020"; else if (percentage < 50) return "040"; else if (percentage < 70) return "060"; else if (percentage < 90) return "080"; return "100"; } static const gchar * gpm_upower_get_device_icon_suffix (UpDevice *device) { gdouble percentage; /* get device properties */ g_object_get (device, "percentage", &percentage, NULL); if (percentage < 10) return "caution"; else if (percentage < 30) return "low"; else if (percentage < 60) return "good"; return "full"; } GIcon * gpm_upower_get_device_icon (UpDevice *device, gboolean use_symbolic) { GString *filename; gchar **iconnames; const gchar *kind_str; const gchar *suffix_str; const gchar *index_str; UpDeviceKind kind; UpDeviceState state; gboolean is_present; gdouble percentage; GIcon *icon = NULL; g_return_val_if_fail (device != NULL, NULL); /* get device properties */ g_object_get (device, "kind", &kind, "state", &state, "percentage", &percentage, "is-present", &is_present, NULL); /* get correct icon prefix */ filename = g_string_new (NULL); /* get the icon from some simple rules */ if (kind == UP_DEVICE_KIND_LINE_POWER) { if (use_symbolic) g_string_append (filename, "ac-adapter-symbolic;"); g_string_append (filename, "ac-adapter;"); } else if (kind == UP_DEVICE_KIND_MONITOR) { if (use_symbolic) g_string_append (filename, "gpm-monitor-symbolic;"); g_string_append (filename, "gpm-monitor;"); } else { kind_str = up_device_kind_to_string (kind); if (!is_present) { if (use_symbolic) g_string_append (filename, "battery-missing-symbolic;"); g_string_append_printf (filename, "gpm-%s-missing;", kind_str); g_string_append_printf (filename, "gpm-%s-000;", kind_str); g_string_append (filename, "battery-missing;"); } else { switch (state) { case UP_DEVICE_STATE_EMPTY: if (use_symbolic) g_string_append (filename, "battery-empty-symbolic;"); g_string_append_printf (filename, "gpm-%s-empty;", kind_str); g_string_append_printf (filename, "gpm-%s-000;", kind_str); g_string_append (filename, "battery-empty;"); break; case UP_DEVICE_STATE_FULLY_CHARGED: if (use_symbolic) { g_string_append (filename, "battery-full-charged-symbolic;"); g_string_append (filename, "battery-full-charging-symbolic;"); } g_string_append_printf (filename, "gpm-%s-full;", kind_str); g_string_append_printf (filename, "gpm-%s-100;", kind_str); g_string_append (filename, "battery-full-charged;"); g_string_append (filename, "battery-full-charging;"); break; case UP_DEVICE_STATE_CHARGING: case UP_DEVICE_STATE_PENDING_CHARGE: suffix_str = gpm_upower_get_device_icon_suffix (device); index_str = gpm_upower_get_device_icon_index (device); if (use_symbolic) g_string_append_printf (filename, "battery-%s-charging-symbolic;", suffix_str); g_string_append_printf (filename, "gpm-%s-%s-charging;", kind_str, index_str); g_string_append_printf (filename, "battery-%s-charging;", suffix_str); break; case UP_DEVICE_STATE_DISCHARGING: case UP_DEVICE_STATE_PENDING_DISCHARGE: suffix_str = gpm_upower_get_device_icon_suffix (device); index_str = gpm_upower_get_device_icon_index (device); if (use_symbolic) g_string_append_printf (filename, "battery-%s-symbolic;", suffix_str); g_string_append_printf (filename, "gpm-%s-%s;", kind_str, index_str); g_string_append_printf (filename, "battery-%s;", suffix_str); break; default: if (use_symbolic) g_string_append (filename, "battery-missing-symbolic;"); g_string_append (filename, "gpm-battery-missing;"); g_string_append (filename, "battery-missing;"); } } } /* nothing matched */ if (filename->len == 0) { g_warning ("nothing matched, falling back to default icon"); g_string_append (filename, "dialog-warning;"); } g_debug ("got filename: %s", filename->str); iconnames = g_strsplit (filename->str, ";", -1); icon = g_themed_icon_new_from_names (iconnames, -1); g_strfreev (iconnames); g_string_free (filename, TRUE); return icon; } /** * gpm_precision_round_down: * @value: The input value * @smallest: The smallest increment allowed * * 101, 10 100 * 95, 10 90 * 0, 10 0 * 112, 10 110 * 100, 10 100 **/ static gint gpm_precision_round_down (gfloat value, gint smallest) { gfloat division; if (fabs (value) < 0.01) return 0; if (smallest == 0) { g_warning ("divisor zero"); return 0; } division = (gfloat) value / (gfloat) smallest; division = floorf (division); division *= smallest; return (gint) division; } gchar * gpm_upower_get_device_summary (UpDevice *device) { const gchar *kind_desc = NULL; const gchar *device_desc = NULL; GString *description; guint time_to_full_round; guint time_to_empty_round; gchar *time_to_full_str = NULL; gchar *time_to_empty_str = NULL; UpDeviceKind kind; UpDeviceState state; gdouble percentage; gboolean is_present; gint64 time_to_full; gint64 time_to_empty; /* get device properties */ g_object_get (device, "kind", &kind, "state", &state, "percentage", &percentage, "is-present", &is_present, "time-to-full", &time_to_full, "time-to-empty", &time_to_empty, NULL); description = g_string_new (NULL); kind_desc = gpm_device_kind_to_localised_string (kind, 1); device_desc = gpm_device_to_localised_string (device); /* not installed */ if (!is_present) { g_string_append (description, device_desc); goto out; } /* don't display all the extra stuff for keyboards and mice */ if (kind == UP_DEVICE_KIND_MOUSE || kind == UP_DEVICE_KIND_KEYBOARD || kind == UP_DEVICE_KIND_PDA) { g_string_append (description, kind_desc); g_string_append_printf (description, " (%.0f%%)", percentage); goto out; } /* we care if we are on AC */ if (kind == UP_DEVICE_KIND_PHONE) { if (state == UP_DEVICE_STATE_CHARGING || !(state == UP_DEVICE_STATE_DISCHARGING)) { g_string_append (description, device_desc); g_string_append_printf (description, " (%.0f%%)", percentage); goto out; } g_string_append (description, kind_desc); g_string_append_printf (description, " (%.0f%%)", percentage); goto out; } /* precalculate so we don't get Unknown time remaining */ time_to_full_round = gpm_precision_round_down (time_to_full, GPM_UP_TIME_PRECISION); time_to_empty_round = gpm_precision_round_down (time_to_empty, GPM_UP_TIME_PRECISION); /* we always display "Laptop battery 16 minutes remaining" as we need to clarify what device we are refering to */ if (state == UP_DEVICE_STATE_FULLY_CHARGED) { g_string_append (description, device_desc); if (kind == UP_DEVICE_KIND_BATTERY && time_to_empty_round > GPM_UP_TEXT_MIN_TIME) { time_to_empty_str = gpm_get_timestring (time_to_empty_round); g_string_append (description, " - "); /* TRANSLATORS: The laptop battery is charged, and we know a time. * The parameter is the time, e.g. 7 hours 6 minutes */ g_string_append_printf (description, _("provides %s laptop runtime"), time_to_empty_str); } goto out; } if (state == UP_DEVICE_STATE_DISCHARGING) { if (time_to_empty_round > GPM_UP_TEXT_MIN_TIME) { time_to_empty_str = gpm_get_timestring (time_to_empty_round); /* TRANSLATORS: the device is discharging, and we have a time remaining * The first parameter is the device type, e.g. "Laptop battery" and * the second is the time, e.g. 7 hours 6 minutes */ g_string_append_printf (description, _("%s %s remaining"), kind_desc, time_to_empty_str); g_string_append_printf (description, " (%.0f%%)", percentage); } else { g_string_append (description, device_desc); g_string_append_printf (description, " (%.0f%%)", percentage); } goto out; } if (state == UP_DEVICE_STATE_CHARGING) { if (time_to_full_round > GPM_UP_TEXT_MIN_TIME && time_to_empty_round > GPM_UP_TEXT_MIN_TIME) { /* display both discharge and charge time */ time_to_full_str = gpm_get_timestring (time_to_full_round); time_to_empty_str = gpm_get_timestring (time_to_empty_round); /* TRANSLATORS: device is charging, and we have a time to full and a percentage * The first parameter is the device type, e.g. "Laptop battery" and * the second is the time, e.g. "7 hours 6 minutes" */ g_string_append_printf (description, _("%s %s until charged"), kind_desc, time_to_full_str); g_string_append_printf (description, " (%.0f%%)", percentage); g_string_append (description, " - "); /* TRANSLATORS: the device is charging, and we have a time to full and empty. * The parameter is a time string, e.g. "7 hours 6 minutes" */ g_string_append_printf (description, _("provides %s battery runtime"), time_to_empty_str); } else if (time_to_full_round > GPM_UP_TEXT_MIN_TIME) { /* display only charge time */ time_to_full_str = gpm_get_timestring (time_to_full_round); /* TRANSLATORS: device is charging, and we have a time to full and a percentage. * The first parameter is the device type, e.g. "Laptop battery" and * the second is the time, e.g. "7 hours 6 minutes" */ g_string_append_printf (description, _("%s %s until charged"), kind_desc, time_to_full_str); g_string_append_printf (description, " (%.0f%%)", percentage); } else { g_string_append (description, device_desc); g_string_append_printf (description, " (%.0f%%)", percentage); } goto out; } if (state == UP_DEVICE_STATE_PENDING_DISCHARGE) { g_string_append (description, device_desc); g_string_append_printf (description, " (%.0f%%)", percentage); goto out; } if (state == UP_DEVICE_STATE_PENDING_CHARGE) { g_string_append (description, device_desc); g_string_append_printf (description, " (%.0f%%)", percentage); goto out; } if (state == UP_DEVICE_STATE_EMPTY) { g_string_append (description, device_desc); goto out; } /* fallback */ g_warning ("in an undefined state we are not charging or " "discharging and the batteries are also not charged"); g_string_append (description, device_desc); g_string_append_printf (description, " (%.0f%%)", percentage); out: g_free (time_to_full_str); g_free (time_to_empty_str); return g_string_free (description, FALSE); } gchar * gpm_upower_get_device_description (UpDevice *device) { GString *details; const gchar *text; gchar *time_str; UpDeviceKind kind; UpDeviceState state; UpDeviceTechnology technology; gdouble percentage; gdouble capacity; gdouble energy; gdouble energy_full; gdouble energy_full_design; gdouble energy_rate; gboolean is_present; gint64 time_to_full; gint64 time_to_empty; gchar *vendor = NULL; gchar *serial = NULL; gchar *model = NULL; g_return_val_if_fail (device != NULL, NULL); /* get device properties */ g_object_get (device, "kind", &kind, "state", &state, "percentage", &percentage, "is-present", &is_present, "time-to-full", &time_to_full, "time-to-empty", &time_to_empty, "technology", &technology, "capacity", &capacity, "energy", &energy, "energy-full", &energy_full, "energy-full-design", &energy_full_design, "energy-rate", &energy_rate, "vendor", &vendor, "serial", &serial, "model", &model, NULL); details = g_string_new (""); text = gpm_device_kind_to_localised_string (kind, 1); /* TRANSLATORS: the type of data, e.g. Laptop battery */ g_string_append_printf (details, "%s %s\n", _("Product:"), text); if (!is_present) { /* TRANSLATORS: device is missing */ g_string_append_printf (details, "%s %s\n", _("Status:"), _("Missing")); } else if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: device is charged */ g_string_append_printf (details, "%s %s\n", _("Status:"), _("Charged")); } else if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: device is charging */ g_string_append_printf (details, "%s %s\n", _("Status:"), _("Charging")); } else if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: device is discharging */ g_string_append_printf (details, "%s %s\n", _("Status:"), _("Discharging")); } if (percentage >= 0) { /* TRANSLATORS: percentage */ g_string_append_printf (details, "%s %.1f%%\n", _("Percentage charge:"), percentage); } if (vendor) { /* TRANSLATORS: manufacturer */ g_string_append_printf (details, "%s %s\n", _("Vendor:"), vendor); } if (technology != UP_DEVICE_TECHNOLOGY_UNKNOWN) { text = gpm_device_technology_to_localised_string (technology); /* TRANSLATORS: how the battery is made, e.g. Lithium Ion */ g_string_append_printf (details, "%s %s\n", _("Technology:"), text); } if (serial) { /* TRANSLATORS: serial number of the battery */ g_string_append_printf (details, "%s %s\n", _("Serial number:"), serial); } if (model) { /* TRANSLATORS: model number of the battery */ g_string_append_printf (details, "%s %s\n", _("Model:"), model); } if (time_to_full > 0) { time_str = gpm_get_timestring (time_to_full); /* TRANSLATORS: time to fully charged */ g_string_append_printf (details, "%s %s\n", _("Charge time:"), time_str); g_free (time_str); } if (time_to_empty > 0) { time_str = gpm_get_timestring (time_to_empty); /* TRANSLATORS: time to empty */ g_string_append_printf (details, "%s %s\n", _("Discharge time:"), time_str); g_free (time_str); } if (capacity > 0) { const gchar *condition; if (capacity > 99) { /* TRANSLATORS: Excellent, Good, Fair and Poor are all related to battery Capacity */ condition = _("Excellent"); } else if (capacity > 90) { condition = _("Good"); } else if (capacity > 70) { condition = _("Fair"); } else { condition = _("Poor"); } /* TRANSLATORS: %.1f is a percentage and %s the condition (Excellent, Good, ...) */ g_string_append_printf (details, "%s %.1f%% (%s)\n", _("Capacity:"), capacity, condition); } if (kind == UP_DEVICE_KIND_BATTERY) { if (energy > 0) { /* TRANSLATORS: current charge */ g_string_append_printf (details, "%s %.1f Wh\n", _("Current charge:"), energy); } if (energy_full > 0 && energy_full_design != energy_full) { /* TRANSLATORS: last full is the charge the battery was seen to charge to */ g_string_append_printf (details, "%s %.1f Wh\n", _("Last full charge:"), energy_full); } if (energy_full_design > 0) { /* Translators: */ /* TRANSLATORS: Design charge is the amount of charge the battery is designed to have when brand new */ g_string_append_printf (details, "%s %.1f Wh\n", _("Design charge:"), energy_full_design); } if (energy_rate > 0) { /* TRANSLATORS: the charge or discharge rate */ g_string_append_printf (details, "%s %.1f W\n", _("Charge rate:"), energy_rate); } } if (kind == UP_DEVICE_KIND_MOUSE || kind == UP_DEVICE_KIND_KEYBOARD) { if (energy > 0) { /* TRANSLATORS: the current charge for CSR devices */ g_string_append_printf (details, "%s %.0f/7\n", _("Current charge:"), energy); } if (energy_full_design > 0) { /* TRANSLATORS: the design charge for CSR devices */ g_string_append_printf (details, "%s %.0f/7\n", _("Design charge:"), energy_full_design); } } /* remove the last \n */ g_string_truncate (details, details->len-1); g_free (vendor); g_free (serial); g_free (model); return g_string_free (details, FALSE); } const gchar * gpm_device_kind_to_localised_string (UpDeviceKind kind, guint number) { const gchar *text = NULL; switch (kind) { case UP_DEVICE_KIND_LINE_POWER: /* TRANSLATORS: system power cord */ text = ngettext ("AC adapter", "AC adapters", number); break; case UP_DEVICE_KIND_BATTERY: /* TRANSLATORS: laptop primary battery */ text = ngettext ("Laptop battery", "Laptop batteries", number); break; case UP_DEVICE_KIND_UPS: /* TRANSLATORS: battery-backed AC power source */ text = ngettext ("UPS", "UPSs", number); break; case UP_DEVICE_KIND_MONITOR: /* TRANSLATORS: a monitor is a device to measure voltage and current */ text = ngettext ("Monitor", "Monitors", number); break; case UP_DEVICE_KIND_MOUSE: /* TRANSLATORS: wireless mice with internal batteries */ text = ngettext ("Mouse", "Mice", number); break; case UP_DEVICE_KIND_KEYBOARD: /* TRANSLATORS: wireless keyboard with internal battery */ text = ngettext ("Keyboard", "Keyboards", number); break; case UP_DEVICE_KIND_PDA: /* TRANSLATORS: portable device */ text = ngettext ("PDA", "PDAs", number); break; case UP_DEVICE_KIND_PHONE: /* TRANSLATORS: cell phone (mobile...) */ text = ngettext ("Cell phone", "Cell phones", number); break; #if UP_CHECK_VERSION(0,9,5) case UP_DEVICE_KIND_MEDIA_PLAYER: /* TRANSLATORS: media player, mp3 etc */ text = ngettext ("Media player", "Media players", number); break; case UP_DEVICE_KIND_TABLET: /* TRANSLATORS: tablet device */ text = ngettext ("Tablet", "Tablets", number); break; case UP_DEVICE_KIND_COMPUTER: /* TRANSLATORS: tablet device */ text = ngettext ("Computer", "Computers", number); break; #endif default: g_warning ("enum unrecognised: %i", kind); text = up_device_kind_to_string (kind); } return text; } const gchar * gpm_device_kind_to_icon (UpDeviceKind kind) { const gchar *icon = NULL; switch (kind) { case UP_DEVICE_KIND_LINE_POWER: icon = "ac-adapter"; break; case UP_DEVICE_KIND_BATTERY: icon = "battery"; break; case UP_DEVICE_KIND_UPS: icon = "network-wired"; break; case UP_DEVICE_KIND_MONITOR: icon = "application-certificate"; break; case UP_DEVICE_KIND_MOUSE: icon = "input-mouse"; break; case UP_DEVICE_KIND_KEYBOARD: icon = "input-keyboard"; break; case UP_DEVICE_KIND_PDA: icon = "pda"; break; case UP_DEVICE_KIND_PHONE: icon = "phone"; break; #if UP_CHECK_VERSION(0,9,5) case UP_DEVICE_KIND_MEDIA_PLAYER: icon = "multimedia-player"; break; case UP_DEVICE_KIND_TABLET: icon = "input-tablet"; break; case UP_DEVICE_KIND_COMPUTER: icon = "computer-apple-ipad"; break; #endif default: g_warning ("enum unrecognised: %i", kind); icon = "gtk-help"; } return icon; } const gchar * gpm_device_technology_to_localised_string (UpDeviceTechnology technology_enum) { const gchar *technology = NULL; switch (technology_enum) { case UP_DEVICE_TECHNOLOGY_LITHIUM_ION: /* TRANSLATORS: battery technology */ technology = _("Lithium Ion"); break; case UP_DEVICE_TECHNOLOGY_LITHIUM_POLYMER: /* TRANSLATORS: battery technology */ technology = _("Lithium Polymer"); break; case UP_DEVICE_TECHNOLOGY_LITHIUM_IRON_PHOSPHATE: /* TRANSLATORS: battery technology */ technology = _("Lithium Iron Phosphate"); break; case UP_DEVICE_TECHNOLOGY_LEAD_ACID: /* TRANSLATORS: battery technology */ technology = _("Lead acid"); break; case UP_DEVICE_TECHNOLOGY_NICKEL_CADMIUM: /* TRANSLATORS: battery technology */ technology = _("Nickel Cadmium"); break; case UP_DEVICE_TECHNOLOGY_NICKEL_METAL_HYDRIDE: /* TRANSLATORS: battery technology */ technology = _("Nickel metal hydride"); break; case UP_DEVICE_TECHNOLOGY_UNKNOWN: /* TRANSLATORS: battery technology */ technology = _("Unknown technology"); break; default: g_assert_not_reached (); break; } return technology; } const gchar * gpm_device_state_to_localised_string (UpDeviceState state) { const gchar *state_string = NULL; switch (state) { case UP_DEVICE_STATE_CHARGING: /* TRANSLATORS: battery state */ state_string = _("Charging"); break; case UP_DEVICE_STATE_DISCHARGING: /* TRANSLATORS: battery state */ state_string = _("Discharging"); break; case UP_DEVICE_STATE_EMPTY: /* TRANSLATORS: battery state */ state_string = _("Empty"); break; case UP_DEVICE_STATE_FULLY_CHARGED: /* TRANSLATORS: battery state */ state_string = _("Charged"); break; case UP_DEVICE_STATE_PENDING_CHARGE: /* TRANSLATORS: battery state */ state_string = _("Waiting to charge"); break; case UP_DEVICE_STATE_PENDING_DISCHARGE: /* TRANSLATORS: battery state */ state_string = _("Waiting to discharge"); break; default: g_assert_not_reached (); break; } return state_string; } const gchar * gpm_device_to_localised_string (UpDevice *device) { UpDeviceState state; UpDeviceKind kind; gboolean present; /* get device parameters */ g_object_get (device, "is-present", &present, "kind", &kind, "state", &state, NULL); /* laptop battery */ if (kind == UP_DEVICE_KIND_BATTERY) { if (!present) { /* TRANSLATORS: device not present */ return _("Laptop battery not present"); } if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Laptop battery is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Laptop battery is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Laptop battery is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Laptop battery is charged"); } if (state == UP_DEVICE_STATE_PENDING_CHARGE) { /* TRANSLATORS: battery state */ return _("Laptop battery is waiting to charge"); } if (state == UP_DEVICE_STATE_PENDING_DISCHARGE) { /* TRANSLATORS: battery state */ return _("Laptop battery is waiting to discharge"); } } /* UPS */ if (kind == UP_DEVICE_KIND_UPS) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("UPS is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("UPS is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("UPS is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("UPS is charged"); } } /* mouse */ if (kind == UP_DEVICE_KIND_MOUSE) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Mouse is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Mouse is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Mouse is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Mouse is charged"); } } /* keyboard */ if (kind == UP_DEVICE_KIND_KEYBOARD) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Keyboard is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Keyboard is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Keyboard is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Keyboard is charged"); } } /* PDA */ if (kind == UP_DEVICE_KIND_PDA) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("PDA is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("PDA is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("PDA is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("PDA is charged"); } } /* phone */ if (kind == UP_DEVICE_KIND_PHONE) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Cell phone is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Cell phone is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Cell phone is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Cell phone is charged"); } } #if UP_CHECK_VERSION(0,9,5) /* media player */ if (kind == UP_DEVICE_KIND_MEDIA_PLAYER) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Media player is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Media player is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Media player is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Media player is charged"); } } /* tablet */ if (kind == UP_DEVICE_KIND_TABLET) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Tablet is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Tablet is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Tablet is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Tablet is charged"); } } /* computer */ if (kind == UP_DEVICE_KIND_COMPUTER) { if (state == UP_DEVICE_STATE_CHARGING) { /* TRANSLATORS: battery state */ return _("Computer is charging"); } if (state == UP_DEVICE_STATE_DISCHARGING) { /* TRANSLATORS: battery state */ return _("Computer is discharging"); } if (state == UP_DEVICE_STATE_EMPTY) { /* TRANSLATORS: battery state */ return _("Computer is empty"); } if (state == UP_DEVICE_STATE_FULLY_CHARGED) { /* TRANSLATORS: battery state */ return _("Computer is charged"); } } #endif return gpm_device_kind_to_localised_string (kind, 1); } static gboolean parse_vm_kernel_cmdline (gboolean *is_virtual_machine) { gboolean ret = FALSE; GRegex *regex; GMatchInfo *match; char *contents; char *word; const char *arg; if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, NULL)) return ret; regex = g_regex_new ("gnome.is_vm=(\\S+)", 0, G_REGEX_MATCH_NOTEMPTY, NULL); if (!g_regex_match (regex, contents, G_REGEX_MATCH_NOTEMPTY, &match)) goto out; word = g_match_info_fetch (match, 0); g_debug ("Found command-line match '%s'", word); arg = word + strlen ("gnome.is_vm="); if (*arg != '0' && *arg != '1') { g_warning ("Invalid value '%s' for gnome.is_vm passed in kernel command line.\n", arg); } else { *is_virtual_machine = atoi (arg); ret = TRUE; } g_free (word); out: g_match_info_free (match); g_regex_unref (regex); g_free (contents); if (ret) g_debug ("Kernel command-line parsed to %d", *is_virtual_machine); return ret; } gboolean gsd_power_is_hardware_a_vm (void) { const gchar *str; gboolean ret = FALSE; GError *error = NULL; GVariant *inner; GVariant *variant = NULL; GDBusConnection *connection; if (parse_vm_kernel_cmdline (&ret)) return ret; connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (connection == NULL) { g_warning ("system bus not available: %s", error->message); g_error_free (error); goto out; } variant = g_dbus_connection_call_sync (connection, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.DBus.Properties", "Get", g_variant_new ("(ss)", "org.freedesktop.systemd1.Manager", "Virtualization"), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_debug ("Failed to get property '%s': %s", "Virtualization", error->message); g_error_free (error); goto out; } /* on bare-metal hardware this is the empty string, * otherwise an identifier such as "kvm", "vmware", etc. */ g_variant_get (variant, "(v)", &inner); str = g_variant_get_string (inner, NULL); if (str != NULL && str[0] != '\0') ret = TRUE; out: if (connection != NULL) g_object_unref (connection); if (variant != NULL) g_variant_unref (variant); return ret; } /* This timer goes off every few minutes, whether the user is idle or not, to try and clean up anything that has gone wrong. It calls disable_builtin_screensaver() so that if xset has been used, or some other program (like xlock) has messed with the XSetScreenSaver() settings, they will be set back to sensible values (if a server extension is in use, messing with xlock can cause the screensaver to never get a wakeup event, and could cause monitor power-saving to occur, and all manner of heinousness.) This code was originally part of gnome-screensaver, see http://git.gnome.org/browse/gnome-screensaver/tree/src/gs-watcher-x11.c?id=fec00b12ec46c86334cfd36b37771cc4632f0d4d#n530 */ static gboolean disable_builtin_screensaver (gpointer unused) { int current_server_timeout, current_server_interval; int current_prefer_blank, current_allow_exp; int desired_server_timeout, desired_server_interval; int desired_prefer_blank, desired_allow_exp; XGetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ¤t_server_timeout, ¤t_server_interval, ¤t_prefer_blank, ¤t_allow_exp); desired_server_timeout = current_server_timeout; desired_server_interval = current_server_interval; desired_prefer_blank = current_prefer_blank; desired_allow_exp = current_allow_exp; desired_server_interval = 0; /* I suspect (but am not sure) that DontAllowExposures might have something to do with powering off the monitor as well, at least on some systems that don't support XDPMS? Who know... */ desired_allow_exp = AllowExposures; /* When we're not using an extension, set the server-side timeout to 0, so that the server never gets involved with screen blanking, and we do it all ourselves. (However, when we *are* using an extension, we tell the server when to notify us, and rather than blanking the screen, the server will send us an X event telling us to blank.) */ desired_server_timeout = 0; if (desired_server_timeout != current_server_timeout || desired_server_interval != current_server_interval || desired_prefer_blank != current_prefer_blank || desired_allow_exp != current_allow_exp) { g_debug ("disabling server builtin screensaver:" " (xset s %d %d; xset s %s; xset s %s)", desired_server_timeout, desired_server_interval, (desired_prefer_blank ? "blank" : "noblank"), (desired_allow_exp ? "expose" : "noexpose")); XSetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), desired_server_timeout, desired_server_interval, desired_prefer_blank, desired_allow_exp); XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); } return TRUE; } guint gsd_power_enable_screensaver_watchdog (void) { int dummy; /* Make sure that Xorg's DPMS extension never gets in our * way. The defaults are now applied in Fedora 20 from * being "0" by default to being "600" by default */ gdk_error_trap_push (); if (DPMSQueryExtension(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &dummy, &dummy)) DPMSSetTimeouts (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 0, 0, 0); gdk_error_trap_pop_ignored (); return g_timeout_add_seconds (XSCREENSAVER_WATCHDOG_TIMEOUT, disable_builtin_screensaver, NULL); } static GsdRROutput * get_primary_output (GsdRRScreen *rr_screen) { GsdRROutput *output = NULL; GsdRROutput **outputs; guint i; /* search all X11 outputs for the device id */ outputs = gsd_rr_screen_list_outputs (rr_screen); if (outputs == NULL) goto out; for (i = 0; outputs[i] != NULL; i++) { if (gsd_rr_output_is_connected (outputs[i]) && gsd_rr_output_is_laptop (outputs[i]) && gsd_rr_output_get_backlight_min (outputs[i]) >= 0 && gsd_rr_output_get_backlight_max (outputs[i]) > 0) { output = outputs[i]; break; } } out: return output; } #ifdef GSD_MOCK static void backlight_set_mock_value (gint value) { const char *filename; char *contents; g_debug ("Settings mock brightness: %d", value); filename = "GSD_MOCK_brightness"; contents = g_strdup_printf ("%d", value); g_file_set_contents (filename, contents, -1, NULL); g_free (contents); } static gint64 backlight_get_mock_value (const char *argument) { const char *filename; char *contents; gint64 ret; if (g_str_equal (argument, "get-max-brightness")) { g_debug ("Returning max mock brightness: %d", GSD_MOCK_MAX_BRIGHTNESS); return GSD_MOCK_MAX_BRIGHTNESS; } if (g_str_equal (argument, "get-brightness")) { filename = "GSD_MOCK_brightness"; ret = GSD_MOCK_DEFAULT_BRIGHTNESS; } else { g_assert_not_reached (); } if (g_file_get_contents (filename, &contents, NULL, NULL)) { ret = g_ascii_strtoll (contents, NULL, 0); g_free (contents); g_debug ("Returning mock brightness: %"G_GINT64_FORMAT, ret); } else { ret = GSD_MOCK_DEFAULT_BRIGHTNESS; backlight_set_mock_value (GSD_MOCK_DEFAULT_BRIGHTNESS); g_debug ("Returning default mock brightness: %"G_GINT64_FORMAT, ret); } return ret; } #endif /* GSD_MOCK */ gboolean backlight_available (GsdRRScreen *rr_screen) { char *path; #ifdef GSD_MOCK return TRUE; #endif if (get_primary_output (rr_screen) != NULL) return TRUE; path = gsd_backlight_helper_get_best_backlight (NULL); if (path == NULL) return FALSE; g_free (path); return TRUE; } /** * backlight_helper_get_value: * * Gets a brightness value from the PolicyKit helper. * * Return value: the signed integer value from the helper, or -1 * for failure. If -1 then @error is set. **/ static gint64 backlight_helper_get_value (const gchar *argument, GError **error) { gboolean ret; gchar *stdout_data = NULL; gint exit_status = 0; gint64 value = -1; gchar *command = NULL; gchar *endptr = NULL; #ifdef GSD_MOCK return backlight_get_mock_value (argument); #endif #ifndef __linux__ /* non-Linux platforms won't have /sys/class/backlight */ g_set_error_literal (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "The sysfs backlight helper is only for Linux"); goto out; #endif /* get the data */ command = g_strdup_printf (LIBEXECDIR "/usd-backlight-helper --%s", argument); ret = g_spawn_command_line_sync (command, &stdout_data, NULL, &exit_status, error); g_debug ("executed %s retval: %i", command, exit_status); if (!ret) goto out; if (WEXITSTATUS (exit_status) != 0) { g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "usd-backlight-helper failed: %s", stdout_data ? stdout_data : "No reason"); goto out; } /* parse */ value = g_ascii_strtoll (stdout_data, &endptr, 10); /* parsing error */ if (endptr == stdout_data) { value = -1; g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "failed to parse value: %s", stdout_data); goto out; } /* out of range */ if (value > G_MAXINT) { value = -1; g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "value out of range: %s", stdout_data); goto out; } /* Fetching the value failed, for some other reason */ if (value < 0) { g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "value negative, but helper did not fail: %s", stdout_data); goto out; } out: g_free (command); g_free (stdout_data); return value; } /** * backlight_helper_set_value: * * Sets a brightness value using the PolicyKit helper. * * Return value: Success. If FALSE then @error is set. **/ static gboolean backlight_helper_set_value (const gchar *argument, gint value, GError **error) { gboolean ret = FALSE; gint exit_status = 0; gchar *command = NULL; #ifdef GSD_MOCK backlight_set_mock_value (value); return TRUE; #endif #ifndef __linux__ /* non-Linux platforms won't have /sys/class/backlight */ g_set_error_literal (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "The sysfs backlight helper is only for Linux"); goto out; #endif /* get the data */ command = g_strdup_printf ("pkexec " LIBEXECDIR "/usd-backlight-helper --%s %i", argument, value); ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, error); g_debug ("executed %s retval: %i", command, exit_status); if (!ret || WEXITSTATUS (exit_status) != 0) goto out; out: g_free (command); return ret; } int backlight_get_abs (GsdRRScreen *rr_screen, GError **error) { GsdRROutput *output; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { return gsd_rr_output_get_backlight (output, error); } /* fall back to the polkit helper */ return backlight_helper_get_value ("get-brightness", error); } int backlight_get_percentage (GsdRRScreen *rr_screen, GError **error) { GsdRROutput *output; gint now; gint value = -1; gint min = 0; gint max; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { min = gsd_rr_output_get_backlight_min (output); max = gsd_rr_output_get_backlight_max (output); now = gsd_rr_output_get_backlight (output, error); if (now < 0) goto out; value = ABS_TO_PERCENTAGE (min, max, now); goto out; } /* fall back to the polkit helper */ max = backlight_helper_get_value ("get-max-brightness", error); if (max < 0) goto out; now = backlight_helper_get_value ("get-brightness", error); if (now < 0) goto out; value = ABS_TO_PERCENTAGE (min, max, now); out: return value; } int backlight_get_min (GsdRRScreen *rr_screen) { GsdRROutput *output; /* if we have no xbacklight device, then hardcode zero as sysfs * offsets everything to 0 as min */ output = get_primary_output (rr_screen); if (output == NULL) return 0; /* get xbacklight value, which maybe non-zero */ return gsd_rr_output_get_backlight_min (output); } int backlight_get_max (GsdRRScreen *rr_screen, GError **error) { gint value; GsdRROutput *output; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { value = gsd_rr_output_get_backlight_max (output); if (value < 0) { g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "failed to get backlight max"); } return value; } /* fall back to the polkit helper */ return backlight_helper_get_value ("get-max-brightness", error); } gboolean backlight_set_percentage (GsdRRScreen *rr_screen, guint value, GError **error) { GsdRROutput *output; gboolean ret = FALSE; gint min = 0; gint max; guint discrete; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { min = gsd_rr_output_get_backlight_min (output); max = gsd_rr_output_get_backlight_max (output); if (min < 0 || max < 0) { g_warning ("no xrandr backlight capability"); return ret; } discrete = PERCENTAGE_TO_ABS (min, max, value); ret = gsd_rr_output_set_backlight (output, discrete, error); return ret; } /* fall back to the polkit helper */ max = backlight_helper_get_value ("get-max-brightness", error); if (max < 0) return ret; discrete = PERCENTAGE_TO_ABS (min, max, value); ret = backlight_helper_set_value ("set-brightness", discrete, error); return ret; } int backlight_step_up (GsdRRScreen *rr_screen, GError **error) { GsdRROutput *output; gboolean ret = FALSE; gint percentage_value = -1; gint min = 0; gint max; gint now; gint step; guint discrete; GsdRRCrtc *crtc; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { crtc = gsd_rr_output_get_crtc (output); if (crtc == NULL) { g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "no crtc for %s", gsd_rr_output_get_name (output)); return percentage_value; } min = gsd_rr_output_get_backlight_min (output); max = gsd_rr_output_get_backlight_max (output); now = gsd_rr_output_get_backlight (output, error); if (now < 0) return percentage_value; step = BRIGHTNESS_STEP_AMOUNT (max - min + 1); discrete = MIN (now + step, max); ret = gsd_rr_output_set_backlight (output, discrete, error); if (ret) percentage_value = ABS_TO_PERCENTAGE (min, max, discrete); return percentage_value; } /* fall back to the polkit helper */ now = backlight_helper_get_value ("get-brightness", error); if (now < 0) return percentage_value; max = backlight_helper_get_value ("get-max-brightness", error); if (max < 0) return percentage_value; step = BRIGHTNESS_STEP_AMOUNT (max - min + 1); discrete = MIN (now + step, max); ret = backlight_helper_set_value ("set-brightness", discrete, error); if (ret) percentage_value = ABS_TO_PERCENTAGE (min, max, discrete); return percentage_value; } int backlight_step_down (GsdRRScreen *rr_screen, GError **error) { GsdRROutput *output; gboolean ret = FALSE; gint percentage_value = -1; gint min = 0; gint max; gint now; gint step; guint discrete; GsdRRCrtc *crtc; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { crtc = gsd_rr_output_get_crtc (output); if (crtc == NULL) { g_set_error (error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "no crtc for %s", gsd_rr_output_get_name (output)); return percentage_value; } min = gsd_rr_output_get_backlight_min (output); max = gsd_rr_output_get_backlight_max (output); now = gsd_rr_output_get_backlight (output, error); if (now < 0) return percentage_value; step = BRIGHTNESS_STEP_AMOUNT (max - min + 1); discrete = MAX (now - step, 0); ret = gsd_rr_output_set_backlight (output, discrete, error); if (ret) percentage_value = ABS_TO_PERCENTAGE (min, max, discrete); return percentage_value; } /* fall back to the polkit helper */ now = backlight_helper_get_value ("get-brightness", error); if (now < 0) return percentage_value; max = backlight_helper_get_value ("get-max-brightness", error); if (max < 0) return percentage_value; step = BRIGHTNESS_STEP_AMOUNT (max - min + 1); discrete = MAX (now - step, 0); ret = backlight_helper_set_value ("set-brightness", discrete, error); if (ret) percentage_value = ABS_TO_PERCENTAGE (min, max, discrete); return percentage_value; } int backlight_set_abs (GsdRRScreen *rr_screen, guint value, GError **error) { GsdRROutput *output; gboolean ret = FALSE; /* prefer xbacklight */ output = get_primary_output (rr_screen); if (output != NULL) { ret = gsd_rr_output_set_backlight (output, value, error); return ret; } /* fall back to the polkit helper */ ret = backlight_helper_set_value ("set-brightness", value, error); return ret; } void reset_idletime (void) { static gboolean inited = FALSE; static KeyCode keycode1, keycode2; static gboolean first_keycode = FALSE; if (inited == FALSE) { keycode1 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Shift_L); keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Shift_R); } gdk_error_trap_push (); /* send a left or right alt key; first press, then release */ XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), first_keycode ? keycode1 : keycode2, True, CurrentTime); XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), first_keycode ? keycode1 : keycode2, False, CurrentTime); first_keycode = !first_keycode; gdk_error_trap_pop_ignored (); } static gboolean randr_output_is_on (GsdRROutput *output) { GsdRRCrtc *crtc; crtc = gsd_rr_output_get_crtc (output); if (!crtc) return FALSE; return gsd_rr_crtc_get_current_mode (crtc) != NULL; } gboolean external_monitor_is_connected (GsdRRScreen *screen) { GsdRROutput **outputs; guint i; #ifdef GSD_MOCK char *mock_external_monitor_contents; if (g_file_get_contents ("GSD_MOCK_EXTERNAL_MONITOR", &mock_external_monitor_contents, NULL, NULL)) { if (mock_external_monitor_contents[0] == '1') { g_free (mock_external_monitor_contents); return TRUE; } else if (mock_external_monitor_contents[0] == '0') { g_free (mock_external_monitor_contents); return FALSE; } g_warning ("Unhandled value for GSD_MOCK_EXTERNAL_MONITOR contents: %s", mock_external_monitor_contents); g_free (mock_external_monitor_contents); } #endif /* GSD_MOCK */ /* see if we have more than one screen plugged in */ outputs = gsd_rr_screen_list_outputs (screen); for (i = 0; outputs[i] != NULL; i++) { if (randr_output_is_on (outputs[i]) && !gsd_rr_output_is_laptop (outputs[i])) return TRUE; } return FALSE; } static void play_sound (void) { ca_context_play (ca_gtk_context_get (), UPS_SOUND_LOOP_ID, CA_PROP_EVENT_ID, "battery-caution", CA_PROP_EVENT_DESCRIPTION, _("Battery is critically low"), NULL); } static gboolean play_loop_timeout_cb (gpointer user_data) { play_sound (); return TRUE; } void play_loop_start (guint *id) { if (*id != 0) return; *id = g_timeout_add_seconds (GSD_POWER_MANAGER_CRITICAL_ALERT_TIMEOUT, (GSourceFunc) play_loop_timeout_cb, NULL); play_sound (); } void play_loop_stop (guint *id) { if (*id == 0) return; ca_context_cancel (ca_gtk_context_get (), UPS_SOUND_LOOP_ID); g_source_remove (*id); *id = 0; } unity-settings-daemon/plugins/power/gpm-common.h0000664000000000000000000000771115172222611017261 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2005-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GPMCOMMON_H #define __GPMCOMMON_H #include #include #include "gsd-rr.h" G_BEGIN_DECLS /* UPower helpers */ gchar *gpm_get_timestring (guint time); const gchar *gpm_device_to_localised_string (UpDevice *device); const gchar *gpm_device_kind_to_localised_string (UpDeviceKind kind, guint number); const gchar *gpm_device_kind_to_icon (UpDeviceKind kind); const gchar *gpm_device_technology_to_localised_string (UpDeviceTechnology technology_enum); const gchar *gpm_device_state_to_localised_string (UpDeviceState state); GIcon *gpm_upower_get_device_icon (UpDevice *device, gboolean use_symbolic); gchar *gpm_upower_get_device_summary (UpDevice *device); gchar *gpm_upower_get_device_description (UpDevice *device); /* Power helpers */ gboolean gsd_power_is_hardware_a_vm (void); guint gsd_power_enable_screensaver_watchdog (void); void reset_idletime (void); /* Backlight helpers */ /* on ACPI machines we have 4-16 levels, on others it's ~150 */ #define BRIGHTNESS_STEP_AMOUNT(max) ((max) < 20 ? 1 : (max) / 20) #define ABS_TO_PERCENTAGE(min, max, value) gsd_power_backlight_abs_to_percentage(min, max, value) #define PERCENTAGE_TO_ABS(min, max, value) (min + (((max - min) * value) / 100)) int gsd_power_backlight_abs_to_percentage (int min, int max, int value); gboolean backlight_available (GsdRRScreen *rr_screen); int backlight_get_abs (GsdRRScreen *rr_screen, GError **error); int backlight_get_percentage (GsdRRScreen *rr_screen, GError **error); int backlight_get_min (GsdRRScreen *rr_screen); int backlight_get_max (GsdRRScreen *rr_screen, GError **error); gboolean backlight_set_percentage (GsdRRScreen *rr_screen, guint value, GError **error); int backlight_step_up (GsdRRScreen *rr_screen, GError **error); int backlight_step_down (GsdRRScreen *rr_screen, GError **error); int backlight_set_abs (GsdRRScreen *rr_screen, guint value, GError **error); /* RandR helpers */ gboolean external_monitor_is_connected (GsdRRScreen *screen); /* Sound helpers */ void play_loop_start (guint *id); void play_loop_stop (guint *id); G_END_DECLS #endif /* __GPMCOMMON_H */ unity-settings-daemon/plugins/power/gsd-backlight-helper.c0000664000000000000000000001623415172222611021163 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2010-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "gsd-backlight-linux.h" #define GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS 0 #define GSD_BACKLIGHT_HELPER_EXIT_CODE_FAILED 1 #define GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID 3 #define GSD_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER 4 #define GSD_BACKLIGHT_HELPER_EXIT_CODE_NO_DEVICES 5 static gboolean gsd_backlight_helper_write (const gchar *filename, gint value, GError **error) { gchar *filename_path = NULL; gchar *text = NULL; gint retval; gint length; gint fd = -1; gboolean ret = TRUE; filename_path = g_build_filename (filename, "brightness", NULL); fd = open (filename_path, O_WRONLY); if (fd < 0) { ret = FALSE; g_set_error (error, 1, 0, "failed to open filename: %s", filename); goto out; } /* convert to text */ text = g_strdup_printf ("%i", value); length = strlen (text); /* write to device file */ retval = write (fd, text, length); if (retval != length) { ret = FALSE; g_set_error (error, 1, 0, "writing '%s' to %s failed", text, filename); goto out; } out: if (fd >= 0) close (fd); g_free (text); g_free (filename_path); return ret; } static gint gsd_backlight_helper_read_value (const gchar *filename, GError **error) { gchar *contents = NULL; gint value; if (g_file_get_contents (filename, &contents, NULL, error)) value = atoi (contents); else value = -1; g_free (contents); if (value < 0 && *error == NULL) g_set_error (error, 1, 0, "got invalid backlight value from %s", filename); return value; } static gint gsd_backlight_helper_get (const gchar *filename, GError **error) { gchar *filename_path = NULL; gint value; filename_path = g_build_filename (filename, "brightness", NULL); value = gsd_backlight_helper_read_value (filename_path, error); g_free (filename_path); return value; } static gint gsd_backlight_helper_get_max (const gchar *filename, GError **error) { gchar *filename_path = NULL; gint value; filename_path = g_build_filename (filename, "max_brightness", NULL); value = gsd_backlight_helper_read_value (filename_path, error); g_free (filename_path); return value; } static gint clamp_minimum (gint max, gint value) { gint minimum; /* If the interface has less than 100 possible values, it's * likely that 0 doesn't turn the backlight off so we let 0 be * set in that case. */ if (max > 99) minimum = 1; else minimum = 0; return MAX (value, minimum); } int main (int argc, char *argv[]) { GOptionContext *context; gint uid; gint euid; guint retval = 0; GError *error = NULL; gint set_brightness = -1; gboolean get_brightness = FALSE; gboolean get_max_brightness = FALSE; gchar *filename = NULL; GsdBacklightType type; const GOptionEntry options[] = { { "set-brightness", '\0', 0, G_OPTION_ARG_INT, &set_brightness, /* command line argument */ "Set the current brightness", NULL }, { "get-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_brightness, /* command line argument */ "Get the current brightness", NULL }, { "get-max-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_max_brightness, /* command line argument */ "Get the number of brightness levels supported", NULL }, { NULL} }; context = g_option_context_new (NULL); g_option_context_set_summary (context, "GNOME Settings Daemon Backlight Helper"); g_option_context_add_main_entries (context, options, NULL); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); #ifndef __linux__ /* the g-s-d plugin should only call this helper on linux */ g_critical ("Attempting to call gsb-backlight-helper on non-Linux"); g_assert_not_reached (); #endif /* no input */ if (set_brightness == -1 && !get_brightness && !get_max_brightness) { g_print ("%s\n", "No valid option was specified"); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID; goto out; } /* find device */ filename = gsd_backlight_helper_get_best_backlight (&type); if (filename == NULL) { retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_NO_DEVICES; g_print ("%s: %s\n", "Could not get or set the value of the backlight", "No backlight devices present"); goto out; } /* GetBrightness */ if (get_brightness) { gint value; value = gsd_backlight_helper_get (filename, &error); if (value < 0) { g_print ("%s: %s\n", "Could not get the value of the backlight", error->message); g_error_free (error); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID; goto out; } /* just print the contents to stdout */ g_print ("%d", value); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS; goto out; } /* GetSteps */ if (get_max_brightness) { gint value; value = gsd_backlight_helper_get_max (filename, &error); if (value < 0) { g_print ("%s: %s\n", "Could not get the maximum value of the backlight", error->message); g_error_free (error); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID; goto out; } /* just print the contents to stdout */ g_print ("%d", value); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS; goto out; } /* check calling UID */ uid = getuid (); euid = geteuid (); if (uid != 0 || euid != 0) { g_print ("%s\n", "This program can only be used by the root user"); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID; goto out; } /* SetBrightness */ if (set_brightness != -1) { gboolean ret = FALSE; gint max = gsd_backlight_helper_get_max (filename, &error); if (max < 0) { g_print ("%s: %s\n", "Could not get the maximum value of the backlight", error->message); g_error_free (error); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID; goto out; } if (type == GSD_BACKLIGHT_TYPE_RAW) set_brightness = clamp_minimum (max, set_brightness); ret = gsd_backlight_helper_write (filename, set_brightness, &error); if (!ret) { g_print ("%s: %s\n", "Could not set the value of the backlight", error->message); g_error_free (error); retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID; goto out; } } /* success */ retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS; out: g_free (filename); return retval; } unity-settings-daemon/plugins/power/gsd-backlight-linux.c0000664000000000000000000000644115172222611021042 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2010-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "config.h" #include "gsd-backlight-linux.h" #ifdef HAVE_GUDEV #include static gchar * gsd_backlight_helper_get_type (GList *devices, const gchar *type) { const gchar *type_tmp; GList *d; for (d = devices; d != NULL; d = d->next) { type_tmp = g_udev_device_get_sysfs_attr (d->data, "type"); if (g_strcmp0 (type_tmp, type) == 0) return g_strdup (g_udev_device_get_sysfs_path (d->data)); } return NULL; } /* * Search for a raw backlight interface, raw backlight interfaces registered * by the drm driver will have the drm-connector as their parent, check the * drm-connector's enabled sysfs attribute so that we pick the right LCD-panel * connector on laptops with hybrid-gfx. Fall back to just picking the first * raw backlight interface if no enabled interface is found. */ static gchar * gsd_backlight_helper_get_raw (GList *devices) { GUdevDevice *parent; const gchar *attr; GList *d; for (d = devices; d != NULL; d = d->next) { attr = g_udev_device_get_sysfs_attr (d->data, "type"); if (g_strcmp0 (attr, "raw") != 0) continue; parent = g_udev_device_get_parent (d->data); if (!parent) continue; attr = g_udev_device_get_sysfs_attr (parent, "enabled"); if (!attr || g_strcmp0 (attr, "enabled") != 0) continue; return g_strdup (g_udev_device_get_sysfs_path (d->data)); } return gsd_backlight_helper_get_type (devices, "raw"); } #endif /* HAVE_GUDEV */ char * gsd_backlight_helper_get_best_backlight (GsdBacklightType *type) { #ifdef HAVE_GUDEV gchar *path = NULL; GList *devices; GUdevClient *client; client = g_udev_client_new (NULL); devices = g_udev_client_query_by_subsystem (client, "backlight"); if (devices == NULL) goto out; /* search the backlight devices and prefer the types: * firmware -> platform -> raw */ path = gsd_backlight_helper_get_type (devices, "firmware"); if (path != NULL) { if (type) *type = GSD_BACKLIGHT_TYPE_FIRMWARE; goto out; } path = gsd_backlight_helper_get_type (devices, "platform"); if (path != NULL) { if (type) *type = GSD_BACKLIGHT_TYPE_PLATFORM; goto out; } path = gsd_backlight_helper_get_raw (devices); if (path != NULL) { if (type) *type = GSD_BACKLIGHT_TYPE_RAW; goto out; } out: g_object_unref (client); g_list_foreach (devices, (GFunc) g_object_unref, NULL); g_list_free (devices); return path; #endif /* HAVE_GUDEV */ return NULL; } unity-settings-daemon/plugins/power/gsd-backlight-linux.h0000664000000000000000000000214015172222611021037 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2010-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ typedef enum { GSD_BACKLIGHT_TYPE_FIRMWARE, GSD_BACKLIGHT_TYPE_PLATFORM, GSD_BACKLIGHT_TYPE_RAW, } GsdBacklightType; char *gsd_backlight_helper_get_best_backlight (GsdBacklightType *type); unity-settings-daemon/plugins/power/gsd-power-constants-update.pl0000775000000000000000000000254215172222611022575 0ustar #!/usr/bin/env perl # Author : Simos Xenitellis . # Author : Bastien Nocera # Version : 1.2 # # Input : gsd-power-constants.h # Output : gsdpowerconstants.py # use strict; # Used for reading the keysymdef symbols. my @constantselements; die "Could not open file gsd-power-constants.h: $!\n" unless open(IN_CONSTANTS, "<:utf8", "gsd-power-constants.h"); # Output: gtk+/gdk/gdkkeysyms.h die "Could not open file gsdpowerconstants.py: $!\n" unless open(OUT_CONSTANTS, ">:utf8", "gsdpowerconstants.py"); print OUT_CONSTANTS<) { next if ( ! /^#define / ); @constantselements = split(/\s+/); die "Internal error, no \@constantselements: $_\n" unless @constantselements; my $constant = $constantselements[1]; my $value = $constantselements[2]; printf OUT_CONSTANTS "%s = %s;\n", $constant, $value; } close IN_CONSTANTS; printf "We just finished converting gsd-power-constants.h to gsdpowerconstants.py\nThank you\n"; unity-settings-daemon/plugins/power/gsd-power-constants.h0000664000000000000000000000330515172222611021124 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2013 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* The blank delay when the screensaver is active */ #define SCREENSAVER_TIMEOUT_BLANK 15 /* seconds */ /* The dim delay when dimming on idle is requested but idle-delay * is set to "Never" */ #define IDLE_DIM_BLANK_DISABLED_MIN 60 /* seconds */ /* Which fraction of the idle-delay is the idle-dim delay */ #define IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER 4.0/5.0 /* The dim delay under which we do not bother dimming */ #define MINIMUM_IDLE_DIM_DELAY 10 /* seconds */ /* The amount of time we'll undim if the machine is idle when plugged in */ #define POWER_UP_TIME_ON_AC 15 /* seconds */ /* Default brightness values for the mock backlight used in the test suite */ #define GSD_MOCK_DEFAULT_BRIGHTNESS 50 #define GSD_MOCK_MAX_BRIGHTNESS 100 unity-settings-daemon/plugins/power/gsd-power-enums-update.c0000664000000000000000000000160615172222611021514 0ustar #include #include static void output_enum_values (GType class_type) { GEnumClass *eclass; guint i; eclass = G_ENUM_CLASS (g_type_class_peek (class_type)); for (i = 0; i < eclass->n_values; i++) { GEnumValue *value = &(eclass->values[i]); g_print ("%s = %d;\n", value->value_name, value->value); } } static void output_flags_values (GType class_type) { GFlagsClass *fclass; guint i; fclass = G_FLAGS_CLASS (g_type_class_peek (class_type)); for (i = 0; i < fclass->n_values; i++) { GFlagsValue *value = &(fclass->values[i]); g_print ("%s = %d;\n", value->value_name, value->value); } } int main (int argc, char **argv) { g_type_class_ref (GSD_POWER_TYPE_INHIBITOR_FLAG); g_type_class_ref (GSD_POWER_TYPE_PRESENCE_STATUS); output_flags_values (GSD_POWER_TYPE_INHIBITOR_FLAG); output_enum_values (GSD_POWER_TYPE_PRESENCE_STATUS); return 0; } unity-settings-daemon/plugins/power/gsd-power-manager.c0000664000000000000000000044113415172222611020523 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2011-2012 Richard Hughes * Copyright (C) 2011 Ritesh Khadgaray * Copyright (C) 2012-2013 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #define UPOWER_ENABLE_DEPRECATED 1 #include #include #include #include #include #include #include "gsd-power-constants.h" #include "gsm-inhibitor-flag.h" #include "gsm-presence-flag.h" #include "gsm-manager-logout-mode.h" #include "gpm-common.h" #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #include "gnome-settings-bus.h" #include "gsd-enums.h" #include "gsd-power-manager.h" #include "gsd-rr.h" #include "gsd-idle-monitor.h" #define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager" #define GNOME_SESSION_DBUS_PATH_PRESENCE "/org/gnome/SessionManager/Presence" #define GNOME_SESSION_DBUS_INTERFACE_PRESENCE "org.gnome.SessionManager.Presence" #define UPOWER_DBUS_NAME "org.freedesktop.UPower" #define UPOWER_DBUS_PATH "/org/freedesktop/UPower" #define UPOWER_DBUS_PATH_KBDBACKLIGHT "/org/freedesktop/UPower/KbdBacklight" #define UPOWER_DBUS_INTERFACE "org.freedesktop.UPower" #define UPOWER_DBUS_INTERFACE_KBDBACKLIGHT "org.freedesktop.UPower.KbdBacklight" #define GSD_POWER_SETTINGS_SCHEMA "com.canonical.unity.settings-daemon.plugins.power" #define GSD_XRANDR_SETTINGS_SCHEMA "com.canonical.unity.settings-daemon.plugins.xrandr" #define GSD_POWER_DBUS_NAME GSD_DBUS_NAME ".Power" #define GSD_POWER_DBUS_PATH GSD_DBUS_PATH "/Power" #define GSD_POWER_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Power" #define GSD_POWER_DBUS_INTERFACE_SCREEN GSD_POWER_DBUS_INTERFACE ".Screen" #define GSD_POWER_DBUS_INTERFACE_KEYBOARD GSD_POWER_DBUS_INTERFACE ".Keyboard" #define GSD_POWER_MANAGER_NOTIFY_TIMEOUT_SHORT 10 * 1000 /* ms */ #define GSD_POWER_MANAGER_NOTIFY_TIMEOUT_LONG 30 * 1000 /* ms */ #define GSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT 30 /* seconds */ #define SYSTEMD_DBUS_NAME "org.freedesktop.login1" #define SYSTEMD_DBUS_PATH "/org/freedesktop/login1" #define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager" /* Keep this in sync with gnome-shell */ #define SCREENSAVER_FADE_TIME 10 /* seconds */ /* Time between notifying the user about a critical action and executing it. * This can be changed with the GSD_ACTION_DELAY constant. */ #ifndef GSD_ACTION_DELAY #define GSD_ACTION_DELAY 20 #endif /* !GSD_ACTION_DELAY */ static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; #define GSD_POWER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_POWER_MANAGER, GsdPowerManagerPrivate)) typedef enum { GSD_POWER_IDLE_MODE_NORMAL, GSD_POWER_IDLE_MODE_DIM, GSD_POWER_IDLE_MODE_BLANK, GSD_POWER_IDLE_MODE_SLEEP } GsdPowerIdleMode; struct GsdPowerManagerPrivate { /* D-Bus */ GsdSessionManager *session; guint name_id; GDBusNodeInfo *introspection_data; GDBusConnection *connection; GCancellable *bus_cancellable; GDBusProxy *session_presence_proxy; /* Settings */ GSettings *settings; GSettings *settings_bus; GSettings *settings_screensaver; GSettings *settings_xrandr; gboolean use_time_primary; guint action_percentage; guint action_time; guint critical_percentage; guint critical_time; guint low_percentage; guint low_time; /* Screensaver */ GsdScreenSaver *screensaver_proxy; gboolean screensaver_active; /* State */ gboolean lid_is_closed; UpClient *up_client; gchar *previous_summary; GIcon *previous_icon; GPtrArray *devices_array; UpDevice *device_composite; GsdRRScreen *rr_screen; NotifyNotification *notification_ups_discharging; NotifyNotification *notification_low; NotifyNotification *notification_sleep_warning; NotifyNotification *notification_logout_warning; GsdPowerActionType sleep_action_type; gboolean battery_is_low; /* laptop battery low, or UPS discharging */ /* Brightness */ gboolean backlight_available; gint pre_dim_brightness; /* level, not percentage */ /* Keyboard */ GDBusProxy *upower_kdb_proxy; gint kbd_brightness_max; gint kbd_brightness_old; gint kbd_brightness_pre_dim; /* Sound */ guint32 critical_alert_timeout_id; /* systemd stuff */ GDBusProxy *logind_proxy; gint inhibit_lid_switch_fd; gboolean inhibit_lid_switch_taken; gboolean inhibit_lid_switch_action; gint inhibit_suspend_fd; gboolean inhibit_suspend_taken; guint inhibit_lid_switch_timer_id; gboolean is_virtual_machine; /* Idles */ GsdIdleMonitor *idle_monitor; guint idle_dim_id; guint idle_blank_id; guint idle_sleep_warning_id; guint idle_sleep_id; GsdPowerIdleMode current_idle_mode; guint temporary_unidle_on_ac_id; GsdPowerIdleMode previous_idle_mode; guint xscreensaver_watchdog_timer_id; }; enum { PROP_0, }; static void gsd_power_manager_class_init (GsdPowerManagerClass *klass); static void gsd_power_manager_init (GsdPowerManager *power_manager); static UpDevice *engine_get_composite_device (GsdPowerManager *manager, UpDevice *original_device); static UpDevice *engine_update_composite_device (GsdPowerManager *manager, UpDevice *original_device); static GIcon *engine_get_icon (GsdPowerManager *manager); static gchar *engine_get_summary (GsdPowerManager *manager); static gdouble engine_get_percentage (GsdPowerManager *manager); static void do_power_action_type (GsdPowerManager *manager, GsdPowerActionType action_type); static void do_lid_closed_action (GsdPowerManager *manager); static void inhibit_lid_switch (GsdPowerManager *manager); static void uninhibit_lid_switch (GsdPowerManager *manager); static void main_battery_or_ups_low_changed (GsdPowerManager *manager, gboolean is_low); static void device_properties_changed_cb (UpDevice *device, GParamSpec *pspec, GsdPowerManager *manager); static gboolean idle_is_session_inhibited (GsdPowerManager *manager, guint mask, gboolean *is_inhibited); static void idle_set_mode (GsdPowerManager *manager, GsdPowerIdleMode mode); static void idle_triggered_idle_cb (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data); static void idle_became_active_cb (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data); G_DEFINE_TYPE (GsdPowerManager, gsd_power_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; GQuark gsd_power_manager_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gsd_power_manager_error"); return quark; } static void notify_close_if_showing (NotifyNotification **notification) { if (*notification == NULL) return; notify_notification_close (*notification, NULL); g_clear_object (notification); } typedef enum { WARNING_NONE = 0, WARNING_DISCHARGING = 1, WARNING_LOW = 2, WARNING_CRITICAL = 3, WARNING_ACTION = 4 } GsdPowerManagerWarning; static GVariant * engine_get_icon_property_variant (GsdPowerManager *manager) { GIcon *icon; GVariant *retval; icon = engine_get_icon (manager); if (icon != NULL) { char *str; str = g_icon_to_string (icon); g_object_unref (icon); retval = g_variant_new_string (str); g_free (str); } else { retval = g_variant_new_string (""); } return retval; } static GVariant * engine_get_tooltip_property_variant (GsdPowerManager *manager) { char *tooltip; GVariant *retval; tooltip = engine_get_summary (manager); retval = g_variant_new_string (tooltip != NULL ? tooltip : ""); g_free (tooltip); return retval; } static void engine_emit_changed (GsdPowerManager *manager, gboolean icon_changed, gboolean state_changed) { GVariantBuilder props_builder; GVariant *props_changed = NULL; GError *error = NULL; /* not yet connected to the bus */ if (manager->priv->connection == NULL) return; g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); if (icon_changed) g_variant_builder_add (&props_builder, "{sv}", "Icon", engine_get_icon_property_variant (manager)); if (state_changed) g_variant_builder_add (&props_builder, "{sv}", "Tooltip", engine_get_tooltip_property_variant (manager)); g_variant_builder_add (&props_builder, "{sv}", "Percentage", g_variant_new_double (engine_get_percentage (manager))); props_changed = g_variant_new ("(s@a{sv}@as)", GSD_POWER_DBUS_INTERFACE, g_variant_builder_end (&props_builder), g_variant_new_strv (NULL, 0)); g_variant_ref_sink (props_changed); if (!g_dbus_connection_emit_signal (manager->priv->connection, NULL, GSD_POWER_DBUS_PATH, "org.freedesktop.DBus.Properties", "PropertiesChanged", props_changed, &error)) goto out; out: if (error) { g_warning ("%s", error->message); g_clear_error (&error); } if (props_changed) g_variant_unref (props_changed); } static GsdPowerManagerWarning engine_get_warning_csr (GsdPowerManager *manager, UpDevice *device) { gdouble percentage; /* get device properties */ g_object_get (device, "percentage", &percentage, NULL); if (percentage < 26.0f) return WARNING_LOW; else if (percentage < 13.0f) return WARNING_CRITICAL; return WARNING_NONE; } static GsdPowerManagerWarning engine_get_warning_percentage (GsdPowerManager *manager, UpDevice *device) { gdouble percentage; /* get device properties */ g_object_get (device, "percentage", &percentage, NULL); if (percentage <= manager->priv->action_percentage) return WARNING_ACTION; if (percentage <= manager->priv->critical_percentage) return WARNING_CRITICAL; if (percentage <= manager->priv->low_percentage) return WARNING_LOW; return WARNING_NONE; } static GsdPowerManagerWarning engine_get_warning_time (GsdPowerManager *manager, UpDevice *device) { UpDeviceKind kind; gint64 time_to_empty; /* get device properties */ g_object_get (device, "kind", &kind, "time-to-empty", &time_to_empty, NULL); /* this is probably an error condition */ if (time_to_empty == 0) { g_debug ("time zero, falling back to percentage for %s", up_device_kind_to_string (kind)); return engine_get_warning_percentage (manager, device); } if (time_to_empty <= manager->priv->action_time) return WARNING_ACTION; if (time_to_empty <= manager->priv->critical_time) return WARNING_CRITICAL; if (time_to_empty <= manager->priv->low_time) return WARNING_LOW; return WARNING_NONE; } /** * This gets the possible engine state for the device according to the * policy, which could be per-percent, or per-time. **/ static GsdPowerManagerWarning engine_get_warning (GsdPowerManager *manager, UpDevice *device) { UpDeviceKind kind; UpDeviceState state; GsdPowerManagerWarning warning_type; /* get device properties */ g_object_get (device, "kind", &kind, "state", &state, NULL); /* default to no engine */ warning_type = WARNING_NONE; /* if the device in question is on ac, don't give a warning */ if (state == UP_DEVICE_STATE_CHARGING) goto out; if (kind == UP_DEVICE_KIND_MOUSE || kind == UP_DEVICE_KIND_KEYBOARD) { warning_type = engine_get_warning_csr (manager, device); } else if (kind == UP_DEVICE_KIND_UPS || kind == UP_DEVICE_KIND_MEDIA_PLAYER || kind == UP_DEVICE_KIND_TABLET || kind == UP_DEVICE_KIND_COMPUTER || kind == UP_DEVICE_KIND_PDA) { warning_type = engine_get_warning_percentage (manager, device); } else if (kind == UP_DEVICE_KIND_PHONE) { warning_type = engine_get_warning_percentage (manager, device); } else if (kind == UP_DEVICE_KIND_BATTERY) { /* only use the time when it is accurate, and settings is not disabled */ if (manager->priv->use_time_primary) warning_type = engine_get_warning_time (manager, device); else warning_type = engine_get_warning_percentage (manager, device); } /* If we have no important engines, we should test for discharging */ if (warning_type == WARNING_NONE) { if (state == UP_DEVICE_STATE_DISCHARGING) warning_type = WARNING_DISCHARGING; } out: return warning_type; } static gchar * engine_get_summary (GsdPowerManager *manager) { guint i; GPtrArray *array; UpDevice *device; UpDeviceState state; GString *tooltip = NULL; gchar *part; gboolean is_present; /* need to get AC state */ tooltip = g_string_new (""); /* do we have specific device types? */ array = manager->priv->devices_array; for (i=0;ilen;i++) { device = g_ptr_array_index (array, i); g_object_get (device, "is-present", &is_present, "state", &state, NULL); if (!is_present) continue; if (state == UP_DEVICE_STATE_EMPTY) continue; part = gpm_upower_get_device_summary (device); if (part != NULL) g_string_append_printf (tooltip, "%s\n", part); g_free (part); } /* remove the last \n */ g_string_truncate (tooltip, tooltip->len-1); g_debug ("tooltip: %s", tooltip->str); return g_string_free (tooltip, FALSE); } static gdouble engine_get_percentage (GsdPowerManager *manager) { guint i; GPtrArray *array; UpDevice *device; UpDeviceKind kind; gboolean is_present; gdouble percentage; array = manager->priv->devices_array; for (i = 0; i < array->len ; i++) { device = g_ptr_array_index (array, i); /* get device properties */ g_object_get (device, "kind", &kind, "is-present", &is_present, NULL); /* if battery then use composite device to cope with multiple batteries */ if (kind == UP_DEVICE_KIND_BATTERY) device = engine_get_composite_device (manager, device); if (is_present) { /* Doing it here as it could be a composite device */ g_object_get (device, "percentage", &percentage, NULL); return percentage; } } return -1; } static GIcon * engine_get_icon_priv (GsdPowerManager *manager, UpDeviceKind device_kind, GsdPowerManagerWarning warning, gboolean use_state) { guint i; GPtrArray *array; UpDevice *device; GsdPowerManagerWarning warning_temp; UpDeviceKind kind; UpDeviceState state; gboolean is_present; /* do we have specific device types? */ array = manager->priv->devices_array; for (i=0;ilen;i++) { device = g_ptr_array_index (array, i); /* get device properties */ g_object_get (device, "kind", &kind, "state", &state, "is-present", &is_present, NULL); /* if battery then use composite device to cope with multiple batteries */ if (kind == UP_DEVICE_KIND_BATTERY) device = engine_get_composite_device (manager, device); warning_temp = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-warning-old")); if (kind == device_kind && is_present) { if (warning != WARNING_NONE) { if (warning_temp == warning) return gpm_upower_get_device_icon (device, TRUE); continue; } if (use_state) { if (state == UP_DEVICE_STATE_CHARGING || state == UP_DEVICE_STATE_DISCHARGING) return gpm_upower_get_device_icon (device, TRUE); continue; } return gpm_upower_get_device_icon (device, TRUE); } } return NULL; } static GIcon * engine_get_icon (GsdPowerManager *manager) { GIcon *icon = NULL; /* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_CRITICAL, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_CRITICAL, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_MOUSE, WARNING_CRITICAL, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_KEYBOARD, WARNING_CRITICAL, FALSE); if (icon != NULL) return icon; /* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_LOW, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_LOW, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_MOUSE, WARNING_LOW, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_KEYBOARD, WARNING_LOW, FALSE); if (icon != NULL) return icon; /* we try (DIS)CHARGING: BATTERY, UPS */ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_NONE, TRUE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_NONE, TRUE); if (icon != NULL) return icon; /* we try PRESENT: BATTERY, UPS */ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_NONE, FALSE); if (icon != NULL) return icon; icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_NONE, FALSE); if (icon != NULL) return icon; /* do not show an icon */ return NULL; } static gboolean engine_recalculate_state_icon (GsdPowerManager *manager) { GIcon *icon; /* show a different icon if we are disconnected */ icon = engine_get_icon (manager); if (g_icon_equal (icon, manager->priv->previous_icon)) { g_clear_object (&icon); return FALSE; } g_clear_object (&manager->priv->previous_icon); manager->priv->previous_icon = icon; g_debug ("Icon changed"); return TRUE; } static gboolean engine_recalculate_state_summary (GsdPowerManager *manager) { char *summary; summary = engine_get_summary (manager); if (g_strcmp0 (manager->priv->previous_summary, summary) == 0) { g_free (summary); return FALSE; } g_free (manager->priv->previous_summary); manager->priv->previous_summary = summary; g_debug ("Summary changed"); return TRUE; } static void engine_recalculate_state (GsdPowerManager *manager) { gboolean icon_changed = FALSE; gboolean state_changed = FALSE; icon_changed = engine_recalculate_state_icon (manager); state_changed = engine_recalculate_state_summary (manager); /* only emit if the icon or summary has changed */ if (icon_changed || state_changed) engine_emit_changed (manager, icon_changed, state_changed); } static UpDevice * engine_get_composite_device (GsdPowerManager *manager, UpDevice *original_device) { guint battery_devices = 0; GPtrArray *array; UpDevice *device; UpDeviceKind kind; UpDeviceKind original_kind; guint i; /* get the type of the original device */ g_object_get (original_device, "kind", &original_kind, NULL); /* find out how many batteries in the system */ array = manager->priv->devices_array; for (i=0;ilen;i++) { device = g_ptr_array_index (array, i); g_object_get (device, "kind", &kind, NULL); if (kind == original_kind) battery_devices++; } /* just use the original device if only one primary battery */ if (battery_devices <= 1) return original_device; /* use the composite device */ device = manager->priv->device_composite; /* return composite device or original device */ return device; } static UpDevice * engine_update_composite_device (GsdPowerManager *manager, UpDevice *original_device) { guint i; gdouble percentage = 0.0; gdouble energy = 0.0; gdouble energy_full = 0.0; gdouble energy_rate = 0.0; gdouble energy_total = 0.0; gdouble energy_full_total = 0.0; gdouble energy_rate_total = 0.0; gint64 time_to_empty = 0; gint64 time_to_full = 0; guint battery_devices = 0; gboolean is_charging = FALSE; gboolean is_discharging = FALSE; gboolean is_fully_charged = TRUE; GPtrArray *array; UpDevice *device; UpDeviceState state; UpDeviceKind kind; UpDeviceKind original_kind; /* get the type of the original device */ g_object_get (original_device, "kind", &original_kind, NULL); /* update the composite device */ array = manager->priv->devices_array; for (i=0;ilen;i++) { device = g_ptr_array_index (array, i); g_object_get (device, "kind", &kind, "state", &state, "energy", &energy, "energy-full", &energy_full, "energy-rate", &energy_rate, NULL); if (kind != original_kind) continue; /* one of these will be charging or discharging */ if (state == UP_DEVICE_STATE_CHARGING) is_charging = TRUE; if (state == UP_DEVICE_STATE_DISCHARGING) is_discharging = TRUE; if (state != UP_DEVICE_STATE_FULLY_CHARGED) is_fully_charged = FALSE; /* sum up composite */ energy_total += energy; energy_full_total += energy_full; energy_rate_total += energy_rate; battery_devices++; } /* just use the original device if only one primary battery */ if (battery_devices == 1) { g_debug ("using original device as only one primary battery"); device = original_device; goto out; } /* use percentage weighted for each battery capacity */ if (energy_full_total > 0.0) percentage = 100.0 * energy_total / energy_full_total; /* set composite state */ if (is_charging) state = UP_DEVICE_STATE_CHARGING; else if (is_discharging) state = UP_DEVICE_STATE_DISCHARGING; else if (is_fully_charged) state = UP_DEVICE_STATE_FULLY_CHARGED; else state = UP_DEVICE_STATE_UNKNOWN; /* calculate a quick and dirty time remaining value */ if (energy_rate_total > 0) { if (state == UP_DEVICE_STATE_DISCHARGING) time_to_empty = 3600 * (energy_total / energy_rate_total); else if (state == UP_DEVICE_STATE_CHARGING) time_to_full = 3600 * ((energy_full_total - energy_total) / energy_rate_total); } /* okay, we can use the composite device */ device = manager->priv->device_composite; g_debug ("printing composite device"); g_object_set (device, "energy", energy, "energy-full", energy_full, "energy-rate", energy_rate, "time-to-empty", time_to_empty, "time-to-full", time_to_full, "percentage", percentage, "state", state, NULL); /* force update of icon */ if (engine_recalculate_state_icon (manager)) engine_emit_changed (manager, TRUE, FALSE); out: /* return composite device or original device */ return device; } static void engine_device_add (GsdPowerManager *manager, UpDevice *device) { GsdPowerManagerWarning warning; UpDeviceState state; UpDeviceKind kind; UpDevice *composite; /* assign warning */ warning = engine_get_warning (manager, device); g_object_set_data (G_OBJECT(device), "engine-warning-old", GUINT_TO_POINTER(warning)); /* get device properties */ g_object_get (device, "kind", &kind, "state", &state, NULL); /* add old state for transitions */ g_debug ("adding %s with state %s", up_device_get_object_path (device), up_device_state_to_string (state)); g_object_set_data (G_OBJECT(device), "engine-state-old", GUINT_TO_POINTER(state)); if (kind == UP_DEVICE_KIND_BATTERY) { g_debug ("updating because we added a device"); composite = engine_update_composite_device (manager, device); /* get the same values for the composite device */ warning = engine_get_warning (manager, composite); g_object_set_data (G_OBJECT(composite), "engine-warning-old", GUINT_TO_POINTER(warning)); g_object_get (composite, "state", &state, NULL); g_object_set_data (G_OBJECT(composite), "engine-state-old", GUINT_TO_POINTER(state)); } g_ptr_array_add (manager->priv->devices_array, g_object_ref(device)); g_signal_connect (device, "notify::state", G_CALLBACK (device_properties_changed_cb), manager); g_signal_connect (device, "notify::warning-level", G_CALLBACK (device_properties_changed_cb), manager); } static gboolean engine_coldplug (GsdPowerManager *manager) { guint i; GPtrArray *array = NULL; UpDevice *device; engine_recalculate_state (manager); /* add to database */ array = up_client_get_devices (manager->priv->up_client); if (array == NULL) goto out; for (i=0;ilen;i++) { device = g_ptr_array_index (array, i); engine_device_add (manager, device); } out: if (array != NULL) g_ptr_array_unref (array); /* never repeat */ return FALSE; } static void engine_device_added_cb (UpClient *client, UpDevice *device, GsdPowerManager *manager) { /* add to list */ g_ptr_array_add (manager->priv->devices_array, g_object_ref (device)); engine_recalculate_state (manager); } static void engine_device_removed_cb (UpClient *client, const char *object_path, GsdPowerManager *manager) { guint i; for (i = 0; i < manager->priv->devices_array->len; i++) { UpDevice *device = g_ptr_array_index (manager->priv->devices_array, i); if (g_strcmp0 (object_path, up_device_get_object_path (device)) == 0) { g_ptr_array_remove_index (manager->priv->devices_array, i); break; } } } static void on_notification_closed (NotifyNotification *notification, gpointer data) { g_object_unref (notification); } static const gchar * get_first_themed_icon_name (GIcon *icon) { const gchar* const *icon_names; const gchar *icon_name = NULL; /* no icon */ if (icon == NULL) goto out; /* just use the first icon */ icon_names = g_themed_icon_get_names (G_THEMED_ICON (icon)); if (icon_names != NULL) icon_name = icon_names[0]; out: return icon_name; } static void create_notification (const char *summary, const char *body, GIcon *icon, NotifyNotification **weak_pointer_location) { NotifyNotification *notification; notification = notify_notification_new (summary, body, icon ? get_first_themed_icon_name (icon) : NULL); *weak_pointer_location = notification; g_object_add_weak_pointer (G_OBJECT (notification), (gpointer *) weak_pointer_location); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); } static void engine_ups_discharging (GsdPowerManager *manager, UpDevice *device) { const gchar *title; gchar *remaining_text = NULL; gdouble percentage; GIcon *icon = NULL; gint64 time_to_empty; GString *message; UpDeviceKind kind; /* get device properties */ g_object_get (device, "kind", &kind, "percentage", &percentage, "time-to-empty", &time_to_empty, NULL); if (kind != UP_DEVICE_KIND_UPS) return; main_battery_or_ups_low_changed (manager, TRUE); /* only show text if there is a valid time */ if (time_to_empty > 0) remaining_text = gpm_get_timestring (time_to_empty); /* TRANSLATORS: UPS is now discharging */ title = _("UPS Discharging"); message = g_string_new (""); if (remaining_text != NULL) { /* TRANSLATORS: tell the user how much time they have got */ g_string_append_printf (message, _("%s of UPS backup power remaining"), remaining_text); } else { g_string_append (message, gpm_device_to_localised_string (device)); } g_string_append_printf (message, " (%.0f%%)", percentage); icon = gpm_upower_get_device_icon (device, TRUE); /* close any existing notification of this class */ notify_close_if_showing (&manager->priv->notification_ups_discharging); /* create a new notification */ create_notification (title, message->str, icon, &manager->priv->notification_ups_discharging); notify_notification_set_timeout (manager->priv->notification_ups_discharging, GSD_POWER_MANAGER_NOTIFY_TIMEOUT_LONG); notify_notification_set_urgency (manager->priv->notification_ups_discharging, NOTIFY_URGENCY_NORMAL); /* TRANSLATORS: this is the notification application name */ notify_notification_set_app_name (manager->priv->notification_ups_discharging, _("Power")); notify_notification_set_hint (manager->priv->notification_ups_discharging, "transient", g_variant_new_boolean (TRUE)); notify_notification_show (manager->priv->notification_ups_discharging, NULL); g_string_free (message, TRUE); if (icon != NULL) g_object_unref (icon); g_free (remaining_text); } static GsdPowerActionType manager_critical_action_get (GsdPowerManager *manager, gboolean is_ups) { GsdPowerActionType policy; GVariant *result = NULL; policy = g_settings_get_enum (manager->priv->settings, "critical-battery-action"); if (policy == GSD_POWER_ACTION_SUSPEND) { if (is_ups == FALSE) { result = g_dbus_proxy_call_sync (manager->priv->logind_proxy, "CanSuspend", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); } } else if (policy == GSD_POWER_ACTION_HIBERNATE) { result = g_dbus_proxy_call_sync (manager->priv->logind_proxy, "CanHibernate", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); } else { /* Other actions need no check */ return policy; } if (result) { const char *s; g_variant_get (result, "(s)", &s); if (g_strcmp0 (s, "yes") != 0) policy = GSD_POWER_ACTION_SHUTDOWN; g_variant_unref (result); } else { policy = GSD_POWER_ACTION_SHUTDOWN; } return policy; } static gboolean manager_critical_action_do (GsdPowerManager *manager, gboolean is_ups) { GsdPowerActionType action_type; /* stop playing the alert as it's too late to do anything now */ play_loop_stop (&manager->priv->critical_alert_timeout_id); action_type = manager_critical_action_get (manager, is_ups); do_power_action_type (manager, action_type); return FALSE; } static gboolean manager_critical_action_do_cb (GsdPowerManager *manager) { manager_critical_action_do (manager, FALSE); return FALSE; } static gboolean manager_critical_ups_action_do_cb (GsdPowerManager *manager) { manager_critical_action_do (manager, TRUE); return FALSE; } static gboolean engine_just_laptop_battery (GsdPowerManager *manager) { UpDevice *device; UpDeviceKind kind; GPtrArray *array; gboolean ret = TRUE; guint i; /* find if there are any other device types that mean we have to * be more specific in our wording */ array = manager->priv->devices_array; for (i=0; ilen; i++) { device = g_ptr_array_index (array, i); g_object_get (device, "kind", &kind, NULL); if (kind != UP_DEVICE_KIND_BATTERY) { ret = FALSE; break; } } return ret; } static void engine_charge_low (GsdPowerManager *manager, UpDevice *device) { const gchar *title = NULL; gboolean ret; gchar *message = NULL; gchar *tmp; gchar *remaining_text; gdouble percentage; GIcon *icon = NULL; gint64 time_to_empty; UpDeviceKind kind; /* get device properties */ g_object_get (device, "kind", &kind, "percentage", &percentage, "time-to-empty", &time_to_empty, NULL); if (kind == UP_DEVICE_KIND_BATTERY) { /* if the user has no other batteries, drop the "Laptop" wording */ ret = engine_just_laptop_battery (manager); if (ret) { /* TRANSLATORS: laptop battery low, and we only have one battery */ title = _("Battery low"); } else { /* TRANSLATORS: laptop battery low, and we have more than one kind of battery */ title = _("Laptop battery low"); } tmp = gpm_get_timestring (time_to_empty); remaining_text = g_strconcat ("", tmp, "", NULL); g_free (tmp); /* TRANSLATORS: tell the user how much time they have got */ message = g_strdup_printf (_("Approximately %s remaining (%.0f%%)"), remaining_text, percentage); g_free (remaining_text); main_battery_or_ups_low_changed (manager, TRUE); } else if (kind == UP_DEVICE_KIND_UPS) { /* TRANSLATORS: UPS is starting to get a little low */ title = _("UPS low"); tmp = gpm_get_timestring (time_to_empty); remaining_text = g_strconcat ("", tmp, "", NULL); g_free (tmp); /* TRANSLATORS: tell the user how much time they have got */ message = g_strdup_printf (_("Approximately %s of remaining UPS backup power (%.0f%%)"), remaining_text, percentage); g_free (remaining_text); } else if (kind == UP_DEVICE_KIND_MOUSE) { /* TRANSLATORS: mouse is getting a little low */ title = _("Mouse battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("Wireless mouse is low in power (%.0f%%)"), percentage); } else if (kind == UP_DEVICE_KIND_KEYBOARD) { /* TRANSLATORS: keyboard is getting a little low */ title = _("Keyboard battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("Wireless keyboard is low in power (%.0f%%)"), percentage); } else if (kind == UP_DEVICE_KIND_PDA) { /* TRANSLATORS: PDA is getting a little low */ title = _("PDA battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("PDA is low in power (%.0f%%)"), percentage); } else if (kind == UP_DEVICE_KIND_PHONE) { /* TRANSLATORS: cell phone (mobile) is getting a little low */ title = _("Cell phone battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("Cell phone is low in power (%.0f%%)"), percentage); } else if (kind == UP_DEVICE_KIND_MEDIA_PLAYER) { /* TRANSLATORS: media player, e.g. mp3 is getting a little low */ title = _("Media player battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("Media player is low in power (%.0f%%)"), percentage); } else if (kind == UP_DEVICE_KIND_TABLET) { /* TRANSLATORS: graphics tablet, e.g. wacom is getting a little low */ title = _("Tablet battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("Tablet is low in power (%.0f%%)"), percentage); } else if (kind == UP_DEVICE_KIND_COMPUTER) { /* TRANSLATORS: computer, e.g. ipad is getting a little low */ title = _("Attached computer battery low"); /* TRANSLATORS: tell user more details */ message = g_strdup_printf (_("Attached computer is low in power (%.0f%%)"), percentage); } /* get correct icon */ icon = gpm_upower_get_device_icon (device, TRUE); /* close any existing notification of this class */ notify_close_if_showing (&manager->priv->notification_low); /* create a new notification */ create_notification (title, message, icon, &manager->priv->notification_low); notify_notification_set_timeout (manager->priv->notification_low, GSD_POWER_MANAGER_NOTIFY_TIMEOUT_LONG); notify_notification_set_urgency (manager->priv->notification_low, NOTIFY_URGENCY_NORMAL); notify_notification_set_app_name (manager->priv->notification_low, _("Power")); notify_notification_set_hint (manager->priv->notification_low, "transient", g_variant_new_boolean (TRUE)); notify_notification_show (manager->priv->notification_low, NULL); /* play the sound, using sounds from the naming spec */ ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "battery-low", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("Battery is low"), NULL); if (icon != NULL) g_object_unref (icon); g_free (message); } static void engine_charge_critical (GsdPowerManager *manager, UpDevice *device) { const gchar *title = NULL; gboolean ret; gchar *message = NULL; gdouble percentage; GIcon *icon = NULL; gint64 time_to_empty; GsdPowerActionType policy; UpDeviceKind kind; /* get device properties */ g_object_get (device, "kind", &kind, "percentage", &percentage, "time-to-empty", &time_to_empty, NULL); if (kind == UP_DEVICE_KIND_BATTERY) { /* if the user has no other batteries, drop the "Laptop" wording */ ret = engine_just_laptop_battery (manager); if (ret) { /* TRANSLATORS: laptop battery critically low, and only have one kind of battery */ title = _("Battery critically low"); } else { /* TRANSLATORS: laptop battery critically low, and we have more than one type of battery */ title = _("Laptop battery critically low"); } /* we have to do different warnings depending on the policy */ policy = manager_critical_action_get (manager, FALSE); /* use different text for different actions */ if (policy == GSD_POWER_ACTION_NOTHING) { /* TRANSLATORS: tell the use to insert the plug, as we're not going to do anything */ message = g_strdup (_("Plug in your AC adapter to avoid losing data.")); } else if (policy == GSD_POWER_ACTION_SUSPEND) { /* TRANSLATORS: give the user a ultimatum */ message = g_strdup_printf (_("Computer will suspend very soon unless it is plugged in.")); } else if (policy == GSD_POWER_ACTION_HIBERNATE) { /* TRANSLATORS: give the user a ultimatum */ message = g_strdup_printf (_("Computer will hibernate very soon unless it is plugged in.")); } else if (policy == GSD_POWER_ACTION_SHUTDOWN) { /* TRANSLATORS: give the user a ultimatum */ message = g_strdup_printf (_("Computer will shutdown very soon unless it is plugged in.")); } main_battery_or_ups_low_changed (manager, TRUE); } else if (kind == UP_DEVICE_KIND_UPS) { gchar *remaining_text; gchar *tmp; /* TRANSLATORS: the UPS is very low */ title = _("UPS critically low"); tmp = gpm_get_timestring (time_to_empty); remaining_text = g_strconcat ("", tmp, "", NULL); g_free (tmp); /* TRANSLATORS: give the user a ultimatum */ message = g_strdup_printf (_("Approximately %s of remaining UPS power (%.0f%%). " "Restore AC power to your computer to avoid losing data."), remaining_text, percentage); g_free (remaining_text); } else if (kind == UP_DEVICE_KIND_MOUSE) { /* TRANSLATORS: the mouse battery is very low */ title = _("Mouse battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("Wireless mouse is very low in power (%.0f%%). " "This device will soon stop functioning if not charged."), percentage); } else if (kind == UP_DEVICE_KIND_KEYBOARD) { /* TRANSLATORS: the keyboard battery is very low */ title = _("Keyboard battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("Wireless keyboard is very low in power (%.0f%%). " "This device will soon stop functioning if not charged."), percentage); } else if (kind == UP_DEVICE_KIND_PDA) { /* TRANSLATORS: the PDA battery is very low */ title = _("PDA battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("PDA is very low in power (%.0f%%). " "This device will soon stop functioning if not charged."), percentage); } else if (kind == UP_DEVICE_KIND_PHONE) { /* TRANSLATORS: the cell battery is very low */ title = _("Cell phone battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("Cell phone is very low in power (%.0f%%). " "This device will soon stop functioning if not charged."), percentage); } else if (kind == UP_DEVICE_KIND_MEDIA_PLAYER) { /* TRANSLATORS: the cell battery is very low */ title = _("Cell phone battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("Media player is very low in power (%.0f%%). " "This device will soon stop functioning if not charged."), percentage); } else if (kind == UP_DEVICE_KIND_TABLET) { /* TRANSLATORS: the cell battery is very low */ title = _("Tablet battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("Tablet is very low in power (%.0f%%). " "This device will soon stop functioning if not charged."), percentage); } else if (kind == UP_DEVICE_KIND_COMPUTER) { /* TRANSLATORS: the cell battery is very low */ title = _("Attached computer battery low"); /* TRANSLATORS: the device is just going to stop working */ message = g_strdup_printf (_("Attached computer is very low in power (%.0f%%). " "The device will soon shutdown if not charged."), percentage); } /* get correct icon */ icon = gpm_upower_get_device_icon (device, TRUE); /* close any existing notification of this class */ notify_close_if_showing (&manager->priv->notification_low); /* create a new notification */ create_notification (title, message, icon, &manager->priv->notification_low); notify_notification_set_timeout (manager->priv->notification_low, NOTIFY_EXPIRES_DEFAULT); notify_notification_set_urgency (manager->priv->notification_low, NOTIFY_URGENCY_CRITICAL); notify_notification_set_app_name (manager->priv->notification_low, _("Power")); notify_notification_show (manager->priv->notification_low, NULL); switch (kind) { case UP_DEVICE_KIND_BATTERY: case UP_DEVICE_KIND_UPS: g_debug ("critical charge level reached, starting sound loop"); play_loop_start (&manager->priv->critical_alert_timeout_id); break; default: /* play the sound, using sounds from the naming spec */ ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "battery-caution", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("Battery is critically low"), NULL); break; } if (icon != NULL) g_object_unref (icon); g_free (message); } static void engine_charge_action (GsdPowerManager *manager, UpDevice *device) { const gchar *title = NULL; gchar *message = NULL; GIcon *icon = NULL; GsdPowerActionType policy; guint timer_id; UpDeviceKind kind; /* get device properties */ g_object_get (device, "kind", &kind, NULL); if (kind == UP_DEVICE_KIND_BATTERY) { /* TRANSLATORS: laptop battery is really, really, low */ title = _("Laptop battery critically low"); /* we have to do different warnings depending on the policy */ policy = manager_critical_action_get (manager, FALSE); /* use different text for different actions */ if (policy == GSD_POWER_ACTION_NOTHING) { /* TRANSLATORS: computer will shutdown without saving data */ message = g_strdup (_("The battery is below the critical level and " "this computer will power-off when the " "battery becomes completely empty.")); } else if (policy == GSD_POWER_ACTION_SUSPEND) { /* TRANSLATORS: computer will suspend */ message = g_strdup (_("The battery is below the critical level and " "this computer is about to suspend.\n" "NOTE: A small amount of power is required " "to keep your computer in a suspended state.")); } else if (policy == GSD_POWER_ACTION_HIBERNATE) { /* TRANSLATORS: computer will hibernate */ message = g_strdup (_("The battery is below the critical level and " "this computer is about to hibernate.")); } else if (policy == GSD_POWER_ACTION_SHUTDOWN) { /* TRANSLATORS: computer will just shutdown */ message = g_strdup (_("The battery is below the critical level and " "this computer is about to shutdown.")); } /* wait 20 seconds for user-panic */ timer_id = g_timeout_add_seconds (GSD_ACTION_DELAY, (GSourceFunc) manager_critical_action_do_cb, manager); g_source_set_name_by_id (timer_id, "[GsdPowerManager] battery critical-action"); } else if (kind == UP_DEVICE_KIND_UPS) { /* TRANSLATORS: UPS is really, really, low */ title = _("UPS critically low"); /* we have to do different warnings depending on the policy */ policy = manager_critical_action_get (manager, TRUE); /* use different text for different actions */ if (policy == GSD_POWER_ACTION_NOTHING) { /* TRANSLATORS: computer will shutdown without saving data */ message = g_strdup (_("UPS is below the critical level and " "this computer will power-off when the " "UPS becomes completely empty.")); } else if (policy == GSD_POWER_ACTION_HIBERNATE) { /* TRANSLATORS: computer will hibernate */ message = g_strdup (_("UPS is below the critical level and " "this computer is about to hibernate.")); } else if (policy == GSD_POWER_ACTION_SHUTDOWN) { /* TRANSLATORS: computer will just shutdown */ message = g_strdup (_("UPS is below the critical level and " "this computer is about to shutdown.")); } /* wait 20 seconds for user-panic */ timer_id = g_timeout_add_seconds (GSD_ACTION_DELAY, (GSourceFunc) manager_critical_ups_action_do_cb, manager); g_source_set_name_by_id (timer_id, "[GsdPowerManager] ups critical-action"); } /* not all types have actions */ if (title == NULL) return; /* get correct icon */ icon = gpm_upower_get_device_icon (device, TRUE); /* close any existing notification of this class */ notify_close_if_showing (&manager->priv->notification_low); /* create a new notification */ create_notification (title, message, icon, &manager->priv->notification_low); notify_notification_set_timeout (manager->priv->notification_low, NOTIFY_EXPIRES_DEFAULT); notify_notification_set_urgency (manager->priv->notification_low, NOTIFY_URGENCY_CRITICAL); notify_notification_set_app_name (manager->priv->notification_low, _("Power")); /* try to show */ notify_notification_show (manager->priv->notification_low, NULL); /* play the sound, using sounds from the naming spec */ ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "battery-caution", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("Battery is critically low"), NULL); if (icon != NULL) g_object_unref (icon); g_free (message); } static void device_properties_changed_cb (UpDevice *device, GParamSpec *pspec, GsdPowerManager *manager) { UpDeviceKind kind; UpDeviceState state; UpDeviceState state_old; GsdPowerManagerWarning warning_old; GsdPowerManagerWarning warning; /* get device properties */ g_object_get (device, "kind", &kind, NULL); /* if battery then use composite device to cope with multiple batteries */ if (kind == UP_DEVICE_KIND_BATTERY) { g_debug ("updating because %s changed", up_device_get_object_path (device)); device = engine_update_composite_device (manager, device); } /* get device properties (may be composite) */ g_object_get (device, "state", &state, NULL); g_debug ("%s state is now %s", up_device_get_object_path (device), up_device_state_to_string (state)); /* see if any interesting state changes have happened */ state_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-state-old")); if (state_old != state) { if (state == UP_DEVICE_STATE_DISCHARGING) { g_debug ("discharging"); engine_ups_discharging (manager, device); } else if (state == UP_DEVICE_STATE_FULLY_CHARGED || state == UP_DEVICE_STATE_CHARGING) { g_debug ("fully charged or charging, hiding notifications if any"); notify_close_if_showing (&manager->priv->notification_low); notify_close_if_showing (&manager->priv->notification_ups_discharging); main_battery_or_ups_low_changed (manager, FALSE); } /* save new state */ g_object_set_data (G_OBJECT(device), "engine-state-old", GUINT_TO_POINTER(state)); } /* check the warning state has not changed */ warning_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-warning-old")); warning = engine_get_warning (manager, device); if (warning != warning_old) { if (warning == WARNING_LOW) { g_debug ("** EMIT: charge-low"); engine_charge_low (manager, device); } else if (warning == WARNING_CRITICAL) { g_debug ("** EMIT: charge-critical"); engine_charge_critical (manager, device); } else if (warning == WARNING_ACTION) { g_debug ("charge-action"); engine_charge_action (manager, device); } /* save new state */ g_object_set_data (G_OBJECT(device), "engine-warning-old", GUINT_TO_POINTER(warning)); } engine_recalculate_state (manager); } static UpDevice * engine_get_primary_device (GsdPowerManager *manager) { guint i; UpDevice *device = NULL; UpDevice *device_tmp; UpDeviceKind kind; UpDeviceState state; gboolean is_present; for (i=0; ipriv->devices_array->len; i++) { device_tmp = g_ptr_array_index (manager->priv->devices_array, i); /* get device properties */ g_object_get (device_tmp, "kind", &kind, "state", &state, "is-present", &is_present, NULL); /* not present */ if (!is_present) continue; /* not discharging */ if (state != UP_DEVICE_STATE_DISCHARGING) continue; /* not battery */ if (kind != UP_DEVICE_KIND_BATTERY) continue; /* use composite device to cope with multiple batteries */ device = g_object_ref (engine_get_composite_device (manager, device_tmp)); break; } return device; } static void gnome_session_shutdown_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *result; GError *error = NULL; result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_warning ("couldn't shutdown using gnome-session: %s", error->message); g_error_free (error); } else { g_variant_unref (result); } } static void gnome_session_shutdown (GsdPowerManager *manager) { g_dbus_proxy_call (G_DBUS_PROXY (manager->priv->session), "Shutdown", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, gnome_session_shutdown_cb, NULL); } static void gnome_session_logout_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *result; GError *error = NULL; result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_warning ("couldn't log out using gnome-session: %s", error->message); g_error_free (error); } else { g_variant_unref (result); } } static void gnome_session_logout (GsdPowerManager *manager, guint logout_mode) { g_dbus_proxy_call (G_DBUS_PROXY (manager->priv->session), "Logout", g_variant_new ("(u)", logout_mode), G_DBUS_CALL_FLAGS_NONE, -1, NULL, gnome_session_logout_cb, NULL); } static void action_poweroff (GsdPowerManager *manager) { if (manager->priv->logind_proxy == NULL) { g_warning ("no systemd support"); return; } g_dbus_proxy_call (manager->priv->logind_proxy, "PowerOff", g_variant_new ("(b)", FALSE), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, NULL, NULL); } static void action_suspend (GsdPowerManager *manager) { if (manager->priv->logind_proxy == NULL) { g_warning ("no systemd support"); return; } g_dbus_proxy_call (manager->priv->logind_proxy, "Suspend", g_variant_new ("(b)", FALSE), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, NULL, NULL); } static void action_hibernate (GsdPowerManager *manager) { if (manager->priv->logind_proxy == NULL) { g_warning ("no systemd support"); return; } g_dbus_proxy_call (manager->priv->logind_proxy, "Hibernate", g_variant_new ("(b)", FALSE), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, NULL, NULL); } static void backlight_enable (GsdPowerManager *manager) { gboolean ret; GError *error = NULL; ret = gsd_rr_screen_set_dpms_mode (manager->priv->rr_screen, GSD_RR_DPMS_ON, &error); if (!ret) { g_warning ("failed to turn the panel on: %s", error->message); g_error_free (error); } g_debug ("TESTSUITE: Unblanked screen"); } static void backlight_disable (GsdPowerManager *manager) { gboolean ret; GError *error = NULL; ret = gsd_rr_screen_set_dpms_mode (manager->priv->rr_screen, GSD_RR_DPMS_OFF, &error); if (!ret) { g_warning ("failed to turn the panel off: %s", error->message); g_error_free (error); } g_debug ("TESTSUITE: Blanked screen"); } static void do_power_action_type (GsdPowerManager *manager, GsdPowerActionType action_type) { switch (action_type) { case GSD_POWER_ACTION_SUSPEND: action_suspend (manager); break; case GSD_POWER_ACTION_INTERACTIVE: gnome_session_shutdown (manager); break; case GSD_POWER_ACTION_HIBERNATE: action_hibernate (manager); break; case GSD_POWER_ACTION_SHUTDOWN: /* this is only used on critically low battery where * hibernate is not available and is marginally better * than just powering down the computer mid-write */ action_poweroff (manager); break; case GSD_POWER_ACTION_BLANK: backlight_disable (manager); break; case GSD_POWER_ACTION_NOTHING: break; case GSD_POWER_ACTION_LOGOUT: gnome_session_logout (manager, GSM_MANAGER_LOGOUT_MODE_FORCE); break; } } static GsmInhibitorFlag get_idle_inhibitors_for_action (GsdPowerActionType action_type) { switch (action_type) { case GSD_POWER_ACTION_BLANK: case GSD_POWER_ACTION_SHUTDOWN: case GSD_POWER_ACTION_INTERACTIVE: return GSM_INHIBITOR_FLAG_IDLE; case GSD_POWER_ACTION_HIBERNATE: case GSD_POWER_ACTION_SUSPEND: return GSM_INHIBITOR_FLAG_SUSPEND; /* in addition to idle */ case GSD_POWER_ACTION_NOTHING: return 0; case GSD_POWER_ACTION_LOGOUT: return GSM_INHIBITOR_FLAG_LOGOUT; /* in addition to idle */ } return 0; } static gboolean is_action_inhibited (GsdPowerManager *manager, GsdPowerActionType action_type) { GsmInhibitorFlag flag; gboolean is_inhibited; flag = get_idle_inhibitors_for_action (action_type); if (!flag) return FALSE; idle_is_session_inhibited (manager, flag, &is_inhibited); return is_inhibited; } static gboolean upower_kbd_get_brightness (GsdPowerManager *manager) { GVariant *k_now = NULL; GError *error = NULL; gint now; k_now = g_dbus_proxy_call_sync (manager->priv->upower_kdb_proxy, "GetBrightness", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (k_now == NULL) { if (error->domain != G_DBUS_ERROR || error->code != G_DBUS_ERROR_UNKNOWN_METHOD) { g_warning ("Failed to get brightness: %s", error->message); } g_error_free (error); return -1; } g_variant_get (k_now, "(i)", &now); g_variant_unref (k_now); return now; } static gboolean upower_kbd_set_brightness (GsdPowerManager *manager, guint value, GError **error) { GVariant *retval; /* update h/w value */ retval = g_dbus_proxy_call_sync (manager->priv->upower_kdb_proxy, "SetBrightness", g_variant_new ("(i)", (gint) value), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); if (retval == NULL) return FALSE; g_variant_unref (retval); return TRUE; } static int upower_kbd_toggle (GsdPowerManager *manager, GError **error) { gboolean ret; int value = -1; if (manager->priv->kbd_brightness_old >= 0) { g_debug ("keyboard toggle off"); ret = upower_kbd_set_brightness (manager, manager->priv->kbd_brightness_old, error); if (ret) { /* succeeded, set to -1 since now no old value */ manager->priv->kbd_brightness_old = -1; value = 0; } } else { g_debug ("keyboard toggle on"); /* save the current value to restore later when untoggling */ manager->priv->kbd_brightness_old = upower_kbd_get_brightness (manager); ret = upower_kbd_set_brightness (manager, 0, error); if (!ret) { /* failed, reset back to -1 */ manager->priv->kbd_brightness_old = -1; } else { value = 0; } } if (ret) return value; return -1; } static gboolean suspend_on_lid_close (GsdPowerManager *manager) { GsdXrandrBootBehaviour val; if (manager->priv->inhibit_lid_switch_action) return FALSE; if (!external_monitor_is_connected (manager->priv->rr_screen)) return TRUE; val = g_settings_get_enum (manager->priv->settings_xrandr, "default-monitors-setup"); return val == GSD_XRANDR_BOOT_BEHAVIOUR_DO_NOTHING; } static gboolean inhibit_lid_switch_timer_cb (GsdPowerManager *manager) { if (suspend_on_lid_close (manager)) { g_debug ("no external monitors for a while; uninhibiting lid close"); uninhibit_lid_switch (manager); manager->priv->inhibit_lid_switch_timer_id = 0; return G_SOURCE_REMOVE; } g_debug ("external monitor still there; trying again later"); return G_SOURCE_CONTINUE; } /* Sets up a timer to be triggered some seconds after closing the laptop lid * when the laptop is *not* suspended for some reason. We'll check conditions * again in the timeout handler to see if we can suspend then. */ static void setup_inhibit_lid_switch_timer (GsdPowerManager *manager) { if (manager->priv->inhibit_lid_switch_timer_id != 0) { g_debug ("lid close safety timer already set up"); return; } g_debug ("setting up lid close safety timer"); manager->priv->inhibit_lid_switch_timer_id = g_timeout_add_seconds (GSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT, (GSourceFunc) inhibit_lid_switch_timer_cb, manager); g_source_set_name_by_id (manager->priv->inhibit_lid_switch_timer_id, "[GsdPowerManager] lid close safety timer"); } static void restart_inhibit_lid_switch_timer (GsdPowerManager *manager) { if (manager->priv->inhibit_lid_switch_timer_id != 0) { g_debug ("restarting lid close safety timer"); g_source_remove (manager->priv->inhibit_lid_switch_timer_id); manager->priv->inhibit_lid_switch_timer_id = 0; setup_inhibit_lid_switch_timer (manager); } } static void setup_lid_closed_action (GsdPowerManager *manager) { GsdPowerActionType policy; if (up_client_get_on_battery (manager->priv->up_client)) { policy = g_settings_get_enum (manager->priv->settings, "lid-close-battery-action"); } else { policy = g_settings_get_enum (manager->priv->settings, "lid-close-ac-action"); } if (policy == GSD_POWER_ACTION_NOTHING) { inhibit_lid_switch (manager); manager->priv->inhibit_lid_switch_action = TRUE; } else { uninhibit_lid_switch (manager); manager->priv->inhibit_lid_switch_action = FALSE; } } static void do_lid_open_action (GsdPowerManager *manager) { /* play a sound, using sounds from the naming spec */ ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "lid-open", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("Lid has been opened"), NULL); /* This might already have happened when resuming, but * if we didn't sleep, we'll need to wake it up */ reset_idletime (); } static void lock_screensaver (GsdPowerManager *manager) { gboolean do_lock; do_lock = g_settings_get_boolean (manager->priv->settings_screensaver, "lock-enabled"); if (!do_lock) { g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->screensaver_proxy), "SetActive", g_variant_new ("(b)", TRUE), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); return; } g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->screensaver_proxy), "Lock", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); } static void do_lid_closed_action (GsdPowerManager *manager) { /* play a sound, using sounds from the naming spec */ ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "lid-close", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("Lid has been closed"), NULL); /* refresh RANDR so we get an accurate view of what monitors are plugged in when the lid is closed */ gsd_rr_screen_refresh (manager->priv->rr_screen, NULL); /* NULL-GError */ restart_inhibit_lid_switch_timer (manager); if (suspend_on_lid_close (manager)) { gboolean is_inhibited; idle_is_session_inhibited (manager, GSM_INHIBITOR_FLAG_SUSPEND, &is_inhibited); if (is_inhibited) { g_debug ("Suspend is inhibited but lid is closed, locking the screen"); /* We put the screensaver on * as we're not suspending, * but the lid is closed */ lock_screensaver (manager); } } else { if (manager->priv->inhibit_lid_switch_action) lock_screensaver (manager); } } static void lid_state_changed_cb (UpClient *client, GParamSpec *pspec, GsdPowerManager *manager) { gboolean tmp; if (!up_client_get_on_battery (client)) { /* if we are playing a critical charge sound loop on AC, stop it */ play_loop_stop (&manager->priv->critical_alert_timeout_id); notify_close_if_showing (&manager->priv->notification_low); main_battery_or_ups_low_changed (manager, FALSE); } setup_lid_closed_action (manager); /* same state */ tmp = up_client_get_lid_is_closed (manager->priv->up_client); if (manager->priv->lid_is_closed == tmp) return; manager->priv->lid_is_closed = tmp; g_debug ("up changed: lid is now %s", tmp ? "closed" : "open"); if (manager->priv->lid_is_closed) do_lid_closed_action (manager); else do_lid_open_action (manager); } static const gchar * idle_mode_to_string (GsdPowerIdleMode mode) { if (mode == GSD_POWER_IDLE_MODE_NORMAL) return "normal"; if (mode == GSD_POWER_IDLE_MODE_DIM) return "dim"; if (mode == GSD_POWER_IDLE_MODE_BLANK) return "blank"; if (mode == GSD_POWER_IDLE_MODE_SLEEP) return "sleep"; return "unknown"; } static const char * idle_watch_id_to_string (GsdPowerManager *manager, guint id) { if (id == manager->priv->idle_dim_id) return "dim"; if (id == manager->priv->idle_blank_id) return "blank"; if (id == manager->priv->idle_sleep_id) return "sleep"; if (id == manager->priv->idle_sleep_warning_id) return "sleep-warning"; return NULL; } static void backlight_emit_changed (GsdPowerManager *manager) { gboolean ret; GError *error = NULL; /* not yet connected to the bus */ if (manager->priv->connection == NULL) return; ret = g_dbus_connection_emit_signal (manager->priv->connection, NULL, GSD_POWER_DBUS_PATH, GSD_POWER_DBUS_INTERFACE_SCREEN, "Changed", NULL, &error); if (!ret) { g_warning ("failed to emit Changed: %s", error->message); g_error_free (error); } } static gboolean display_backlight_dim (GsdPowerManager *manager, gint idle_percentage, GError **error) { gint min; gint max; gint now; gint idle; gboolean ret = FALSE; if (!manager->priv->backlight_available) return TRUE; now = backlight_get_abs (manager->priv->rr_screen, error); if (now < 0) { goto out; } /* is the dim brightness actually *dimmer* than the * brightness we have now? */ min = backlight_get_min (manager->priv->rr_screen); max = backlight_get_max (manager->priv->rr_screen, error); if (max < 0) { goto out; } idle = PERCENTAGE_TO_ABS (min, max, idle_percentage); if (idle > now) { g_debug ("brightness already now %i/%i, so " "ignoring dim to %i/%i", now, max, idle, max); ret = TRUE; goto out; } ret = backlight_set_abs (manager->priv->rr_screen, idle, error); if (!ret) { goto out; } /* save for undim */ manager->priv->pre_dim_brightness = now; out: return ret; } static gboolean kbd_backlight_dim (GsdPowerManager *manager, gint idle_percentage, GError **error) { gboolean ret; gint idle; gint max; gint now; if (manager->priv->upower_kdb_proxy == NULL) return TRUE; now = upower_kbd_get_brightness (manager); max = manager->priv->kbd_brightness_max; idle = PERCENTAGE_TO_ABS (0, max, idle_percentage); if (idle > now) { g_debug ("kbd brightness already now %i/%i, so " "ignoring dim to %i/%i", now, max, idle, max); return TRUE; } ret = upower_kbd_set_brightness (manager, idle, error); if (!ret) return FALSE; /* save for undim */ manager->priv->kbd_brightness_pre_dim = now; return TRUE; } static gboolean is_session_active (GsdPowerManager *manager) { GVariant *variant; gboolean is_session_active = FALSE; variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (manager->priv->session), "SessionIsActive"); if (variant) { is_session_active = g_variant_get_boolean (variant); g_variant_unref (variant); } return is_session_active; } static void idle_set_mode (GsdPowerManager *manager, GsdPowerIdleMode mode) { gboolean ret = FALSE; GError *error = NULL; gint idle_percentage; GsdPowerActionType action_type; gboolean is_active = FALSE; /* Ignore attempts to set "less idle" modes */ if (mode <= manager->priv->current_idle_mode && mode != GSD_POWER_IDLE_MODE_NORMAL) { g_debug ("Not going to 'less idle' mode %s (current: %s)", idle_mode_to_string (mode), idle_mode_to_string (manager->priv->current_idle_mode)); return; } /* ensure we're still on an active console */ is_active = is_session_active (manager); if (!is_active) { g_debug ("ignoring state transition to %s as inactive", idle_mode_to_string (mode)); return; } /* don't do any power saving if we're a VM */ if (manager->priv->is_virtual_machine) { g_debug ("ignoring state transition to %s as virtual machine", idle_mode_to_string (mode)); return; } manager->priv->current_idle_mode = mode; g_debug ("Doing a state transition: %s", idle_mode_to_string (mode)); /* if we're moving to an idle mode, make sure * we add a watch to take us back to normal */ if (mode != GSD_POWER_IDLE_MODE_NORMAL) { gsd_idle_monitor_add_user_active_watch (manager->priv->idle_monitor, idle_became_active_cb, manager, NULL); } /* save current brightness, and set dim level */ if (mode == GSD_POWER_IDLE_MODE_DIM) { /* display backlight */ idle_percentage = g_settings_get_int (manager->priv->settings, "idle-brightness"); ret = display_backlight_dim (manager, idle_percentage, &error); if (!ret) { g_warning ("failed to set dim backlight to %i%%: %s", idle_percentage, error->message); g_clear_error (&error); } /* keyboard backlight */ ret = kbd_backlight_dim (manager, idle_percentage, &error); if (!ret) { g_warning ("failed to set dim kbd backlight to %i%%: %s", idle_percentage, error->message); g_clear_error (&error); } /* turn off screen and kbd */ } else if (mode == GSD_POWER_IDLE_MODE_BLANK) { backlight_disable (manager); /* only toggle keyboard if present and not already toggled */ if (manager->priv->upower_kdb_proxy && manager->priv->kbd_brightness_old == -1) { if (upower_kbd_toggle (manager, &error) < 0) { g_warning ("failed to turn the kbd backlight off: %s", error->message); g_error_free (error); } } /* sleep */ } else if (mode == GSD_POWER_IDLE_MODE_SLEEP) { if (up_client_get_on_battery (manager->priv->up_client)) { action_type = g_settings_get_enum (manager->priv->settings, "sleep-inactive-battery-type"); } else { action_type = g_settings_get_enum (manager->priv->settings, "sleep-inactive-ac-type"); } do_power_action_type (manager, action_type); /* turn on screen and restore user-selected brightness level */ } else if (mode == GSD_POWER_IDLE_MODE_NORMAL) { backlight_enable (manager); /* reset brightness if we dimmed */ if (manager->priv->pre_dim_brightness >= 0) { ret = backlight_set_abs (manager->priv->rr_screen, manager->priv->pre_dim_brightness, &error); if (!ret) { g_warning ("failed to restore backlight to %i: %s", manager->priv->pre_dim_brightness, error->message); g_clear_error (&error); } else { manager->priv->pre_dim_brightness = -1; } } /* only toggle keyboard if present and already toggled off */ if (manager->priv->upower_kdb_proxy && manager->priv->kbd_brightness_old != -1) { if (upower_kbd_toggle (manager, &error) < 0) { g_warning ("failed to turn the kbd backlight on: %s", error->message); g_clear_error (&error); } } /* reset kbd brightness if we dimmed */ if (manager->priv->kbd_brightness_pre_dim >= 0) { ret = upower_kbd_set_brightness (manager, manager->priv->kbd_brightness_pre_dim, &error); if (!ret) { g_warning ("failed to restore kbd backlight to %i: %s", manager->priv->kbd_brightness_pre_dim, error->message); g_error_free (error); } manager->priv->kbd_brightness_pre_dim = -1; } } } static gboolean idle_is_session_inhibited (GsdPowerManager *manager, GsmInhibitorFlag mask, gboolean *is_inhibited) { GVariant *variant; GsmInhibitorFlag inhibited_actions; /* not yet connected to gnome-session */ if (manager->priv->session == NULL) return FALSE; variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (manager->priv->session), "InhibitedActions"); if (!variant) return FALSE; inhibited_actions = g_variant_get_uint32 (variant); g_variant_unref (variant); *is_inhibited = (inhibited_actions & mask); return TRUE; } static void clear_idle_watch (GsdIdleMonitor *monitor, guint *id) { if (*id == 0) return; gsd_idle_monitor_remove_watch (monitor, *id); *id = 0; } static void idle_configure (GsdPowerManager *manager) { gboolean is_idle_inhibited; GsdPowerActionType action_type; guint timeout_blank; guint timeout_sleep; guint timeout_dim; gboolean on_battery; if (!idle_is_session_inhibited (manager, GSM_INHIBITOR_FLAG_IDLE, &is_idle_inhibited)) { /* Session isn't available yet, postpone */ return; } /* are we inhibited from going idle */ if (!is_session_active (manager) || is_idle_inhibited) { g_debug ("inhibited or inactive, so using normal state"); idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL); clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_blank_id); clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_sleep_id); clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_dim_id); clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_sleep_warning_id); notify_close_if_showing (&manager->priv->notification_sleep_warning); return; } /* set up blank callback only when the screensaver is on, * as it's what will drive the blank */ on_battery = up_client_get_on_battery (manager->priv->up_client); timeout_blank = 0; if (manager->priv->screensaver_active) { /* The tail is wagging the dog. * The screensaver coming on will blank the screen. * If an event occurs while the screensaver is on, * the aggressive idle watch will handle it */ timeout_blank = SCREENSAVER_TIMEOUT_BLANK; } clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_blank_id); if (timeout_blank != 0) { g_debug ("setting up blank callback for %is", timeout_blank); manager->priv->idle_blank_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor, timeout_blank * 1000, idle_triggered_idle_cb, manager, NULL); } /* only do the sleep timeout when the session is idle * and we aren't inhibited from sleeping (or logging out, etc.) */ action_type = g_settings_get_enum (manager->priv->settings, on_battery ? "sleep-inactive-battery-type" : "sleep-inactive-ac-type"); timeout_sleep = 0; if (!is_action_inhibited (manager, action_type)) { timeout_sleep = g_settings_get_int (manager->priv->settings, on_battery ? "sleep-inactive-battery-timeout" : "sleep-inactive-ac-timeout"); } clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_sleep_id); clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_sleep_warning_id); if (timeout_sleep != 0) { g_debug ("setting up sleep callback %is", timeout_sleep); manager->priv->idle_sleep_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor, timeout_sleep * 1000, idle_triggered_idle_cb, manager, NULL); if (action_type == GSD_POWER_ACTION_LOGOUT || action_type == GSD_POWER_ACTION_SUSPEND || action_type == GSD_POWER_ACTION_HIBERNATE) { guint timeout_sleep_warning; manager->priv->sleep_action_type = action_type; timeout_sleep_warning = timeout_sleep * IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER; if (timeout_sleep_warning < MINIMUM_IDLE_DIM_DELAY) timeout_sleep_warning = 0; g_debug ("setting up sleep warning callback %is", timeout_sleep_warning); manager->priv->idle_sleep_warning_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor, timeout_sleep_warning * 1000, idle_triggered_idle_cb, manager, NULL); } } if (manager->priv->idle_sleep_warning_id == 0) notify_close_if_showing (&manager->priv->notification_sleep_warning); /* set up dim callback for when the screen lock is not active, * but only if we actually want to dim. */ timeout_dim = 0; if (manager->priv->screensaver_active) { /* Don't dim when the screen lock is active */ } else if (!on_battery) { /* Don't dim when charging */ } else if (manager->priv->battery_is_low) { /* Aggressively blank when battery is low */ timeout_dim = SCREENSAVER_TIMEOUT_BLANK; } else { if (g_settings_get_boolean (manager->priv->settings, "idle-dim")) { timeout_dim = g_settings_get_uint (manager->priv->settings_bus, "idle-delay"); if (timeout_dim == 0) { timeout_dim = IDLE_DIM_BLANK_DISABLED_MIN; } else { timeout_dim *= IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER; /* Don't bother dimming if the idle-delay is * too low, we'll do that when we bring down the * screen lock */ if (timeout_dim < MINIMUM_IDLE_DIM_DELAY) timeout_dim = 0; } } } clear_idle_watch (manager->priv->idle_monitor, &manager->priv->idle_dim_id); if (timeout_dim != 0) { g_debug ("setting up dim callback for %is", timeout_dim); manager->priv->idle_dim_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor, timeout_dim * 1000, idle_triggered_idle_cb, manager, NULL); } } static void main_battery_or_ups_low_changed (GsdPowerManager *manager, gboolean is_low) { if (is_low == manager->priv->battery_is_low) return; manager->priv->battery_is_low = is_low; idle_configure (manager); } static gboolean temporary_unidle_done_cb (GsdPowerManager *manager) { idle_set_mode (manager, manager->priv->previous_idle_mode); manager->priv->temporary_unidle_on_ac_id = 0; return FALSE; } static void set_temporary_unidle_on_ac (GsdPowerManager *manager, gboolean enable) { if (!enable) { if (manager->priv->temporary_unidle_on_ac_id != 0) { g_source_remove (manager->priv->temporary_unidle_on_ac_id); manager->priv->temporary_unidle_on_ac_id = 0; idle_set_mode (manager, manager->priv->previous_idle_mode); } } else { /* Don't overwrite the previous idle mode when an unidle is * already on-going */ if (manager->priv->temporary_unidle_on_ac_id != 0) { g_source_remove (manager->priv->temporary_unidle_on_ac_id); } else { manager->priv->previous_idle_mode = manager->priv->current_idle_mode; idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL); } manager->priv->temporary_unidle_on_ac_id = g_timeout_add_seconds (POWER_UP_TIME_ON_AC, (GSourceFunc) temporary_unidle_done_cb, manager); } } static void up_client_on_battery_cb (UpClient *client, GParamSpec *pspec, GsdPowerManager *manager) { if (up_client_get_on_battery (manager->priv->up_client)) { ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "power-unplug", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("On battery power"), NULL); } else { ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "power-plug", /* TRANSLATORS: this is the sound description */ CA_PROP_EVENT_DESCRIPTION, _("On AC power"), NULL); } idle_configure (manager); if (manager->priv->lid_is_closed) return; if (manager->priv->current_idle_mode == GSD_POWER_IDLE_MODE_BLANK || manager->priv->current_idle_mode == GSD_POWER_IDLE_MODE_DIM || manager->priv->temporary_unidle_on_ac_id != 0) set_temporary_unidle_on_ac (manager, TRUE); } static void gsd_power_manager_finalize (GObject *object) { GsdPowerManager *manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_POWER_MANAGER (object)); manager = GSD_POWER_MANAGER (object); g_return_if_fail (manager->priv != NULL); g_clear_object (&manager->priv->connection); if (manager->priv->name_id != 0) g_bus_unown_name (manager->priv->name_id); G_OBJECT_CLASS (gsd_power_manager_parent_class)->finalize (object); } static void gsd_power_manager_class_init (GsdPowerManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_power_manager_finalize; g_type_class_add_private (klass, sizeof (GsdPowerManagerPrivate)); } static void session_presence_proxy_ready_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); manager->priv->session_presence_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (manager->priv->session_presence_proxy == NULL) { g_warning ("Could not connect to gnome-sesson: %s", error->message); g_error_free (error); return; } } static void handle_screensaver_active (GsdPowerManager *manager, GVariant *parameters) { gboolean active; g_variant_get (parameters, "(b)", &active); g_debug ("Received screensaver ActiveChanged signal: %d (old: %d)", active, manager->priv->screensaver_active); if (manager->priv->screensaver_active != active) { manager->priv->screensaver_active = active; idle_configure (manager); /* Setup blank as soon as the screensaver comes on, * and its fade has finished. * * See also idle_configure() */ if (active) idle_set_mode (manager, GSD_POWER_IDLE_MODE_BLANK); } } static void screensaver_signal_cb (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { if (g_strcmp0 (signal_name, "ActiveChanged") == 0) handle_screensaver_active (GSD_POWER_MANAGER (user_data), parameters); } static void power_keyboard_proxy_ready_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *k_max = NULL; GError *error = NULL; GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); manager->priv->upower_kdb_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (manager->priv->upower_kdb_proxy == NULL) { g_warning ("Could not connect to UPower: %s", error->message); g_error_free (error); goto out; } k_max = g_dbus_proxy_call_sync (manager->priv->upower_kdb_proxy, "GetMaxBrightness", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (k_max == NULL) { if (error->domain != G_DBUS_ERROR || error->code != G_DBUS_ERROR_UNKNOWN_METHOD) { g_warning ("Failed to get max brightness: %s", error->message); } g_error_free (error); goto out; } g_variant_get (k_max, "(i)", &manager->priv->kbd_brightness_max); /* set brightness to max if not currently set so is something * sensible */ if (upower_kbd_get_brightness (manager) < 0) { gboolean ret; ret = upower_kbd_set_brightness (manager, manager->priv->kbd_brightness_max, &error); if (!ret) { g_warning ("failed to initialize kbd backlight to %i: %s", manager->priv->kbd_brightness_max, error->message); g_error_free (error); } } out: if (k_max != NULL) g_variant_unref (k_max); } static void show_sleep_warning (GsdPowerManager *manager) { /* close any existing notification of this class */ notify_close_if_showing (&manager->priv->notification_sleep_warning); /* create a new notification */ switch (manager->priv->sleep_action_type) { case GSD_POWER_ACTION_LOGOUT: create_notification (_("Automatic logout"), _("You will soon log out because of inactivity."), NULL, &manager->priv->notification_sleep_warning); break; case GSD_POWER_ACTION_SUSPEND: create_notification (_("Automatic suspend"), _("Computer will suspend very soon because of inactivity."), NULL, &manager->priv->notification_sleep_warning); break; case GSD_POWER_ACTION_HIBERNATE: create_notification (_("Automatic hibernation"), _("Computer will suspend very soon because of inactivity."), NULL, &manager->priv->notification_sleep_warning); break; default: g_assert_not_reached (); break; } notify_notification_set_timeout (manager->priv->notification_sleep_warning, NOTIFY_EXPIRES_DEFAULT); notify_notification_set_urgency (manager->priv->notification_sleep_warning, NOTIFY_URGENCY_CRITICAL); notify_notification_set_app_name (manager->priv->notification_sleep_warning, _("Power")); notify_notification_show (manager->priv->notification_sleep_warning, NULL); if (manager->priv->sleep_action_type == GSD_POWER_ACTION_LOGOUT) set_temporary_unidle_on_ac (manager, TRUE); } static void idle_triggered_idle_cb (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data) { GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); const char *id_name; id_name = idle_watch_id_to_string (manager, watch_id); if (id_name == NULL) g_debug ("idletime watch: %i", watch_id); else g_debug ("idletime watch: %s (%i)", id_name, watch_id); if (watch_id == manager->priv->idle_dim_id) { idle_set_mode (manager, GSD_POWER_IDLE_MODE_DIM); } else if (watch_id == manager->priv->idle_blank_id) { idle_set_mode (manager, GSD_POWER_IDLE_MODE_BLANK); } else if (watch_id == manager->priv->idle_sleep_id) { idle_set_mode (manager, GSD_POWER_IDLE_MODE_SLEEP); } else if (watch_id == manager->priv->idle_sleep_warning_id) { show_sleep_warning (manager); } } static void idle_became_active_cb (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data) { GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); g_debug ("idletime reset"); set_temporary_unidle_on_ac (manager, FALSE); /* close any existing notification about idleness */ notify_close_if_showing (&manager->priv->notification_sleep_warning); idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL); } static void engine_settings_key_changed_cb (GSettings *settings, const gchar *key, GsdPowerManager *manager) { if (g_strcmp0 (key, "use-time-for-policy") == 0) { manager->priv->use_time_primary = g_settings_get_boolean (settings, key); return; } if (g_str_has_prefix (key, "sleep-inactive") || g_str_equal (key, "idle-delay") || g_str_equal (key, "idle-dim")) { idle_configure (manager); return; } if (g_str_has_prefix (key, "lid-close")) { setup_lid_closed_action (manager); return; } } static void engine_session_properties_changed_cb (GDBusProxy *session, GVariant *changed, char **invalidated, GsdPowerManager *manager) { GVariant *v; v = g_variant_lookup_value (changed, "SessionIsActive", G_VARIANT_TYPE_BOOLEAN); if (v) { gboolean active; active = g_variant_get_boolean (v); g_debug ("Received session is active change: now %s", active ? "active" : "inactive"); /* when doing the fast-user-switch into a new account, * ensure the new account is undimmed and with the backlight on */ if (active) idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL); g_variant_unref (v); } v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32); if (v) { g_variant_unref (v); g_debug ("Received gnome session inhibitor change"); idle_configure (manager); } } static void inhibit_lid_switch_done (GObject *source, GAsyncResult *result, gpointer user_data) { GDBusProxy *proxy = G_DBUS_PROXY (source); GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); GError *error = NULL; GVariant *res; GUnixFDList *fd_list = NULL; gint idx; res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error); if (res == NULL) { g_warning ("Unable to inhibit lid switch: %s", error->message); g_error_free (error); } else { g_variant_get (res, "(h)", &idx); manager->priv->inhibit_lid_switch_fd = g_unix_fd_list_get (fd_list, idx, &error); if (manager->priv->inhibit_lid_switch_fd == -1) { g_warning ("Failed to receive system inhibitor fd: %s", error->message); g_error_free (error); } g_debug ("System inhibitor fd is %d", manager->priv->inhibit_lid_switch_fd); g_object_unref (fd_list); g_variant_unref (res); } } static void inhibit_lid_switch (GsdPowerManager *manager) { GVariant *params; if (manager->priv->inhibit_lid_switch_taken) { g_debug ("already inhibited lid-switch"); return; } g_debug ("Adding lid switch system inhibitor"); manager->priv->inhibit_lid_switch_taken = TRUE; params = g_variant_new ("(ssss)", "handle-lid-switch", g_get_user_name (), "Multiple displays attached", "block"); g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy, "Inhibit", params, 0, G_MAXINT, NULL, NULL, inhibit_lid_switch_done, manager); } static void uninhibit_lid_switch (GsdPowerManager *manager) { if (manager->priv->inhibit_lid_switch_fd == -1) { g_debug ("no lid-switch inhibitor"); return; } g_debug ("Removing lid switch system inhibitor"); close (manager->priv->inhibit_lid_switch_fd); manager->priv->inhibit_lid_switch_fd = -1; manager->priv->inhibit_lid_switch_taken = FALSE; } static void inhibit_suspend_done (GObject *source, GAsyncResult *result, gpointer user_data) { GDBusProxy *proxy = G_DBUS_PROXY (source); GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); GError *error = NULL; GVariant *res; GUnixFDList *fd_list = NULL; gint idx; res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error); if (res == NULL) { g_warning ("Unable to inhibit suspend: %s", error->message); g_error_free (error); } else { g_variant_get (res, "(h)", &idx); manager->priv->inhibit_suspend_fd = g_unix_fd_list_get (fd_list, idx, &error); if (manager->priv->inhibit_suspend_fd == -1) { g_warning ("Failed to receive system inhibitor fd: %s", error->message); g_error_free (error); } g_debug ("System inhibitor fd is %d", manager->priv->inhibit_suspend_fd); g_object_unref (fd_list); g_variant_unref (res); } } /* We take a delay inhibitor here, which causes logind to send a * PrepareForSleep signal, which gives us a chance to lock the screen * and do some other preparations. */ static void inhibit_suspend (GsdPowerManager *manager) { if (manager->priv->inhibit_suspend_taken) { g_debug ("already inhibited lid-switch"); return; } g_debug ("Adding suspend delay inhibitor"); manager->priv->inhibit_suspend_taken = TRUE; g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy, "Inhibit", g_variant_new ("(ssss)", "sleep", g_get_user_name (), "GNOME needs to lock the screen", "delay"), 0, G_MAXINT, NULL, NULL, inhibit_suspend_done, manager); } static void uninhibit_suspend (GsdPowerManager *manager) { if (manager->priv->inhibit_suspend_fd == -1) { g_debug ("no suspend delay inhibitor"); return; } g_debug ("Removing suspend delay inhibitor"); close (manager->priv->inhibit_suspend_fd); manager->priv->inhibit_suspend_fd = -1; manager->priv->inhibit_suspend_taken = FALSE; } static void on_randr_event (GsdRRScreen *screen, gpointer user_data) { GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); if (suspend_on_lid_close (manager)) { restart_inhibit_lid_switch_timer (manager); return; } /* when a second monitor is plugged in, we take the * handle-lid-switch inhibitor lock of logind to prevent * it from suspending. * * Uninhibiting is done in the inhibit_lid_switch_timer, * since we want to give users a few seconds when unplugging * and replugging an external monitor, not suspend right away. */ inhibit_lid_switch (manager); setup_inhibit_lid_switch_timer (manager); } #ifdef GSD_MOCK static gboolean received_sigusr2 (GsdPowerManager *manager) { on_randr_event (NULL, manager); return TRUE; } #endif /* GSD_MOCK */ static void handle_suspend_actions (GsdPowerManager *manager) { backlight_disable (manager); uninhibit_suspend (manager); } static void handle_resume_actions (GsdPowerManager *manager) { /* close existing notifications on resume, the system power * state is probably different now */ notify_close_if_showing (&manager->priv->notification_low); notify_close_if_showing (&manager->priv->notification_ups_discharging); main_battery_or_ups_low_changed (manager, FALSE); /* ensure we turn the panel back on after resume */ backlight_enable (manager); /* And work-around Xorg bug: * https://bugs.freedesktop.org/show_bug.cgi?id=59576 */ reset_idletime (); /* set up the delay again */ inhibit_suspend (manager); } static void logind_proxy_signal_cb (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); gboolean is_about_to_suspend; if (g_strcmp0 (signal_name, "PrepareForSleep") != 0) return; g_variant_get (parameters, "(b)", &is_about_to_suspend); if (is_about_to_suspend) { handle_suspend_actions (manager); } else { handle_resume_actions (manager); } } gboolean gsd_power_manager_start (GsdPowerManager *manager, GError **error) { g_debug ("Starting power manager"); gnome_settings_profile_start (NULL); /* coldplug the list of screens */ manager->priv->rr_screen = gsd_rr_screen_new (gdk_screen_get_default (), error); if (manager->priv->rr_screen == NULL) { g_debug ("Couldn't detect any screens, disabling plugin"); return FALSE; } /* Check for XTEST support */ if (supports_xtest () == FALSE) { g_debug ("XTEST extension required, disabling plugin"); return FALSE; } /* Set up the logind proxy */ manager->priv->logind_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL, SYSTEMD_DBUS_NAME, SYSTEMD_DBUS_PATH, SYSTEMD_DBUS_INTERFACE, NULL, error); if (manager->priv->logind_proxy == NULL) { g_debug ("No systemd (logind) support, disabling plugin"); return FALSE; } g_signal_connect (manager->priv->logind_proxy, "g-signal", G_CALLBACK (logind_proxy_signal_cb), manager); /* Set up a delay inhibitor to be informed about suspend attempts */ inhibit_suspend (manager); /* track the active session */ manager->priv->session = gnome_settings_bus_get_session_proxy (); g_signal_connect (manager->priv->session, "g-properties-changed", G_CALLBACK (engine_session_properties_changed_cb), manager); manager->priv->screensaver_proxy = gnome_settings_bus_get_screen_saver_proxy (); g_signal_connect (manager->priv->screensaver_proxy, "g-signal", G_CALLBACK (screensaver_signal_cb), manager); manager->priv->kbd_brightness_old = -1; manager->priv->kbd_brightness_pre_dim = -1; manager->priv->pre_dim_brightness = -1; manager->priv->settings = g_settings_new (GSD_POWER_SETTINGS_SCHEMA); g_signal_connect (manager->priv->settings, "changed", G_CALLBACK (engine_settings_key_changed_cb), manager); manager->priv->settings_screensaver = g_settings_new ("org.gnome.desktop.screensaver"); manager->priv->settings_bus = g_settings_new ("org.gnome.desktop.session"); g_signal_connect (manager->priv->settings_bus, "changed", G_CALLBACK (engine_settings_key_changed_cb), manager); manager->priv->settings_xrandr = g_settings_new (GSD_XRANDR_SETTINGS_SCHEMA); manager->priv->up_client = up_client_new (); manager->priv->lid_is_closed = up_client_get_lid_is_closed (manager->priv->up_client); g_signal_connect (manager->priv->up_client, "device-added", G_CALLBACK (engine_device_added_cb), manager); g_signal_connect (manager->priv->up_client, "device-removed", G_CALLBACK (engine_device_removed_cb), manager); g_signal_connect_after (manager->priv->up_client, "notify::lid-is-closed", G_CALLBACK (lid_state_changed_cb), manager); g_signal_connect (manager->priv->up_client, "notify::on-battery", G_CALLBACK (up_client_on_battery_cb), manager); g_signal_connect_after (manager->priv->up_client, "notify::on-battery", G_CALLBACK (lid_state_changed_cb), manager); /* connect to UPower for keyboard backlight control */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL, UPOWER_DBUS_NAME, UPOWER_DBUS_PATH_KBDBACKLIGHT, UPOWER_DBUS_INTERFACE_KBDBACKLIGHT, NULL, power_keyboard_proxy_ready_cb, manager); /* connect to the session */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, 0, NULL, GNOME_SESSION_DBUS_NAME, GNOME_SESSION_DBUS_PATH_PRESENCE, GNOME_SESSION_DBUS_INTERFACE_PRESENCE, NULL, session_presence_proxy_ready_cb, manager); manager->priv->devices_array = g_ptr_array_new_with_free_func (g_object_unref); /* create a fake virtual composite battery */ manager->priv->device_composite = up_device_new (); g_object_set (manager->priv->device_composite, "kind", UP_DEVICE_KIND_BATTERY, "is-rechargeable", TRUE, "native-path", "dummy:composite_battery", "power-supply", TRUE, "is-present", TRUE, NULL); /* get percentage policy */ manager->priv->low_percentage = g_settings_get_int (manager->priv->settings, "percentage-low"); manager->priv->critical_percentage = g_settings_get_int (manager->priv->settings, "percentage-critical"); manager->priv->action_percentage = g_settings_get_int (manager->priv->settings, "percentage-action"); /* get time policy */ manager->priv->low_time = g_settings_get_int (manager->priv->settings, "time-low"); manager->priv->critical_time = g_settings_get_int (manager->priv->settings, "time-critical"); manager->priv->action_time = g_settings_get_int (manager->priv->settings, "time-action"); /* we can disable this if the time remaining is inaccurate or just plain wrong */ manager->priv->use_time_primary = g_settings_get_boolean (manager->priv->settings, "use-time-for-policy"); /* create IDLETIME watcher */ manager->priv->idle_monitor = g_object_ref (gsd_idle_monitor_get_core ()); /* set up the screens */ g_signal_connect (manager->priv->rr_screen, "changed", G_CALLBACK (on_randr_event), manager); on_randr_event (manager->priv->rr_screen, manager); #ifdef GSD_MOCK g_unix_signal_add (SIGUSR2, (GSourceFunc) received_sigusr2, manager); #endif /* GSD_MOCK */ /* check whether a backlight is available */ manager->priv->backlight_available = backlight_available (manager->priv->rr_screen); /* ensure the default dpms timeouts are cleared */ backlight_enable (manager); /* coldplug the engine */ engine_coldplug (manager); idle_configure (manager); manager->priv->xscreensaver_watchdog_timer_id = gsd_power_enable_screensaver_watchdog (); /* don't blank inside a VM */ manager->priv->is_virtual_machine = gsd_power_is_hardware_a_vm (); setup_lid_closed_action (manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_power_manager_stop (GsdPowerManager *manager) { GPtrArray *devices; int i; g_debug ("Stopping power manager"); if (manager->priv->inhibit_lid_switch_timer_id != 0) { g_source_remove (manager->priv->inhibit_lid_switch_timer_id); manager->priv->inhibit_lid_switch_timer_id = 0; } if (manager->priv->bus_cancellable != NULL) { g_cancellable_cancel (manager->priv->bus_cancellable); g_object_unref (manager->priv->bus_cancellable); manager->priv->bus_cancellable = NULL; } if (manager->priv->introspection_data) { g_dbus_node_info_unref (manager->priv->introspection_data); manager->priv->introspection_data = NULL; } g_signal_handlers_disconnect_by_data (manager->priv->up_client, manager); g_clear_object (&manager->priv->session); g_clear_object (&manager->priv->settings); g_clear_object (&manager->priv->settings_screensaver); g_clear_object (&manager->priv->settings_bus); g_clear_object (&manager->priv->up_client); if (manager->priv->inhibit_lid_switch_fd != -1) { close (manager->priv->inhibit_lid_switch_fd); manager->priv->inhibit_lid_switch_fd = -1; manager->priv->inhibit_lid_switch_taken = FALSE; manager->priv->inhibit_lid_switch_action = FALSE; } if (manager->priv->inhibit_suspend_fd != -1) { close (manager->priv->inhibit_suspend_fd); manager->priv->inhibit_suspend_fd = -1; manager->priv->inhibit_suspend_taken = FALSE; } g_clear_object (&manager->priv->logind_proxy); if (manager->priv->rr_screen) { g_signal_handlers_disconnect_by_data (manager->priv->rr_screen, manager); g_clear_object (&manager->priv->rr_screen); } devices = manager->priv->devices_array; if (devices != NULL) { for (i = 0; i < devices->len; i++) g_signal_handlers_disconnect_by_data (g_ptr_array_index (devices, i), manager); g_ptr_array_unref (devices); manager->priv->devices_array = NULL; } g_clear_object (&manager->priv->device_composite); g_clear_object (&manager->priv->previous_icon); g_clear_pointer (&manager->priv->previous_summary, g_free); g_clear_object (&manager->priv->session_presence_proxy); g_clear_object (&manager->priv->screensaver_proxy); play_loop_stop (&manager->priv->critical_alert_timeout_id); g_clear_object (&manager->priv->idle_monitor); if (manager->priv->xscreensaver_watchdog_timer_id > 0) { g_source_remove (manager->priv->xscreensaver_watchdog_timer_id); manager->priv->xscreensaver_watchdog_timer_id = 0; } } static void gsd_power_manager_init (GsdPowerManager *manager) { manager->priv = GSD_POWER_MANAGER_GET_PRIVATE (manager); manager->priv->inhibit_lid_switch_fd = -1; manager->priv->inhibit_suspend_fd = -1; manager->priv->inhibit_lid_switch_action = FALSE; manager->priv->bus_cancellable = g_cancellable_new (); } /* returns new level */ static void handle_method_call_keyboard (GsdPowerManager *manager, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation) { gint now; gint step; gint value = -1; gboolean ret; guint percentage; GError *error = NULL; if (g_strcmp0 (method_name, "StepUp") == 0) { g_debug ("keyboard step up"); now = upower_kbd_get_brightness (manager); step = BRIGHTNESS_STEP_AMOUNT (manager->priv->kbd_brightness_max); value = MIN (now + step, manager->priv->kbd_brightness_max); ret = upower_kbd_set_brightness (manager, value, &error); } else if (g_strcmp0 (method_name, "StepDown") == 0) { g_debug ("keyboard step down"); now = upower_kbd_get_brightness (manager); step = BRIGHTNESS_STEP_AMOUNT (manager->priv->kbd_brightness_max); value = MAX (now - step, 0); ret = upower_kbd_set_brightness (manager, value, &error); } else if (g_strcmp0 (method_name, "Toggle") == 0) { value = upower_kbd_toggle (manager, &error); ret = (value >= 0); } else { g_assert_not_reached (); } /* return value */ if (!ret) { g_dbus_method_invocation_take_error (invocation, error); } else { percentage = ABS_TO_PERCENTAGE (0, manager->priv->kbd_brightness_max, value); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", percentage)); } } static void handle_method_call_screen (GsdPowerManager *manager, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation) { gboolean ret = FALSE; gint value = -1; guint value_tmp; GError *error = NULL; if (!manager->priv->backlight_available) { g_set_error_literal (&error, GSD_POWER_MANAGER_ERROR, GSD_POWER_MANAGER_ERROR_FAILED, "Screen backlight not available"); goto out; } if (g_strcmp0 (method_name, "GetPercentage") == 0) { g_debug ("screen get percentage"); value = backlight_get_percentage (manager->priv->rr_screen, &error); } else if (g_strcmp0 (method_name, "SetPercentage") == 0) { g_debug ("screen set percentage"); g_variant_get (parameters, "(u)", &value_tmp); ret = backlight_set_percentage (manager->priv->rr_screen, value_tmp, &error); if (ret) { value = value_tmp; backlight_emit_changed (manager); } } else if (g_strcmp0 (method_name, "StepUp") == 0) { g_debug ("screen step up"); value = backlight_step_up (manager->priv->rr_screen, &error); if (value != -1) backlight_emit_changed (manager); } else if (g_strcmp0 (method_name, "StepDown") == 0) { g_debug ("screen step down"); value = backlight_step_down (manager->priv->rr_screen, &error); if (value != -1) backlight_emit_changed (manager); } else { g_assert_not_reached (); } out: /* return value */ if (value < 0) { g_dbus_method_invocation_take_error (invocation, error); } else { g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", value)); } } static GVariant * device_to_variant_blob (UpDevice *device) { const gchar *object_path; gchar *device_icon; gdouble percentage; GIcon *icon; guint64 time_empty, time_full; guint64 time_state = 0; GVariant *value; UpDeviceKind kind; UpDeviceState state; icon = gpm_upower_get_device_icon (device, TRUE); device_icon = g_icon_to_string (icon); g_object_get (device, "kind", &kind, "percentage", &percentage, "state", &state, "time-to-empty", &time_empty, "time-to-full", &time_full, NULL); /* only return time for these simple states */ if (state == UP_DEVICE_STATE_DISCHARGING) time_state = time_empty; else if (state == UP_DEVICE_STATE_CHARGING) time_state = time_full; /* get an object path, even for the composite device */ object_path = up_device_get_object_path (device); if (object_path == NULL) object_path = GSD_DBUS_PATH; /* format complex object */ value = g_variant_new ("(susdut)", object_path, kind, device_icon, percentage, state, time_state); g_free (device_icon); g_object_unref (icon); return value; } static void handle_method_call_main (GsdPowerManager *manager, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation) { GPtrArray *array; guint i; GVariantBuilder *builder; GVariant *tuple = NULL; GVariant *value = NULL; UpDevice *device; /* return object */ if (g_strcmp0 (method_name, "GetPrimaryDevice") == 0) { /* get the virtual device */ device = engine_get_primary_device (manager); if (device == NULL) { g_dbus_method_invocation_return_dbus_error (invocation, "org.gnome.SettingsDaemon.Power.Failed", "There is no primary device."); return; } /* return the value */ value = device_to_variant_blob (device); tuple = g_variant_new_tuple (&value, 1); g_dbus_method_invocation_return_value (invocation, tuple); g_object_unref (device); return; } /* return array */ if (g_strcmp0 (method_name, "GetDevices") == 0) { /* create builder */ builder = g_variant_builder_new (G_VARIANT_TYPE("a(susdut)")); /* add each tuple to the array */ array = manager->priv->devices_array; for (i=0; ilen; i++) { device = g_ptr_array_index (array, i); value = device_to_variant_blob (device); g_variant_builder_add_value (builder, value); } /* return the value */ value = g_variant_builder_end (builder); tuple = g_variant_new_tuple (&value, 1); g_dbus_method_invocation_return_value (invocation, tuple); g_variant_builder_unref (builder); return; } g_assert_not_reached (); } static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); /* Check session pointer as a proxy for whether the manager is in the start or stop state */ if (manager->priv->session == NULL) { return; } g_debug ("Calling method '%s.%s' for Power", interface_name, method_name); if (g_strcmp0 (interface_name, GSD_POWER_DBUS_INTERFACE) == 0) { handle_method_call_main (manager, method_name, parameters, invocation); } else if (g_strcmp0 (interface_name, GSD_POWER_DBUS_INTERFACE_SCREEN) == 0) { handle_method_call_screen (manager, method_name, parameters, invocation); } else if (g_strcmp0 (interface_name, GSD_POWER_DBUS_INTERFACE_KEYBOARD) == 0) { handle_method_call_keyboard (manager, method_name, parameters, invocation); } else { g_warning ("not recognised interface: %s", interface_name); } } static GVariant * handle_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); GVariant *retval = NULL; /* Check session pointer as a proxy for whether the manager is in the start or stop state */ if (manager->priv->session == NULL) { return NULL; } if (g_strcmp0 (property_name, "Icon") == 0) { retval = engine_get_icon_property_variant (manager); } else if (g_strcmp0 (property_name, "Tooltip") == 0) { retval = engine_get_tooltip_property_variant (manager); } else if (g_strcmp0 (property_name, "Percentage") == 0) { gdouble percentage; percentage = engine_get_percentage (manager); if (percentage >= 0) retval = g_variant_new_double (percentage); } return retval; } static const GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, NULL, /* SetProperty */ }; static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdPowerManager *manager) { GDBusConnection *connection; GDBusInterfaceInfo **infos; GError *error = NULL; guint i; connection = g_bus_get_finish (res, &error); if (connection == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; infos = manager->priv->introspection_data->interfaces; for (i = 0; infos[i] != NULL; i++) { g_dbus_connection_register_object (connection, GSD_POWER_DBUS_PATH, infos[i], &interface_vtable, manager, NULL, NULL); } manager->priv->name_id = g_bus_own_name_on_connection (connection, GSD_POWER_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); } static void register_manager_dbus (GsdPowerManager *manager) { manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (manager->priv->introspection_data != NULL); g_bus_get (G_BUS_TYPE_SESSION, manager->priv->bus_cancellable, (GAsyncReadyCallback) on_bus_gotten, manager); } GsdPowerManager * gsd_power_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_POWER_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); register_manager_dbus (manager_object); } return GSD_POWER_MANAGER (manager_object); } unity-settings-daemon/plugins/power/gsd-power-manager.h0000664000000000000000000000467215172222611020532 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_POWER_MANAGER_H #define __GSD_POWER_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_POWER_MANAGER (gsd_power_manager_get_type ()) #define GSD_POWER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_POWER_MANAGER, GsdPowerManager)) #define GSD_POWER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_POWER_MANAGER, GsdPowerManagerClass)) #define GSD_IS_POWER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_POWER_MANAGER)) #define GSD_IS_POWER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_POWER_MANAGER)) #define GSD_POWER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_POWER_MANAGER, GsdPowerManagerClass)) #define GSD_POWER_MANAGER_ERROR (gsd_power_manager_error_quark ()) typedef struct GsdPowerManagerPrivate GsdPowerManagerPrivate; typedef struct { GObject parent; GsdPowerManagerPrivate *priv; } GsdPowerManager; typedef struct { GObjectClass parent_class; } GsdPowerManagerClass; enum { GSD_POWER_MANAGER_ERROR_FAILED }; GType gsd_power_manager_get_type (void); GQuark gsd_power_manager_error_quark (void); GsdPowerManager * gsd_power_manager_new (void); gboolean gsd_power_manager_start (GsdPowerManager *manager, GError **error); void gsd_power_manager_stop (GsdPowerManager *manager); G_END_DECLS #endif /* __GSD_POWER_MANAGER_H */ unity-settings-daemon/plugins/power/gsd-power-plugin.c0000664000000000000000000000201515172222611020376 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-power-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdPower, gsd_power) unity-settings-daemon/plugins/power/gsdpowerconstants.py0000664000000000000000000000113215172222611021167 0ustar # File auto-generated from script http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/power/gsd-power-constants-update.pl # Modified by the GTK+ Team and others 1997-2012. See the AUTHORS # file for a list of people on the GTK+ Team. See the ChangeLog # files for a list of changes. These files are distributed with # GTK+ at ftp://ftp.gtk.org/pub/gtk/. SCREENSAVER_TIMEOUT_BLANK = 15; IDLE_DIM_BLANK_DISABLED_MIN = 60; IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER = 4.0/5.0; MINIMUM_IDLE_DIM_DELAY = 10; POWER_UP_TIME_ON_AC = 15; GSD_MOCK_DEFAULT_BRIGHTNESS = 50; GSD_MOCK_MAX_BRIGHTNESS = 100; unity-settings-daemon/plugins/power/gsm-inhibitor-flag.h0000664000000000000000000000240415172222611020664 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef __GSM_INHIBITOR_FLAG_H__ #define __GSM_INHIBITOR_FLAG_H__ #include G_BEGIN_DECLS typedef enum { GSM_INHIBITOR_FLAG_LOGOUT = 1 << 0, GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1, GSM_INHIBITOR_FLAG_SUSPEND = 1 << 2, GSM_INHIBITOR_FLAG_IDLE = 1 << 3, GSM_INHIBITOR_FLAG_AUTOMOUNT = 1 << 4 } GsmInhibitorFlag; G_END_DECLS #endif /* __GSM_INHIBITOR_FLAG_H__ */ unity-settings-daemon/plugins/power/gsm-manager-logout-mode.h0000664000000000000000000000223315172222611021631 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSM_MANAGER_LOGOUT_MODE_H #define __GSM_MANAGER_LOGOUT_MODE_H G_BEGIN_DECLS typedef enum { GSM_MANAGER_LOGOUT_MODE_NORMAL = 0, GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION, GSM_MANAGER_LOGOUT_MODE_FORCE } GsmManagerLogoutMode; G_END_DECLS #endif /* __GSM_MANAGER_LOGOUT_MODE_H */ unity-settings-daemon/plugins/power/gsm-presence-flag.h0000664000000000000000000000221215172222611020476 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2009 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef __GSM_PRESENCE_FLAG_H__ #define __GSM_PRESENCE_FLAG_H__ G_BEGIN_DECLS typedef enum { GSM_PRESENCE_STATUS_AVAILABLE = 0, GSM_PRESENCE_STATUS_INVISIBLE, GSM_PRESENCE_STATUS_BUSY, GSM_PRESENCE_STATUS_IDLE, } GsmPresenceStatus; G_END_DECLS #endif /* __GSM_PRESENCE_FLAG_H__ */ unity-settings-daemon/plugins/power/power.gnome-settings-plugin.in0000664000000000000000000000025015172222611022750 0ustar [GNOME Settings Plugin] Module=power IAge=0 Priority=1 _Name=Power _Description=Power plugin Authors=Richard Hughes Copyright=Copyright © 2011 Richard Hughes Website= unity-settings-daemon/plugins/power/test-power.c0000664000000000000000000000030515172222611017304 0ustar #define NEW gsd_power_manager_new #define START gsd_power_manager_start #define STOP gsd_power_manager_stop #define MANAGER GsdPowerManager #include "gsd-power-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/power/test.py0000775000000000000000000006617315172222611016402 0ustar #!/usr/bin/env python '''GNOME settings daemon tests for power plugin.''' __author__ = 'Martin Pitt ' __copyright__ = '(C) 2013 Canonical Ltd.' __license__ = 'GPL v2 or later' import unittest import subprocess import sys import time import os import os.path import signal project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) builddir = os.environ.get('BUILDDIR', os.path.dirname(__file__)) sys.path.insert(0, os.path.join(project_root, 'tests')) sys.path.insert(0, builddir) import gsdtestcase import gsdpowerconstants import gsdpowerenums import dbus from gi.repository import Gio class PowerPluginTest(gsdtestcase.GSDTestCase): '''Test the power plugin''' def setUp(self): self.daemon_death_expected = False self.session_log_write = open(os.path.join(self.workdir, 'gnome-session.log'), 'wb') self.session = subprocess.Popen(['gnome-session', '-f', '-a', os.path.join(self.workdir, 'autostart'), '--session=dummy', '--debug'], stdout=self.session_log_write, stderr=subprocess.STDOUT) # wait until the daemon is on the bus try: self.wait_for_bus_object('org.gnome.SessionManager', '/org/gnome/SessionManager') except: # on failure, print log with open(self.session_log_write.name) as f: print('----- session log -----\n%s\n------' % f.read()) raise self.session_log = open(self.session_log_write.name) self.obj_session_mgr = self.session_bus_con.get_object( 'org.gnome.SessionManager', '/org/gnome/SessionManager') # start mock upowerd (self.upowerd, self.obj_upower) = self.spawn_server_template( 'upower', {'OnBattery': True, 'LidIsClosed': False}, stdout=subprocess.PIPE) gsdtestcase.set_nonblock(self.upowerd.stdout) # start mock gnome-shell screensaver (self.screensaver, self.obj_screensaver) = self.spawn_server_template( 'gnome_screensaver', stdout=subprocess.PIPE) gsdtestcase.set_nonblock(self.screensaver.stdout) self.start_logind() # Set up the gnome-session presence obj_session_presence = self.session_bus_con.get_object( 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence') self.obj_session_presence_props = dbus.Interface(obj_session_presence, dbus.PROPERTIES_IFACE) # ensure that our tests don't lock the screen when the screensaver # gets active self.settings_screensaver = Gio.Settings('org.gnome.desktop.screensaver') self.settings_screensaver['lock-enabled'] = False self.settings_gsd_power = Gio.Settings('com.canonical.unity.settings-daemon.plugins.power') # start power plugin self.settings_gsd_power['active'] = False Gio.Settings.sync() self.plugin_log_write = open(os.path.join(self.workdir, 'plugin_power.log'), 'wb') # avoid painfully long delays of actions for tests env = os.environ.copy() env['GSD_DISABLE_BACKLIGHT_HELPER'] = '1' self.daemon = subprocess.Popen( [os.path.join(builddir, 'usd-test-power')], # comment out this line if you want to see the logs in real time stdout=self.plugin_log_write, stderr=subprocess.STDOUT, env=env) # you can use this for reading the current daemon log in tests self.plugin_log = open(self.plugin_log_write.name) # wait until plugin is ready timeout = 100 while timeout > 0: time.sleep(0.1) timeout -= 1 log = self.plugin_log.read() if 'System inhibitor fd is' in log: break # always start with zero idle time self.reset_idle_timer() # flush notification log try: self.p_notify.stdout.read() except IOError: pass def tearDown(self): daemon_running = self.daemon.poll() == None if daemon_running: self.daemon.terminate() self.daemon.wait() self.plugin_log.close() self.plugin_log_write.flush() self.plugin_log_write.close() self.upowerd.terminate() self.upowerd.wait() self.screensaver.terminate() self.screensaver.wait() self.stop_session() self.stop_logind() # reset all changed gsettings, so that tests are independent from each # other for schema in [self.settings_gsd_power, self.settings_session, self.settings_screensaver]: for k in schema.list_keys(): schema.reset(k) Gio.Settings.sync() try: os.unlink('GSD_MOCK_EXTERNAL_MONITOR') except OSError: pass try: os.unlink('GSD_MOCK_brightness') except OSError: pass # we check this at the end so that the other cleanup always happens self.assertTrue(daemon_running or self.daemon_death_expected, 'daemon died during the test') def stop_session(self): '''Stop GNOME session''' assert self.session self.session.terminate() self.session.wait() self.session_log_write.flush() self.session_log_write.close() self.session_log.close() def get_status(self): return self.obj_session_presence_props.Get('org.gnome.SessionManager.Presence', 'status') def get_brightness(self): f = open('GSD_MOCK_brightness', 'r') ret = f.read() f.close() return int(ret) def set_has_external_monitor(self, external): f = open('GSD_MOCK_EXTERNAL_MONITOR', 'w') if external: f.write('1') else: f.write('0') f.close () os.kill(self.daemon.pid, signal.SIGUSR2) def check_for_logout(self, timeout): '''Check that logout is requested. Fail after the tiven timeout. ''' # check that it request suspend while timeout > 0: time.sleep(1) timeout -= 1 # check that it requested suspend try: log = self.session_log.read() except IOError: break if log and (b'GsmManager: requesting logout' in log): break else: self.fail('timed out waiting for gnome-session logout call') def check_no_logout(self, seconds): '''Check that no logout is requested in the given time''' # wait for specified time to ensure it didn't do anything time.sleep(seconds) # check that it did not logout log = self.session_log.read() if log: self.assertFalse(b'GsmManager: requesting logout' in log, 'unexpected logout request') def check_for_suspend(self, timeout): '''Check that Suspend() or Hibernate() is requested. Fail after the tiven timeout. ''' # check that it request suspend while timeout > 0: time.sleep(1) timeout -= 1 # check that it requested suspend try: log = self.logind.stdout.read() except IOError: break if log and (b' Suspend ' in log or b' Hibernate ' in log): break else: self.fail('timed out waiting for logind Suspend() call') def check_no_suspend(self, seconds): '''Check that no Suspend or Hibernate is requested in the given time''' # wait for specified time to ensure it didn't do anything time.sleep(seconds) # check that it did not suspend or hibernate log = self.logind.stdout.read() if log: self.assertFalse(b' Suspend' in log, 'unexpected Suspend request') self.assertFalse(b' Hibernate' in log, 'unexpected Hibernate request') def check_no_dim(self, seconds): '''Check that mode is not set to dim in the given time''' # wait for specified time to ensure it didn't do anything time.sleep(seconds) # check that we don't dim log = self.plugin_log.read() if log: self.assertFalse(b'Doing a state transition: dim' in log, 'unexpected dim request') def check_dim(self, timeout): '''Check that mode is set to dim in the given time''' # wait for specified time to ensure it didn't do anything while timeout > 0: time.sleep(1) timeout -= 1 # check that it requested dim log = self.plugin_log.read() if 'Doing a state transition: dim' in log: break else: self.fail('timed out waiting for dim') def check_undim(self, timeout): '''Check that mode is set to normal in the given time''' # wait for specified time to ensure it didn't do anything while timeout > 0: time.sleep(1) timeout -= 1 # check that it requested normal log = self.plugin_log.read() if 'Doing a state transition: normal' in log: break else: self.fail('timed out waiting for normal mode') def check_blank(self, timeout): '''Check that blank is requested. Fail after the given timeout. ''' # check that it request blank while timeout > 0: time.sleep(1) timeout -= 1 # check that it requested blank log = self.plugin_log.read() if 'TESTSUITE: Blanked screen' in log: break else: self.fail('timed out waiting for blank') def check_unblank(self, timeout): '''Check that unblank is requested. Fail after the given timeout. ''' # check that it request blank while timeout > 0: time.sleep(1) timeout -= 1 # check that it requested unblank log = self.plugin_log.read() if 'TESTSUITE: Unblanked screen' in log: break else: self.fail('timed out waiting for unblank') def check_no_blank(self, seconds): '''Check that no blank is requested in the given time''' # wait for specified time to ensure it didn't blank time.sleep(seconds) # check that it did not blank log = self.plugin_log.read() self.assertFalse('TESTSUITE: Blanked screen' in log, 'unexpected blank request') def test_sleep_inactive_blank(self): '''screensaver/blank interaction''' # create suspend inhibitor which should have no effect on the idle inhibit_id = self.obj_session_mgr.Inhibit( 'testsuite', dbus.UInt32(0), 'for testing', dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND)) self.obj_screensaver.SetActive(True) self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on') # blank is supposed to happen straight away self.check_blank(2) # wiggle the mouse now and check for unblank; this is expected to pop up # the locked screen saver self.reset_idle_timer() self.check_unblank(2) self.assertTrue(self.get_brightness() == gsdpowerconstants.GSD_MOCK_DEFAULT_BRIGHTNESS , 'incorrect unblanked brightness') # Check for no blank before the normal blank timeout self.check_no_blank(gsdpowerconstants.SCREENSAVER_TIMEOUT_BLANK - 4) self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on') # and check for blank after the blank timeout self.check_blank(10) # Drop inhibitor self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id)) def test_session_idle_delay(self): '''verify that session idle delay works as expected when changed''' # Verify that idle is set after 5 seconds self.settings_session['idle-delay'] = 5 self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) time.sleep(7) self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE) # Raise the idle delay, and see that we stop being idle # and get idle again after the timeout self.settings_session['idle-delay'] = 10 self.reset_idle_timer() time.sleep(5) os.kill(self.session.pid, signal.SIGUSR2) self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) time.sleep(10) self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE) # Lower the delay again, and see that we get idle as we should self.settings_session['idle-delay'] = 5 self.reset_idle_timer() time.sleep(2) os.kill(self.session.pid, signal.SIGUSR2) self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) time.sleep(5) self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE) def test_idle_time_reset_on_resume(self): '''Check that the IDLETIME is reset when resuming''' # Go idle self.settings_session['idle-delay'] = 5 self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) time.sleep(7) self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE) # Go to sleep self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [True], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(1) # Wake up self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [False], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(1) # And check we're not idle self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) def test_sleep_inactive_battery(self): '''sleep-inactive-battery-timeout''' self.settings_session['idle-delay'] = 2 self.settings_gsd_power['sleep-inactive-battery-timeout'] = 5 self.settings_gsd_power['sleep-inactive-battery-type'] = 'suspend' # wait for idle delay; should not yet suspend self.check_no_suspend(2) # suspend should happen after inactive sleep timeout + 1 s notification # delay + 1 s error margin self.check_for_suspend(7) def test_sleep_inhibition(self): '''Does not sleep under idle inhibition''' idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER) self.settings_session['idle-delay'] = idle_delay self.settings_gsd_power['sleep-inactive-battery-timeout'] = 5 self.settings_gsd_power['sleep-inactive-battery-type'] = 'suspend' # create inhibitor inhibit_id = self.obj_session_mgr.Inhibit( 'testsuite', dbus.UInt32(0), 'for testing', dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_IDLE | gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND)) self.check_no_suspend(idle_delay + 2) self.check_no_dim(0) # Check that we didn't go to idle either self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id)) def test_lock_on_lid_close(self): '''Check that we do lock on lid closing, if the machine will not suspend''' self.settings_screensaver['lock-enabled'] = True # create inhibitor inhibit_id = self.obj_session_mgr.Inhibit( 'testsuite', dbus.UInt32(0), 'for testing', dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND)) # Close the lid self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check that we've blanked time.sleep(2) self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on') self.check_blank(2) # Drop the inhibit and see whether we suspend self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id)) self.check_for_suspend(5) def test_blank_on_lid_close(self): '''Check that we do blank on lid closing, if the machine will not suspend''' # create inhibitor inhibit_id = self.obj_session_mgr.Inhibit( 'testsuite', dbus.UInt32(0), 'for testing', dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND)) # Close the lid self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check that we've blanked self.check_blank(4) # Drop the inhibit and see whether we suspend self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id)) self.check_for_suspend(5) def test_unblank_on_lid_open(self): '''Check that we do unblank on lid opening, if the machine will not suspend''' # create inhibitor inhibit_id = self.obj_session_mgr.Inhibit( 'testsuite', dbus.UInt32(0), 'for testing', dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND)) # Close the lid self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check that we've blanked self.check_blank(2) # Reopen the lid self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', False) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check for unblanking self.check_unblank(2) # Drop the inhibit self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id)) def test_dim(self): '''Check that we do go to dim''' idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER) self.settings_session['idle-delay'] = idle_delay self.settings_gsd_power['sleep-inactive-battery-timeout'] = idle_delay + 1 self.settings_gsd_power['sleep-inactive-battery-type'] = 'suspend' # This is an absolute percentage, and our brightness is 0..100 dim_level = self.settings_gsd_power['idle-brightness']; # Check that we're not idle self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) # Wait and check we're not idle, but dimmed self.check_dim(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY) self.assertTrue(self.get_brightness() == dim_level, 'incorrect dim brightness') self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE) # Bring down the screensaver self.obj_screensaver.SetActive(True) self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on') # Check that we blank self.check_blank(2) # Go to sleep self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [True], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(1) # Wake up self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [False], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(1) # And check that we have the pre-dim brightness self.assertTrue(self.get_brightness() == gsdpowerconstants.GSD_MOCK_DEFAULT_BRIGHTNESS , 'incorrect unblanked brightness') def test_no_suspend_lid_close(self): '''Check that we don't suspend on lid close with an external monitor''' # Add an external monitor self.set_has_external_monitor(True) time.sleep (1) # Close the lid self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check for no suspend, and for no screen blanking self.check_no_suspend (10) self.check_no_blank(0) # Unplug the external monitor self.set_has_external_monitor(False) self.check_for_suspend (10) def test_action_critical_battery(self): '''action on critical battery''' # add a fake battery with 30%/2 hours charge to upower bat_path = self.obj_upower.AddDischargingBattery('mock_BAT', 'Mock Bat', 30.0, 1200) obj_bat = self.system_bus_con.get_object('org.freedesktop.UPower', bat_path) self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat_path], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(1) # now change battery to critical charge obj_bat.Set('org.freedesktop.UPower.Device', 'TimeToEmpty', dbus.Int64(30, variant_level=1), dbus_interface=dbus.PROPERTIES_IFACE) obj_bat.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') self.obj_upower.EmitSignal('', 'DeviceChanged', 's', [obj_bat.object_path], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(0.5) # we should have gotten a notification now notify_log = self.p_notify.stdout.read() self.check_for_suspend(5) # verify notification self.assertRegex(notify_log, b'[0-9.]+ Notify "Power" 0 "battery-.*" ".*battery critical.*"') def test_action_critical_battery_on_start(self): '''action on critical battery on startup''' # add a fake battery with 2%/1 minute charge to upower bat_path = self.obj_upower.AddDischargingBattery('mock_BAT', 'Mock Bat', 2.0, 60) obj_bat = self.system_bus_con.get_object('org.freedesktop.UPower', bat_path) self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat_path], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(5) # we should have gotten a notification now notify_log = self.p_notify.stdout.read() self.check_for_suspend(5) # verify notification self.assertRegex(notify_log, b'[0-9.]+ Notify "Power" 0 "battery-.*" ".*battery critical.*"') def test_action_multiple_batteries(self): '''critical actions for multiple batteries''' # add two fake batteries to upower bat1_path = self.obj_upower.AddDischargingBattery('mock_BAT1', 'Bat0', 30.0, 1200) obj_bat1 = self.system_bus_con.get_object('org.freedesktop.UPower', bat1_path) self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat1_path], dbus_interface='org.freedesktop.DBus.Mock') bat2_path = self.obj_upower.AddDischargingBattery('mock_BAT2', 'Bat2', 40.0, 1600) obj_bat2 = self.system_bus_con.get_object('org.freedesktop.UPower', bat2_path) self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat2_path], dbus_interface='org.freedesktop.DBus.Mock') time.sleep(1) # now change one battery to critical charge obj_bat1.Set('org.freedesktop.UPower.Device', 'TimeToEmpty', dbus.Int64(30, variant_level=1), dbus_interface=dbus.PROPERTIES_IFACE) obj_bat1.Set('org.freedesktop.UPower.Device', 'Energy', dbus.Double(0.5, variant_level=1), dbus_interface=dbus.PROPERTIES_IFACE) obj_bat1.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') self.obj_upower.EmitSignal('', 'DeviceChanged', 's', [bat1_path], dbus_interface='org.freedesktop.DBus.Mock') # wait long enough to ensure it didn't do anything (as we still have # the second battery) self.check_no_suspend(5) # now change the other battery to critical charge as well obj_bat2.Set('org.freedesktop.UPower.Device', 'TimeToEmpty', dbus.Int64(25, variant_level=1), dbus_interface=dbus.PROPERTIES_IFACE) obj_bat2.Set('org.freedesktop.UPower.Device', 'Energy', dbus.Double(0.4, variant_level=1), dbus_interface=dbus.PROPERTIES_IFACE) obj_bat2.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') self.obj_upower.EmitSignal('', 'DeviceChanged', 's', [bat2_path], dbus_interface='org.freedesktop.DBus.Mock') self.check_for_suspend(5) def test_forced_logout(self): '''Test forced logout''' self.daemon_death_expected = True idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER) self.settings_session['idle-delay'] = idle_delay self.settings_gsd_power['sleep-inactive-battery-timeout'] = idle_delay + 1 self.settings_gsd_power['sleep-inactive-battery-type'] = 'logout' self.check_for_logout(idle_delay + 2) # The notification should have been received before the logout, but it's saved anyway notify_log = self.p_notify.stdout.read() self.assertTrue(b'You will soon log out because of inactivity.' in notify_log) def test_forced_logout_inhibition(self): '''Test we don't force logout when inhibited''' idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER) self.settings_session['idle-delay'] = idle_delay self.settings_gsd_power['sleep-inactive-battery-timeout'] = idle_delay + 1 self.settings_gsd_power['sleep-inactive-battery-type'] = 'logout' # create suspend inhibitor which should stop us logging out inhibit_id = self.obj_session_mgr.Inhibit( 'testsuite', dbus.UInt32(0), 'for testing', dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_LOGOUT)) self.check_no_logout(idle_delay + 3) # Drop inhibitor self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id)) def test_unindle_on_ac_plug(self): idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER) self.settings_session['idle-delay'] = idle_delay # Wait for idle self.check_dim(idle_delay + 2) # Plug in the AC self.obj_upower.Set('org.freedesktop.UPower', 'OnBattery', False) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check that we undim self.check_undim(gsdpowerconstants.POWER_UP_TIME_ON_AC / 2) # And wait a little more to see us dim again self.check_dim(idle_delay + 2) # Unplug the AC self.obj_upower.Set('org.freedesktop.UPower', 'OnBattery', True) self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock') # Check that we undim self.check_undim(gsdpowerconstants.POWER_UP_TIME_ON_AC / 2) # And wait a little more to see us dim again self.check_dim(idle_delay + 2) # avoid writing to stderr unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) unity-settings-daemon/plugins/remote-display/0000775000000000000000000000000015172222611016633 5ustar unity-settings-daemon/plugins/remote-display/Makefile.am0000664000000000000000000000311615172222611020670 0ustar plugin_name = remote-display plugin_LTLIBRARIES = libremote-display.la libremote_display_la_SOURCES = \ gsd-remote-display-manager.c \ gsd-remote-display-manager.h \ gsd-remote-display-plugin.c libremote_display_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libremote_display_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libremote_display_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS) libremote_display_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(NULL) libexec_PROGRAMS = usd-test-remote-display usd_test_remote_display_SOURCES = \ test-remote-display.c \ gsd-remote-display-manager.c \ gsd-remote-display-manager.h usd_test_remote_display_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) usd_test_remote_display_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_remote_display_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = remote-display.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = $(plugin_in_files) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/remote-display/gsd-remote-display-manager.c0000664000000000000000000001642115172222611024124 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-settings-bus.h" #include "gnome-settings-profile.h" #include "gsd-remote-display-manager.h" #define GSD_REMOTE_DISPLAY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManagerPrivate)) struct GsdRemoteDisplayManagerPrivate { GSettings *desktop_settings; GDBusProxy *vino_proxy; GCancellable *cancellable; guint vino_watch_id; gboolean vnc_in_use; }; static void gsd_remote_display_manager_class_init (GsdRemoteDisplayManagerClass *klass); static void gsd_remote_display_manager_init (GsdRemoteDisplayManager *remote_display_manager); G_DEFINE_TYPE (GsdRemoteDisplayManager, gsd_remote_display_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void update_settings_from_variant (GsdRemoteDisplayManager *manager, GVariant *variant) { manager->priv->vnc_in_use = g_variant_get_boolean (variant); g_debug ("%s because of remote display status (vnc: %d)", !manager->priv->vnc_in_use ? "Enabling" : "Disabling", manager->priv->vnc_in_use); g_settings_set_boolean (manager->priv->desktop_settings, "enable-animations", !manager->priv->vnc_in_use); } static void props_changed (GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, GsdRemoteDisplayManager *manager) { GVariant *v; v = g_variant_lookup_value (changed_properties, "Connected", G_VARIANT_TYPE_BOOLEAN); if (v) { g_debug ("Received connected change"); update_settings_from_variant (manager, v); g_variant_unref (v); } } static void got_vino_proxy (GObject *source_object, GAsyncResult *res, GsdRemoteDisplayManager *manager) { GError *error = NULL; GVariant *v; manager->priv->vino_proxy = g_dbus_proxy_new_finish (res, &error); if (manager->priv->vino_proxy == NULL) { g_warning ("Failed to get Vino's D-Bus proxy: %s", error->message); g_error_free (error); return; } g_signal_connect (manager->priv->vino_proxy, "g-properties-changed", G_CALLBACK (props_changed), manager); v = g_dbus_proxy_get_cached_property (manager->priv->vino_proxy, "Connected"); if (v) { g_debug ("Setting original state"); update_settings_from_variant (manager, v); g_variant_unref (v); } } static void vino_appeared_cb (GDBusConnection *connection, const gchar *name, const gchar *name_owner, GsdRemoteDisplayManager *manager) { g_debug ("Vino appeared"); g_dbus_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE, NULL, name, "/org/gnome/vino/screens/0", "org.gnome.VinoScreen", manager->priv->cancellable, (GAsyncReadyCallback) got_vino_proxy, manager); } static void vino_vanished_cb (GDBusConnection *connection, const char *name, GsdRemoteDisplayManager *manager) { g_debug ("Vino vanished"); if (manager->priv->cancellable != NULL) { g_cancellable_cancel (manager->priv->cancellable); g_clear_object (&manager->priv->cancellable); } g_clear_object (&manager->priv->vino_proxy); /* And reset for us to have animations */ g_settings_set_boolean (manager->priv->desktop_settings, "enable-animations", TRUE); } static gboolean gsd_display_has_extension (const gchar *ext) { int op, event, error; return XQueryExtension (gdk_x11_get_default_xdisplay (), ext, &op, &event, &error); } gboolean gsd_remote_display_manager_start (GsdRemoteDisplayManager *manager, GError **error) { g_debug ("Starting remote-display manager"); gnome_settings_profile_start (NULL); manager->priv->desktop_settings = g_settings_new ("org.gnome.desktop.interface"); /* Check if spice is used: * https://bugzilla.gnome.org/show_bug.cgi?id=680195#c7 * This doesn't change at run-time, so it's to the point */ if (g_file_test ("/dev/virtio-ports/com.redhat.spice.0", G_FILE_TEST_EXISTS)) { g_debug ("Disabling animations because SPICE is in use"); g_settings_set_boolean (manager->priv->desktop_settings, "enable-animations", FALSE); goto out; } /* Xvnc exposes an extension named VNC-EXTENSION */ if (gsd_display_has_extension ("VNC-EXTENSION")) { g_debug ("Disabling animations because VNC-EXTENSION was detected"); g_settings_set_boolean (manager->priv->desktop_settings, "enable-animations", FALSE); goto out; } /* Monitor Vino's usage */ manager->priv->vino_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, "org.gnome.Vino", G_BUS_NAME_WATCHER_FLAGS_NONE, (GBusNameAppearedCallback) vino_appeared_cb, (GBusNameVanishedCallback) vino_vanished_cb, manager, NULL); out: gnome_settings_profile_end (NULL); return TRUE; } void gsd_remote_display_manager_stop (GsdRemoteDisplayManager *manager) { g_debug ("Stopping remote_display manager"); if (manager->priv->cancellable != NULL) { g_cancellable_cancel (manager->priv->cancellable); g_clear_object (&manager->priv->cancellable); } g_clear_object (&manager->priv->vino_proxy); if (manager->priv->desktop_settings) { g_settings_reset (manager->priv->desktop_settings, "enable-animations"); g_clear_object (&manager->priv->desktop_settings); } } static void gsd_remote_display_manager_class_init (GsdRemoteDisplayManagerClass *klass) { g_type_class_add_private (klass, sizeof (GsdRemoteDisplayManagerPrivate)); } static void gsd_remote_display_manager_init (GsdRemoteDisplayManager *manager) { manager->priv = GSD_REMOTE_DISPLAY_MANAGER_GET_PRIVATE (manager); } GsdRemoteDisplayManager * gsd_remote_display_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_REMOTE_DISPLAY_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_REMOTE_DISPLAY_MANAGER (manager_object); } unity-settings-daemon/plugins/remote-display/gsd-remote-display-manager.h0000664000000000000000000000503515172222611024130 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_REMOTE_DISPLAY_MANAGER_H #define __GSD_REMOTE_DISPLAY_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_REMOTE_DISPLAY_MANAGER (gsd_remote_display_manager_get_type ()) #define GSD_REMOTE_DISPLAY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManager)) #define GSD_REMOTE_DISPLAY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManagerClass)) #define GSD_IS_REMOTE_DISPLAY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER)) #define GSD_IS_REMOTE_DISPLAY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_REMOTE_DISPLAY_MANAGER)) #define GSD_REMOTE_DISPLAY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManagerClass)) typedef struct GsdRemoteDisplayManagerPrivate GsdRemoteDisplayManagerPrivate; typedef struct { GObject parent; GsdRemoteDisplayManagerPrivate *priv; } GsdRemoteDisplayManager; typedef struct { GObjectClass parent_class; } GsdRemoteDisplayManagerClass; GType gsd_remote_display_manager_get_type (void); GsdRemoteDisplayManager *gsd_remote_display_manager_new (void); gboolean gsd_remote_display_manager_start (GsdRemoteDisplayManager *manager, GError **error); void gsd_remote_display_manager_stop (GsdRemoteDisplayManager *manager); G_END_DECLS #endif /* __GSD_REMOTE_DISPLAY_MANAGER_H */ unity-settings-daemon/plugins/remote-display/gsd-remote-display-plugin.c0000664000000000000000000000217315172222611024007 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-remote-display-manager.h" struct GsdRemoteDisplayPluginPrivate { GsdRemoteDisplayManager *manager; }; GNOME_SETTINGS_PLUGIN_REGISTER (GsdRemoteDisplay, gsd_remote_display) unity-settings-daemon/plugins/remote-display/remote-display.gnome-settings-plugin.in0000664000000000000000000000032315172222611026355 0ustar [GNOME Settings Plugin] Module=remote-display IAge=0 Priority=8 _Name=Remote Display _Description=Disable animations on remote displays Authors=Bastien Nocera Copyright=Copyright © 2012 Bastien Nocera Website= unity-settings-daemon/plugins/remote-display/test-remote-display.c0000664000000000000000000000036115172222611022712 0ustar #define NEW gsd_remote_display_manager_new #define START gsd_remote_display_manager_start #define STOP gsd_remote_display_manager_stop #define MANAGER GsdRemoteDisplayManager #include "gsd-remote-display-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/rfkill/0000775000000000000000000000000015172222611015160 5ustar unity-settings-daemon/plugins/rfkill/61-unity-settings-daemon-rfkill.rules0000664000000000000000000000044415172222611024212 0ustar # Get access to /dev/rfkill for users # See https://bugzilla.redhat.com/show_bug.cgi?id=514798 # # Simplified by Kay Sievers # https://bugzilla.redhat.com/show_bug.cgi?id=733326 # See also https://bugzilla.gnome.org/show_bug.cgi?id=711373 KERNEL=="rfkill", SUBSYSTEM=="misc", TAG+="uaccess" unity-settings-daemon/plugins/rfkill/Makefile.am0000664000000000000000000000327615172222611017224 0ustar plugin_name = rfkill libexec_PROGRAMS = gsd-test-rfkill gsd_test_rfkill_SOURCES = \ gsd-rfkill-manager.h \ gsd-rfkill-manager.c \ rfkill-glib.c \ rfkill-glib.h \ rfkill.h \ test-rfkill.c gsd_test_rfkill_CFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_builddir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) gsd_test_rfkill_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = librfkill.la librfkill_la_SOURCES = \ gsd-rfkill-plugin.c \ gsd-rfkill-manager.h \ gsd-rfkill-manager.c \ rfkill-glib.c \ rfkill-glib.h \ rfkill.h librfkill_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_builddir)/gnome-settings-daemon \ -I$(top_srcdir)/data/ \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) librfkill_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(RFKILL_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) librfkill_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) librfkill_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(RFKILL_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = rfkill.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) udevrulesdir = $(prefix)/lib/udev/rules.d udevrules_DATA = 61-unity-settings-daemon-rfkill.rules EXTRA_DIST = $(plugin_in_files) $(udevrules_DATA) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/rfkill/gsd-rfkill-manager.c0000664000000000000000000006456015172222611021005 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2010,2011 Red Hat, Inc. * * Author: Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #include "gsd-rfkill-manager.h" #include "rfkill-glib.h" #include "gnome-settings-bus.h" #define GSD_RFKILL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_RFKILL_MANAGER, GsdRfkillManagerPrivate)) struct GsdRfkillManagerPrivate { GDBusNodeInfo *introspection_data; guint name_id; GDBusConnection *connection; GCancellable *cancellable; CcRfkillGlib *rfkill; GHashTable *killswitches; GHashTable *bt_killswitches; /* In addition to using the rfkill kernel subsystem (which is exposed by wlan, wimax, bluetooth, nfc, some platform drivers and some usb modems), we need to go through NetworkManager, which in turn will tell ModemManager to write the right commands in the USB bus to take external modems down, all from userspace. */ GDBusProxy *nm_client; gboolean wwan_enabled; GDBusObjectManager *mm_client; gboolean wwan_interesting; gchar *chassis_type; }; #define GSD_RFKILL_DBUS_NAME GSD_DBUS_NAME ".Rfkill" #define GSD_RFKILL_DBUS_PATH GSD_DBUS_PATH "/Rfkill" static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " " " " " " " ""; static void gsd_rfkill_manager_class_init (GsdRfkillManagerClass *klass); static void gsd_rfkill_manager_init (GsdRfkillManager *rfkill_manager); static void gsd_rfkill_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdRfkillManager, gsd_rfkill_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void gsd_rfkill_manager_class_init (GsdRfkillManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_rfkill_manager_finalize; g_type_class_add_private (klass, sizeof (GsdRfkillManagerPrivate)); } static void gsd_rfkill_manager_init (GsdRfkillManager *manager) { manager->priv = GSD_RFKILL_MANAGER_GET_PRIVATE (manager); } static gboolean engine_get_airplane_mode_helper (GHashTable *killswitches) { GHashTableIter iter; gpointer key, value; if (g_hash_table_size (killswitches) == 0) return FALSE; g_hash_table_iter_init (&iter, killswitches); while (g_hash_table_iter_next (&iter, &key, &value)) { int state; state = GPOINTER_TO_INT (value); /* A single rfkill switch that's unblocked? Airplane mode is off */ if (state == RFKILL_STATE_UNBLOCKED) return FALSE; } return TRUE; } static gboolean engine_get_bluetooth_airplane_mode (GsdRfkillManager *manager) { return engine_get_airplane_mode_helper (manager->priv->bt_killswitches); } static gboolean engine_get_bluetooth_hardware_airplane_mode (GsdRfkillManager *manager) { GHashTableIter iter; gpointer key, value; /* If we have no killswitches, hw airplane mode is off. */ if (g_hash_table_size (manager->priv->bt_killswitches) == 0) return FALSE; g_hash_table_iter_init (&iter, manager->priv->bt_killswitches); while (g_hash_table_iter_next (&iter, &key, &value)) { int state; state = GPOINTER_TO_INT (value); /* A single rfkill switch that's not hw blocked? Hw airplane mode is off */ if (state != RFKILL_STATE_HARD_BLOCKED) { return FALSE; } } return TRUE; } static gboolean engine_get_has_bluetooth_airplane_mode (GsdRfkillManager *manager) { return (g_hash_table_size (manager->priv->bt_killswitches) > 0); } static gboolean engine_get_airplane_mode (GsdRfkillManager *manager) { if (!manager->priv->wwan_interesting) return engine_get_airplane_mode_helper (manager->priv->killswitches); /* wwan enabled? then airplane mode is off (because an USB modem could be on in this state) */ return engine_get_airplane_mode_helper (manager->priv->killswitches) && !manager->priv->wwan_enabled; } static gboolean engine_get_hardware_airplane_mode (GsdRfkillManager *manager) { GHashTableIter iter; gpointer key, value; /* If we have no killswitches, hw airplane mode is off. */ if (g_hash_table_size (manager->priv->killswitches) == 0) return FALSE; g_hash_table_iter_init (&iter, manager->priv->killswitches); while (g_hash_table_iter_next (&iter, &key, &value)) { int state; state = GPOINTER_TO_INT (value); /* A single rfkill switch that's not hw blocked? Hw airplane mode is off */ if (state != RFKILL_STATE_HARD_BLOCKED) { return FALSE; } } return TRUE; } static gboolean engine_get_has_airplane_mode (GsdRfkillManager *manager) { return (g_hash_table_size (manager->priv->killswitches) > 0) || manager->priv->wwan_interesting; } static gboolean engine_get_should_show_airplane_mode (GsdRfkillManager *manager) { return (g_strcmp0 (manager->priv->chassis_type, "desktop") != 0) && (g_strcmp0 (manager->priv->chassis_type, "server") != 0) && (g_strcmp0 (manager->priv->chassis_type, "vm") != 0) && (g_strcmp0 (manager->priv->chassis_type, "container") != 0); } static void engine_properties_changed (GsdRfkillManager *manager) { GVariantBuilder props_builder; GVariant *props_changed = NULL; /* not yet connected to the session bus */ if (manager->priv->connection == NULL) return; g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&props_builder, "{sv}", "AirplaneMode", g_variant_new_boolean (engine_get_airplane_mode (manager))); g_variant_builder_add (&props_builder, "{sv}", "HardwareAirplaneMode", g_variant_new_boolean (engine_get_hardware_airplane_mode (manager))); g_variant_builder_add (&props_builder, "{sv}", "HasAirplaneMode", g_variant_new_boolean (engine_get_has_airplane_mode (manager))); g_variant_builder_add (&props_builder, "{sv}", "ShouldShowAirplaneMode", g_variant_new_boolean (engine_get_should_show_airplane_mode (manager))); g_variant_builder_add (&props_builder, "{sv}", "BluetoothAirplaneMode", g_variant_new_boolean (engine_get_bluetooth_airplane_mode (manager))); g_variant_builder_add (&props_builder, "{sv}", "BluetoothHardwareAirplaneMode", g_variant_new_boolean (engine_get_bluetooth_hardware_airplane_mode (manager))); g_variant_builder_add (&props_builder, "{sv}", "BluetoothHasAirplaneMode", g_variant_new_boolean (engine_get_has_bluetooth_airplane_mode (manager))); props_changed = g_variant_new ("(s@a{sv}@as)", GSD_RFKILL_DBUS_NAME, g_variant_builder_end (&props_builder), g_variant_new_strv (NULL, 0)); g_dbus_connection_emit_signal (manager->priv->connection, NULL, GSD_RFKILL_DBUS_PATH, "org.freedesktop.DBus.Properties", "PropertiesChanged", props_changed, NULL); } static void rfkill_changed (CcRfkillGlib *rfkill, GList *events, GsdRfkillManager *manager) { GList *l; int value; for (l = events; l != NULL; l = l->next) { struct rfkill_event *event = l->data; switch (event->op) { case RFKILL_OP_ADD: case RFKILL_OP_CHANGE: if (event->hard) value = RFKILL_STATE_HARD_BLOCKED; else if (event->soft) value = RFKILL_STATE_SOFT_BLOCKED; else value = RFKILL_STATE_UNBLOCKED; g_hash_table_insert (manager->priv->killswitches, GINT_TO_POINTER (event->idx), GINT_TO_POINTER (value)); if (event->type == RFKILL_TYPE_BLUETOOTH) g_hash_table_insert (manager->priv->bt_killswitches, GINT_TO_POINTER (event->idx), GINT_TO_POINTER (value)); g_debug ("%s %srfkill with ID %d", event->op == RFKILL_OP_ADD ? "Added" : "Changed", event->type == RFKILL_TYPE_BLUETOOTH ? "Bluetooth " : "", event->idx); break; case RFKILL_OP_DEL: g_hash_table_remove (manager->priv->killswitches, GINT_TO_POINTER (event->idx)); if (event->type == RFKILL_TYPE_BLUETOOTH) g_hash_table_remove (manager->priv->bt_killswitches, GINT_TO_POINTER (event->idx)); g_debug ("Removed %srfkill with ID %d", event->type == RFKILL_TYPE_BLUETOOTH ? "Bluetooth " : "", event->idx); break; } } engine_properties_changed (manager); } static void rfkill_set_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; ret = cc_rfkill_glib_send_change_all_event_finish (CC_RFKILL_GLIB (source_object), res, &error); if (!ret) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) g_debug ("Timed out waiting for blocked rfkills"); else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to set RFKill: %s", error->message); g_error_free (error); } } static void set_wwan_complete (GObject *object, GAsyncResult *result, gpointer user_data) { GError *error; GVariant *variant; error = NULL; variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), result, &error); if (variant == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Failed to set WWAN power status: %s", error->message); g_error_free (error); } else { g_variant_unref (variant); } } static gboolean engine_set_bluetooth_airplane_mode (GsdRfkillManager *manager, gboolean enable) { cc_rfkill_glib_send_change_all_event (manager->priv->rfkill, RFKILL_TYPE_BLUETOOTH, enable, manager->priv->cancellable, rfkill_set_cb, manager); return TRUE; } static gboolean engine_set_airplane_mode (GsdRfkillManager *manager, gboolean enable) { cc_rfkill_glib_send_change_all_event (manager->priv->rfkill, RFKILL_TYPE_ALL, enable, manager->priv->cancellable, rfkill_set_cb, manager); /* Note: we set the the NM property even if there are no modems, so we don't need to resync when one is plugged in */ if (manager->priv->nm_client) { g_dbus_proxy_call (manager->priv->nm_client, "org.freedesktop.DBus.Properties.Set", g_variant_new ("(ssv)", "org.freedesktop.NetworkManager", "WwanEnabled", g_variant_new_boolean (!enable)), G_DBUS_CALL_FLAGS_NONE, -1, /* timeout */ manager->priv->cancellable, set_wwan_complete, NULL); } return TRUE; } static gboolean handle_set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data) { GsdRfkillManager *manager = GSD_RFKILL_MANAGER (user_data); if (g_strcmp0 (property_name, "AirplaneMode") == 0) { gboolean airplane_mode; g_variant_get (value, "b", &airplane_mode); return engine_set_airplane_mode (manager, airplane_mode); } else if (g_strcmp0 (property_name, "BluetoothAirplaneMode") == 0) { gboolean airplane_mode; g_variant_get (value, "b", &airplane_mode); return engine_set_bluetooth_airplane_mode (manager, airplane_mode); } return FALSE; } static GVariant * handle_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { GsdRfkillManager *manager = GSD_RFKILL_MANAGER (user_data); /* Check session pointer as a proxy for whether the manager is in the start or stop state */ if (manager->priv->connection == NULL) { return NULL; } if (g_strcmp0 (property_name, "AirplaneMode") == 0) { gboolean airplane_mode; airplane_mode = engine_get_airplane_mode (manager); return g_variant_new_boolean (airplane_mode); } if (g_strcmp0 (property_name, "HardwareAirplaneMode") == 0) { gboolean hw_airplane_mode; hw_airplane_mode = engine_get_hardware_airplane_mode (manager); return g_variant_new_boolean (hw_airplane_mode); } if (g_strcmp0 (property_name, "ShouldShowAirplaneMode") == 0) { gboolean should_show_airplane_mode; should_show_airplane_mode = engine_get_should_show_airplane_mode (manager); return g_variant_new_boolean (should_show_airplane_mode); } if (g_strcmp0 (property_name, "HasAirplaneMode") == 0) { gboolean has_airplane_mode; has_airplane_mode = engine_get_has_airplane_mode (manager); return g_variant_new_boolean (has_airplane_mode); } if (g_strcmp0 (property_name, "BluetoothAirplaneMode") == 0) { gboolean airplane_mode; airplane_mode = engine_get_bluetooth_airplane_mode (manager); return g_variant_new_boolean (airplane_mode); } if (g_strcmp0 (property_name, "BluetoothHardwareAirplaneMode") == 0) { gboolean hw_airplane_mode; hw_airplane_mode = engine_get_bluetooth_hardware_airplane_mode (manager); return g_variant_new_boolean (hw_airplane_mode); } if (g_strcmp0 (property_name, "BluetoothHasAirplaneMode") == 0) { gboolean has_airplane_mode; has_airplane_mode = engine_get_has_bluetooth_airplane_mode (manager); return g_variant_new_boolean (has_airplane_mode); } return NULL; } static const GDBusInterfaceVTable interface_vtable = { NULL, handle_get_property, handle_set_property }; static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdRfkillManager *manager) { GDBusConnection *connection; GError *error = NULL; connection = g_bus_get_finish (res, &error); if (connection == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; g_dbus_connection_register_object (connection, GSD_RFKILL_DBUS_PATH, manager->priv->introspection_data->interfaces[0], &interface_vtable, manager, NULL, NULL); manager->priv->name_id = g_bus_own_name_on_connection (connection, GSD_RFKILL_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); } static void sync_wwan_enabled (GsdRfkillManager *manager) { GVariant *property; property = g_dbus_proxy_get_cached_property (manager->priv->nm_client, "WwanEnabled"); if (property == NULL) { /* GDBus telling us NM went down */ return; } manager->priv->wwan_enabled = g_variant_get_boolean (property); engine_properties_changed (manager); g_variant_unref (property); } static void nm_signal (GDBusProxy *proxy, char *sender_name, char *signal_name, GVariant *parameters, gpointer user_data) { GsdRfkillManager *manager = user_data; GVariant *changed; GVariant *property; if (g_strcmp0 (signal_name, "PropertiesChanged") == 0) { changed = g_variant_get_child_value (parameters, 0); property = g_variant_lookup_value (changed, "WwanEnabled", G_VARIANT_TYPE ("b")); g_dbus_proxy_set_cached_property (proxy, "WwanEnabled", property); if (property != NULL) { sync_wwan_enabled (manager); g_variant_unref (property); } g_variant_unref (changed); } } static void on_nm_proxy_gotten (GObject *source, GAsyncResult *result, gpointer user_data) { GsdRfkillManager *manager = user_data; GDBusProxy *proxy; GError *error; error = NULL; proxy = g_dbus_proxy_new_for_bus_finish (result, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) g_warning ("Failed to acquire NetworkManager proxy: %s", error->message); g_error_free (error); goto out; } manager->priv->nm_client = proxy; g_signal_connect (manager->priv->nm_client, "g-signal", G_CALLBACK (nm_signal), manager); sync_wwan_enabled (manager); out: g_object_unref (manager); } static void sync_wwan_interesting (GDBusObjectManager *object_manager, GDBusObject *object, GDBusInterface *interface, gpointer user_data) { GsdRfkillManager *manager = user_data; GList *objects; objects = g_dbus_object_manager_get_objects (object_manager); manager->priv->wwan_interesting = (objects != NULL); engine_properties_changed (manager); g_list_free_full (objects, g_object_unref); } static void on_mm_proxy_gotten (GObject *source, GAsyncResult *result, gpointer user_data) { GsdRfkillManager *manager = user_data; GDBusObjectManager *proxy; GError *error; error = NULL; proxy = g_dbus_object_manager_client_new_for_bus_finish (result, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) g_warning ("Failed to acquire ModemManager proxy: %s", error->message); g_error_free (error); goto out; } manager->priv->mm_client = proxy; g_signal_connect (manager->priv->mm_client, "interface-added", G_CALLBACK (sync_wwan_interesting), manager); g_signal_connect (manager->priv->mm_client, "interface-removed", G_CALLBACK (sync_wwan_interesting), manager); sync_wwan_interesting (manager->priv->mm_client, NULL, NULL, manager); out: g_object_unref (manager); } gboolean gsd_rfkill_manager_start (GsdRfkillManager *manager, GError **error) { gnome_settings_profile_start (NULL); manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (manager->priv->introspection_data != NULL); manager->priv->killswitches = g_hash_table_new (g_direct_hash, g_direct_equal); manager->priv->bt_killswitches = g_hash_table_new (g_direct_hash, g_direct_equal); manager->priv->rfkill = cc_rfkill_glib_new (); g_signal_connect (G_OBJECT (manager->priv->rfkill), "changed", G_CALLBACK (rfkill_changed), manager); cc_rfkill_glib_open (manager->priv->rfkill); manager->priv->cancellable = g_cancellable_new (); manager->priv->chassis_type = gnome_settings_get_chassis_type (); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, /* g-interface-info */ "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", manager->priv->cancellable, on_nm_proxy_gotten, g_object_ref (manager)); g_dbus_object_manager_client_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, "org.freedesktop.ModemManager1", "/org/freedesktop/ModemManager1", NULL, NULL, NULL, /* get_proxy_type and closure */ manager->priv->cancellable, on_mm_proxy_gotten, g_object_ref (manager)); /* Start process of owning a D-Bus name */ g_bus_get (G_BUS_TYPE_SESSION, manager->priv->cancellable, (GAsyncReadyCallback) on_bus_gotten, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_rfkill_manager_stop (GsdRfkillManager *manager) { GsdRfkillManagerPrivate *p = manager->priv; g_debug ("Stopping rfkill manager"); if (manager->priv->name_id != 0) { g_bus_unown_name (manager->priv->name_id); manager->priv->name_id = 0; } g_clear_pointer (&p->introspection_data, g_dbus_node_info_unref); g_clear_object (&p->connection); g_clear_object (&p->rfkill); g_clear_pointer (&p->killswitches, g_hash_table_destroy); g_clear_pointer (&p->bt_killswitches, g_hash_table_destroy); if (p->cancellable) { g_cancellable_cancel (p->cancellable); g_clear_object (&p->cancellable); } g_clear_object (&p->nm_client); g_clear_object (&p->mm_client); p->wwan_enabled = FALSE; p->wwan_interesting = FALSE; g_clear_pointer (&p->chassis_type, g_free); } static void gsd_rfkill_manager_finalize (GObject *object) { GsdRfkillManager *manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_RFKILL_MANAGER (object)); manager = GSD_RFKILL_MANAGER (object); g_return_if_fail (manager->priv != NULL); gsd_rfkill_manager_stop (manager); G_OBJECT_CLASS (gsd_rfkill_manager_parent_class)->finalize (object); } GsdRfkillManager * gsd_rfkill_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_RFKILL_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_RFKILL_MANAGER (manager_object); } unity-settings-daemon/plugins/rfkill/gsd-rfkill-manager.h0000664000000000000000000000436515172222611021007 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #ifndef __GSD_RFKILL_MANAGER_H #define __GSD_RFKILL_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_RFKILL_MANAGER (gsd_rfkill_manager_get_type ()) #define GSD_RFKILL_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_RFKILL_MANAGER, GsdRfkillManager)) #define GSD_RFKILL_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_RFKILL_MANAGER, GsdRfkillManagerClass)) #define GSD_IS_RFKILL_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_RFKILL_MANAGER)) #define GSD_IS_RFKILL_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_RFKILL_MANAGER)) #define GSD_RFKILL_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_RFKILL_MANAGER, GsdRfkillManagerClass)) typedef struct GsdRfkillManagerPrivate GsdRfkillManagerPrivate; typedef struct { GObject parent; GsdRfkillManagerPrivate *priv; } GsdRfkillManager; typedef struct { GObjectClass parent_class; } GsdRfkillManagerClass; GType gsd_rfkill_manager_get_type (void); GsdRfkillManager * gsd_rfkill_manager_new (void); gboolean gsd_rfkill_manager_start (GsdRfkillManager *manager, GError **error); void gsd_rfkill_manager_stop (GsdRfkillManager *manager); G_END_DECLS #endif /* __GSD_RFKILL_MANAGER_H */ unity-settings-daemon/plugins/rfkill/gsd-rfkill-plugin.c0000664000000000000000000000175715172222611020670 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-rfkill-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdRfkill, gsd_rfkill) unity-settings-daemon/plugins/rfkill/rfkill-glib.c0000664000000000000000000003174315172222611017532 0ustar /* * * gnome-bluetooth - Bluetooth integration for GNOME * * Copyright (C) 2012 Bastien Nocera * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include "rfkill-glib.h" enum { CHANGED, LAST_SIGNAL }; static int signals[LAST_SIGNAL] = { 0 }; #define CC_RFKILL_GLIB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ CC_RFKILL_TYPE_GLIB, CcRfkillGlibPrivate)) struct CcRfkillGlibPrivate { GOutputStream *stream; GIOChannel *channel; guint watch_id; /* Pending Bluetooth enablement */ guint change_all_timeout_id; struct rfkill_event *event; GSimpleAsyncResult *simple; GCancellable *cancellable; }; G_DEFINE_TYPE(CcRfkillGlib, cc_rfkill_glib, G_TYPE_OBJECT) #define CHANGE_ALL_TIMEOUT 500 static const char *type_to_string (unsigned int type); gboolean cc_rfkill_glib_send_event_finish (CcRfkillGlib *rfkill, GAsyncResult *res, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); g_return_val_if_fail (RFKILL_IS_GLIB (rfkill), FALSE); g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == cc_rfkill_glib_send_event); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; return (g_simple_async_result_get_op_res_gssize (simple) >= 0); } static void write_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; gssize ret; ret = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object), res, &error); if (ret < 0) g_simple_async_result_take_error (simple, error); else g_simple_async_result_set_op_res_gssize (simple, ret); g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); } void cc_rfkill_glib_send_event (CcRfkillGlib *rfkill, struct rfkill_event *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; g_return_if_fail (RFKILL_IS_GLIB (rfkill)); g_return_if_fail (rfkill->priv->stream); simple = g_simple_async_result_new (G_OBJECT (rfkill), callback, user_data, cc_rfkill_glib_send_event); g_output_stream_write_async (rfkill->priv->stream, event, sizeof(struct rfkill_event), G_PRIORITY_DEFAULT, cancellable, write_done_cb, simple); } gboolean cc_rfkill_glib_send_change_all_event_finish (CcRfkillGlib *rfkill, GAsyncResult *res, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); g_return_val_if_fail (RFKILL_IS_GLIB (rfkill), FALSE); g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == cc_rfkill_glib_send_change_all_event); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; return g_simple_async_result_get_op_res_gboolean (simple); } static void write_change_all_again_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcRfkillGlib *rfkill = user_data; GError *error = NULL; gssize ret; g_debug ("Finished writing second RFKILL_OP_CHANGE_ALL event"); ret = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object), res, &error); if (ret < 0) g_simple_async_result_take_error (rfkill->priv->simple, error); else g_simple_async_result_set_op_res_gboolean (rfkill->priv->simple, ret >= 0); g_simple_async_result_complete_in_idle (rfkill->priv->simple); g_clear_object (&rfkill->priv->simple); g_clear_pointer (&rfkill->priv->event, g_free); } static gboolean write_change_all_timeout_cb (CcRfkillGlib *rfkill) { g_assert (rfkill->priv->event); g_debug ("Sending second RFKILL_OP_CHANGE_ALL timed out"); g_simple_async_result_set_error (rfkill->priv->simple, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "Enabling rfkill for %s timed out", type_to_string (rfkill->priv->event->type)); g_simple_async_result_complete_in_idle (rfkill->priv->simple); g_clear_object (&rfkill->priv->simple); g_clear_pointer (&rfkill->priv->event, g_free); g_clear_object (&rfkill->priv->cancellable); rfkill->priv->change_all_timeout_id = 0; return G_SOURCE_REMOVE; } static void write_change_all_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcRfkillGlib *rfkill = user_data; GError *error = NULL; gssize ret; g_debug ("Sending original RFKILL_OP_CHANGE_ALL event done"); ret = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object), res, &error); if (ret < 0) { g_simple_async_result_take_error (rfkill->priv->simple, error); goto bail; } else if (rfkill->priv->event->soft == 1 || rfkill->priv->event->type != RFKILL_TYPE_BLUETOOTH) { g_simple_async_result_set_op_res_gboolean (rfkill->priv->simple, ret >= 0); goto bail; } rfkill->priv->change_all_timeout_id = g_timeout_add (CHANGE_ALL_TIMEOUT, (GSourceFunc) write_change_all_timeout_cb, rfkill); return; bail: g_simple_async_result_complete_in_idle (rfkill->priv->simple); g_clear_object (&rfkill->priv->simple); g_clear_pointer (&rfkill->priv->event, g_free); g_clear_object (&rfkill->priv->cancellable); } void cc_rfkill_glib_send_change_all_event (CcRfkillGlib *rfkill, guint rfkill_type, gboolean enable, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; struct rfkill_event *event; g_return_if_fail (RFKILL_IS_GLIB (rfkill)); g_return_if_fail (rfkill->priv->stream); simple = g_simple_async_result_new (G_OBJECT (rfkill), callback, user_data, cc_rfkill_glib_send_change_all_event); if (rfkill->priv->change_all_timeout_id > 0) { g_source_remove (rfkill->priv->change_all_timeout_id); rfkill->priv->change_all_timeout_id = 0; write_change_all_timeout_cb (rfkill); } event = g_new0 (struct rfkill_event, 1); event->op = RFKILL_OP_CHANGE_ALL; event->type = rfkill_type; event->soft = enable ? 1 : 0; rfkill->priv->event = event; rfkill->priv->simple = simple; rfkill->priv->cancellable = cancellable ? g_object_ref (cancellable) : NULL; rfkill->priv->change_all_timeout_id = 0; g_output_stream_write_async (rfkill->priv->stream, event, sizeof(struct rfkill_event), G_PRIORITY_DEFAULT, cancellable, write_change_all_done_cb, rfkill); } static const char * type_to_string (unsigned int type) { switch (type) { case RFKILL_TYPE_ALL: return "ALL"; case RFKILL_TYPE_WLAN: return "WLAN"; case RFKILL_TYPE_BLUETOOTH: return "BLUETOOTH"; case RFKILL_TYPE_UWB: return "UWB"; case RFKILL_TYPE_WIMAX: return "WIMAX"; case RFKILL_TYPE_WWAN: return "WWAN"; default: return "UNKNOWN"; } } static const char * op_to_string (unsigned int op) { switch (op) { case RFKILL_OP_ADD: return "ADD"; case RFKILL_OP_DEL: return "DEL"; case RFKILL_OP_CHANGE: return "CHANGE"; case RFKILL_OP_CHANGE_ALL: return "CHANGE_ALL"; default: g_assert_not_reached (); } } static void print_event (struct rfkill_event *event) { g_debug ("RFKILL event: idx %u type %u (%s) op %u (%s) soft %u hard %u", event->idx, event->type, type_to_string (event->type), event->op, op_to_string (event->op), event->soft, event->hard); } static gboolean got_change_event (GList *events) { GList *l; g_assert (events != NULL); for (l = events ; l != NULL; l = l->next) { struct rfkill_event *event = l->data; if (event->op == RFKILL_OP_CHANGE) return TRUE; } return FALSE; } static void emit_changed_signal_and_free (CcRfkillGlib *rfkill, GList *events) { if (events == NULL) return; g_signal_emit (G_OBJECT (rfkill), signals[CHANGED], 0, events); if (rfkill->priv->change_all_timeout_id > 0 && got_change_event (events)) { g_debug ("Received a change event after a RFKILL_OP_CHANGE_ALL event, re-sending RFKILL_OP_CHANGE_ALL"); g_output_stream_write_async (rfkill->priv->stream, rfkill->priv->event, sizeof(struct rfkill_event), G_PRIORITY_DEFAULT, rfkill->priv->cancellable, write_change_all_again_done_cb, rfkill); g_source_remove (rfkill->priv->change_all_timeout_id); rfkill->priv->change_all_timeout_id = 0; } g_list_free_full (events, g_free); } static gboolean event_cb (GIOChannel *source, GIOCondition condition, CcRfkillGlib *rfkill) { GList *events; events = NULL; if (condition & G_IO_IN) { GIOStatus status; struct rfkill_event event; gsize read; status = g_io_channel_read_chars (source, (char *) &event, sizeof(event), &read, NULL); while (status == G_IO_STATUS_NORMAL && read == sizeof(event)) { struct rfkill_event *event_ptr; print_event (&event); event_ptr = g_memdup (&event, sizeof(event)); events = g_list_prepend (events, event_ptr); status = g_io_channel_read_chars (source, (char *) &event, sizeof(event), &read, NULL); } events = g_list_reverse (events); } else { g_debug ("Something unexpected happened on rfkill fd"); return FALSE; } emit_changed_signal_and_free (rfkill, events); return TRUE; } static void cc_rfkill_glib_init (CcRfkillGlib *rfkill) { CcRfkillGlibPrivate *priv; priv = CC_RFKILL_GLIB_GET_PRIVATE (rfkill); rfkill->priv = priv; } int cc_rfkill_glib_open (CcRfkillGlib *rfkill) { CcRfkillGlibPrivate *priv; int fd; int ret; GList *events; g_return_val_if_fail (RFKILL_IS_GLIB (rfkill), -1); g_return_val_if_fail (rfkill->priv->stream == NULL, -1); priv = rfkill->priv; fd = open("/dev/rfkill", O_RDWR); if (fd < 0) { if (errno == EACCES) g_warning ("Could not open RFKILL control device, please verify your installation"); return fd; } ret = fcntl(fd, F_SETFL, O_NONBLOCK); if (ret < 0) { g_debug ("Can't set RFKILL control device to non-blocking"); close(fd); return ret; } events = NULL; while (1) { struct rfkill_event event; struct rfkill_event *event_ptr; ssize_t len; len = read(fd, &event, sizeof(event)); if (len < 0) { if (errno == EAGAIN) break; g_debug ("Reading of RFKILL events failed"); break; } if (len != RFKILL_EVENT_SIZE_V1) { g_warning ("Wrong size of RFKILL event\n"); continue; } if (event.op != RFKILL_OP_ADD) continue; g_debug ("Read killswitch of type '%s' (idx=%d): soft %d hard %d", type_to_string (event.type), event.idx, event.soft, event.hard); event_ptr = g_memdup (&event, sizeof(event)); events = g_list_prepend (events, event_ptr); } /* Setup monitoring */ priv->channel = g_io_channel_unix_new (fd); priv->watch_id = g_io_add_watch (priv->channel, G_IO_IN | G_IO_HUP | G_IO_ERR, (GIOFunc) event_cb, rfkill); if (events) { events = g_list_reverse (events); emit_changed_signal_and_free (rfkill, events); } else { g_debug ("No rfkill device available on startup"); } /* Setup write stream */ priv->stream = g_unix_output_stream_new (fd, TRUE); return fd; } static void cc_rfkill_glib_finalize (GObject *object) { CcRfkillGlib *rfkill; CcRfkillGlibPrivate *priv; rfkill = CC_RFKILL_GLIB (object); priv = rfkill->priv; if (priv->change_all_timeout_id > 0) write_change_all_timeout_cb (rfkill); /* cleanup monitoring */ if (priv->watch_id > 0) { g_source_remove (priv->watch_id); priv->watch_id = 0; g_io_channel_shutdown (priv->channel, FALSE, NULL); g_io_channel_unref (priv->channel); } g_clear_object (&priv->stream); G_OBJECT_CLASS(cc_rfkill_glib_parent_class)->finalize(object); } static void cc_rfkill_glib_class_init(CcRfkillGlibClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; g_type_class_add_private(klass, sizeof(CcRfkillGlibPrivate)); object_class->finalize = cc_rfkill_glib_finalize; signals[CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CcRfkillGlibClass, changed), NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); } CcRfkillGlib * cc_rfkill_glib_new (void) { return CC_RFKILL_GLIB (g_object_new (CC_RFKILL_TYPE_GLIB, NULL)); } unity-settings-daemon/plugins/rfkill/rfkill-glib.h0000664000000000000000000000556115172222611017536 0ustar /* * * gnome-bluetooth - Bluetooth integration for GNOME * * Copyright (C) 2012 Bastien Nocera * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef __CC_RFKILL_GLIB_H #define __CC_RFKILL_GLIB_H #include #include #include "rfkill.h" G_BEGIN_DECLS #define CC_RFKILL_TYPE_GLIB (cc_rfkill_glib_get_type()) #define CC_RFKILL_GLIB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ CC_RFKILL_TYPE_GLIB, CcRfkillGlib)) #define CC_RFKILL_GLIB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ CC_RFKILL_TYPE_GLIB, CcRfkillGlibClass)) #define RFKILL_IS_GLIB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ CC_RFKILL_TYPE_GLIB)) #define RFKILL_IS_GLIB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \ CC_RFKILL_TYPE_GLIB)) #define RFKILL_GET_GLIB_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ CC_RFKILL_TYPE_GLIB, CcRfkillGlibClass)) typedef struct CcRfkillGlibPrivate CcRfkillGlibPrivate; typedef struct _CcRfkillGlib { GObject parent; CcRfkillGlibPrivate *priv; } CcRfkillGlib; typedef struct _CcRfkillGlibClass { GObjectClass parent_class; void (*changed) (CcRfkillGlib *rfkill, GList *events); } CcRfkillGlibClass; GType cc_rfkill_glib_get_type (void); CcRfkillGlib *cc_rfkill_glib_new (void); int cc_rfkill_glib_open (CcRfkillGlib *rfkill); void cc_rfkill_glib_send_event (CcRfkillGlib *rfkill, struct rfkill_event *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean cc_rfkill_glib_send_event_finish (CcRfkillGlib *rfkill, GAsyncResult *res, GError **error); void cc_rfkill_glib_send_change_all_event (CcRfkillGlib *rfkill, guint rfkill_type, gboolean enable, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean cc_rfkill_glib_send_change_all_event_finish (CcRfkillGlib *rfkill, GAsyncResult *res, GError **error); G_END_DECLS #endif /* __CC_RFKILL_GLIB_H */ unity-settings-daemon/plugins/rfkill/rfkill.gnome-settings-plugin.in0000664000000000000000000000026315172222611023232 0ustar [GNOME Settings Plugin] Module=rfkill IAge=0 # Default Priority # Priority=100 _Name=Rfkill _Description=Rfkill plugin Authors=Bastien Nocera Copyright=Copyright © 2013 Website= unity-settings-daemon/plugins/rfkill/rfkill.h0000664000000000000000000000667415172222611016631 0ustar #ifndef __RFKILL_H #define __RFKILL_H /* * Copyright (C) 2006 - 2007 Ivo van Doorn * Copyright (C) 2007 Dmitry Torokhov * Copyright 2009 Johannes Berg * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include /* define userspace visible states */ #define RFKILL_STATE_SOFT_BLOCKED 0 #define RFKILL_STATE_UNBLOCKED 1 #define RFKILL_STATE_HARD_BLOCKED 2 /** * enum rfkill_type - type of rfkill switch. * * @RFKILL_TYPE_ALL: toggles all switches (requests only - not a switch type) * @RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. * @RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. * @RFKILL_TYPE_UWB: switch is on a ultra wideband device. * @RFKILL_TYPE_WIMAX: switch is on a WiMAX device. * @RFKILL_TYPE_WWAN: switch is on a wireless WAN device. * @RFKILL_TYPE_GPS: switch is on a GPS device. * @RFKILL_TYPE_FM: switch is on a FM radio device. * @NUM_RFKILL_TYPES: number of defined rfkill types */ enum rfkill_type { RFKILL_TYPE_ALL = 0, RFKILL_TYPE_WLAN, RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_UWB, RFKILL_TYPE_WIMAX, RFKILL_TYPE_WWAN, RFKILL_TYPE_GPS, RFKILL_TYPE_FM, NUM_RFKILL_TYPES, }; /** * enum rfkill_operation - operation types * @RFKILL_OP_ADD: a device was added * @RFKILL_OP_DEL: a device was removed * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all) */ enum rfkill_operation { RFKILL_OP_ADD = 0, RFKILL_OP_DEL, RFKILL_OP_CHANGE, RFKILL_OP_CHANGE_ALL, }; /** * struct rfkill_event - events for userspace on /dev/rfkill * @idx: index of dev rfkill * @type: type of the rfkill struct * @op: operation code * @hard: hard state (0/1) * @soft: soft state (0/1) * * Structure used for userspace communication on /dev/rfkill, * used for events from the kernel and control to the kernel. */ struct rfkill_event { __u32 idx; __u8 type; __u8 op; __u8 soft, hard; } __attribute__((packed)); /* * We are planning to be backward and forward compatible with changes * to the event struct, by adding new, optional, members at the end. * When reading an event (whether the kernel from userspace or vice * versa) we need to accept anything that's at least as large as the * version 1 event size, but might be able to accept other sizes in * the future. * * One exception is the kernel -- we already have two event sizes in * that we've made the 'hard' member optional since our only option * is to ignore it anyway. */ #define RFKILL_EVENT_SIZE_V1 8 /* ioctl for turning off rfkill-input (if present) */ #define RFKILL_IOC_MAGIC 'R' #define RFKILL_IOC_NOINPUT 1 #define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT) /* and that's all userspace gets */ #endif /* RFKILL_H */ unity-settings-daemon/plugins/rfkill/test-rfkill.c0000664000000000000000000000031215172222611017560 0ustar #define NEW gsd_rfkill_manager_new #define START gsd_rfkill_manager_start #define STOP gsd_rfkill_manager_stop #define MANAGER GsdRfkillManager #include "gsd-rfkill-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/screensaver-proxy/0000775000000000000000000000000015172222611017374 5ustar unity-settings-daemon/plugins/screensaver-proxy/Makefile.am0000664000000000000000000000342415172222611021433 0ustar plugin_name = screensaver-proxy plugin_LTLIBRARIES = libscreensaver-proxy.la libscreensaver_proxy_la_SOURCES = \ gsd-screensaver-proxy-manager.c \ gsd-screensaver-proxy-manager.h \ gsd-screensaver-proxy-plugin.c libscreensaver_proxy_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libscreensaver_proxy_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libscreensaver_proxy_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS) libscreensaver_proxy_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(NULL) libexec_PROGRAMS = usd-test-screensaver-proxy usd_test_screensaver_proxy_SOURCES = \ test-screensaver-proxy.c \ gsd-screensaver-proxy-manager.c \ gsd-screensaver-proxy-manager.h usd_test_screensaver_proxy_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) usd_test_screensaver_proxy_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_screensaver_proxy_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = screensaver-proxy.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = $(plugin_in_files) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/screensaver-proxy/gsd-screensaver-proxy-manager.c0000664000000000000000000004532715172222611025435 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "gnome-settings-bus.h" #include "gnome-settings-profile.h" #include "gsd-screensaver-proxy-manager.h" #include "gsd-idle-monitor.h" #define GSD_SCREENSAVER_PROXY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManagerPrivate)) /* As available in: * https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/ksmserver/screenlocker/dbus/org.freedesktop.ScreenSaver.xml * and documented in: * https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/ksmserver/screenlocker/interface.h */ static const gchar introspection_xml[] = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; static const gchar introspection_xml2[] = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; #define GSD_SCREENSAVER_PROXY_DBUS_SERVICE "org.freedesktop.ScreenSaver" #define GSD_SCREENSAVER_PROXY_DBUS_PATH "/org/freedesktop/ScreenSaver" #define GSD_SCREENSAVER_PROXY_DBUS_PATH2 "/ScreenSaver" #define GSD_SCREENSAVER_PROXY_DBUS_INTERFACE "org.freedesktop.ScreenSaver" #define GSM_INHIBITOR_FLAG_IDLE 1 << 3 struct GsdScreensaverProxyManagerPrivate { GsdSessionManager *session; GsdScreenSaver *screensaver; GDBusConnection *connection; GCancellable *bus_cancellable; GDBusNodeInfo *introspection_data; GDBusNodeInfo *introspection_data2; guint name_id; GHashTable *watch_ht; /* key = sender, value = name watch id */ GHashTable *cookie_ht; /* key = cookie, value = sender */ }; static void gsd_screensaver_proxy_manager_class_init (GsdScreensaverProxyManagerClass *klass); static void gsd_screensaver_proxy_manager_init (GsdScreensaverProxyManager *screensaver_proxy_manager); static void gsd_screensaver_proxy_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdScreensaverProxyManager, gsd_screensaver_proxy_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void name_vanished_cb (GDBusConnection *connection, const gchar *name, GsdScreensaverProxyManager *manager) { GHashTableIter iter; gpointer cookie_ptr; const char *sender; /* Look for all the cookies under that name, * and call uninhibit for them */ g_hash_table_iter_init (&iter, manager->priv->cookie_ht); while (g_hash_table_iter_next (&iter, &cookie_ptr, (gpointer *) &sender)) { if (g_strcmp0 (sender, name) == 0) { guint cookie = GPOINTER_TO_UINT (cookie_ptr); g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->session), "Uninhibit", g_variant_new ("(u)", cookie), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); g_debug ("Removing cookie %u for sender %s", cookie, sender); g_hash_table_iter_remove (&iter); } } g_hash_table_remove (manager->priv->watch_ht, name); } static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GsdScreensaverProxyManager *manager = GSD_SCREENSAVER_PROXY_MANAGER (user_data); GError *error = NULL; GVariant *ret = NULL; /* Check session pointer as a proxy for whether the manager is in the start or stop state */ if (manager->priv->session == NULL || manager->priv->screensaver == NULL) { goto unimplemented; } g_debug ("Calling method '%s.%s' for ScreenSaver Proxy", interface_name, method_name); if (g_strcmp0 (method_name, "Inhibit") == 0) { const char *app_id; const char *reason; guint cookie; g_variant_get (parameters, "(ss)", &app_id, &reason); ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->session), "Inhibit", g_variant_new ("(susu)", app_id, 0, reason, GSM_INHIBITOR_FLAG_IDLE), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); g_variant_get (ret, "(u)", &cookie); g_hash_table_insert (manager->priv->cookie_ht, GUINT_TO_POINTER (cookie), g_strdup (sender)); if (g_hash_table_lookup (manager->priv->watch_ht, sender) == NULL) { guint watch_id; watch_id = g_bus_watch_name_on_connection (manager->priv->connection, sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, (GBusNameVanishedCallback) name_vanished_cb, manager, NULL); g_hash_table_insert (manager->priv->watch_ht, g_strdup (sender), GUINT_TO_POINTER (watch_id)); } } else if (g_strcmp0 (method_name, "UnInhibit") == 0) { guint cookie; g_variant_get (parameters, "(u)", &cookie); g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->session), "Uninhibit", parameters, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); g_debug ("Removing cookie %u from the list for %s", cookie, sender); g_hash_table_remove (manager->priv->cookie_ht, GUINT_TO_POINTER (cookie)); } else if (g_strcmp0 (method_name, "Lock") == 0 || g_strcmp0 (method_name, "SimulateUserActivity") == 0 || g_strcmp0 (method_name, "GetActive") == 0 || g_strcmp0 (method_name, "GetActiveTime") == 0 || g_strcmp0 (method_name, "SetActive") == 0) { ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->screensaver), method_name, parameters, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error == NULL && g_strcmp0 (method_name, "SetActive") == 0) { g_variant_unref (ret); /* Returning the actual Activate state here is not possible, * as calling GetActive at this point might return an invalid * value if the activation process is still ongoing. */ ret = g_variant_ref (parameters); } } else if (g_strcmp0 (method_name, "GetSessionIdleTime") == 0) { GsdIdleMonitor *idle_monitor = gsd_idle_monitor_get_core (); gint64 idle_time_ms = gsd_idle_monitor_get_idletime (idle_monitor); ret = g_variant_new ("(u)", idle_time_ms / 1000); } else { goto unimplemented; } if (error != NULL) { g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); return; } g_dbus_method_invocation_return_value (invocation, ret); return; unimplemented: g_dbus_method_invocation_return_dbus_error (invocation, "org.freedesktop.DBus.Error.NotSupported", "This method is not implemented"); } static const GDBusInterfaceVTable interface_vtable = { handle_method_call, NULL, /* GetProperty */ NULL, /* SetProperty */ }; static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdScreensaverProxyManager *manager) { GDBusConnection *connection; GDBusInterfaceInfo **infos; GError *error = NULL; if (manager->priv->bus_cancellable == NULL || g_cancellable_is_cancelled (manager->priv->bus_cancellable)) { g_warning ("Operation has been cancelled, so not retrieving session bus"); return; } connection = g_bus_get_finish (res, &error); if (connection == NULL) { g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; infos = manager->priv->introspection_data->interfaces; g_dbus_connection_register_object (connection, GSD_SCREENSAVER_PROXY_DBUS_PATH, infos[0], &interface_vtable, manager, NULL, NULL); infos = manager->priv->introspection_data2->interfaces; g_dbus_connection_register_object (connection, GSD_SCREENSAVER_PROXY_DBUS_PATH2, infos[0], &interface_vtable, manager, NULL, NULL); manager->priv->name_id = g_bus_own_name_on_connection (manager->priv->connection, GSD_SCREENSAVER_PROXY_DBUS_SERVICE, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); } static void register_manager_dbus (GsdScreensaverProxyManager *manager) { manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); manager->priv->introspection_data2 = g_dbus_node_info_new_for_xml (introspection_xml2, NULL); manager->priv->bus_cancellable = g_cancellable_new (); g_assert (manager->priv->introspection_data != NULL); g_assert (manager->priv->introspection_data2 != NULL); g_bus_get (G_BUS_TYPE_SESSION, manager->priv->bus_cancellable, (GAsyncReadyCallback) on_bus_gotten, manager); } gboolean gsd_screensaver_proxy_manager_start (GsdScreensaverProxyManager *manager, GError **error) { g_debug ("Starting screensaver-proxy manager"); gnome_settings_profile_start (NULL); manager->priv->session = gnome_settings_bus_get_session_proxy (); manager->priv->screensaver = gnome_settings_bus_get_screen_saver_proxy (); manager->priv->watch_ht = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_bus_unwatch_name); manager->priv->cookie_ht = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_free); gnome_settings_profile_end (NULL); return TRUE; } void gsd_screensaver_proxy_manager_stop (GsdScreensaverProxyManager *manager) { g_debug ("Stopping screensaver_proxy manager"); g_clear_object (&manager->priv->session); g_clear_object (&manager->priv->screensaver); g_clear_pointer (&manager->priv->watch_ht, g_hash_table_destroy); g_clear_pointer (&manager->priv->cookie_ht, g_hash_table_destroy); } static void gsd_screensaver_proxy_manager_class_init (GsdScreensaverProxyManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_screensaver_proxy_manager_finalize; g_type_class_add_private (klass, sizeof (GsdScreensaverProxyManagerPrivate)); } static void gsd_screensaver_proxy_manager_init (GsdScreensaverProxyManager *manager) { manager->priv = GSD_SCREENSAVER_PROXY_MANAGER_GET_PRIVATE (manager); } static void gsd_screensaver_proxy_manager_finalize (GObject *object) { GsdScreensaverProxyManager *manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_SCREENSAVER_PROXY_MANAGER (object)); manager = GSD_SCREENSAVER_PROXY_MANAGER (object); g_return_if_fail (manager->priv != NULL); gsd_screensaver_proxy_manager_stop (manager); if (manager->priv->name_id != 0) { g_bus_unown_name (manager->priv->name_id); manager->priv->name_id = 0; } g_clear_object (&manager->priv->connection); g_clear_object (&manager->priv->bus_cancellable); g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); g_clear_pointer (&manager->priv->introspection_data2, g_dbus_node_info_unref); G_OBJECT_CLASS (gsd_screensaver_proxy_manager_parent_class)->finalize (object); } GsdScreensaverProxyManager * gsd_screensaver_proxy_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_SCREENSAVER_PROXY_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); register_manager_dbus (manager_object); } return GSD_SCREENSAVER_PROXY_MANAGER (manager_object); } unity-settings-daemon/plugins/screensaver-proxy/gsd-screensaver-proxy-manager.h0000664000000000000000000000516715172222611025440 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_SCREENSAVER_PROXY_MANAGER_H #define __GSD_SCREENSAVER_PROXY_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_SCREENSAVER_PROXY_MANAGER (gsd_screensaver_proxy_manager_get_type ()) #define GSD_SCREENSAVER_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManager)) #define GSD_SCREENSAVER_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManagerClass)) #define GSD_IS_SCREENSAVER_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER)) #define GSD_IS_SCREENSAVER_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SCREENSAVER_PROXY_MANAGER)) #define GSD_SCREENSAVER_PROXY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManagerClass)) typedef struct GsdScreensaverProxyManagerPrivate GsdScreensaverProxyManagerPrivate; typedef struct { GObject parent; GsdScreensaverProxyManagerPrivate *priv; } GsdScreensaverProxyManager; typedef struct { GObjectClass parent_class; } GsdScreensaverProxyManagerClass; GType gsd_screensaver_proxy_manager_get_type (void); GsdScreensaverProxyManager *gsd_screensaver_proxy_manager_new (void); gboolean gsd_screensaver_proxy_manager_start (GsdScreensaverProxyManager *manager, GError **error); void gsd_screensaver_proxy_manager_stop (GsdScreensaverProxyManager *manager); G_END_DECLS #endif /* __GSD_SCREENSAVER_PROXY_MANAGER_H */ unity-settings-daemon/plugins/screensaver-proxy/gsd-screensaver-proxy-plugin.c0000664000000000000000000000205715172222611025312 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2012 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-screensaver-proxy-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdScreensaverProxy, gsd_screensaver_proxy) unity-settings-daemon/plugins/screensaver-proxy/screensaver-proxy.gnome-settings-plugin.in0000664000000000000000000000035515172222611027664 0ustar [GNOME Settings Plugin] Module=screensaver-proxy IAge=0 Priority=8 _Name=Screensaver Proxy _Description=Proxy FreeDesktop screensaver inhibition to gnome-session Authors=Bastien Nocera Copyright=Copyright © 2012 Bastien Nocera Website= unity-settings-daemon/plugins/screensaver-proxy/test-screensaver-proxy.c0000664000000000000000000000040015172222611024206 0ustar #define NEW gsd_screensaver_proxy_manager_new #define START gsd_screensaver_proxy_manager_start #define STOP gsd_screensaver_proxy_manager_stop #define MANAGER GsdScreensaverProxyManager #include "gsd-screensaver-proxy-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/sharing/0000775000000000000000000000000015172222611015330 5ustar unity-settings-daemon/plugins/sharing/Makefile.am0000664000000000000000000000246115172222611017367 0ustar plugin_name = sharing plugin_LTLIBRARIES = libsharing.la libsharing_la_SOURCES = \ gsd-sharing-manager.c \ gsd-sharing-manager.h \ gsd-sharing-enums.h \ gsd-sharing-plugin.c libsharing_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_builddir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libsharing_la_CFLAGS = \ -I$(top_srcdir)/plugins/common \ $(SHARING_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) libsharing_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS) libsharing_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(SHARING_LIBS) \ $(NULL) noinst_PROGRAMS = gsd-test-sharing gsd_test_sharing_SOURCES = \ gsd-sharing-manager.c \ gsd-sharing-manager.h \ test-sharing.c gsd_test_sharing_CFLAGS = $(libsharing_la_CFLAGS) gsd_test_sharing_CPPFLAGS = $(libsharing_la_CPPFLAGS) gsd_test_sharing_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SHARING_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_in_files = sharing.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = $(plugin_in_files) CLEANFILES = $(plugin_DATA) DISTCLEANFILES = $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/sharing/gsd-sharing-enums.h0000664000000000000000000000214415172222611021035 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #ifndef __GSD_SHARING_ENUMS_H #define __GSD_SHARING_ENUMS_H G_BEGIN_DECLS typedef enum { GSD_SHARING_STATUS_OFFLINE, GSD_SHARING_STATUS_DISABLED_MOBILE_BROADBAND, GSD_SHARING_STATUS_DISABLED_LOW_SECURITY, GSD_SHARING_STATUS_AVAILABLE } GsdSharingStatus; G_END_DECLS #endif /* __GSD_SHARING_ENUMS_H */ unity-settings-daemon/plugins/sharing/gsd-sharing-manager.c0000664000000000000000000007154715172222611021330 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Bastien Nocera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #include "config.h" #include #include #include #include #include #ifdef HAVE_NETWORK_MANAGER #include #endif /* HAVE_NETWORK_MANAGER */ #include "gnome-settings-plugin.h" #include "gnome-settings-profile.h" #include "gsd-sharing-manager.h" #include "gsd-sharing-enums.h" #define GSD_SHARING_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SHARING_MANAGER, GsdSharingManagerPrivate)) typedef struct { const char *name; GSettings *settings; gboolean started; GSubprocess *process; } ServiceInfo; struct GsdSharingManagerPrivate { GDBusNodeInfo *introspection_data; guint name_id; GDBusConnection *connection; GCancellable *cancellable; #ifdef HAVE_NETWORK_MANAGER NMClient *client; #endif /* HAVE_NETWORK_MANAGER */ GHashTable *services; char *current_network; char *current_network_name; char *carrier_type; GsdSharingStatus sharing_status; }; #define GSD_SHARING_DBUS_NAME GSD_DBUS_NAME ".Sharing" #define GSD_SHARING_DBUS_PATH GSD_DBUS_PATH "/Sharing" static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; static void gsd_sharing_manager_class_init (GsdSharingManagerClass *klass); static void gsd_sharing_manager_init (GsdSharingManager *manager); static void gsd_sharing_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdSharingManager, gsd_sharing_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static const char * const services[] = { "rygel", "vino-server", "gnome-user-share-webdav" }; static void gsd_sharing_manager_start_service (GsdSharingManager *manager, ServiceInfo *service) { GDesktopAppInfo *app; const char *exec; char *desktop, **argvp; GError *error = NULL; if (service->started) return; g_debug ("About to start %s", service->name); desktop = g_strdup_printf ("%s.desktop", service->name); app = g_desktop_app_info_new (desktop); g_free (desktop); if (!app) { g_warning ("Could not find desktop file for service '%s'", service->name); return; } exec = g_app_info_get_commandline (G_APP_INFO (app)); if (!g_shell_parse_argv (exec, NULL, &argvp, &error)) { g_warning ("Could not parse command-line '%s': %s", exec, error->message); g_error_free (error); g_object_unref (app); return; } service->process = g_subprocess_newv ((const gchar * const*) argvp, G_SUBPROCESS_FLAGS_NONE, &error); if (!service->process) { g_warning ("Could not start command-line '%s': %s", exec, error->message); g_error_free (error); service->started = FALSE; } else { service->started = TRUE; } g_strfreev (argvp); g_object_unref (app); } #ifdef HAVE_NETWORK_MANAGER static gboolean service_is_enabled_on_current_connection (GsdSharingManager *manager, ServiceInfo *service) { char **connections; int j; gboolean ret; connections = g_settings_get_strv (service->settings, "enabled-connections"); ret = FALSE; for (j = 0; connections[j] != NULL; j++) { if (g_strcmp0 (connections[j], manager->priv->current_network) == 0) { ret = TRUE; break; } } g_strfreev (connections); return ret; } #else static gboolean service_is_enabled_on_current_connection (GsdSharingManager *manager, ServiceInfo *service) { return FALSE; } #endif /* HAVE_NETWORK_MANAGER */ static void gsd_sharing_manager_stop_service (GsdSharingManager *manager, ServiceInfo *service) { if (!service->started || service->process == NULL) { return; } g_debug ("About to stop %s", service->name); g_subprocess_send_signal (service->process, SIGTERM); g_clear_object (&service->process); service->started = FALSE; } static void gsd_sharing_manager_sync_services (GsdSharingManager *manager) { GList *services, *l; services = g_hash_table_get_values (manager->priv->services); for (l = services; l != NULL; l = l->next) { ServiceInfo *service = l->data; gboolean should_be_started = FALSE; if (manager->priv->sharing_status == GSD_SHARING_STATUS_AVAILABLE && service_is_enabled_on_current_connection (manager, service)) should_be_started = TRUE; if (service->started != should_be_started) { if (service->started) gsd_sharing_manager_stop_service (manager, service); else gsd_sharing_manager_start_service (manager, service); } } g_list_free (services); } #ifdef HAVE_NETWORK_MANAGER static void properties_changed (GsdSharingManager *manager) { GVariantBuilder props_builder; GVariant *props_changed = NULL; /* not yet connected to the session bus */ if (manager->priv->connection == NULL) return; g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&props_builder, "{sv}", "CurrentNetwork", g_variant_new_string (manager->priv->current_network)); g_variant_builder_add (&props_builder, "{sv}", "CurrentNetworkName", g_variant_new_string (manager->priv->current_network_name)); g_variant_builder_add (&props_builder, "{sv}", "CarrierType", g_variant_new_string (manager->priv->carrier_type)); g_variant_builder_add (&props_builder, "{sv}", "SharingStatus", g_variant_new_uint32 (manager->priv->sharing_status)); props_changed = g_variant_new ("(s@a{sv}@as)", GSD_SHARING_DBUS_NAME, g_variant_builder_end (&props_builder), g_variant_new_strv (NULL, 0)); g_dbus_connection_emit_signal (manager->priv->connection, NULL, GSD_SHARING_DBUS_PATH, "org.freedesktop.DBus.Properties", "PropertiesChanged", props_changed, NULL); } static char ** get_connections_for_service (GsdSharingManager *manager, const char *service_name) { ServiceInfo *service; service = g_hash_table_lookup (manager->priv->services, service_name); return g_settings_get_strv (service->settings, "enabled-connections"); } #else static char ** get_connections_for_service (GsdSharingManager *manager, const char *service_name) { const char * const * connections [] = { NULL }; return g_strdupv ((char **) connections); } #endif /* HAVE_NETWORK_MANAGER */ static gboolean check_service (GsdSharingManager *manager, const char *service_name, GError **error) { if (g_hash_table_lookup (manager->priv->services, service_name)) return TRUE; g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", service_name); return FALSE; } static gboolean gsd_sharing_manager_enable_service (GsdSharingManager *manager, const char *service_name, GError **error) { ServiceInfo *service; char **connections; GPtrArray *array; guint i; if (!check_service (manager, service_name, error)) return FALSE; if (manager->priv->sharing_status != GSD_SHARING_STATUS_AVAILABLE) { g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Sharing cannot be enabled on this network, status is '%d'", manager->priv->sharing_status); return FALSE; } service = g_hash_table_lookup (manager->priv->services, service_name); connections = g_settings_get_strv (service->settings, "enabled-connections"); array = g_ptr_array_new (); for (i = 0; connections[i] != NULL; i++) { if (g_strcmp0 (connections[i], manager->priv->current_network) == 0) goto bail; g_ptr_array_add (array, connections[i]); } g_ptr_array_add (array, manager->priv->current_network); g_ptr_array_add (array, NULL); g_settings_set_strv (service->settings, "enabled-connections", (const gchar *const *) array->pdata); bail: gsd_sharing_manager_start_service (manager, service); g_ptr_array_unref (array); g_strfreev (connections); return TRUE; } static gboolean gsd_sharing_manager_disable_service (GsdSharingManager *manager, const char *service_name, const char *network_name, GError **error) { ServiceInfo *service; char **connections; GPtrArray *array; guint i; if (!check_service (manager, service_name, error)) return FALSE; service = g_hash_table_lookup (manager->priv->services, service_name); connections = g_settings_get_strv (service->settings, "enabled-connections"); array = g_ptr_array_new (); for (i = 0; connections[i] != NULL; i++) { if (g_strcmp0 (connections[i], network_name) != 0) g_ptr_array_add (array, connections[i]); } g_ptr_array_add (array, NULL); g_settings_set_strv (service->settings, "enabled-connections", (const gchar *const *) array->pdata); g_ptr_array_unref (array); g_strfreev (connections); if (g_str_equal (network_name, manager->priv->current_network)) gsd_sharing_manager_stop_service (manager, service); return TRUE; } #ifdef HAVE_NETWORK_MANAGER static const char * get_type_and_name_for_connection_uuid (GsdSharingManager *manager, const char *uuid, const char **name) { NMRemoteConnection *conn; const char *type; if (!manager->priv->client) return NULL; conn = nm_client_get_connection_by_uuid (manager->priv->client, uuid); if (!conn) return NULL; type = nm_connection_get_connection_type (NM_CONNECTION (conn)); *name = nm_connection_get_id (NM_CONNECTION (conn)); return type; } #else static const char * get_type_and_name_for_connection_uuid (GsdSharingManager *manager, const char *id, const char **name) { return NULL; } #endif /* HAVE_NETWORK_MANAGER */ #ifdef HAVE_NETWORK_MANAGER static gboolean connection_is_low_security (GsdSharingManager *manager, const char *uuid) { NMRemoteConnection *conn; if (!manager->priv->client) return TRUE; conn = nm_client_get_connection_by_uuid (manager->priv->client, uuid); if (!conn) return TRUE; /* Disable sharing on open Wi-Fi * XXX: Also do this for WEP networks? */ return (nm_connection_get_setting_wireless_security (NM_CONNECTION (conn)) == NULL); } #endif /* HAVE_NETWORK_MANAGER */ static GVariant * gsd_sharing_manager_list_networks (GsdSharingManager *manager, const char *service_name, GError **error) { char **connections; GVariantBuilder builder; guint i; if (!check_service (manager, service_name, error)) return NULL; #ifdef HAVE_NETWORK_MANAGER if (!manager->priv->client) { g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Not ready yet"); return NULL; } #endif /* HAVE_NETWORK_MANAGER */ connections = get_connections_for_service (manager, service_name); g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a(sss))")); g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sss)")); for (i = 0; connections[i] != NULL; i++) { const char *type, *name; type = get_type_and_name_for_connection_uuid (manager, connections[i], &name); if (!type) continue; g_variant_builder_add (&builder, "(sss)", connections[i], name, type); } g_strfreev (connections); g_variant_builder_close (&builder); return g_variant_builder_end (&builder); } static GVariant * handle_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { GsdSharingManager *manager = GSD_SHARING_MANAGER (user_data); /* Check session pointer as a proxy for whether the manager is in the start or stop state */ if (manager->priv->connection == NULL) return NULL; if (g_strcmp0 (property_name, "CurrentNetwork") == 0) { return g_variant_new_string (manager->priv->current_network); } if (g_strcmp0 (property_name, "CurrentNetworkName") == 0) { return g_variant_new_string (manager->priv->current_network_name); } if (g_strcmp0 (property_name, "CarrierType") == 0) { return g_variant_new_string (manager->priv->carrier_type); } if (g_strcmp0 (property_name, "SharingStatus") == 0) { return g_variant_new_uint32 (manager->priv->sharing_status); } return NULL; } static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GsdSharingManager *manager = (GsdSharingManager *) user_data; g_debug ("Calling method '%s' for sharing", method_name); /* Check session pointer as a proxy for whether the manager is in the start or stop state */ if (manager->priv->connection == NULL) return; if (g_strcmp0 (method_name, "EnableService") == 0) { const char *service; GError *error = NULL; g_variant_get (parameters, "(&s)", &service); if (!gsd_sharing_manager_enable_service (manager, service, &error)) g_dbus_method_invocation_take_error (invocation, error); else g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_strcmp0 (method_name, "DisableService") == 0) { const char *service; const char *network_name; GError *error = NULL; g_variant_get (parameters, "(&s&s)", &service, &network_name); if (!gsd_sharing_manager_disable_service (manager, service, network_name, &error)) g_dbus_method_invocation_take_error (invocation, error); else g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_strcmp0 (method_name, "ListNetworks") == 0) { const char *service; GError *error = NULL; GVariant *variant; g_variant_get (parameters, "(&s)", &service); variant = gsd_sharing_manager_list_networks (manager, service, &error); if (!variant) g_dbus_method_invocation_take_error (invocation, error); else g_dbus_method_invocation_return_value (invocation, variant); } } static const GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, NULL }; static void on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdSharingManager *manager) { GDBusConnection *connection; GError *error = NULL; connection = g_bus_get_finish (res, &error); if (connection == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Could not get session bus: %s", error->message); g_error_free (error); return; } manager->priv->connection = connection; g_dbus_connection_register_object (connection, GSD_SHARING_DBUS_PATH, manager->priv->introspection_data->interfaces[0], &interface_vtable, manager, NULL, NULL); manager->priv->name_id = g_bus_own_name_on_connection (connection, GSD_SHARING_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); } #ifdef HAVE_NETWORK_MANAGER static void primary_connection_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GsdSharingManager *manager = user_data; NMActiveConnection *a_con; a_con = nm_client_get_primary_connection (manager->priv->client); g_clear_pointer (&manager->priv->current_network, g_free); g_clear_pointer (&manager->priv->current_network_name, g_free); g_clear_pointer (&manager->priv->carrier_type, g_free); if (a_con) { manager->priv->current_network = g_strdup (nm_active_connection_get_uuid (a_con)); manager->priv->current_network_name = g_strdup (nm_active_connection_get_id (a_con)); manager->priv->carrier_type = g_strdup (nm_active_connection_get_connection_type (a_con)); if (manager->priv->carrier_type == NULL) manager->priv->carrier_type = g_strdup (""); } else { manager->priv->current_network = g_strdup (""); manager->priv->current_network_name = g_strdup (""); manager->priv->carrier_type = g_strdup (""); } if (!a_con) { manager->priv->sharing_status = GSD_SHARING_STATUS_OFFLINE; } else if (*(manager->priv->carrier_type) == '\0') { /* Missing carrier type information? */ manager->priv->sharing_status = GSD_SHARING_STATUS_OFFLINE; } else if (g_str_equal (manager->priv->carrier_type, "bluetooth") || g_str_equal (manager->priv->carrier_type, "gsm") || g_str_equal (manager->priv->carrier_type, "cdma")) { manager->priv->sharing_status = GSD_SHARING_STATUS_DISABLED_MOBILE_BROADBAND; } else if (g_str_equal (manager->priv->carrier_type, "802-11-wireless")) { if (connection_is_low_security (manager, manager->priv->current_network)) manager->priv->sharing_status = GSD_SHARING_STATUS_DISABLED_LOW_SECURITY; else manager->priv->sharing_status = GSD_SHARING_STATUS_AVAILABLE; } else { manager->priv->sharing_status = GSD_SHARING_STATUS_AVAILABLE; } g_debug ("current network: %s", manager->priv->current_network); g_debug ("current network name: %s", manager->priv->current_network_name); g_debug ("conn type: %s", manager->priv->carrier_type); g_debug ("status: %d", manager->priv->sharing_status); properties_changed (manager); gsd_sharing_manager_sync_services (manager); } static void nm_client_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GsdSharingManager *manager = user_data; GError *error = NULL; NMClient *client; client = nm_client_new_finish (res, &error); if (!client) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Couldn't get NMClient: %s", error->message); g_error_free (error); return; } manager->priv->client = client; g_signal_connect (G_OBJECT (client), "notify::primary-connection", G_CALLBACK (primary_connection_changed), manager); primary_connection_changed (NULL, NULL, manager); } #endif /* HAVE_NETWORK_MANAGER */ #define RYGEL_BUS_NAME "org.gnome.Rygel1" #define RYGEL_OBJECT_PATH "/org/gnome/Rygel1" #define RYGEL_INTERFACE_NAME "org.gnome.Rygel1" static void gsd_sharing_manager_disable_rygel (void) { GDBusConnection *connection; gchar *path; path = g_build_filename (g_get_user_config_dir (), "autostart", "rygel.desktop", NULL); if (!g_file_test (path, G_FILE_TEST_IS_SYMLINK | G_FILE_TEST_IS_REGULAR)) goto out; g_unlink (path); connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (connection) { g_dbus_connection_call (connection, RYGEL_BUS_NAME, RYGEL_OBJECT_PATH, RYGEL_INTERFACE_NAME, "Shutdown", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); } g_object_unref (connection); out: g_free (path); } gboolean gsd_sharing_manager_start (GsdSharingManager *manager, GError **error) { g_debug ("Starting sharing manager"); gnome_settings_profile_start (NULL); manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (manager->priv->introspection_data != NULL); gsd_sharing_manager_disable_rygel (); manager->priv->cancellable = g_cancellable_new (); #ifdef HAVE_NETWORK_MANAGER nm_client_new_async (manager->priv->cancellable, nm_client_ready, manager); #endif /* HAVE_NETWORK_MANAGER */ /* Start process of owning a D-Bus name */ g_bus_get (G_BUS_TYPE_SESSION, manager->priv->cancellable, (GAsyncReadyCallback) on_bus_gotten, manager); gnome_settings_profile_end (NULL); return TRUE; } void gsd_sharing_manager_stop (GsdSharingManager *manager) { g_debug ("Stopping sharing manager"); manager->priv->sharing_status = GSD_SHARING_STATUS_OFFLINE; gsd_sharing_manager_sync_services (manager); if (manager->priv->cancellable) { g_cancellable_cancel (manager->priv->cancellable); g_clear_object (&manager->priv->cancellable); } #ifdef HAVE_NETWORK_MANAGER g_clear_object (&manager->priv->client); #endif /* HAVE_NETWORK_MANAGER */ if (manager->priv->name_id != 0) { g_bus_unown_name (manager->priv->name_id); manager->priv->name_id = 0; } g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); g_clear_object (&manager->priv->connection); g_clear_pointer (&manager->priv->current_network, g_free); g_clear_pointer (&manager->priv->current_network_name, g_free); g_clear_pointer (&manager->priv->carrier_type, g_free); } static void gsd_sharing_manager_class_init (GsdSharingManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_sharing_manager_finalize; g_type_class_add_private (klass, sizeof (GsdSharingManagerPrivate)); } static void service_free (gpointer pointer) { ServiceInfo *service = pointer; g_clear_object (&service->settings); g_free (service); } static void gsd_sharing_manager_init (GsdSharingManager *manager) { guint i; manager->priv = GSD_SHARING_MANAGER_GET_PRIVATE (manager); manager->priv->services = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, service_free); /* Default state */ manager->priv->current_network = g_strdup (""); manager->priv->current_network_name = g_strdup (""); manager->priv->carrier_type = g_strdup (""); manager->priv->sharing_status = GSD_SHARING_STATUS_OFFLINE; for (i = 0; i < G_N_ELEMENTS (services); i++) { ServiceInfo *service; char *path; service = g_new0 (ServiceInfo, 1); service->name = services[i]; path = g_strdup_printf ("/com/canonical/unity/settings-daemon/plugins/sharing/%s/", services[i]); service->settings = g_settings_new_with_path ("com.canonical.unity.settings-daemon.plugins.sharing.service", path); g_free (path); g_hash_table_insert (manager->priv->services, (gpointer) services[i], service); } } static void gsd_sharing_manager_finalize (GObject *object) { GsdSharingManager *manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_SHARING_MANAGER (object)); manager = GSD_SHARING_MANAGER (object); g_return_if_fail (manager->priv != NULL); gsd_sharing_manager_stop (manager); g_hash_table_unref (manager->priv->services); G_OBJECT_CLASS (gsd_sharing_manager_parent_class)->finalize (object); } GsdSharingManager * gsd_sharing_manager_new (void) { if (manager_object != NULL) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_SHARING_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_SHARING_MANAGER (manager_object); } unity-settings-daemon/plugins/sharing/gsd-sharing-manager.h0000664000000000000000000000435715172222611021330 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #ifndef __GSD_SHARING_MANAGER_H #define __GSD_SHARING_MANAGER_H #include G_BEGIN_DECLS #define GSD_TYPE_SHARING_MANAGER (gsd_sharing_manager_get_type ()) #define GSD_SHARING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SHARING_MANAGER, GsdSharingManager)) #define GSD_SHARING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SHARING_MANAGER, GsdSharingManagerClass)) #define GSD_IS_SHARING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SHARING_MANAGER)) #define GSD_IS_SHARING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SHARING_MANAGER)) #define GSD_SHARING_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SHARING_MANAGER, GsdSharingManagerClass)) typedef struct GsdSharingManagerPrivate GsdSharingManagerPrivate; typedef struct { GObject parent; GsdSharingManagerPrivate *priv; } GsdSharingManager; typedef struct { GObjectClass parent_class; } GsdSharingManagerClass; GType gsd_sharing_manager_get_type (void); GsdSharingManager * gsd_sharing_manager_new (void); gboolean gsd_sharing_manager_start (GsdSharingManager *manager, GError **error); void gsd_sharing_manager_stop (GsdSharingManager *manager); G_END_DECLS #endif /* __GSD_SHARING_MANAGER_H */ unity-settings-daemon/plugins/sharing/gsd-sharing-plugin.c0000664000000000000000000000171615172222611021203 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-sharing-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdSharing, gsd_sharing) unity-settings-daemon/plugins/sharing/sharing.gnome-settings-plugin.in0000664000000000000000000000032415172222611023550 0ustar [GNOME Settings Plugin] Module=sharing IAge=0 # 100 is the default load Priority Priority=100 Name=Sharing Description=Sharing plugin Authors=Bastien Nocera Copyright=Copyright © 2014 AUTHOR unity-settings-daemon/plugins/sharing/test-sharing.c0000664000000000000000000000031715172222611020105 0ustar #define NEW gsd_sharing_manager_new #define START gsd_sharing_manager_start #define STOP gsd_sharing_manager_stop #define MANAGER GsdSharingManager #include "gsd-sharing-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/smartcard/0000775000000000000000000000000015172222611015655 5ustar unity-settings-daemon/plugins/smartcard/Makefile.am0000664000000000000000000000326415172222611017716 0ustar plugin_name = smartcard libexec_PROGRAMS = usd-test-smartcard usd_test_smartcard_SOURCES = \ gsd-smartcard-manager.h \ gsd-smartcard-manager.c \ gsd-smartcard.h \ gsd-smartcard.c \ test-smartcard.c usd_test_smartcard_CFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(NSS_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_smartcard_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(NSS_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = \ libsmartcard.la libsmartcard_la_SOURCES = \ gsd-smartcard-plugin.h \ gsd-smartcard-plugin.c \ gsd-smartcard.h \ gsd-smartcard.c \ gsd-smartcard-manager.h \ gsd-smartcard-manager.c libsmartcard_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \ $(AM_CPPFLAGS) libsmartcard_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(NSS_CFLAGS) \ $(AM_CFLAGS) libsmartcard_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libsmartcard_la_LIBADD = \ $(SETTINGS_PLUGIN_LIBS) \ $(NSS_LIBS) @GSD_INTLTOOL_PLUGIN_RULE@ plugin_in_files = \ smartcard.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) unity-settings-daemon/plugins/smartcard/gsd-smartcard-manager.c0000664000000000000000000014362515172222611022177 0ustar /* gsd-smartcard-manager.c - object for monitoring smartcard insertion and * removal events * * Copyright (C) 2006, 2009 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Written By: Ray Strode */ #include "config.h" #include "gsd-smartcard-manager.h" #define SMARTCARD_ENABLE_INTERNAL_API #include "gsd-smartcard.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef GSD_SMARTCARD_MANAGER_DRIVER #define GSD_SMARTCARD_MANAGER_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so" #endif #ifndef GSD_SMARTCARD_MANAGER_NSS_DB #define GSD_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb" #endif #ifndef GSD_MAX_OPEN_FILE_DESCRIPTORS #define GSD_MAX_OPEN_FILE_DESCRIPTORS 1024 #endif #ifndef GSD_OPEN_FILE_DESCRIPTORS_DIR #define GSD_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd" #endif typedef enum _GsdSmartcardManagerState GsdSmartcardManagerState; typedef struct _GsdSmartcardManagerWorker GsdSmartcardManagerWorker; enum _GsdSmartcardManagerState { GSD_SMARTCARD_MANAGER_STATE_STOPPED = 0, GSD_SMARTCARD_MANAGER_STATE_STARTING, GSD_SMARTCARD_MANAGER_STATE_STARTED, GSD_SMARTCARD_MANAGER_STATE_STOPPING, }; struct _GsdSmartcardManagerPrivate { GsdSmartcardManagerState state; GList *modules; char *module_path; GList *workers; GPid smartcard_event_watcher_pid; GHashTable *smartcards; guint poll_timeout_id; guint32 is_unstoppable : 1; guint32 nss_is_loaded : 1; }; struct _GsdSmartcardManagerWorker { GsdSmartcardManager *manager; int manager_fd; GThread *thread; SECMODModule *module; GHashTable *smartcards; int fd; GSource *event_source; guint32 nss_is_loaded : 1; }; static void gsd_smartcard_manager_finalize (GObject *object); static void gsd_smartcard_manager_class_install_signals (GsdSmartcardManagerClass *service_class); static void gsd_smartcard_manager_class_install_properties (GsdSmartcardManagerClass *service_class); static void gsd_smartcard_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gsd_smartcard_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gsd_smartcard_manager_set_module_path (GsdSmartcardManager *manager, const char *module_path); static void gsd_smartcard_manager_card_removed_handler (GsdSmartcardManager *manager, GsdSmartcard *card); static void gsd_smartcard_manager_card_inserted_handler (GsdSmartcardManager *manager_class, GsdSmartcard *card); static gboolean gsd_smartcard_manager_stop_now (GsdSmartcardManager *manager); static void gsd_smartcard_manager_queue_stop (GsdSmartcardManager *manager); static GsdSmartcardManagerWorker *gsd_smartcard_manager_create_worker (GsdSmartcardManager *manager, SECMODModule *module); static GsdSmartcardManagerWorker * gsd_smartcard_manager_worker_new (GsdSmartcardManager *manager, int worker_fd, int manager_fd, SECMODModule *module); static void gsd_smartcard_manager_worker_free (GsdSmartcardManagerWorker *worker); static gboolean open_pipe (int *write_fd, int *read_fd); static gboolean read_bytes (int fd, gpointer bytes, gsize num_bytes); static gboolean write_bytes (int fd, gconstpointer bytes, gsize num_bytes); static GsdSmartcard *read_smartcard (int fd, SECMODModule *module); static gboolean write_smartcard (int fd, GsdSmartcard *card); enum { PROP_0 = 0, PROP_MODULE_PATH, NUMBER_OF_PROPERTIES }; enum { SMARTCARD_INSERTED = 0, SMARTCARD_REMOVED, ERROR, NUMBER_OF_SIGNALS }; static guint gsd_smartcard_manager_signals[NUMBER_OF_SIGNALS]; G_DEFINE_TYPE (GsdSmartcardManager, gsd_smartcard_manager, G_TYPE_OBJECT); static void gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *manager_class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (manager_class); gobject_class->finalize = gsd_smartcard_manager_finalize; gsd_smartcard_manager_class_install_signals (manager_class); gsd_smartcard_manager_class_install_properties (manager_class); g_type_class_add_private (manager_class, sizeof (GsdSmartcardManagerPrivate)); } static void gsd_smartcard_manager_class_install_properties (GsdSmartcardManagerClass *card_class) { GObjectClass *object_class; GParamSpec *param_spec; object_class = G_OBJECT_CLASS (card_class); object_class->set_property = gsd_smartcard_manager_set_property; object_class->get_property = gsd_smartcard_manager_get_property; param_spec = g_param_spec_string ("module-path", "Module Path", "path to smartcard PKCS #11 driver", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec); } static void gsd_smartcard_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GsdSmartcardManager *manager = GSD_SMARTCARD_MANAGER (object); switch (prop_id) { case PROP_MODULE_PATH: gsd_smartcard_manager_set_module_path (manager, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gsd_smartcard_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GsdSmartcardManager *manager = GSD_SMARTCARD_MANAGER (object); char *module_path; switch (prop_id) { case PROP_MODULE_PATH: module_path = gsd_smartcard_manager_get_module_path (manager); g_value_set_string (value, module_path); g_free (module_path); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } char * gsd_smartcard_manager_get_module_path (GsdSmartcardManager *manager) { return manager->priv->module_path; } static void gsd_smartcard_manager_set_module_path (GsdSmartcardManager *manager, const char *module_path) { if ((manager->priv->module_path == NULL) && (module_path == NULL)) { return; } if (((manager->priv->module_path == NULL) || (module_path == NULL) || (strcmp (manager->priv->module_path, module_path) != 0))) { g_free (manager->priv->module_path); manager->priv->module_path = g_strdup (module_path); g_object_notify (G_OBJECT (manager), "module-path"); } } static void gsd_smartcard_manager_card_removed_handler (GsdSmartcardManager *manager, GsdSmartcard *card) { g_debug ("informing smartcard of its removal"); _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED); g_debug ("done"); } static void gsd_smartcard_manager_card_inserted_handler (GsdSmartcardManager *manager, GsdSmartcard *card) { g_debug ("informing smartcard of its insertion"); _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED); g_debug ("done"); } static void gsd_smartcard_manager_class_install_signals (GsdSmartcardManagerClass *manager_class) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (manager_class); gsd_smartcard_manager_signals[SMARTCARD_INSERTED] = g_signal_new ("smartcard-inserted", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GsdSmartcardManagerClass, smartcard_inserted), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); manager_class->smartcard_inserted = gsd_smartcard_manager_card_inserted_handler; gsd_smartcard_manager_signals[SMARTCARD_REMOVED] = g_signal_new ("smartcard-removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GsdSmartcardManagerClass, smartcard_removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); manager_class->smartcard_removed = gsd_smartcard_manager_card_removed_handler; gsd_smartcard_manager_signals[ERROR] = g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdSmartcardManagerClass, error), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); manager_class->error = NULL; } static gboolean slot_id_equal (CK_SLOT_ID *slot_id_1, CK_SLOT_ID *slot_id_2) { g_assert (slot_id_1 != NULL); g_assert (slot_id_2 != NULL); return *slot_id_1 == *slot_id_2; } static gboolean slot_id_hash (CK_SLOT_ID *slot_id) { guint32 upper_bits, lower_bits; int temp; if (sizeof (CK_SLOT_ID) == sizeof (int)) { return g_int_hash (slot_id); } upper_bits = ((*slot_id) >> 31) - 1; lower_bits = (*slot_id) & 0xffffffff; /* The upper bits are almost certainly always zero, * so let's degenerate to g_int_hash for the * (very) common case */ temp = lower_bits + upper_bits; return upper_bits + g_int_hash (&temp); } static void gsd_smartcard_manager_init (GsdSmartcardManager *manager) { g_debug ("initializing smartcard manager"); manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerPrivate); manager->priv->poll_timeout_id = 0; manager->priv->is_unstoppable = FALSE; manager->priv->smartcards = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref); } static void gsd_smartcard_manager_finalize (GObject *object) { GsdSmartcardManager *manager; GObjectClass *gobject_class; manager = GSD_SMARTCARD_MANAGER (object); gobject_class = G_OBJECT_CLASS (gsd_smartcard_manager_parent_class); gsd_smartcard_manager_stop_now (manager); g_hash_table_destroy (manager->priv->smartcards); manager->priv->smartcards = NULL; gobject_class->finalize (object); } GQuark gsd_smartcard_manager_error_quark (void) { static GQuark error_quark = 0; if (error_quark == 0) { error_quark = g_quark_from_static_string ("gsd-smartcard-manager-error-quark"); } return error_quark; } GsdSmartcardManager * gsd_smartcard_manager_new_default (void) { return gsd_smartcard_manager_new (NULL); } GsdSmartcardManager * gsd_smartcard_manager_new (const char *module_path) { GsdSmartcardManager *instance; instance = GSD_SMARTCARD_MANAGER (g_object_new (GSD_TYPE_SMARTCARD_MANAGER, "module-path", module_path, NULL)); return instance; } static void gsd_smartcard_manager_emit_error (GsdSmartcardManager *manager, GError *error) { manager->priv->is_unstoppable = TRUE; g_signal_emit (manager, gsd_smartcard_manager_signals[ERROR], 0, error); manager->priv->is_unstoppable = FALSE; } static void gsd_smartcard_manager_emit_smartcard_inserted (GsdSmartcardManager *manager, GsdSmartcard *card) { manager->priv->is_unstoppable = TRUE; g_signal_emit (manager, gsd_smartcard_manager_signals[SMARTCARD_INSERTED], 0, card); manager->priv->is_unstoppable = FALSE; } static void gsd_smartcard_manager_emit_smartcard_removed (GsdSmartcardManager *manager, GsdSmartcard *card) { manager->priv->is_unstoppable = TRUE; g_signal_emit (manager, gsd_smartcard_manager_signals[SMARTCARD_REMOVED], 0, card); manager->priv->is_unstoppable = FALSE; } static gboolean gsd_smartcard_manager_check_for_and_process_events (GIOChannel *io_channel, GIOCondition condition, GsdSmartcardManagerWorker *worker) { GsdSmartcard *card; GsdSmartcardManager *manager; gboolean should_stop; guchar event_type; char *card_name; int fd; manager = worker->manager; g_debug ("event!"); card = NULL; should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR); if (should_stop) { g_debug ("received %s on event socket, stopping " "manager...", (condition & G_IO_HUP) && (condition & G_IO_ERR)? "error and hangup" : (condition & G_IO_HUP)? "hangup" : "error"); } if (!(condition & G_IO_IN)) { g_debug ("nevermind outta here!"); goto out; } fd = g_io_channel_unix_get_fd (io_channel); event_type = '\0'; if (!read_bytes (fd, &event_type, 1)) { g_debug ("could not read event type, stopping"); should_stop = TRUE; goto out; } card = read_smartcard (fd, worker->module); if (card == NULL) { g_debug ("could not read card, stopping"); should_stop = TRUE; goto out; } card_name = gsd_smartcard_get_name (card); g_debug ("card '%s' had event %c", card_name, event_type); switch (event_type) { case 'I': g_hash_table_replace (manager->priv->smartcards, card_name, card); card_name = NULL; gsd_smartcard_manager_emit_smartcard_inserted (manager, card); card = NULL; break; case 'R': gsd_smartcard_manager_emit_smartcard_removed (manager, card); if (!g_hash_table_remove (manager->priv->smartcards, card_name)) { g_debug ("got removal event of unknown card!"); } g_free (card_name); card_name = NULL; card = NULL; break; default: g_free (card_name); card_name = NULL; g_object_unref (card); should_stop = TRUE; break; } out: if (should_stop) { GError *error; error = g_error_new (GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source")); gsd_smartcard_manager_emit_error (manager, error); g_error_free (error); gsd_smartcard_manager_stop_now (manager); return FALSE; } return TRUE; } static void stop_manager (GsdSmartcardManager *manager) { manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STOPPED; if (manager->priv->nss_is_loaded) { NSS_Shutdown (); manager->priv->nss_is_loaded = FALSE; } g_debug ("smartcard manager stopped"); } static void stop_worker (GsdSmartcardManagerWorker *worker) { GsdSmartcardManager *manager; manager = worker->manager; if (worker->event_source != NULL) { g_source_destroy (worker->event_source); worker->event_source = NULL; } if (worker->thread != NULL) { SECMOD_CancelWait (worker->module); worker->thread = NULL; } SECMOD_DestroyModule (worker->module); manager->priv->workers = g_list_remove (manager->priv->workers, worker); if (manager->priv->workers == NULL && manager->priv->state != GSD_SMARTCARD_MANAGER_STATE_STOPPED) { stop_manager (manager); } } static void gsd_smartcard_manager_event_processing_stopped_handler (GsdSmartcardManagerWorker *worker) { worker->event_source = NULL; stop_worker (worker); } static gboolean open_pipe (int *write_fd, int *read_fd) { int pipe_fds[2] = { -1, -1 }; g_assert (write_fd != NULL); g_assert (read_fd != NULL); if (pipe (pipe_fds) < 0) { return FALSE; } if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) { close (pipe_fds[0]); close (pipe_fds[1]); return FALSE; } if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) { close (pipe_fds[0]); close (pipe_fds[1]); return FALSE; } *read_fd = pipe_fds[0]; *write_fd = pipe_fds[1]; return TRUE; } static void gsd_smartcard_manager_stop_watching_for_events (GsdSmartcardManager *manager) { GList *node; node = manager->priv->workers; while (node != NULL) { GsdSmartcardManagerWorker *worker; GList *next_node; worker = (GsdSmartcardManagerWorker *) node->data; next_node = node->next; stop_worker (worker); node = next_node; } } static gboolean load_nss (GError **error) { SECStatus status = SECSuccess; static const guint32 flags = NSS_INIT_READONLY | NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD; g_debug ("attempting to load NSS database '%s'", GSD_SMARTCARD_MANAGER_NSS_DB); PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); status = NSS_Initialize (GSD_SMARTCARD_MANAGER_NSS_DB, "", "", SECMOD_DB, flags); if (status != SECSuccess) { gsize error_message_size; char *error_message; error_message_size = PR_GetErrorTextLength (); if (error_message_size == 0) { g_debug ("NSS security system could not be initialized"); g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, _("NSS security system could not be initialized")); goto out; } error_message = g_slice_alloc0 (error_message_size); PR_GetErrorText (error_message); g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, "%s", error_message); g_debug ("NSS security system could not be initialized - %s", error_message); g_slice_free1 (error_message_size, error_message); goto out; } g_debug ("NSS database sucessfully loaded"); return TRUE; out: g_debug ("NSS database couldn't be sucessfully loaded"); return FALSE; } static GList * get_available_modules (GsdSmartcardManager *manager) { SECMODModuleList *module_list, *tmp; GList *modules; g_debug ("Getting list of suitable modules"); module_list = SECMOD_GetDefaultModuleList (); modules = NULL; for (tmp = module_list; tmp != NULL; tmp = tmp->next) { if (!SECMOD_HasRemovableSlots (tmp->module) || !tmp->module->loaded) continue; g_debug ("Using module '%s'", tmp->module->commonName); modules = g_list_prepend (modules, SECMOD_ReferenceModule (tmp->module)); } return modules; } static gboolean load_driver (GsdSmartcardManager *manager, char *module_path, GError **error) { GList *modules; char *module_spec; gboolean module_explicitly_specified; g_debug ("attempting to load driver..."); modules = NULL; module_explicitly_specified = module_path != NULL; if (module_explicitly_specified) { SECMODModule *module; module_spec = g_strdup_printf ("library=\"%s\"", module_path); g_debug ("loading smartcard driver using spec '%s'", module_spec); module = SECMOD_LoadUserModule (module_spec, NULL /* parent */, FALSE /* recurse */); g_free (module_spec); module_spec = NULL; if (SECMOD_HasRemovableSlots (module) && module->loaded) { modules = g_list_prepend (modules, module); } else { g_debug ("fallback module found but not %s", SECMOD_HasRemovableSlots (module)? "removable" : "loaded"); SECMOD_DestroyModule (module); } } else { SECMODListLock *lock; lock = SECMOD_GetDefaultModuleListLock (); if (lock != NULL) { SECMOD_GetReadLock (lock); modules = get_available_modules (manager); SECMOD_ReleaseReadLock (lock); } /* fallback to compiled in driver path */ if (modules == NULL) { SECMODModule *module; module_path = GSD_SMARTCARD_MANAGER_DRIVER; module_spec = g_strdup_printf ("library=\"%s\"", module_path); g_debug ("loading smartcard driver using spec '%s'", module_spec); module = SECMOD_LoadUserModule (module_spec, NULL /* parent */, FALSE /* recurse */); g_free (module_spec); module_spec = NULL; if (SECMOD_HasRemovableSlots (module) && module->loaded) { modules = g_list_prepend (modules, module); } else { g_debug ("fallback module found but not loaded"); SECMOD_DestroyModule (module); } } } if (!module_explicitly_specified && modules == NULL) { g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, _("no suitable smartcard driver could be found")); } else if (modules == NULL) { gsize error_message_size; char *error_message; error_message_size = PR_GetErrorTextLength (); if (error_message_size == 0) { g_debug ("smartcard driver '%s' could not be loaded", module_path); g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, _("smartcard driver '%s' could not be " "loaded"), module_path); goto out; } error_message = g_slice_alloc0 (error_message_size); PR_GetErrorText (error_message); g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, "%s", error_message); g_debug ("smartcard driver '%s' could not be loaded - %s", module_path, error_message); g_slice_free1 (error_message_size, error_message); } manager->priv->modules = modules; out: return manager->priv->modules != NULL; } static void gsd_smartcard_manager_get_all_cards (GsdSmartcardManager *manager) { GList *node; int i; node = manager->priv->workers; while (node != NULL) { GsdSmartcardManagerWorker *worker; worker = (GsdSmartcardManagerWorker *) node->data; for (i = 0; i < worker->module->slotCount; i++) { GsdSmartcard *card; CK_SLOT_ID slot_id; int slot_series; char *card_name; slot_id = PK11_GetSlotID (worker->module->slots[i]); slot_series = PK11_GetSlotSeries (worker->module->slots[i]); card = _gsd_smartcard_new (worker->module, slot_id, slot_series); card_name = gsd_smartcard_get_name (card); g_hash_table_replace (manager->priv->smartcards, card_name, card); } node = node->next; } } static GsdSmartcardManagerWorker * start_worker (GsdSmartcardManager *manager, SECMODModule *module, GError **error) { GIOChannel *io_channel; GSource *source; GsdSmartcardManagerWorker *worker; worker = gsd_smartcard_manager_create_worker (manager, module); if (worker == NULL) { g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, _("could not watch for incoming card events - %s"), g_strerror (errno)); goto out; } io_channel = g_io_channel_unix_new (worker->manager_fd); source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP); g_io_channel_unref (io_channel); io_channel = NULL; worker->event_source = source; g_source_set_callback (worker->event_source, (GSourceFunc) (GIOFunc) gsd_smartcard_manager_check_for_and_process_events, worker, (GDestroyNotify) gsd_smartcard_manager_event_processing_stopped_handler); g_source_attach (worker->event_source, NULL); g_source_unref (worker->event_source); out: return worker; } static void start_workers (GsdSmartcardManager *manager) { GList *node; node = manager->priv->modules; while (node != NULL) { SECMODModule *module; GsdSmartcardManagerWorker *worker; GError *error; module = (SECMODModule *) node->data; error = NULL; worker = start_worker (manager, module, &error); if (worker == NULL) { g_warning ("%s", error->message); g_error_free (error); } else { manager->priv->workers = g_list_prepend (manager->priv->workers, worker); } node = node->next; } } gboolean gsd_smartcard_manager_start (GsdSmartcardManager *manager, GError **error) { GError *nss_error; if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STARTED) { g_debug ("smartcard manager already started"); return TRUE; } manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STARTING; nss_error = NULL; if (!manager->priv->nss_is_loaded && !load_nss (&nss_error)) { g_propagate_error (error, nss_error); goto out; } manager->priv->nss_is_loaded = TRUE; if (manager->priv->modules == NULL) { if (!load_driver (manager, manager->priv->module_path, &nss_error)) { g_propagate_error (error, nss_error); goto out; } } start_workers (manager); /* populate the hash with cards that are already inserted */ gsd_smartcard_manager_get_all_cards (manager); manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STARTED; out: /* don't leave it in a half started state */ if (manager->priv->state != GSD_SMARTCARD_MANAGER_STATE_STARTED) { g_debug ("smartcard manager could not be completely started"); gsd_smartcard_manager_stop (manager); } else { g_debug ("smartcard manager started"); } return manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STARTED; } static gboolean gsd_smartcard_manager_stop_now (GsdSmartcardManager *manager) { if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STOPPED) { return FALSE; } gsd_smartcard_manager_stop_watching_for_events (manager); return FALSE; } static void gsd_smartcard_manager_queue_stop (GsdSmartcardManager *manager) { manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STOPPING; g_idle_add ((GSourceFunc) gsd_smartcard_manager_stop_now, manager); } void gsd_smartcard_manager_stop (GsdSmartcardManager *manager) { if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STOPPED) { return; } if (manager->priv->is_unstoppable) { gsd_smartcard_manager_queue_stop (manager); return; } gsd_smartcard_manager_stop_now (manager); } static void gsd_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id, GsdSmartcard *card, gboolean *is_inserted) { g_assert (is_inserted != NULL); if (gsd_smartcard_is_login_card (card)) { *is_inserted = TRUE; } } gboolean gsd_smartcard_manager_login_card_is_inserted (GsdSmartcardManager *manager) { gboolean is_inserted; is_inserted = FALSE; g_hash_table_foreach (manager->priv->smartcards, (GHFunc) gsd_smartcard_manager_check_for_login_card, &is_inserted); return is_inserted; } static GsdSmartcardManagerWorker * gsd_smartcard_manager_worker_new (GsdSmartcardManager *manager, int worker_fd, int manager_fd, SECMODModule *module) { GsdSmartcardManagerWorker *worker; worker = g_slice_new0 (GsdSmartcardManagerWorker); worker->manager = manager; worker->fd = worker_fd; worker->manager_fd = manager_fd; worker->module = module; worker->smartcards = g_hash_table_new_full ((GHashFunc) slot_id_hash, (GEqualFunc) slot_id_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref); return worker; } static void gsd_smartcard_manager_worker_free (GsdSmartcardManagerWorker *worker) { if (worker->smartcards != NULL) { g_hash_table_destroy (worker->smartcards); worker->smartcards = NULL; } g_slice_free (GsdSmartcardManagerWorker, worker); } static gboolean read_bytes (int fd, gpointer bytes, gsize num_bytes) { size_t bytes_left; size_t total_bytes_read; ssize_t bytes_read; bytes_left = (size_t) num_bytes; total_bytes_read = 0; do { bytes_read = read (fd, (char *) bytes + total_bytes_read, bytes_left); g_assert (bytes_read <= (ssize_t) bytes_left); if (bytes_read <= 0) { if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN)) { continue; } bytes_left = 0; } else { bytes_left -= bytes_read; total_bytes_read += bytes_read; } } while (bytes_left > 0); if (total_bytes_read < (size_t) num_bytes) { return FALSE; } return TRUE; } static gboolean write_bytes (int fd, gconstpointer bytes, gsize num_bytes) { size_t bytes_left; size_t total_bytes_written; ssize_t bytes_written; bytes_left = (size_t) num_bytes; total_bytes_written = 0; do { bytes_written = write (fd, (char *) bytes + total_bytes_written, bytes_left); g_assert (bytes_written <= (ssize_t) bytes_left); if (bytes_written <= 0) { if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN)) { continue; } bytes_left = 0; } else { bytes_left -= bytes_written; total_bytes_written += bytes_written; } } while (bytes_left > 0); if (total_bytes_written < (size_t) num_bytes) { return FALSE; } return TRUE; } static GsdSmartcard * read_smartcard (int fd, SECMODModule *module) { GsdSmartcard *card; char *card_name; gsize card_name_size; card_name_size = 0; if (!read_bytes (fd, &card_name_size, sizeof (card_name_size))) { return NULL; } card_name = g_slice_alloc0 (card_name_size); if (!read_bytes (fd, card_name, card_name_size)) { g_slice_free1 (card_name_size, card_name); return NULL; } card = _gsd_smartcard_new_from_name (module, card_name); g_slice_free1 (card_name_size, card_name); return card; } static gboolean write_smartcard (int fd, GsdSmartcard *card) { gsize card_name_size; char *card_name; card_name = gsd_smartcard_get_name (card); card_name_size = strlen (card_name) + 1; if (!write_bytes (fd, &card_name_size, sizeof (card_name_size))) { g_free (card_name); return FALSE; } if (!write_bytes (fd, card_name, card_name_size)) { g_free (card_name); return FALSE; } g_free (card_name); return TRUE; } static gboolean gsd_smartcard_manager_worker_emit_smartcard_removed (GsdSmartcardManagerWorker *worker, GsdSmartcard *card, GError **error) { g_debug ("card '%s' removed!", gsd_smartcard_get_name (card)); if (!write_bytes (worker->fd, "R", 1)) { goto error_out; } if (!write_smartcard (worker->fd, card)) { goto error_out; } return TRUE; error_out: g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, "%s", g_strerror (errno)); return FALSE; } static gboolean gsd_smartcard_manager_worker_emit_smartcard_inserted (GsdSmartcardManagerWorker *worker, GsdSmartcard *card, GError **error) { g_debug ("card '%s' inserted!", gsd_smartcard_get_name (card)); if (!write_bytes (worker->fd, "I", 1)) { goto error_out; } if (!write_smartcard (worker->fd, card)) { goto error_out; } return TRUE; error_out: g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, "%s", g_strerror (errno)); return FALSE; } static gboolean gsd_smartcard_manager_worker_watch_for_and_process_event (GsdSmartcardManagerWorker *worker, GError **error) { PK11SlotInfo *slot; CK_SLOT_ID slot_id, *key = NULL; int slot_series, card_slot_series; GsdSmartcard *card; GError *processing_error; gboolean ret; g_debug ("waiting for card event"); ret = FALSE; slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1)); processing_error = NULL; if (slot == NULL) { int error_code; error_code = PORT_GetError (); if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) { g_debug ("spurrious event occurred"); return TRUE; } /* FIXME: is there a function to convert from a PORT error * code to a translated string? */ g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, _("encountered unexpected error while " "waiting for smartcard events")); goto out; } /* the slot id and series together uniquely identify a card. * You can never have two cards with the same slot id at the * same time, however (I think), so we can key off of it. */ slot_id = PK11_GetSlotID (slot); slot_series = PK11_GetSlotSeries (slot); /* First check to see if there is a card that we're currently * tracking in the slot. */ key = g_new (CK_SLOT_ID, 1); *key = slot_id; card = g_hash_table_lookup (worker->smartcards, key); if (card != NULL) { card_slot_series = gsd_smartcard_get_slot_series (card); } else { card_slot_series = -1; } if (PK11_IsPresent (slot)) { /* Now, check to see if their is a new card in the slot. * If there was a different card in the slot now than * there was before, then we need to emit a removed signal * for the old card (we don't want unpaired insertion events). */ if ((card != NULL) && card_slot_series != slot_series) { if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { g_propagate_error (error, processing_error); goto out; } } card = _gsd_smartcard_new (worker->module, slot_id, slot_series); g_hash_table_replace (worker->smartcards, key, card); key = NULL; if (!gsd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { g_propagate_error (error, processing_error); goto out; } } else { /* if we aren't tracking the card, just discard the event. * We don't want unpaired remove events. Note on startup * NSS will generate an "insertion" event if a card is * already inserted in the slot. */ if ((card != NULL)) { /* FIXME: i'm not sure about this code. Maybe we * shouldn't do this at all, or maybe we should do it * n times (where n = slot_series - card_slot_series + 1) * * Right now, i'm just doing it once. */ if ((slot_series - card_slot_series) > 1) { if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { g_propagate_error (error, processing_error); goto out; } g_hash_table_remove (worker->smartcards, key); card = _gsd_smartcard_new (worker->module, slot_id, slot_series); g_hash_table_replace (worker->smartcards, key, card); key = NULL; if (!gsd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { g_propagate_error (error, processing_error); goto out; } } if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { g_propagate_error (error, processing_error); goto out; } g_hash_table_remove (worker->smartcards, key); card = NULL; } else { g_debug ("got spurious remove event"); } } ret = TRUE; out: g_free (key); PK11_FreeSlot (slot); return ret; } static void gsd_smartcard_manager_worker_run (GsdSmartcardManagerWorker *worker) { GError *error; gboolean should_continue; do { error = NULL; should_continue = gsd_smartcard_manager_worker_watch_for_and_process_event (worker, &error); } while (should_continue); if (error != NULL) { g_debug ("could not process card event - %s", error->message); g_error_free (error); } gsd_smartcard_manager_worker_free (worker); } static GsdSmartcardManagerWorker * gsd_smartcard_manager_create_worker (GsdSmartcardManager *manager, SECMODModule *module) { GsdSmartcardManagerWorker *worker; int write_fd, read_fd; write_fd = -1; read_fd = -1; if (!open_pipe (&write_fd, &read_fd)) { return NULL; } worker = gsd_smartcard_manager_worker_new (manager, write_fd, read_fd, module); worker->thread = g_thread_create ((GThreadFunc) gsd_smartcard_manager_worker_run, worker, FALSE, NULL); if (worker->thread == NULL) { gsd_smartcard_manager_worker_free (worker); return NULL; } return worker; } #ifdef GSD_SMARTCARD_MANAGER_ENABLE_TEST #include static GMainLoop *event_loop; static gboolean should_exit_on_next_remove = FALSE; static gboolean on_timeout (GsdSmartcardManager *manager) { GError *error; g_print ("Re-enabling manager.\n"); if (!gsd_smartcard_manager_start (manager, &error)) { g_warning ("could not start smartcard manager - %s", error->message); g_error_free (error); return TRUE; } g_print ("Please re-insert smartcard\n"); should_exit_on_next_remove = TRUE; return FALSE; } static void on_device_inserted (GsdSmartcardManager *manager, GsdSmartcard *card) { g_print ("smartcard inserted!\n"); g_print ("Please remove it.\n"); } static void on_device_removed (GsdSmartcardManager *manager, GsdSmartcard *card) { g_print ("smartcard removed!\n"); if (should_exit_on_next_remove) { g_main_loop_quit (event_loop); } else { g_print ("disabling manager for 2 seconds\n"); gsd_smartcard_manager_stop (manager); g_timeout_add_seconds (2, (GSourceFunc) on_timeout, manager); } } int main (int argc, char *argv[]) { GsdSmartcardManager *manager; GError *error; g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); g_message ("creating instance of 'smartcard manager' object..."); manager = gsd_smartcard_manager_new (NULL); g_message ("'smartcard manager' object created successfully"); g_signal_connect (manager, "smartcard-inserted", G_CALLBACK (on_device_inserted), NULL); g_signal_connect (manager, "smartcard-removed", G_CALLBACK (on_device_removed), NULL); g_message ("starting listener..."); error = NULL; if (!gsd_smartcard_manager_start (manager, &error)) { g_warning ("could not start smartcard manager - %s", error->message); g_error_free (error); return 1; } event_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (event_loop); g_main_loop_unref (event_loop); event_loop = NULL; g_message ("destroying previously created 'smartcard manager' object..."); g_object_unref (manager); manager = NULL; g_message ("'smartcard manager' object destroyed successfully"); return 0; } #endif unity-settings-daemon/plugins/smartcard/gsd-smartcard-manager.h0000664000000000000000000000716015172222611022175 0ustar /* gsd-smartcard-manager.h - object for monitoring smartcard insertion and * removal events * * Copyright (C) 2006, 2009 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Written by: Ray Strode */ #ifndef GSD_SMARTCARD_MANAGER_H #define GSD_SMARTCARD_MANAGER_H #define GSD_SMARTCARD_ENABLE_INTERNAL_API #include "gsd-smartcard.h" #include #include G_BEGIN_DECLS #define GSD_TYPE_SMARTCARD_MANAGER (gsd_smartcard_manager_get_type ()) #define GSD_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManager)) #define GSD_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass)) #define GSD_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER)) #define GSD_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER)) #define GSD_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass)) #define GSD_SMARTCARD_MANAGER_ERROR (gsd_smartcard_manager_error_quark ()) typedef struct _GsdSmartcardManager GsdSmartcardManager; typedef struct _GsdSmartcardManagerClass GsdSmartcardManagerClass; typedef struct _GsdSmartcardManagerPrivate GsdSmartcardManagerPrivate; typedef enum _GsdSmartcardManagerError GsdSmartcardManagerError; struct _GsdSmartcardManager { GObject parent; /*< private > */ GsdSmartcardManagerPrivate *priv; }; struct _GsdSmartcardManagerClass { GObjectClass parent_class; /* Signals */ void (*smartcard_inserted) (GsdSmartcardManager *manager, GsdSmartcard *token); void (*smartcard_removed) (GsdSmartcardManager *manager, GsdSmartcard *token); void (*error) (GsdSmartcardManager *manager, GError *error); }; enum _GsdSmartcardManagerError { GSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0, GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS }; GType gsd_smartcard_manager_get_type (void) G_GNUC_CONST; GQuark gsd_smartcard_manager_error_quark (void) G_GNUC_CONST; GsdSmartcardManager *gsd_smartcard_manager_new_default (void); GsdSmartcardManager *gsd_smartcard_manager_new (const char *module); gboolean gsd_smartcard_manager_start (GsdSmartcardManager *manager, GError **error); void gsd_smartcard_manager_stop (GsdSmartcardManager *manager); char *gsd_smartcard_manager_get_module_path (GsdSmartcardManager *manager); gboolean gsd_smartcard_manager_login_card_is_inserted (GsdSmartcardManager *manager); G_END_DECLS #endif /* GSD_SMARTCARD_MANAGER_H */ unity-settings-daemon/plugins/smartcard/gsd-smartcard-plugin.c0000664000000000000000000002405215172222611022053 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include "gnome-settings-plugin.h" #include "gnome-settings-bus.h" #include "gsd-smartcard-plugin.h" #include "gsd-smartcard-manager.h" struct GsdSmartcardPluginPrivate { GsdSmartcardManager *manager; guint32 is_active : 1; }; typedef enum { GSD_SMARTCARD_REMOVE_ACTION_NONE, GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN, GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT, } GsdSmartcardRemoveAction; #define SM_LOGOUT_MODE_FORCE 2 #define KEY_REMOVE_ACTION "removal-action" #define GSD_SMARTCARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginPrivate)) GNOME_SETTINGS_PLUGIN_REGISTER (GsdSmartcardPlugin, gsd_smartcard_plugin); static void simulate_user_activity (GsdSmartcardPlugin *plugin) { GsdScreenSaver *screensaver_proxy; GDBusProxy *screensaver_proxy; g_debug ("GsdSmartcardPlugin telling screensaver about smart card insertion"); screensaver_proxy = gnome_settings_bus_get_screen_saver_proxy (); gsd_screen_saver_call_simulate_user_activity_sync (screensaver_proxy, NULL, NULL); g_object_unref (screensaver_proxy); } static void lock_screen (GsdSmartcardPlugin *plugin) { GDBusProxy *screensaver_proxy; g_debug ("GsdSmartcardPlugin telling screensaver to lock screen"); screensaver_proxy = gnome_settings_bus_get_screen_saver_proxy (); gsd_screen_saver_call_lock_sync (screensaver_proxy, NULL, NULL); g_object_unref (screensaver_proxy); } static void force_logout (GsdSmartcardPlugin *plugin) { GDBusProxy *sm_proxy; GError *error; GVariant *res; g_debug ("GsdSmartcardPlugin telling session manager to force logout"); sm_proxy = gnome_settings_bus_get_session_proxy (); error = NULL; res = g_dbus_proxy_call_sync (sm_proxy, "Logout", g_variant_new ("(i)", SM_LOGOUT_MODE_FORCE), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (! res) { g_warning ("GsdSmartcardPlugin Unable to force logout: %s", error->message); g_error_free (error); } else g_variant_unref (res); g_object_unref (sm_proxy); } static void gsd_smartcard_plugin_init (GsdSmartcardPlugin *plugin) { plugin->priv = GSD_SMARTCARD_PLUGIN_GET_PRIVATE (plugin); g_debug ("GsdSmartcardPlugin initializing"); plugin->priv->manager = gsd_smartcard_manager_new (NULL); } static void gsd_smartcard_plugin_finalize (GObject *object) { GsdSmartcardPlugin *plugin; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_SMARTCARD_PLUGIN (object)); g_debug ("GsdSmartcardPlugin finalizing"); plugin = GSD_SMARTCARD_PLUGIN (object); g_return_if_fail (plugin->priv != NULL); if (plugin->priv->manager != NULL) { g_object_unref (plugin->priv->manager); } G_OBJECT_CLASS (gsd_smartcard_plugin_parent_class)->finalize (object); } static void smartcard_inserted_cb (GsdSmartcardManager *card_monitor, GsdSmartcard *card, GsdSmartcardPlugin *plugin) { char *name; name = gsd_smartcard_get_name (card); g_debug ("GsdSmartcardPlugin smart card '%s' inserted", name); g_free (name); simulate_user_activity (plugin); } static gboolean user_logged_in_with_smartcard (void) { return g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL; } static GsdSmartcardRemoveAction get_configured_remove_action (GsdSmartcardPlugin *plugin) { GSettings *settings; char *remove_action_string; GsdSmartcardRemoveAction remove_action; settings = g_settings_new ("com.canonical.unity.settings-daemon.peripherals.smartcard"); remove_action_string = g_settings_get_string (settings, KEY_REMOVE_ACTION); if (remove_action_string == NULL) { g_warning ("GsdSmartcardPlugin unable to get smartcard remove action"); remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE; } else if (strcmp (remove_action_string, "none") == 0) { remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE; } else if (strcmp (remove_action_string, "lock_screen") == 0) { remove_action = GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN; } else if (strcmp (remove_action_string, "force_logout") == 0) { remove_action = GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT; } else { g_warning ("GsdSmartcardPlugin unknown smartcard remove action"); remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE; } g_object_unref (settings); return remove_action; } static void process_smartcard_removal (GsdSmartcardPlugin *plugin) { GsdSmartcardRemoveAction remove_action; g_debug ("GsdSmartcardPlugin processing smartcard removal"); remove_action = get_configured_remove_action (plugin); switch (remove_action) { case GSD_SMARTCARD_REMOVE_ACTION_NONE: return; case GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN: lock_screen (plugin); break; case GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT: force_logout (plugin); break; } } static void smartcard_removed_cb (GsdSmartcardManager *card_monitor, GsdSmartcard *card, GsdSmartcardPlugin *plugin) { char *name; name = gsd_smartcard_get_name (card); g_debug ("GsdSmartcardPlugin smart card '%s' removed", name); g_free (name); if (!gsd_smartcard_is_login_card (card)) { g_debug ("GsdSmartcardPlugin removed smart card was not used to login"); return; } process_smartcard_removal (plugin); } static void impl_activate (GnomeSettingsPlugin *plugin) { GError *error; GsdSmartcardPlugin *smartcard_plugin = GSD_SMARTCARD_PLUGIN (plugin); if (smartcard_plugin->priv->is_active) { g_debug ("GsdSmartcardPlugin Not activating smartcard plugin, because it's " "already active"); return; } if (!user_logged_in_with_smartcard ()) { g_debug ("GsdSmartcardPlugin Not activating smartcard plugin, because user didn't use " " smartcard to log in"); smartcard_plugin->priv->is_active = FALSE; return; } g_debug ("GsdSmartcardPlugin Activating smartcard plugin"); error = NULL; if (!gsd_smartcard_manager_start (smartcard_plugin->priv->manager, &error)) { g_warning ("GsdSmartcardPlugin Unable to start smartcard manager: %s", error->message); g_error_free (error); } g_signal_connect (smartcard_plugin->priv->manager, "smartcard-removed", G_CALLBACK (smartcard_removed_cb), smartcard_plugin); g_signal_connect (smartcard_plugin->priv->manager, "smartcard-inserted", G_CALLBACK (smartcard_inserted_cb), smartcard_plugin); if (!gsd_smartcard_manager_login_card_is_inserted (smartcard_plugin->priv->manager)) { g_debug ("GsdSmartcardPlugin processing smartcard removal immediately user logged in with smartcard " "and it's not inserted"); process_smartcard_removal (smartcard_plugin); } smartcard_plugin->priv->is_active = TRUE; } static void impl_deactivate (GnomeSettingsPlugin *plugin) { GsdSmartcardPlugin *smartcard_plugin = GSD_SMARTCARD_PLUGIN (plugin); if (!smartcard_plugin->priv->is_active) { g_debug ("GsdSmartcardPlugin Not deactivating smartcard plugin, " "because it's already inactive"); return; } g_debug ("GsdSmartcardPlugin Deactivating smartcard plugin"); gsd_smartcard_manager_stop (smartcard_plugin->priv->manager); g_signal_handlers_disconnect_by_func (smartcard_plugin->priv->manager, smartcard_removed_cb, smartcard_plugin); g_signal_handlers_disconnect_by_func (smartcard_plugin->priv->manager, smartcard_inserted_cb, smartcard_plugin); smartcard_plugin->priv->is_active = FALSE; } static void gsd_smartcard_plugin_class_init (GsdSmartcardPluginClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GnomeSettingsPluginClass *plugin_class = GNOME_SETTINGS_PLUGIN_CLASS (klass); object_class->finalize = gsd_smartcard_plugin_finalize; plugin_class->activate = impl_activate; plugin_class->deactivate = impl_deactivate; g_type_class_add_private (klass, sizeof (GsdSmartcardPluginPrivate)); } unity-settings-daemon/plugins/smartcard/gsd-smartcard-plugin.h0000664000000000000000000000426715172222611022066 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2010 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_SMARTCARD_PLUGIN_H__ #define __GSD_SMARTCARD_PLUGIN_H__ #include #include #include #include "gnome-settings-plugin.h" G_BEGIN_DECLS #define GSD_TYPE_SMARTCARD_PLUGIN (gsd_smartcard_plugin_get_type ()) #define GSD_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPlugin)) #define GSD_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginClass)) #define GSD_IS_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SMARTCARD_PLUGIN)) #define GSD_IS_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SMARTCARD_PLUGIN)) #define GSD_SMARTCARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginClass)) typedef struct GsdSmartcardPluginPrivate GsdSmartcardPluginPrivate; typedef struct { GnomeSettingsPlugin parent; GsdSmartcardPluginPrivate *priv; } GsdSmartcardPlugin; typedef struct { GnomeSettingsPluginClass parent_class; } GsdSmartcardPluginClass; GType gsd_smartcard_plugin_get_type (void) G_GNUC_CONST; /* All the plugins must implement this function */ G_MODULE_EXPORT GType register_gnome_settings_plugin (GTypeModule *module); G_END_DECLS #endif /* __GSD_SMARTCARD_PLUGIN_H__ */ unity-settings-daemon/plugins/smartcard/gsd-smartcard.c0000664000000000000000000004424115172222611020561 0ustar /* gsd-smartcard.c - smartcard object * * Copyright (C) 2006 Ray Strode * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "config.h" #define GSD_SMARTCARD_ENABLE_INTERNAL_API #include "gsd-smartcard.h" #include #include #include #include #include #include #include #include #include #include #include struct _GsdSmartcardPrivate { SECMODModule *module; GsdSmartcardState state; CK_SLOT_ID slot_id; int slot_series; PK11SlotInfo *slot; char *name; CERTCertificate *signing_certificate; CERTCertificate *encryption_certificate; }; static void gsd_smartcard_finalize (GObject *object); static void gsd_smartcard_class_install_signals (GsdSmartcardClass *card_class); static void gsd_smartcard_class_install_properties (GsdSmartcardClass *card_class); static void gsd_smartcard_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gsd_smartcard_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gsd_smartcard_set_name (GsdSmartcard *card, const char *name); static void gsd_smartcard_set_slot_id (GsdSmartcard *card, int slot_id); static void gsd_smartcard_set_slot_series (GsdSmartcard *card, int slot_series); static void gsd_smartcard_set_module (GsdSmartcard *card, SECMODModule *module); static PK11SlotInfo *gsd_smartcard_find_slot_from_id (GsdSmartcard *card, int slot_id); static PK11SlotInfo *gsd_smartcard_find_slot_from_card_name (GsdSmartcard *card, const char *card_name); #ifndef GSD_SMARTCARD_DEFAULT_SLOT_ID #define GSD_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) #endif #ifndef GSD_SMARTCARD_DEFAULT_SLOT_SERIES #define GSD_SMARTCARD_DEFAULT_SLOT_SERIES -1 #endif enum { PROP_0 = 0, PROP_NAME, PROP_SLOT_ID, PROP_SLOT_SERIES, PROP_MODULE, NUMBER_OF_PROPERTIES }; enum { INSERTED, REMOVED, NUMBER_OF_SIGNALS }; static guint gsd_smartcard_signals[NUMBER_OF_SIGNALS]; G_DEFINE_TYPE (GsdSmartcard, gsd_smartcard, G_TYPE_OBJECT); static void gsd_smartcard_class_init (GsdSmartcardClass *card_class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (card_class); gobject_class->finalize = gsd_smartcard_finalize; gsd_smartcard_class_install_signals (card_class); gsd_smartcard_class_install_properties (card_class); g_type_class_add_private (card_class, sizeof (GsdSmartcardPrivate)); } static void gsd_smartcard_class_install_signals (GsdSmartcardClass *card_class) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (card_class); gsd_smartcard_signals[INSERTED] = g_signal_new ("inserted", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdSmartcardClass, inserted), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gsd_smartcard_signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GsdSmartcardClass, removed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void gsd_smartcard_class_install_properties (GsdSmartcardClass *card_class) { GObjectClass *object_class; GParamSpec *param_spec; object_class = G_OBJECT_CLASS (card_class); object_class->set_property = gsd_smartcard_set_property; object_class->get_property = gsd_smartcard_get_property; param_spec = g_param_spec_ulong ("slot-id", "Slot ID", "The slot the card is in", 1, G_MAXULONG, GSD_SMARTCARD_DEFAULT_SLOT_ID, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec); param_spec = g_param_spec_int ("slot-series", "Slot Series", "per-slot card identifier", -1, G_MAXINT, GSD_SMARTCARD_DEFAULT_SLOT_SERIES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec); param_spec = g_param_spec_string ("name", "name", "name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_NAME, param_spec); param_spec = g_param_spec_pointer ("module", "Module", "smartcard driver", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_MODULE, param_spec); } static void gsd_smartcard_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GsdSmartcard *card = GSD_SMARTCARD (object); switch (prop_id) { case PROP_NAME: gsd_smartcard_set_name (card, g_value_get_string (value)); break; case PROP_SLOT_ID: gsd_smartcard_set_slot_id (card, g_value_get_ulong (value)); break; case PROP_SLOT_SERIES: gsd_smartcard_set_slot_series (card, g_value_get_int (value)); break; case PROP_MODULE: gsd_smartcard_set_module (card, (SECMODModule *) g_value_get_pointer (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } CK_SLOT_ID gsd_smartcard_get_slot_id (GsdSmartcard *card) { return card->priv->slot_id; } GsdSmartcardState gsd_smartcard_get_state (GsdSmartcard *card) { return card->priv->state; } char * gsd_smartcard_get_name (GsdSmartcard *card) { return g_strdup (card->priv->name); } gboolean gsd_smartcard_is_login_card (GsdSmartcard *card) { const char *login_card_name; login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); if ((login_card_name == NULL) || (card->priv->name == NULL)) { return FALSE; } if (strcmp (card->priv->name, login_card_name) == 0) { return TRUE; } return FALSE; } static void gsd_smartcard_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GsdSmartcard *card = GSD_SMARTCARD (object); switch (prop_id) { case PROP_NAME: g_value_take_string (value, gsd_smartcard_get_name (card)); break; case PROP_SLOT_ID: g_value_set_ulong (value, (gulong) gsd_smartcard_get_slot_id (card)); break; case PROP_SLOT_SERIES: g_value_set_int (value, gsd_smartcard_get_slot_series (card)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gsd_smartcard_set_name (GsdSmartcard *card, const char *name) { if (name == NULL) { return; } if ((card->priv->name == NULL) || (strcmp (card->priv->name, name) != 0)) { g_free (card->priv->name); card->priv->name = g_strdup (name); if (card->priv->slot == NULL) { card->priv->slot = gsd_smartcard_find_slot_from_card_name (card, card->priv->name); if (card->priv->slot != NULL) { int slot_id, slot_series; slot_id = PK11_GetSlotID (card->priv->slot); if (slot_id != card->priv->slot_id) { gsd_smartcard_set_slot_id (card, slot_id); } slot_series = PK11_GetSlotSeries (card->priv->slot); if (slot_series != card->priv->slot_series) { gsd_smartcard_set_slot_series (card, slot_series); } _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED); } else { _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED); } } g_object_notify (G_OBJECT (card), "name"); } } static void gsd_smartcard_set_slot_id (GsdSmartcard *card, int slot_id) { if (card->priv->slot_id != slot_id) { card->priv->slot_id = slot_id; if (card->priv->slot == NULL) { card->priv->slot = gsd_smartcard_find_slot_from_id (card, card->priv->slot_id); if (card->priv->slot != NULL) { const char *card_name; card_name = PK11_GetTokenName (card->priv->slot); if ((card->priv->name == NULL) || ((card_name != NULL) && (strcmp (card_name, card->priv->name) != 0))) { gsd_smartcard_set_name (card, card_name); } _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED); } else { _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED); } } g_object_notify (G_OBJECT (card), "slot-id"); } } static void gsd_smartcard_set_slot_series (GsdSmartcard *card, int slot_series) { if (card->priv->slot_series != slot_series) { card->priv->slot_series = slot_series; g_object_notify (G_OBJECT (card), "slot-series"); } } static void gsd_smartcard_set_module (GsdSmartcard *card, SECMODModule *module) { gboolean should_notify; if (card->priv->module != module) { should_notify = TRUE; } else { should_notify = FALSE; } if (card->priv->module != NULL) { SECMOD_DestroyModule (card->priv->module); card->priv->module = NULL; } if (module != NULL) { card->priv->module = SECMOD_ReferenceModule (module); } if (should_notify) { g_object_notify (G_OBJECT (card), "module"); } } int gsd_smartcard_get_slot_series (GsdSmartcard *card) { return card->priv->slot_series; } static void gsd_smartcard_init (GsdSmartcard *card) { g_debug ("initializing smartcard "); card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, GSD_TYPE_SMARTCARD, GsdSmartcardPrivate); } static void gsd_smartcard_finalize (GObject *object) { GsdSmartcard *card; GObjectClass *gobject_class; card = GSD_SMARTCARD (object); g_free (card->priv->name); gsd_smartcard_set_module (card, NULL); gobject_class = G_OBJECT_CLASS (gsd_smartcard_parent_class); gobject_class->finalize (object); } GQuark gsd_smartcard_error_quark (void) { static GQuark error_quark = 0; if (error_quark == 0) { error_quark = g_quark_from_static_string ("gsd-smartcard-error-quark"); } return error_quark; } GsdSmartcard * _gsd_smartcard_new (SECMODModule *module, CK_SLOT_ID slot_id, int slot_series) { GsdSmartcard *card; g_return_val_if_fail (module != NULL, NULL); g_return_val_if_fail (slot_id >= 1, NULL); g_return_val_if_fail (slot_series > 0, NULL); g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL); card = GSD_SMARTCARD (g_object_new (GSD_TYPE_SMARTCARD, "module", module, "slot-id", (gulong) slot_id, "slot-series", slot_series, NULL)); return card; } GsdSmartcard * _gsd_smartcard_new_from_name (SECMODModule *module, const char *name) { GsdSmartcard *card; g_return_val_if_fail (module != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); card = GSD_SMARTCARD (g_object_new (GSD_TYPE_SMARTCARD, "module", module, "name", name, NULL)); return card; } void _gsd_smartcard_set_state (GsdSmartcard *card, GsdSmartcardState state) { /* gsd_smartcard_fetch_certificates (card); */ if (card->priv->state != state) { card->priv->state = state; if (state == GSD_SMARTCARD_STATE_INSERTED) { g_signal_emit (card, gsd_smartcard_signals[INSERTED], 0); } else if (state == GSD_SMARTCARD_STATE_REMOVED) { g_signal_emit (card, gsd_smartcard_signals[REMOVED], 0); } else { g_assert_not_reached (); } } } /* So we could conceivably make the closure data a pointer to the card * or something similiar and then emit signals when we want passwords, * but it's probably easier to just get the password up front and use * it. So we just take the passed in g_malloc'd (well probably, who knows) * and strdup it using NSPR's memory allocation routines. */ static char * gsd_smartcard_password_handler (PK11SlotInfo *slot, PRBool is_retrying, const char *password) { if (is_retrying) { return NULL; } return password != NULL? PL_strdup (password): NULL; } gboolean gsd_smartcard_unlock (GsdSmartcard *card, const char *password) { SECStatus status; PK11_SetPasswordFunc ((PK11PasswordFunc) gsd_smartcard_password_handler); /* we pass PR_TRUE to load certificates */ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password); if (status != SECSuccess) { g_debug ("could not unlock card - %d", status); return FALSE; } return TRUE; } static PK11SlotInfo * gsd_smartcard_find_slot_from_card_name (GsdSmartcard *card, const char *card_name) { int i; for (i = 0; i < card->priv->module->slotCount; i++) { const char *slot_card_name; slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]); if ((slot_card_name != NULL) && (strcmp (slot_card_name, card_name) == 0)) { return card->priv->module->slots[i]; } } return NULL; } static PK11SlotInfo * gsd_smartcard_find_slot_from_id (GsdSmartcard *card, int slot_id) { int i; for (i = 0; i < card->priv->module->slotCount; i++) { if (PK11_GetSlotID (card->priv->module->slots[i]) == slot_id) { return card->priv->module->slots[i]; } } return NULL; } unity-settings-daemon/plugins/smartcard/gsd-smartcard.h0000664000000000000000000000656215172222611020572 0ustar /* securitycard.h - api for reading and writing data to a security card * * Copyright (C) 2006 Ray Strode * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef GSD_SMARTCARD_H #define GSD_SMARTCARD_H #include #include #include G_BEGIN_DECLS #define GSD_TYPE_SMARTCARD (gsd_smartcard_get_type ()) #define GSD_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_SMARTCARD, GsdSmartcard)) #define GSD_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_SMARTCARD, GsdSmartcardClass)) #define GSD_IS_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_SMARTCARD)) #define GSD_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_SMARTCARD)) #define GSD_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_SMARTCARD, GsdSmartcardClass)) #define GSD_SMARTCARD_ERROR (gsd_smartcard_error_quark ()) typedef struct _GsdSmartcardClass GsdSmartcardClass; typedef struct _GsdSmartcard GsdSmartcard; typedef struct _GsdSmartcardPrivate GsdSmartcardPrivate; typedef enum _GsdSmartcardError GsdSmartcardError; typedef enum _GsdSmartcardState GsdSmartcardState; typedef struct _GsdSmartcardRequest GsdSmartcardRequest; struct _GsdSmartcard { GObject parent; /*< private > */ GsdSmartcardPrivate *priv; }; struct _GsdSmartcardClass { GObjectClass parent_class; void (* inserted) (GsdSmartcard *card); void (* removed) (GsdSmartcard *card); }; enum _GsdSmartcardError { GSD_SMARTCARD_ERROR_GENERIC = 0, }; enum _GsdSmartcardState { GSD_SMARTCARD_STATE_INSERTED = 0, GSD_SMARTCARD_STATE_REMOVED, }; GType gsd_smartcard_get_type (void) G_GNUC_CONST; GQuark gsd_smartcard_error_quark (void) G_GNUC_CONST; CK_SLOT_ID gsd_smartcard_get_slot_id (GsdSmartcard *card); gint gsd_smartcard_get_slot_series (GsdSmartcard *card); GsdSmartcardState gsd_smartcard_get_state (GsdSmartcard *card); char *gsd_smartcard_get_name (GsdSmartcard *card); gboolean gsd_smartcard_is_login_card (GsdSmartcard *card); gboolean gsd_smartcard_unlock (GsdSmartcard *card, const char *password); /* don't under any circumstances call these functions */ #ifdef GSD_SMARTCARD_ENABLE_INTERNAL_API GsdSmartcard *_gsd_smartcard_new (SECMODModule *module, CK_SLOT_ID slot_id, gint slot_series); GsdSmartcard *_gsd_smartcard_new_from_name (SECMODModule *module, const char *name); void _gsd_smartcard_set_state (GsdSmartcard *card, GsdSmartcardState state); #endif G_END_DECLS #endif /* GSD_SMARTCARD_H */ unity-settings-daemon/plugins/smartcard/smartcard.gnome-settings-plugin.in0000664000000000000000000000025715172222611024427 0ustar [GNOME Settings Plugin] Module=smartcard IAge=0 Priority=8 _Name=Smartcard _Description=Smartcard plugin Authors=Ray Strode Copyright=Copyright © 2010 Red Hat, Inc. Website= unity-settings-daemon/plugins/smartcard/test-smartcard.c0000664000000000000000000000034115172222611020754 0ustar #define NEW gsd_smartcard_manager_new_default #define START gsd_smartcard_manager_start #define STOP gsd_smartcard_manager_stop #define MANAGER GsdSmartcardManager #include "gsd-smartcard-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/sound/0000775000000000000000000000000015172222611015025 5ustar unity-settings-daemon/plugins/sound/Makefile.am0000664000000000000000000000255215172222611017065 0ustar plugin_name = sound libexec_PROGRAMS = usd-test-sound usd_test_sound_SOURCES = \ gsd-sound-manager.h \ gsd-sound-manager.c \ test-sound.c usd_test_sound_CFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(SOUND_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(AM_CFLAGS) usd_test_sound_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(SOUND_LIBS) \ $(SETTINGS_PLUGIN_LIBS) plugin_LTLIBRARIES = \ libsound.la libsound_la_SOURCES = \ gsd-sound-plugin.c \ gsd-sound-manager.h \ gsd-sound-manager.c libsound_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libsound_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(SOUND_CFLAGS) \ $(AM_CFLAGS) libsound_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libsound_la_LIBADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(SETTINGS_PLUGIN_LIBS) \ $(SOUND_LIBS) plugin_in_files = \ sound.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/sound/gsd-sound-manager.c0000664000000000000000000002725615172222611020520 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Lennart Poettering * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gsd-sound-manager.h" #include "gnome-settings-profile.h" #define GSD_SOUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerPrivate)) struct GsdSoundManagerPrivate { GSettings *settings; GList *monitors; guint timeout; }; static void gsd_sound_manager_class_init (GsdSoundManagerClass *klass); static void gsd_sound_manager_init (GsdSoundManager *sound_manager); static void gsd_sound_manager_finalize (GObject *object); G_DEFINE_TYPE (GsdSoundManager, gsd_sound_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void sample_info_cb (pa_context *c, const pa_sample_info *i, int eol, void *userdata) { pa_operation *o; if (!i) return; g_debug ("Found sample %s", i->name); /* We only flush those samples which have an XDG sound name * attached, because only those originate from themeing */ if (!(pa_proplist_gets (i->proplist, PA_PROP_EVENT_ID))) return; g_debug ("Dropping sample %s from cache", i->name); if (!(o = pa_context_remove_sample (c, i->name, NULL, NULL))) { g_debug ("pa_context_remove_sample (): %s", pa_strerror (pa_context_errno (c))); return; } pa_operation_unref (o); /* We won't wait until the operation is actually executed to * speed things up a bit.*/ } static void flush_cache (void) { pa_mainloop *ml = NULL; pa_context *c = NULL; pa_proplist *pl = NULL; pa_operation *o = NULL; g_debug ("Flushing sample cache"); if (!(ml = pa_mainloop_new ())) { g_debug ("Failed to allocate pa_mainloop"); goto fail; } if (!(pl = pa_proplist_new ())) { g_debug ("Failed to allocate pa_proplist"); goto fail; } pa_proplist_sets (pl, PA_PROP_APPLICATION_NAME, PACKAGE_NAME); pa_proplist_sets (pl, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION); pa_proplist_sets (pl, PA_PROP_APPLICATION_ID, "org.gnome.SettingsDaemon"); if (!(c = pa_context_new_with_proplist (pa_mainloop_get_api (ml), PACKAGE_NAME, pl))) { g_debug ("Failed to allocate pa_context"); goto fail; } pa_proplist_free (pl); pl = NULL; if (pa_context_connect (c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) { g_debug ("pa_context_connect(): %s", pa_strerror (pa_context_errno (c))); goto fail; } /* Wait until the connection is established */ while (pa_context_get_state (c) != PA_CONTEXT_READY) { if (!PA_CONTEXT_IS_GOOD (pa_context_get_state (c))) { g_debug ("Connection failed: %s", pa_strerror (pa_context_errno (c))); goto fail; } if (pa_mainloop_iterate (ml, TRUE, NULL) < 0) { g_debug ("pa_mainloop_iterate() failed"); goto fail; } } /* Enumerate all cached samples */ if (!(o = pa_context_get_sample_info_list (c, sample_info_cb, NULL))) { g_debug ("pa_context_get_sample_info_list(): %s", pa_strerror (pa_context_errno (c))); goto fail; } /* Wait until our operation is finished and there's nothing * more queued to send to the server */ while (pa_operation_get_state (o) == PA_OPERATION_RUNNING || pa_context_is_pending (c)) { if (!PA_CONTEXT_IS_GOOD (pa_context_get_state (c))) { g_debug ("Connection failed: %s", pa_strerror (pa_context_errno (c))); goto fail; } if (pa_mainloop_iterate (ml, TRUE, NULL) < 0) { g_debug ("pa_mainloop_iterate() failed"); goto fail; } } g_debug ("Sample cache flushed"); fail: if (o) { pa_operation_cancel (o); pa_operation_unref (o); } if (c) { pa_context_disconnect (c); pa_context_unref (c); } if (pl) pa_proplist_free (pl); if (ml) pa_mainloop_free (ml); } static gboolean flush_cb (GsdSoundManager *manager) { flush_cache (); manager->priv->timeout = 0; return FALSE; } static void trigger_flush (GsdSoundManager *manager) { if (manager->priv->timeout) g_source_remove (manager->priv->timeout); /* We delay the flushing a bit so that we can coalesce * multiple changes into a single cache flush */ manager->priv->timeout = g_timeout_add (500, (GSourceFunc) flush_cb, manager); } static void settings_changed_cb (GSettings *settings, const char *key, GsdSoundManager *manager) { trigger_flush (manager); } static void register_config_callback (GsdSoundManager *manager) { manager->priv->settings = g_settings_new ("org.gnome.desktop.sound"); g_signal_connect (G_OBJECT (manager->priv->settings), "changed", G_CALLBACK (settings_changed_cb), manager); } static void file_monitor_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event, GsdSoundManager *manager) { g_debug ("Theme dir changed"); trigger_flush (manager); } static gboolean register_directory_callback (GsdSoundManager *manager, const char *path, GError **error) { GFile *f; GFileMonitor *m; gboolean succ = FALSE; g_debug ("Registering directory monitor for %s", path); f = g_file_new_for_path (path); m = g_file_monitor_directory (f, 0, NULL, error); if (m != NULL) { g_signal_connect (m, "changed", G_CALLBACK (file_monitor_changed_cb), manager); manager->priv->monitors = g_list_prepend (manager->priv->monitors, m); succ = TRUE; } g_object_unref (f); return succ; } gboolean gsd_sound_manager_start (GsdSoundManager *manager, GError **error) { guint i; const gchar * const * dirs; char *p; g_debug ("Starting sound manager"); gnome_settings_profile_start (NULL); /* We listen for change of the selected theme ... */ register_config_callback (manager); /* ... and we listen to changes of the theme base directories * in $HOME ...*/ p = g_build_filename (g_get_user_data_dir (), "sounds", NULL); /* See bug #694134 - the initial commit had the permissions below wrong * so users may have the directory without the right permissions. Fix * them up if so. */ if (!g_access (p, F_OK) && g_access (p, R_OK | W_OK | X_OK) != 0) { g_debug ("Permissions on %s wrong; resetting", p); g_chmod (p, S_IRUSR | S_IWUSR | S_IXUSR); } if (g_mkdir_with_parents(p, 0700) == 0) register_directory_callback (manager, p, NULL); g_free (p); /* ... and globally. */ dirs = g_get_system_data_dirs (); for (i = 0; dirs[i] != NULL; i++) { p = g_build_filename (dirs[i], "sounds", NULL); if (g_file_test (p, G_FILE_TEST_IS_DIR)) register_directory_callback (manager, p, NULL); g_free (p); } gnome_settings_profile_end (NULL); return TRUE; } void gsd_sound_manager_stop (GsdSoundManager *manager) { g_debug ("Stopping sound manager"); if (manager->priv->settings != NULL) { g_object_unref (manager->priv->settings); manager->priv->settings = NULL; } if (manager->priv->timeout) { g_source_remove (manager->priv->timeout); manager->priv->timeout = 0; } while (manager->priv->monitors) { g_file_monitor_cancel (G_FILE_MONITOR (manager->priv->monitors->data)); g_object_unref (manager->priv->monitors->data); manager->priv->monitors = g_list_delete_link (manager->priv->monitors, manager->priv->monitors); } } static GObject * gsd_sound_manager_constructor ( GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdSoundManager *m; m = GSD_SOUND_MANAGER (G_OBJECT_CLASS (gsd_sound_manager_parent_class)->constructor ( type, n_construct_properties, construct_properties)); return G_OBJECT (m); } static void gsd_sound_manager_dispose (GObject *object) { GsdSoundManager *manager; manager = GSD_SOUND_MANAGER (object); gsd_sound_manager_stop (manager); G_OBJECT_CLASS (gsd_sound_manager_parent_class)->dispose (object); } static void gsd_sound_manager_class_init (GsdSoundManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_sound_manager_constructor; object_class->dispose = gsd_sound_manager_dispose; object_class->finalize = gsd_sound_manager_finalize; g_type_class_add_private (klass, sizeof (GsdSoundManagerPrivate)); } static void gsd_sound_manager_init (GsdSoundManager *manager) { manager->priv = GSD_SOUND_MANAGER_GET_PRIVATE (manager); } static void gsd_sound_manager_finalize (GObject *object) { GsdSoundManager *sound_manager; g_return_if_fail (object != NULL); g_return_if_fail (GSD_IS_SOUND_MANAGER (object)); sound_manager = GSD_SOUND_MANAGER (object); g_return_if_fail (sound_manager->priv); G_OBJECT_CLASS (gsd_sound_manager_parent_class)->finalize (object); } GsdSoundManager * gsd_sound_manager_new (void) { if (manager_object) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_SOUND_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_SOUND_MANAGER (manager_object); } unity-settings-daemon/plugins/sound/gsd-sound-manager.h0000664000000000000000000000412015172222611020506 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Lennart Poettering * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_SOUND_MANAGER_H #define __GSD_SOUND_MANAGER_H #include #include G_BEGIN_DECLS #define GSD_TYPE_SOUND_MANAGER (gsd_sound_manager_get_type ()) #define GSD_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManager)) #define GSD_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerClass)) #define GSD_IS_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SOUND_MANAGER)) #define GSD_IS_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SOUND_MANAGER)) #define GSD_SOUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerClass)) typedef struct GsdSoundManagerPrivate GsdSoundManagerPrivate; typedef struct { GObject parent; GsdSoundManagerPrivate *priv; } GsdSoundManager; typedef struct { GObjectClass parent_class; } GsdSoundManagerClass; GType gsd_sound_manager_get_type (void) G_GNUC_CONST; GsdSoundManager *gsd_sound_manager_new (void); gboolean gsd_sound_manager_start (GsdSoundManager *manager, GError **error); void gsd_sound_manager_stop (GsdSoundManager *manager); G_END_DECLS #endif /* __GSD_SOUND_MANAGER_H */ unity-settings-daemon/plugins/sound/gsd-sound-plugin.c0000664000000000000000000000202515172222611020367 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 Lennart Poettering * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-sound-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdSound, gsd_sound) unity-settings-daemon/plugins/sound/sound.gnome-settings-plugin.in0000664000000000000000000000025215172222611022742 0ustar [GNOME Settings Plugin] Module=sound IAge=0 Priority=5 _Name=Sound _Description=Sound Sample Cache plugin Authors=Lennart Poettering Copyright=Copyright © 2008 Website= unity-settings-daemon/plugins/sound/test-sound.c0000664000000000000000000000030515172222611017274 0ustar #define NEW gsd_sound_manager_new #define START gsd_sound_manager_start #define STOP gsd_sound_manager_stop #define MANAGER GsdSoundManager #include "gsd-sound-manager.h" #include "test-plugin.h" unity-settings-daemon/plugins/updates/0000775000000000000000000000000015172222611015342 5ustar unity-settings-daemon/plugins/updates/Makefile.am0000664000000000000000000000220515172222611017375 0ustar plugin_name = updates plugin_LTLIBRARIES = \ libupdates.la libupdates_la_SOURCES = \ gsd-updates-common.h \ gsd-updates-plugin.c \ gsd-updates-refresh.h \ gsd-updates-refresh.c \ gsd-updates-firmware.h \ gsd-updates-firmware.c \ gsd-updates-manager.h \ gsd-updates-manager.c libupdates_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) libupdates_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(GUDEV_CFLAGS) \ -DG_UDEV_API_IS_SUBJECT_TO_CHANGE \ $(PACKAGEKIT_CFLAGS) \ -DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE \ -DDATADIR=\"$(datadir)\" \ -DBINDIR=\"$(bindir)\" \ -DLIBEXECDIR=\"$(libexecdir)\" \ -I$(top_srcdir)/data \ $(AM_CFLAGS) libupdates_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libupdates_la_LIBADD = \ $(SETTINGS_PLUGIN_LIBS) \ $(PACKAGEKIT_LIBS) plugin_in_files = \ updates.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST = \ $(plugin_in_files) CLEANFILES = \ $(plugin_DATA) DISTCLEANFILES = \ $(plugin_DATA) @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/updates/gsd-updates-common.h0000664000000000000000000000422715172222611021226 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GSD_UPDATES_COMMON_H #define __GSD_UPDATES_COMMON_H G_BEGIN_DECLS #define GSD_SETTINGS_BANNED_FIRMWARE "banned-firmware" #define GSD_SETTINGS_CONNECTION_USE_MOBILE "connection-use-mobile" #define GSD_SETTINGS_ENABLE_CHECK_FIRMWARE "enable-check-firmware" #define GSD_SETTINGS_FREQUENCY_GET_UPDATES "frequency-get-updates" #define GSD_SETTINGS_FREQUENCY_GET_UPGRADES "frequency-get-upgrades" #define GSD_SETTINGS_FREQUENCY_REFRESH_CACHE "frequency-refresh-cache" #define GSD_SETTINGS_FREQUENCY_UPDATES_NOTIFICATION "frequency-updates-notification" #define GSD_SETTINGS_IGNORED_DEVICES "ignored-devices" #define GSD_SETTINGS_LAST_UPDATES_NOTIFICATION "last-updates-notification" #define GSD_SETTINGS_MEDIA_REPO_FILENAMES "media-repo-filenames" #define GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES "notify-distro-upgrades" #define GSD_SETTINGS_SCHEMA "com.canonical.unity.settings-daemon.plugins.updates" #define GSD_SETTINGS_UPDATE_BATTERY "update-battery" #define GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES "auto-download-updates" G_END_DECLS #endif /* __GSD_UPDATES_COMMON_H */ unity-settings-daemon/plugins/updates/gsd-updates-firmware.c0000664000000000000000000010750415172222611021547 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007-2012 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #include #include #include #include #ifdef HAVE_GUDEV #include #endif #include "gsd-updates-common.h" #include "gsd-updates-firmware.h" static void gsd_updates_firmware_finalize (GObject *object); #define GSD_UPDATES_FIRMWARE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_UPDATES_TYPE_FIRMWARE, GsdUpdatesFirmwarePrivate)) #define GSD_UPDATES_FIRMWARE_MISSING_DIR "/run/udev/firmware-missing" #define GSD_UPDATES_FIRMWARE_LOADING_DIR "/lib/firmware" #define GSD_UPDATES_FIRMWARE_LOGIN_DELAY 10 /* seconds */ #define GSD_UPDATES_FIRMWARE_PROCESS_DELAY 2 /* seconds */ #define GSD_UPDATES_FIRMWARE_INSERT_DELAY 2 /* seconds */ #define GSD_UPDATES_FIRMWARE_DEVICE_REBIND_PROGRAM "/usr/sbin/pk-device-rebind" struct GsdUpdatesFirmwarePrivate { GSettings *settings; GFileMonitor *monitor; GPtrArray *array_requested; PkTask *task; GPtrArray *packages_found; guint timeout_id; }; typedef enum { FIRMWARE_SUBSYSTEM_USB, FIRMWARE_SUBSYSTEM_PCI, FIRMWARE_SUBSYSTEM_UNKNOWN } FirmwareSubsystem; typedef struct { gchar *filename; gchar *sysfs_path; gchar *model; gchar *id; FirmwareSubsystem subsystem; } GsdUpdatesFirmwareRequest; G_DEFINE_TYPE (GsdUpdatesFirmware, gsd_updates_firmware, G_TYPE_OBJECT) static void install_package_ids (GsdUpdatesFirmware *firmware); static void ignore_devices (GsdUpdatesFirmware *firmware); static gboolean subsystem_can_replug (FirmwareSubsystem subsystem) { if (subsystem == FIRMWARE_SUBSYSTEM_USB) return TRUE; return FALSE; } static GsdUpdatesFirmwareRequest * request_new (const gchar *filename, const gchar *sysfs_path) { GsdUpdatesFirmwareRequest *req; #ifdef HAVE_GUDEV GUdevDevice *device; GUdevClient *client; const gchar *subsystem; const gchar *model; const gchar *id_vendor; const gchar *id_product; #endif req = g_new0 (GsdUpdatesFirmwareRequest, 1); req->filename = g_strdup (filename); req->sysfs_path = g_strdup (sysfs_path); req->subsystem = FIRMWARE_SUBSYSTEM_UNKNOWN; #ifdef HAVE_GUDEV /* get all subsystems */ client = g_udev_client_new (NULL); device = g_udev_client_query_by_sysfs_path (client, sysfs_path); if (device == NULL) goto out; /* find subsystem, which will affect if we have to replug, or reboot */ subsystem = g_udev_device_get_subsystem (device); if (g_strcmp0 (subsystem, "usb") == 0) { req->subsystem = FIRMWARE_SUBSYSTEM_USB; } else if (g_strcmp0 (subsystem, "pci") == 0) { req->subsystem = FIRMWARE_SUBSYSTEM_PCI; } else { g_warning ("subsystem unrecognised: %s", subsystem); } /* get model, so we can show something sensible */ model = g_udev_device_get_property (device, "ID_MODEL"); if (model != NULL && model[0] != '\0') { req->model = g_strdup (model); /* replace invalid chars */ g_strdelimit (req->model, "_", ' '); } /* create ID so we can ignore the specific device */ id_vendor = g_udev_device_get_property (device, "ID_VENDOR"); id_product = g_udev_device_get_property (device, "ID_MODEL_ID"); req->id = g_strdup_printf ("%s_%s", id_vendor, id_product); out: if (device != NULL) g_object_unref (device); g_object_unref (client); #endif return req; } static void request_free (GsdUpdatesFirmwareRequest *req) { g_free (req->filename); g_free (req->model); g_free (req->sysfs_path); g_free (req->id); g_free (req); } static gboolean device_rebind (GsdUpdatesFirmware *firmware) { gboolean ret; gchar *argv[4]; gchar *rebind_stderr = NULL; gchar *rebind_stdout = NULL; GError *error = NULL; gint exit_status = 0; guint i; GPtrArray *array; const GsdUpdatesFirmwareRequest *req; GString *string; string = g_string_new (""); /* make a string array of all the devices to replug */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); g_string_append_printf (string, "%s ", req->sysfs_path); } /* remove trailing space */ if (string->len > 0) g_string_set_size (string, string->len-1); /* use PolicyKit to do this as root */ argv[0] = "pkexec"; argv[1] = GSD_UPDATES_FIRMWARE_DEVICE_REBIND_PROGRAM; argv[2] = string->str; argv[3] = NULL; ret = g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &rebind_stdout, &rebind_stderr, &exit_status, &error); if (!ret) { g_warning ("failed to spawn '%s': %s", argv[1], error->message); g_error_free (error); goto out; } /* if we failed to rebind the device */ if (exit_status != 0) { g_warning ("failed to rebind: %s, %s", rebind_stdout, rebind_stderr); ret = FALSE; goto out; } out: g_free (rebind_stdout); g_free (rebind_stderr); g_string_free (string, TRUE); return ret; } static void libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data) { GsdUpdatesFirmware *firmware = GSD_UPDATES_FIRMWARE (data); if (g_strcmp0 (action, "install-firmware") == 0) { install_package_ids (firmware); } else if (g_strcmp0 (action, "ignore-devices") == 0) { ignore_devices (firmware); } else { g_warning ("unknown action id: %s", action); } notify_notification_close (notification, NULL); } static void on_notification_closed (NotifyNotification *notification, gpointer data) { g_object_unref (notification); } static void require_restart (GsdUpdatesFirmware *firmware) { const gchar *message; gboolean ret; GError *error = NULL; NotifyNotification *notification; /* TRANSLATORS: we need to restart so the new hardware can re-request the firmware */ message = _("You will need to restart this computer before the hardware will work correctly."); /* TRANSLATORS: title of libnotify bubble */ notification = notify_notification_new (_("Additional software was installed"), message, NULL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER); notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); /* show the bubble */ ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } } static void require_replug (GsdUpdatesFirmware *firmware) { const gchar *message; gboolean ret; GError *error = NULL; NotifyNotification *notification; /* TRANSLATORS: we need to remove an replug so the new hardware can re-request the firmware */ message = _("You will need to remove and then reinsert the hardware before it will work correctly."); /* TRANSLATORS: title of libnotify bubble */ notification = notify_notification_new (_("Additional software was installed"), message, NULL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER); notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); /* show the bubble */ ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } } static void require_nothing (GsdUpdatesFirmware *firmware) { const gchar *message; gboolean ret; GError *error = NULL; NotifyNotification *notification; /* TRANSLATORS: we need to remove an replug so the new hardware can re-request the firmware */ message = _("Your hardware has been set up and is now ready to use."); /* TRANSLATORS: title of libnotify bubble */ notification = notify_notification_new (_("Additional software was installed"), message, NULL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER); notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); /* show the bubble */ ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } } static void install_packages_cb (GObject *object, GAsyncResult *res, GsdUpdatesFirmware *firmware) { PkClient *client = PK_CLIENT (object); GError *error = NULL; PkResults *results = NULL; GPtrArray *array = NULL; gboolean restart = FALSE; const GsdUpdatesFirmwareRequest *req; gboolean ret; guint i; PkError *error_code = NULL; /* get the results */ results = pk_client_generic_finish (client, res, &error); if (results == NULL) { g_warning ("failed to install file: %s", error->message); g_error_free (error); goto out; } /* check error code */ error_code = pk_results_get_error_code (results); if (error_code != NULL) { g_warning ("failed to install file: %s, %s", pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code)); goto out; } /* go through all the requests, and find the worst type */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); ret = subsystem_can_replug (req->subsystem); if (!ret) { restart = TRUE; break; } } /* can we just rebind the device */ ret = g_file_test (GSD_UPDATES_FIRMWARE_DEVICE_REBIND_PROGRAM, G_FILE_TEST_EXISTS); if (ret) { ret = device_rebind (firmware); if (ret) { require_nothing (firmware); goto out; } } else { /* give the user the correct message */ if (restart) require_restart (firmware); else require_replug (firmware); } /* clear array */ g_ptr_array_set_size (firmware->priv->array_requested, 0); out: if (error_code != NULL) g_object_unref (error_code); if (array != NULL) g_ptr_array_unref (array); if (results != NULL) g_object_unref (results); } static gchar ** package_array_to_strv (GPtrArray *array) { PkPackage *item; gchar **results; guint i; results = g_new0 (gchar *, array->len+1); for (i=0; ilen; i++) { item = g_ptr_array_index (array, i); results[i] = g_strdup (pk_package_get_id (item)); } return results; } static void install_package_ids (GsdUpdatesFirmware *firmware) { gchar **package_ids; /* install all of the firmware files */ package_ids = package_array_to_strv (firmware->priv->packages_found); pk_client_install_packages_async (PK_CLIENT(firmware->priv->task), TRUE, package_ids, NULL, NULL, NULL, (GAsyncReadyCallback) install_packages_cb, firmware); g_strfreev (package_ids); } static void ignore_devices (GsdUpdatesFirmware *firmware) { gchar *existing = NULL; GsdUpdatesFirmwareRequest *req; GPtrArray *array; GString *string; guint i; /* get from settings */ existing = g_settings_get_string (firmware->priv->settings, GSD_SETTINGS_IGNORED_DEVICES); /* get existing string */ string = g_string_new (existing); if (string->len > 0) g_string_append (string, ","); /* add all listed devices */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); g_string_append_printf (string, "%s,", req->id); } /* remove final ',' */ if (string->len > 2) g_string_set_size (string, string->len - 1); /* set new string */ g_settings_set_string (firmware->priv->settings, GSD_SETTINGS_IGNORED_DEVICES, string->str); g_free (existing); g_string_free (string, TRUE); } static PkPackage * check_available (GsdUpdatesFirmware *firmware, const gchar *filename) { guint length = 0; GPtrArray *array = NULL; GError *error = NULL; PkPackage *item = NULL; PkBitfield filter; PkResults *results; gchar **values = NULL; PkError *error_code = NULL; /* search for newest not installed package */ filter = pk_bitfield_from_enums (PK_FILTER_ENUM_NOT_INSTALLED, PK_FILTER_ENUM_NEWEST, -1); values = g_strsplit (filename, "&", -1); results = pk_client_search_files (PK_CLIENT(firmware->priv->task), filter, values, NULL, NULL, NULL, &error); if (results == NULL) { g_warning ("failed to search file %s: %s", filename, error->message); g_error_free (error); goto out; } /* check error code */ error_code = pk_results_get_error_code (results); if (error_code != NULL) { g_warning ("failed to search file: %s, %s", pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code)); goto out; } /* make sure we have one package */ array = pk_results_get_package_array (results); if (array->len == 0) g_debug ("no package providing %s found", filename); else if (array->len != 1) g_warning ("not one package providing %s found (%i)", filename, length); else item = g_object_ref (g_ptr_array_index (array, 0)); out: g_strfreev (values); if (error_code != NULL) g_object_unref (error_code); if (array != NULL) g_ptr_array_unref (array); if (results != NULL) g_object_unref (results); return item; } static void remove_duplicate (GPtrArray *array) { guint i, j; const gchar *val; const gchar *val_tmp; /* remove each duplicate entry */ for (i=0; ilen; i++) { val = g_ptr_array_index (array, i); for (j=i+1; jlen; j++) { val_tmp = g_ptr_array_index (array, j); if (g_strcmp0 (val_tmp, val) == 0) g_ptr_array_remove_index_fast (array, j); } } } static gboolean delay_timeout_cb (gpointer data) { guint i; gboolean ret; GString *string; GsdUpdatesFirmware *firmware = GSD_UPDATES_FIRMWARE (data); NotifyNotification *notification; GPtrArray *array; GError *error = NULL; PkPackage *item = NULL; const GsdUpdatesFirmwareRequest *req; gboolean has_data = FALSE; /* message string */ string = g_string_new (""); /* try to find each firmware file in an available package */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); /* save to new array if we found one package for this file */ item = check_available (firmware, req->filename); if (item != NULL) { g_ptr_array_add (firmware->priv->packages_found, item); g_object_unref (item); } } /* nothing to do */ if (firmware->priv->packages_found->len == 0) { g_debug ("no packages providing any of the missing firmware"); goto out; } /* check we don't want the same package more than once */ remove_duplicate (firmware->priv->packages_found); /* have we got any models to array */ for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); if (req->model != NULL) { has_data = TRUE; break; } } /* TRANSLATORS: we need another package to keep udev quiet */ g_string_append (string, _("Additional firmware is required to make hardware in this computer function correctly.")); /* sdd what information we have */ if (has_data) { g_string_append (string, "\n"); for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); if (req->model != NULL) g_string_append_printf (string, "\n• %s", req->model); } g_string_append (string, "\n"); } /* TRANSLATORS: title of libnotify bubble */ notification = notify_notification_new (_("Additional firmware required"), string->str, NULL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER); notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW); notify_notification_add_action (notification, "install-firmware", /* TRANSLATORS: button label */ _("Install firmware"), libnotify_cb, firmware, NULL); notify_notification_add_action (notification, "ignore-devices", /* TRANSLATORS: we should ignore this device and not ask anymore */ _("Ignore devices"), libnotify_cb, firmware, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } out: g_string_free (string, TRUE); /* never repeat */ return FALSE; } static void remove_banned (GsdUpdatesFirmware *firmware, GPtrArray *array) { gboolean ret; gchar **banned = NULL; gchar *banned_str; GsdUpdatesFirmwareRequest *req; guint i, j; /* get from settings */ banned_str = g_settings_get_string (firmware->priv->settings, GSD_SETTINGS_BANNED_FIRMWARE); if (banned_str == NULL) { g_warning ("could not read banned list"); goto out; } /* nothing in list, common case */ if (banned_str[0] == '\0') { g_debug ("nothing in banned list"); goto out; } /* split using "," */ banned = g_strsplit (banned_str, ",", 0); /* remove any banned pattern matches */ i = 0; while (i < array->len) { ret = FALSE; req = g_ptr_array_index (array, i); for (j=0; banned[j] != NULL; j++) { ret = g_pattern_match_simple (banned[j], req->filename); if (ret) { g_debug ("match %s for %s, removing", banned[j], req->filename); g_ptr_array_remove_index_fast (array, i); break; } } if (!ret) i++; } out: g_free (banned_str); g_strfreev (banned); } static void remove_ignored (GsdUpdatesFirmware *firmware, GPtrArray *array) { gboolean ret; gchar **ignored = NULL; gchar *ignored_str; GsdUpdatesFirmwareRequest *req; guint i, j; /* get from settings */ ignored_str = g_settings_get_string (firmware->priv->settings, GSD_SETTINGS_IGNORED_DEVICES); if (ignored_str == NULL) { g_warning ("could not read ignored list"); goto out; } /* nothing in list, common case */ if (ignored_str[0] == '\0') { g_debug ("nothing in ignored list"); goto out; } /* split using "," */ ignored = g_strsplit (ignored_str, ",", 0); /* remove any ignored pattern matches */ i = 0; while (i < array->len) { ret = FALSE; req = g_ptr_array_index (array, i); if (req->id == NULL) continue; for (j=0; ignored[j] != NULL; j++) { ret = g_pattern_match_simple (ignored[j], req->id); if (ret) { g_debug ("match %s for %s, removing", ignored[j], req->id); g_ptr_array_remove_index_fast (array, i); break; } } if (!ret) i++; } out: g_free (ignored_str); g_strfreev (ignored); } static gchar * udev_text_decode (const gchar *data) { guint i; guint j; gchar *decode; decode = g_strdup (data); for (i = 0, j = 0; data[i] != '\0'; j++) { if (memcmp (&data[i], "\\x2f", 4) == 0) { decode[j] = '/'; i += 4; } else if (memcmp (&data[i], "\\x5c", 4) == 0) { decode[j] = '\\'; i += 4; } else { decode[j] = data[i]; i++; } } decode[j] = '\0'; return decode; } static gchar * get_device (GsdUpdatesFirmware *firmware, const gchar *filename) { GFile *file; GFileInfo *info; const gchar *symlink_path; gchar *syspath = NULL; GError *error = NULL; gchar *target = NULL; gchar *tmp; /* get the file data */ file = g_file_new_for_path (filename); info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, G_FILE_QUERY_INFO_NONE, NULL, &error); if (info == NULL) { g_warning ("Failed to get symlink: %s", error->message); g_error_free (error); goto out; } /* /devices/pci0000:00/0000:00:1d.0/usb5/5-2/firmware/5-2 */ symlink_path = g_file_info_get_symlink_target (info); if (symlink_path == NULL) { g_warning ("failed to get symlink target"); goto out; } /* prepend sys to make '/sys/devices/pci0000:00/0000:00:1d.0/usb5/5-2/firmware/5-2' */ syspath = g_strconcat ("/sys", symlink_path, NULL); /* start with the longest, and try to find a sub-path that exists */ tmp = &syspath[strlen (syspath)]; while (tmp != NULL) { *tmp = '\0'; g_debug ("testing %s", target); if (g_file_test (syspath, G_FILE_TEST_EXISTS)) { target = g_strdup (syspath); goto out; } tmp = g_strrstr (syspath, "/"); } out: if (info != NULL) g_object_unref (info); g_object_unref (file); g_free (syspath); return target; } static void add_filename (GsdUpdatesFirmware *firmware, const gchar *filename_no_path) { gboolean ret; gchar *filename_path = NULL; gchar *missing_path = NULL; gchar *sysfs_path = NULL; GsdUpdatesFirmwareRequest *req; GPtrArray *array; guint i; /* this is the file we want to load */ filename_path = g_build_filename (GSD_UPDATES_FIRMWARE_LOADING_DIR, filename_no_path, NULL); /* file already exists */ ret = g_file_test (filename_path, G_FILE_TEST_EXISTS); if (ret) goto out; /* this is the file that udev created for us */ missing_path = g_build_filename (GSD_UPDATES_FIRMWARE_MISSING_DIR, filename_no_path, NULL); g_debug ("filename=%s -> %s", missing_path, filename_path); /* get symlink target */ sysfs_path = get_device (firmware, missing_path); if (sysfs_path == NULL) goto out; /* find any previous requests with this path or firmware */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); if (g_strcmp0 (sysfs_path, req->sysfs_path) == 0) { g_debug ("ignoring previous sysfs request for %s", sysfs_path); goto out; } if (g_strcmp0 (filename_path, req->filename) == 0) { g_debug ("ignoring previous filename request for %s", filename_path); goto out; } } /* create new request object */ req = request_new (filename_path, sysfs_path); g_ptr_array_add (firmware->priv->array_requested, req); out: g_free (missing_path); g_free (filename_path); g_free (sysfs_path); } static void scan_directory (GsdUpdatesFirmware *firmware) { gboolean ret; GError *error = NULL; GDir *dir; const gchar *filename; gchar *filename_decoded; guint i; GPtrArray *array; const GsdUpdatesFirmwareRequest *req; guint scan_id = 0; /* should we check and show the user */ ret = g_settings_get_boolean (firmware->priv->settings, GSD_SETTINGS_ENABLE_CHECK_FIRMWARE); if (!ret) { g_debug ("not showing thanks to GSettings"); return; } /* open the directory of requests */ dir = g_dir_open (GSD_UPDATES_FIRMWARE_MISSING_DIR, 0, &error); if (dir == NULL) { if (error->code != G_FILE_ERROR_NOENT) { g_warning ("failed to open directory: %s", error->message); } g_error_free (error); return; } /* find all the firmware requests */ filename = g_dir_read_name (dir); while (filename != NULL) { filename_decoded = udev_text_decode (filename); add_filename (firmware, filename_decoded); g_free (filename_decoded); /* next file */ filename = g_dir_read_name (dir); } g_dir_close (dir); /* debugging */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); g_debug ("requested: %s", req->filename); } /* remove banned files */ remove_banned (firmware, array); /* remove ignored devices */ remove_ignored (firmware, array); /* debugging */ array = firmware->priv->array_requested; for (i=0; ilen; i++) { req = g_ptr_array_index (array, i); g_debug ("searching for: %s", req->filename); } /* don't spam the user at startup, so wait a little delay */ if (array->len > 0) { scan_id = g_timeout_add_seconds (GSD_UPDATES_FIRMWARE_PROCESS_DELAY, delay_timeout_cb, firmware); g_source_set_name_by_id (scan_id, "[GsdUpdatesFirmware] process"); } } static gboolean scan_directory_cb (GsdUpdatesFirmware *firmware) { scan_directory (firmware); firmware->priv->timeout_id = 0; return FALSE; } static void monitor_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, GsdUpdatesFirmware *firmware) { if (firmware->priv->timeout_id > 0) { g_debug ("clearing timeout as device changed"); g_source_remove (firmware->priv->timeout_id); } /* wait for the device to settle */ firmware->priv->timeout_id = g_timeout_add_seconds (GSD_UPDATES_FIRMWARE_INSERT_DELAY, (GSourceFunc) scan_directory_cb, firmware); g_source_set_name_by_id (firmware->priv->timeout_id, "[GsdUpdatesFirmware] changed"); } static void gsd_updates_firmware_class_init (GsdUpdatesFirmwareClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_updates_firmware_finalize; g_type_class_add_private (klass, sizeof (GsdUpdatesFirmwarePrivate)); } static void gsd_updates_firmware_init (GsdUpdatesFirmware *firmware) { GFile *file; GError *error = NULL; firmware->priv = GSD_UPDATES_FIRMWARE_GET_PRIVATE (firmware); firmware->priv->timeout_id = 0; firmware->priv->packages_found = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); firmware->priv->array_requested = g_ptr_array_new_with_free_func ((GDestroyNotify) request_free); firmware->priv->settings = g_settings_new (GSD_SETTINGS_SCHEMA); firmware->priv->task = pk_task_new (); g_object_set (firmware->priv->task, "background", TRUE, NULL); /* setup watch for new hardware */ file = g_file_new_for_path (GSD_UPDATES_FIRMWARE_MISSING_DIR); firmware->priv->monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, &error); if (firmware->priv->monitor == NULL) { g_warning ("failed to setup monitor: %s", error->message); g_error_free (error); goto out; } /* limit to one per second */ g_file_monitor_set_rate_limit (firmware->priv->monitor, 1000); /* get notified of changes */ g_signal_connect (firmware->priv->monitor, "changed", G_CALLBACK (monitor_changed_cb), firmware); out: g_object_unref (file); firmware->priv->timeout_id = g_timeout_add_seconds (GSD_UPDATES_FIRMWARE_LOGIN_DELAY, (GSourceFunc) scan_directory_cb, firmware); g_source_set_name_by_id (firmware->priv->timeout_id, "[GsdUpdatesFirmware] login coldplug"); } static void gsd_updates_firmware_finalize (GObject *object) { GsdUpdatesFirmware *firmware; g_return_if_fail (GSD_UPDATES_IS_FIRMWARE (object)); firmware = GSD_UPDATES_FIRMWARE (object); g_return_if_fail (firmware->priv != NULL); g_ptr_array_unref (firmware->priv->array_requested); g_ptr_array_unref (firmware->priv->packages_found); g_object_unref (PK_CLIENT(firmware->priv->task)); g_object_unref (firmware->priv->settings); if (firmware->priv->monitor != NULL) g_object_unref (firmware->priv->monitor); if (firmware->priv->timeout_id > 0) g_source_remove (firmware->priv->timeout_id); G_OBJECT_CLASS (gsd_updates_firmware_parent_class)->finalize (object); } GsdUpdatesFirmware * gsd_updates_firmware_new (void) { GsdUpdatesFirmware *firmware; firmware = g_object_new (GSD_UPDATES_TYPE_FIRMWARE, NULL); return GSD_UPDATES_FIRMWARE (firmware); } unity-settings-daemon/plugins/updates/gsd-updates-firmware.h0000664000000000000000000000367015172222611021553 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GSD_UPDATES_FIRMWARE_H #define __GSD_UPDATES_FIRMWARE_H #include G_BEGIN_DECLS #define GSD_UPDATES_TYPE_FIRMWARE (gsd_updates_firmware_get_type ()) #define GSD_UPDATES_FIRMWARE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_UPDATES_TYPE_FIRMWARE, GsdUpdatesFirmware)) #define GSD_UPDATES_FIRMWARE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_UPDATES_TYPE_FIRMWARE, GsdUpdatesFirmwareClass)) #define GSD_UPDATES_IS_FIRMWARE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_UPDATES_TYPE_FIRMWARE)) typedef struct GsdUpdatesFirmwarePrivate GsdUpdatesFirmwarePrivate; typedef struct { GObject parent; GsdUpdatesFirmwarePrivate *priv; } GsdUpdatesFirmware; typedef struct { GObjectClass parent_class; } GsdUpdatesFirmwareClass; GType gsd_updates_firmware_get_type (void); GsdUpdatesFirmware *gsd_updates_firmware_new (void); G_END_DECLS #endif /* __GSD_UPDATES_FIRMWARE_H */ unity-settings-daemon/plugins/updates/gsd-updates-manager.c0000664000000000000000000016152715172222611021352 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include "gsd-enums.h" #include "gsd-updates-manager.h" #include "gsd-updates-firmware.h" #include "gsd-updates-refresh.h" #include "gsd-updates-common.h" #include "gnome-settings-profile.h" #include "gnome-settings-bus.h" #define GSD_UPDATES_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerPrivate)) #define MAX_FAILED_GET_UPDATES 10 /* the maximum number of tries */ #define GSD_UPDATES_ICON_NORMAL "software-update-available-symbolic" #define GSD_UPDATES_ICON_URGENT "software-update-urgent-symbolic" #define GSD_UPDATES_CHECK_OFFLINE_TIMEOUT 30 /* time in seconds */ struct GsdUpdatesManagerPrivate { GCancellable *cancellable; GsdUpdatesRefresh *refresh; GsdUpdatesFirmware *firmware; GSettings *settings_proxy; GSettings *settings_ftp; GSettings *settings_gsd; GSettings *settings_http; guint number_updates_critical_last_shown; guint offline_update_id; PkError *offline_update_error; NotifyNotification *notification_updates; PkControl *control; PkTask *task; guint inhibit_cookie; GsdSessionManager *proxy_session; guint update_viewer_watcher_id; GVolumeMonitor *volume_monitor; guint failed_get_updates_count; GPtrArray *update_packages; }; static void gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass); static void gsd_updates_manager_init (GsdUpdatesManager *updates_manager); G_DEFINE_TYPE (GsdUpdatesManager, gsd_updates_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; static void child_exit_cb (GPid pid, gint status, gpointer user_data) { g_spawn_close_pid (pid); } static void clear_offline_updates_message (void) { gboolean ret; GError *error = NULL; gchar *argv[3]; GPid pid; argv[0] = "pkexec"; argv[1] = LIBEXECDIR "/pk-clear-offline-update"; argv[2] = NULL; ret = g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, &error); if (!ret) { g_warning ("Failure clearing offline update message: %s", error->message); g_error_free (error); return; } g_child_watch_add (pid, child_exit_cb, NULL); } static void show_offline_updates_error (GsdUpdatesManager *manager) { const gchar *title; gboolean show_geeky = FALSE; GString *msg; GtkWidget *dialog; /* TRANSLATORS: this is when the offline update failed */ title = _("Failed To Update"); msg = g_string_new (""); switch (pk_error_get_code (manager->priv->offline_update_error)) { case PK_ERROR_ENUM_UNFINISHED_TRANSACTION: /* TRANSLATORS: the transaction could not be completed * as a previous transaction was unfinished */ g_string_append (msg, _("A previous update was unfinished.")); show_geeky = TRUE; break; case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED: case PK_ERROR_ENUM_NO_CACHE: case PK_ERROR_ENUM_NO_NETWORK: case PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY: case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES: /* TRANSLATORS: the package manager needed to download * something with no network available */ g_string_append (msg, _("Network access was required but not available.")); break; case PK_ERROR_ENUM_BAD_GPG_SIGNATURE: case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED: case PK_ERROR_ENUM_GPG_FAILURE: case PK_ERROR_ENUM_MISSING_GPG_SIGNATURE: case PK_ERROR_ENUM_PACKAGE_CORRUPT: /* TRANSLATORS: if the package is not signed correctly * */ g_string_append (msg, _("An update was not signed in the correct way.")); show_geeky = TRUE; break; case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED: case PK_ERROR_ENUM_FILE_CONFLICTS: case PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE: case PK_ERROR_ENUM_PACKAGE_CONFLICTS: /* TRANSLATORS: the transaction failed in a way the user * probably cannot comprehend. Package management systems * really are teh suck.*/ g_string_append (msg, _("The update could not be completed.")); show_geeky = TRUE; break; case PK_ERROR_ENUM_TRANSACTION_CANCELLED: /* TRANSLATORS: the user aborted the update manually */ g_string_append (msg, _("The update was cancelled.")); break; case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE: case PK_ERROR_ENUM_UPDATE_NOT_FOUND: /* TRANSLATORS: the user must have updated manually after * the updates were prepared */ g_string_append (msg, _("An offline update was requested but no packages required updating.")); break; case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE: /* TRANSLATORS: we ran out of disk space */ g_string_append (msg, _("No space was left on the drive.")); break; case PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD: case PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL: case PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE: /* TRANSLATORS: the update process failed in a general * way, usually this message will come from source distros * like gentoo */ g_string_append (msg, _("An update failed to install correctly.")); show_geeky = TRUE; break; default: /* TRANSLATORS: We didn't handle the error type */ g_string_append (msg, _("The offline update failed in an unexpected way.")); show_geeky = TRUE; break; } if (show_geeky) { g_string_append_printf (msg, "\n%s\n\n%s", /* TRANSLATORS: these are geeky messages from the * package manager no mortal is supposed to understand, * but google might know what they mean */ _("Detailed errors from the package manager follow:"), pk_error_get_details (manager->priv->offline_update_error)); } dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s", title); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", msg->str); g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); gtk_widget_show (dialog); clear_offline_updates_message (); g_string_free (msg, TRUE); } static void libnotify_action_cb (NotifyNotification *notification, gchar *action, gpointer user_data) { gboolean ret; GError *error = NULL; GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data); notify_notification_close (notification, NULL); if (g_strcmp0 (action, "distro-upgrade-info") == 0) { ret = g_spawn_command_line_async (DATADIR "/PackageKit/pk-upgrade-distro.sh", &error); if (!ret) { g_warning ("Failure launching pk-upgrade-distro.sh: %s", error->message); g_error_free (error); } goto out; } if (g_strcmp0 (action, "show-update-viewer") == 0) { ret = g_spawn_command_line_async (BINDIR "/gpk-update-viewer", &error); if (!ret) { g_warning ("Failure launching update viewer: %s", error->message); g_error_free (error); } goto out; } if (g_strcmp0 (action, "clear-offline-updates") == 0) { clear_offline_updates_message (); goto out; } if (g_strcmp0 (action, "error-offline-updates") == 0) { show_offline_updates_error (manager); goto out; } if (g_strcmp0 (action, "cancel") == 0) { /* try to cancel */ g_cancellable_cancel (manager->priv->cancellable); goto out; } g_warning ("unknown action id: %s", action); out: return; } static void on_notification_closed (NotifyNotification *notification, gpointer data) { g_object_unref (notification); } static void get_distro_upgrades_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager) { const gchar *title; gboolean ret; gchar *name = NULL; GError *error = NULL; GPtrArray *array = NULL; GString *string = NULL; guint i; NotifyNotification *notification; PkClient *client = PK_CLIENT(object); PkDistroUpgrade *item; PkError *error_code = NULL; PkResults *results; PkUpdateStateEnum state; /* get the results */ results = pk_client_generic_finish (PK_CLIENT(client), res, &error); if (results == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } if (error->domain != PK_CLIENT_ERROR || error->code != PK_CLIENT_ERROR_NOT_SUPPORTED) { g_warning ("failed to get upgrades: %s", error->message); } g_error_free (error); goto out; } /* check error code */ error_code = pk_results_get_error_code (results); if (error_code != NULL) { g_warning ("failed to get upgrades: %s, %s", pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code)); goto out; } /* process results */ array = pk_results_get_distro_upgrade_array (results); /* any updates? */ if (array->len == 0) { g_debug ("no upgrades"); goto out; } /* do we do the notification? */ ret = g_settings_get_boolean (manager->priv->settings_gsd, GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES); if (!ret) { g_debug ("ignoring due to GSettings"); goto out; } /* find the upgrade string */ string = g_string_new (""); for (i=0; i < array->len; i++) { item = (PkDistroUpgrade *) g_ptr_array_index (array, i); g_object_get (item, "name", &name, "state", &state, NULL); g_string_append_printf (string, "%s (%s)\n", name, pk_distro_upgrade_enum_to_string (state)); g_free (name); } if (string->len != 0) g_string_set_size (string, string->len-1); /* TRANSLATORS: a distro update is available, e.g. Fedora 8 to Fedora 9 */ title = _("Distribution upgrades available"); notification = notify_notification_new (title, string->str, GSD_UPDATES_ICON_NORMAL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER); notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); notify_notification_add_action (notification, "distro-upgrade-info", /* TRANSLATORS: provides more information about the upgrade */ _("More information"), libnotify_action_cb, manager, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } out: if (error_code != NULL) g_object_unref (error_code); if (array != NULL) g_ptr_array_unref (array); if (string != NULL) g_string_free (string, TRUE); if (results != NULL) g_object_unref (results); } static void due_get_upgrades_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager) { /* optimize the amount of downloaded data by setting the cache age */ pk_client_set_cache_age (PK_CLIENT(manager->priv->task), g_settings_get_int (manager->priv->settings_gsd, GSD_SETTINGS_FREQUENCY_GET_UPGRADES)); /* get new distro upgrades list */ pk_client_get_distro_upgrades_async (PK_CLIENT(manager->priv->task), NULL, NULL, NULL, (GAsyncReadyCallback) get_distro_upgrades_finished_cb, manager); } static void refresh_cache_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager) { PkClient *client = PK_CLIENT(object); PkResults *results; GError *error = NULL; PkError *error_code = NULL; /* get the results */ results = pk_client_generic_finish (PK_CLIENT(client), res, &error); if (results == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } g_warning ("failed to refresh the cache: %s", error->message); g_error_free (error); return; } /* check error code */ error_code = pk_results_get_error_code (results); if (error_code != NULL) { g_warning ("failed to refresh the cache: %s, %s", pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code)); } if (error_code != NULL) g_object_unref (error_code); if (results != NULL) g_object_unref (results); } static void due_refresh_cache_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager) { /* optimize the amount of downloaded data by setting the cache age */ pk_client_set_cache_age (PK_CLIENT(manager->priv->task), g_settings_get_int (manager->priv->settings_gsd, GSD_SETTINGS_FREQUENCY_REFRESH_CACHE)); pk_client_refresh_cache_async (PK_CLIENT(manager->priv->task), TRUE, NULL, NULL, NULL, (GAsyncReadyCallback) refresh_cache_finished_cb, manager); } static void notify_critical_updates (GsdUpdatesManager *manager, GPtrArray *array) { const gchar *message; const gchar *title; gboolean ret; GError *error = NULL; NotifyNotification *notification; /* if the number of critical updates is the same as the last notification, * then skip the notifcation as we don't want to bombard the user every hour */ if (array->len == manager->priv->number_updates_critical_last_shown) { g_debug ("ignoring as user ignored last warning"); return; } /* save for comparison later */ manager->priv->number_updates_critical_last_shown = array->len; /* TRANSLATORS: title in the libnotify popup */ title = ngettext ("Update", "Updates", array->len); /* TRANSLATORS: message when there are security updates */ message = ngettext ("An important software update is available", "Important software updates are available", array->len); /* close any existing notification */ if (manager->priv->notification_updates != NULL) { notify_notification_close (manager->priv->notification_updates, NULL); manager->priv->notification_updates = NULL; } /* do the bubble */ g_debug ("title=%s, message=%s", title, message); notification = notify_notification_new (title, message, GSD_UPDATES_ICON_URGENT); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, 15000); notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL); notify_notification_add_action (notification, "show-update-viewer", /* TRANSLATORS: button: open the update viewer to install updates*/ _("Install updates"), libnotify_action_cb, manager, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } /* track so we can prevent doubled notifications */ manager->priv->notification_updates = notification; g_object_add_weak_pointer (G_OBJECT (manager->priv->notification_updates), (void **) &manager->priv->notification_updates); } static void notify_normal_updates_maybe (GsdUpdatesManager *manager, GPtrArray *array) { const gchar *message; const gchar *title; gboolean ret; GError *error = NULL; guint64 time_last_notify; guint64 time_now; guint freq_updates_notify; NotifyNotification *notification; /* find out if enough time has passed since the last notification */ time_now = g_get_real_time () / 1000000; freq_updates_notify = g_settings_get_int (manager->priv->settings_gsd, GSD_SETTINGS_FREQUENCY_UPDATES_NOTIFICATION); g_settings_get (manager->priv->settings_gsd, GSD_SETTINGS_LAST_UPDATES_NOTIFICATION, "t", &time_last_notify); if (time_last_notify > 0 && (guint64) freq_updates_notify > time_now - time_last_notify) { g_debug ("not showing non-critical notification as already shown %i hours ago", (guint) (time_now - time_last_notify) / (60 * 60)); return; } /* TRANSLATORS: title in the libnotify popup */ title = ngettext ("Update", "Updates", array->len); /* TRANSLATORS: message when there are non-security updates */ message = ngettext ("A software update is available.", "Software updates are available.", array->len); /* close any existing notification */ if (manager->priv->notification_updates != NULL) { notify_notification_close (manager->priv->notification_updates, NULL); manager->priv->notification_updates = NULL; } /* do the bubble */ g_debug ("title=%s, message=%s", title, message); notification = notify_notification_new (title, message, GSD_UPDATES_ICON_NORMAL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, 15000); notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); notify_notification_add_action (notification, "show-update-viewer", /* TRANSLATORS: button: open the update viewer to install updates*/ _("Install updates"), libnotify_action_cb, manager, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } /* reset notification time */ g_settings_set (manager->priv->settings_gsd, GSD_SETTINGS_LAST_UPDATES_NOTIFICATION, "t", time_now); /* track so we can prevent doubled notifications */ manager->priv->notification_updates = notification; g_object_add_weak_pointer (G_OBJECT (manager->priv->notification_updates), (void **) &manager->priv->notification_updates); } static void notify_failed_get_updates_maybe (GsdUpdatesManager *manager) { const gchar *button; const gchar *message; const gchar *title; gboolean ret; GError *error = NULL; NotifyNotification *notification; /* give the user a break */ if (manager->priv->failed_get_updates_count++ < MAX_FAILED_GET_UPDATES) { g_debug ("failed GetUpdates, but will retry %i more times before notification", MAX_FAILED_GET_UPDATES - manager->priv->failed_get_updates_count); goto out; } /* TRANSLATORS: the updates mechanism */ title = _("Updates"); /* TRANSLATORS: we failed to get the updates multiple times, * and now we need to inform the user that something might be wrong */ message = _("Unable to access software updates"); /* TRANSLATORS: try again, this time launching the update viewer */ button = _("Try again"); notification = notify_notification_new (title, message, GSD_UPDATES_ICON_NORMAL); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, 120*1000); notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); notify_notification_add_action (notification, "show-update-viewer", button, libnotify_action_cb, manager, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("failed to show notification: %s", error->message); g_error_free (error); } out: /* reset, even if the message failed */ manager->priv->failed_get_updates_count = 0; } static void check_updates_for_importance (GsdUpdatesManager *manager) { guint i; PkPackage *pkg; GPtrArray *important_array; /* check each package */ important_array = g_ptr_array_new (); for (i = 0; i < manager->priv->update_packages->len; i++) { pkg = g_ptr_array_index (manager->priv->update_packages, i); if (pk_package_get_info (pkg) == PK_INFO_ENUM_SECURITY || pk_package_get_info (pkg) == PK_INFO_ENUM_IMPORTANT) g_ptr_array_add (important_array, pkg); } if (important_array->len > 0) { notify_critical_updates (manager, important_array); } else { notify_normal_updates_maybe (manager, manager->priv->update_packages); } g_ptr_array_unref (important_array); } static void package_download_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager) { PkClient *client = PK_CLIENT(object); PkResults *results; GError *error = NULL; PkError *error_code = NULL; /* get the results */ results = pk_client_generic_finish (PK_CLIENT(client), res, &error); if (results == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } g_warning ("failed to download: %s", error->message); g_error_free (error); notify_failed_get_updates_maybe (manager); return; } /* check error code */ error_code = pk_results_get_error_code (results); if (error_code != NULL) { g_warning ("failed to download: %s, %s", pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code)); switch (pk_error_get_code (error_code)) { case PK_ERROR_ENUM_CANCELLED_PRIORITY: case PK_ERROR_ENUM_TRANSACTION_CANCELLED: g_debug ("ignoring error"); break; default: notify_failed_get_updates_maybe (manager); break; } goto out; } /* check to see if should notify */ check_updates_for_importance (manager); out: if (error_code != NULL) g_object_unref (error_code); if (results != NULL) g_object_unref (results); } static void auto_download_updates (GsdUpdatesManager *manager) { gchar **package_ids; guint i; PkPackage *pkg; /* download each package */ package_ids = g_new0 (gchar *, manager->priv->update_packages->len + 1); for (i = 0; i < manager->priv->update_packages->len; i++) { pkg = g_ptr_array_index (manager->priv->update_packages, i); package_ids[i] = g_strdup (pk_package_get_id (pkg)); } #if PK_CHECK_VERSION(0,8,1) /* we've set only-download in PkTask */ pk_task_update_packages_async (manager->priv->task, package_ids, manager->priv->cancellable, NULL, NULL, (GAsyncReadyCallback) package_download_finished_cb, manager); #else /* download them all */ pk_client_download_packages_async (PK_CLIENT(manager->priv->task), package_ids, NULL, /* this means system cache */ manager->priv->cancellable, NULL, NULL, (GAsyncReadyCallback) package_download_finished_cb, manager); #endif g_strfreev (package_ids); } static void get_updates_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager) { PkClient *client = PK_CLIENT(object); PkResults *results; GError *error = NULL; gboolean ret; PkError *error_code = NULL; /* get the results */ results = pk_client_generic_finish (PK_CLIENT(client), res, &error); if (results == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } g_warning ("failed to get updates: %s", error->message); g_error_free (error); notify_failed_get_updates_maybe (manager); goto out; } /* check error code */ error_code = pk_results_get_error_code (results); if (error_code != NULL) { g_warning ("failed to get updates: %s, %s", pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code)); switch (pk_error_get_code (error_code)) { case PK_ERROR_ENUM_CANCELLED_PRIORITY: case PK_ERROR_ENUM_TRANSACTION_CANCELLED: g_debug ("ignoring error"); break; default: notify_failed_get_updates_maybe (manager); break; } goto out; } /* we succeeded, so clear the count */ manager->priv->failed_get_updates_count = 0; /* so we can download or check for important & security updates */ if (manager->priv->update_packages != NULL) g_ptr_array_unref (manager->priv->update_packages); manager->priv->update_packages = pk_results_get_package_array (results); /* we have no updates */ if (manager->priv->update_packages->len == 0) { g_debug ("no updates"); goto out; } /* should we auto-download the updates? */ ret = g_settings_get_boolean (manager->priv->settings_gsd, GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES); if (ret) { auto_download_updates (manager); goto out; } /* just check to see if should notify */ check_updates_for_importance (manager); out: if (error_code != NULL) g_object_unref (error_code); if (results != NULL) g_object_unref (results); } static void query_updates (GsdUpdatesManager *manager) { /* optimize the amount of downloaded data by setting the cache age */ pk_client_set_cache_age (PK_CLIENT(manager->priv->task), g_settings_get_int (manager->priv->settings_gsd, GSD_SETTINGS_FREQUENCY_GET_UPDATES)); /* get new update list */ pk_client_get_updates_async (PK_CLIENT(manager->priv->task), pk_bitfield_value (PK_FILTER_ENUM_NONE), manager->priv->cancellable, NULL, NULL, (GAsyncReadyCallback) get_updates_finished_cb, manager); } static void due_get_updates_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager) { query_updates (manager); } static gchar * get_proxy_http (GsdUpdatesManager *manager) { gboolean ret; gchar *host = NULL; gchar *password = NULL; gchar *proxy = NULL; gchar *username = NULL; GString *string = NULL; guint port; GDesktopProxyMode proxy_mode; proxy_mode = g_settings_get_enum (manager->priv->settings_proxy, "mode"); if (proxy_mode != G_DESKTOP_PROXY_MODE_MANUAL) goto out; host = g_settings_get_string (manager->priv->settings_http, "host"); if (host == NULL) goto out; port = g_settings_get_int (manager->priv->settings_http, "port"); /* use an HTTP auth string? */ ret = g_settings_get_boolean (manager->priv->settings_http, "use-authentication"); if (ret) { username = g_settings_get_string (manager->priv->settings_http, "authentication-user"); password = g_settings_get_string (manager->priv->settings_http, "authentication-password"); } /* make PackageKit proxy string */ string = g_string_new (host); if (port > 0) g_string_append_printf (string, ":%i", port); if (username != NULL && password != NULL) g_string_append_printf (string, "@%s:%s", username, password); else if (username != NULL) g_string_append_printf (string, "@%s", username); else if (password != NULL) g_string_append_printf (string, "@:%s", password); proxy = g_string_free (string, FALSE); out: g_free (host); g_free (username); g_free (password); return proxy; } static gchar * get_proxy_ftp (GsdUpdatesManager *manager) { gchar *host = NULL; gchar *proxy = NULL; GString *string = NULL; guint port; GDesktopProxyMode proxy_mode; proxy_mode = g_settings_get_enum (manager->priv->settings_proxy, "mode"); if (proxy_mode != G_DESKTOP_PROXY_MODE_MANUAL) goto out; host = g_settings_get_string (manager->priv->settings_ftp, "host"); if (host == NULL) goto out; port = g_settings_get_int (manager->priv->settings_ftp, "port"); if (port == 0) goto out; /* make PackageKit proxy string */ string = g_string_new (host); if (port > 0) g_string_append_printf (string, ":%i", port); proxy = g_string_free (string, FALSE); out: g_free (host); return proxy; } static void set_proxy_cb (GObject *object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; PkControl *control = PK_CONTROL (object); /* get the result */ ret = pk_control_set_proxy_finish (control, res, &error); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("failed to set proxies: %s", error->message); g_error_free (error); } } static void reload_proxy_settings (GsdUpdatesManager *manager) { gchar *proxy_http; gchar *proxy_ftp; proxy_http = get_proxy_http (manager); proxy_ftp = get_proxy_ftp (manager); /* send to daemon */ pk_control_set_proxy_async (manager->priv->control, proxy_http, proxy_ftp, NULL, set_proxy_cb, manager); g_free (proxy_http); g_free (proxy_ftp); } static void settings_changed_cb (GSettings *settings, const char *key, GsdUpdatesManager *manager) { reload_proxy_settings (manager); } static void settings_gsd_changed_cb (GSettings *settings, const char *key, GsdUpdatesManager *manager) { } static void session_inhibit (GsdUpdatesManager *manager) { const gchar *reason; GError *error = NULL; GVariant *retval = NULL; /* state invalid somehow */ if (manager->priv->inhibit_cookie != 0) { g_warning ("already locked"); goto out; } /* TRANSLATORS: the reason why we've inhibited it */ reason = _("A transaction that cannot be interrupted is running"); retval = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->proxy_session), "Inhibit", g_variant_new ("(susu)", "gnome-settings-daemon", /* app-id */ 0, /* xid */ reason, /* reason */ 4 /* flags */), G_DBUS_CALL_FLAGS_NONE, -1, manager->priv->cancellable, &error); if (retval == NULL) { g_warning ("failed to inhibit gnome-session: %s", error->message); g_error_free (error); goto out; } /* get cookie */ g_variant_get (retval, "(u)", &manager->priv->inhibit_cookie); out: if (retval != NULL) g_variant_unref (retval); } static void session_uninhibit (GsdUpdatesManager *manager) { GError *error = NULL; GVariant *retval = NULL; /* state invalid somehow */ if (manager->priv->inhibit_cookie == 0) { g_warning ("not locked"); goto out; } retval = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->proxy_session), "Uninhibit", g_variant_new ("(u)", manager->priv->inhibit_cookie), G_DBUS_CALL_FLAGS_NONE, -1, manager->priv->cancellable, &error); if (retval == NULL) { g_warning ("failed to uninhibit gnome-session: %s", error->message); g_error_free (error); goto out; } out: manager->priv->inhibit_cookie = 0; if (retval != NULL) g_variant_unref (retval); } static void notify_locked_cb (PkControl *control, GParamSpec *pspec, GsdUpdatesManager *manager) { gboolean locked; g_object_get (control, "locked", &locked, NULL); /* TODO: locked is a bit harsh, we can probably still allow * reboot when packages are downloading or the transaction is * depsolving */ if (locked) { session_inhibit (manager); } else { session_uninhibit (manager); } } static void update_viewer_appeared_cb (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data); /* close any existing notification */ if (manager->priv->notification_updates != NULL) { g_debug ("update viewer on the bus, clearing bubble"); notify_notification_close (manager->priv->notification_updates, NULL); manager->priv->notification_updates = NULL; } } static gboolean file_exists_in_root (const gchar *root, const gchar *filename) { gboolean ret = FALSE; GFile *source; gchar *source_path; source_path = g_build_filename (root, filename, NULL); source = g_file_new_for_path (source_path); /* ignore virtual mountpoints */ if (!g_file_is_native (source)) goto out; /* an interesting file exists */ ret = g_file_query_exists (source, NULL); g_debug ("checking for %s: %s", source_path, ret ? "yes" : "no"); if (!ret) goto out; out: g_free (source_path); g_object_unref (source); return ret; } static void mount_added_cb (GVolumeMonitor *volume_monitor, GMount *mount, GsdUpdatesManager *manager) { gboolean ret = FALSE; gchar **filenames = NULL; gchar *media_repo_filenames; gchar *root_path; GFile *root; guint i; /* check if any installed media is an install disk */ root = g_mount_get_root (mount); root_path = g_file_get_path (root); /* use settings */ media_repo_filenames = g_settings_get_string (manager->priv->settings_gsd, GSD_SETTINGS_MEDIA_REPO_FILENAMES); if (media_repo_filenames == NULL) { g_warning ("failed to get media repo filenames"); goto out; } /* search each possible filename */ filenames = g_strsplit (media_repo_filenames, ",", -1); for (i=0; filenames[i] != NULL; i++) { ret = file_exists_in_root (root_path, filenames[i]); if (ret) break; } /* do an updates check with the new media */ if (ret) query_updates (manager); out: g_strfreev (filenames); g_free (media_repo_filenames); g_free (root_path); g_object_unref (root); } #define PK_OFFLINE_UPDATE_RESULTS_GROUP "PackageKit Offline Update Results" #define PK_OFFLINE_UPDATE_RESULTS_FILENAME "/var/lib/PackageKit/offline-update-competed" static gboolean check_offline_update_cb (gpointer user_data) { const gchar *message; const gchar *title; gboolean ret; gboolean success; gchar *error_code = NULL; gchar *error_details = NULL; gchar *packages = NULL; GError *error = NULL; GKeyFile *key_file = NULL; GsdUpdatesManager *manager = (GsdUpdatesManager *) user_data; guint i; guint num_packages = 1; NotifyNotification *notification; PkErrorEnum error_enum = PK_ERROR_ENUM_UNKNOWN; /* was any offline update attempted */ if (!g_file_test (PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_FILE_TEST_EXISTS)) goto out; /* open the file and see what happened */ key_file = g_key_file_new (); ret = g_key_file_load_from_file (key_file, PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_KEY_FILE_NONE, &error); if (!ret) { g_warning ("failed to open %s: %s", PK_OFFLINE_UPDATE_RESULTS_FILENAME, error->message); g_error_free (error); goto out; } success = g_key_file_get_boolean (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "Success", NULL); if (success) { packages = g_key_file_get_string (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "Packages", NULL); if (packages == NULL) { g_warning ("No 'Packages' in %s", PK_OFFLINE_UPDATE_RESULTS_FILENAME); goto out; } /* count the packages for translators */ for (i = 0; packages[i] != '\0'; i++) { if (packages[i] == ',') num_packages++; } /* TRANSLATORS: title in the libnotify popup */ title = ngettext ("Software Update Installed", "Software Updates Installed", num_packages); /* TRANSLATORS: message when we've done offline updates */ message = ngettext ("An important OS update has been installed.", "Important OS updates have been installed.", num_packages); /* no need to keep the file around anymore */ clear_offline_updates_message (); } else { /* get error details */ manager->priv->offline_update_error = pk_error_new (); error_code = g_key_file_get_string (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "ErrorCode", NULL); if (error_code != NULL) error_enum = pk_error_enum_from_string (error_code); error_details = g_key_file_get_string (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "ErrorDetails", NULL); g_object_set (manager->priv->offline_update_error, "code", error_enum, "details", error_details, NULL); /* TRANSLATORS: title in the libnotify popup */ title = _("Software Updates Failed"); /* TRANSLATORS: message when we've not done offline updates */ message = _("An important OS update failed to be installed."); } /* do the bubble */ g_debug ("title=%s, message=%s", title, message); notification = notify_notification_new (title, message, GSD_UPDATES_ICON_URGENT); notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer"); notify_notification_set_app_name (notification, _("Software Updates")); notify_notification_set_timeout (notification, -1); notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); if (success) { #if 0 notify_notification_add_action (notification, "review-offline-updates", /* TRANSLATORS: button: review the offline update changes */ _("Review"), libnotify_action_cb, manager, NULL); #endif } else { notify_notification_add_action (notification, "error-offline-updates", /* TRANSLATORS: button: review the offline update changes */ _("Show details"), libnotify_action_cb, manager, NULL); } notify_notification_add_action (notification, "clear-offline-updates", /* TRANSLATORS: button: clear notification */ _("OK"), libnotify_action_cb, manager, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notification_closed), NULL); ret = notify_notification_show (notification, &error); if (!ret) { g_warning ("error: %s", error->message); g_error_free (error); } out: g_free (packages); g_free (error_code); g_free (error_details); if (key_file != NULL) g_key_file_free (key_file); manager->priv->offline_update_id = 0; return FALSE; } gboolean gsd_updates_manager_start (GsdUpdatesManager *manager, GError **error) { gboolean ret = FALSE; g_debug ("Starting updates manager"); /* use PackageKit */ manager->priv->cancellable = g_cancellable_new (); manager->priv->control = pk_control_new (); g_signal_connect (manager->priv->control, "notify::locked", G_CALLBACK (notify_locked_cb), manager); manager->priv->task = pk_task_new (); g_object_set (manager->priv->task, "background", TRUE, "interactive", FALSE, #if PK_CHECK_VERSION(0,8,1) "only-download", TRUE, #endif NULL); /* watch UDev for missing firmware */ manager->priv->firmware = gsd_updates_firmware_new (); /* get automatic callbacks about when we should check for * updates, refresh-caches and upgrades */ manager->priv->refresh = gsd_updates_refresh_new (); g_signal_connect (manager->priv->refresh, "get-upgrades", G_CALLBACK (due_get_upgrades_cb), manager); g_signal_connect (manager->priv->refresh, "refresh-cache", G_CALLBACK (due_refresh_cache_cb), manager); g_signal_connect (manager->priv->refresh, "get-updates", G_CALLBACK (due_get_updates_cb), manager); /* get proxy settings */ manager->priv->settings_proxy = g_settings_new ("org.gnome.system.proxy"); g_signal_connect (manager->priv->settings_proxy, "changed", G_CALLBACK (settings_changed_cb), manager); /* get http settings */ manager->priv->settings_http = g_settings_new ("org.gnome.system.proxy.http"); g_signal_connect (manager->priv->settings_http, "changed", G_CALLBACK (settings_changed_cb), manager); /* get ftp settings */ manager->priv->settings_ftp = g_settings_new ("org.gnome.system.proxy.ftp"); g_signal_connect (manager->priv->settings_ftp, "changed", G_CALLBACK (settings_changed_cb), manager); /* get ftp settings */ manager->priv->settings_gsd = g_settings_new ("com.canonical.unity.settings-daemon.plugins.updates"); g_signal_connect (manager->priv->settings_gsd, "changed", G_CALLBACK (settings_gsd_changed_cb), manager); /* use gnome-session for the idle detection */ manager->priv->proxy_session = gnome_settings_bus_get_session_proxy (); if (manager->priv->proxy_session == NULL) goto out; /* if the update viewer is started, then hide the notification */ manager->priv->update_viewer_watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, "org.freedesktop.PackageKit.UpdateViewer", G_BUS_NAME_WATCHER_FLAGS_NONE, update_viewer_appeared_cb, NULL, manager, NULL); /* get a volume monitor so we can watch media */ manager->priv->volume_monitor = g_volume_monitor_get (); g_signal_connect (manager->priv->volume_monitor, "mount-added", G_CALLBACK (mount_added_cb), manager); /* coldplug */ reload_proxy_settings (manager); /* check for offline update */ manager->priv->offline_update_id = g_timeout_add_seconds (GSD_UPDATES_CHECK_OFFLINE_TIMEOUT, check_offline_update_cb, manager); /* success */ ret = TRUE; g_debug ("Started updates manager"); out: return ret; } void gsd_updates_manager_stop (GsdUpdatesManager *manager) { g_debug ("Stopping updates manager"); g_clear_object (&manager->priv->settings_proxy); g_clear_object (&manager->priv->settings_http); g_clear_object (&manager->priv->settings_ftp); g_clear_object (&manager->priv->settings_gsd); g_clear_object (&manager->priv->control); g_clear_object (&manager->priv->task); g_clear_object (&manager->priv->refresh); g_clear_object (&manager->priv->firmware); g_clear_object (&manager->priv->proxy_session); g_clear_object (&manager->priv->volume_monitor); if (manager->priv->cancellable) { g_cancellable_cancel (manager->priv->cancellable); g_clear_object (&manager->priv->cancellable); } if (manager->priv->update_viewer_watcher_id != 0) { g_bus_unwatch_name (manager->priv->update_viewer_watcher_id); manager->priv->update_viewer_watcher_id = 0; } if (manager->priv->offline_update_id) { g_source_remove (manager->priv->offline_update_id); manager->priv->offline_update_id = 0; } if (manager->priv->update_packages != NULL) { g_ptr_array_unref (manager->priv->update_packages); manager->priv->update_packages = NULL; } g_clear_object (&manager->priv->offline_update_error); } static GObject * gsd_updates_manager_constructor ( GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GsdUpdatesManager *m; m = GSD_UPDATES_MANAGER (G_OBJECT_CLASS (gsd_updates_manager_parent_class)->constructor ( type, n_construct_properties, construct_properties)); return G_OBJECT (m); } static void gsd_updates_manager_dispose (GObject *object) { GsdUpdatesManager *manager; manager = GSD_UPDATES_MANAGER (object); gsd_updates_manager_stop (manager); G_OBJECT_CLASS (gsd_updates_manager_parent_class)->dispose (object); } static void gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gsd_updates_manager_constructor; object_class->dispose = gsd_updates_manager_dispose; g_type_class_add_private (klass, sizeof (GsdUpdatesManagerPrivate)); } static void gsd_updates_manager_init (GsdUpdatesManager *manager) { manager->priv = GSD_UPDATES_MANAGER_GET_PRIVATE (manager); } GsdUpdatesManager * gsd_updates_manager_new (void) { if (manager_object) { g_object_ref (manager_object); } else { manager_object = g_object_new (GSD_TYPE_UPDATES_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); } return GSD_UPDATES_MANAGER (manager_object); } unity-settings-daemon/plugins/updates/gsd-updates-manager.h0000664000000000000000000000420515172222611021344 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __GSD_UPDATES_MANAGER_H #define __GSD_UPDATES_MANAGER_H #include #include G_BEGIN_DECLS #define GSD_TYPE_UPDATES_MANAGER (gsd_updates_manager_get_type ()) #define GSD_UPDATES_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManager)) #define GSD_UPDATES_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerClass)) #define GSD_IS_UPDATES_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_UPDATES_MANAGER)) #define GSD_IS_UPDATES_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_UPDATES_MANAGER)) #define GSD_UPDATES_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerClass)) typedef struct GsdUpdatesManagerPrivate GsdUpdatesManagerPrivate; typedef struct { GObject parent; GsdUpdatesManagerPrivate *priv; } GsdUpdatesManager; typedef struct { GObjectClass parent_class; } GsdUpdatesManagerClass; GType gsd_updates_manager_get_type (void) G_GNUC_CONST; GsdUpdatesManager *gsd_updates_manager_new (void); gboolean gsd_updates_manager_start (GsdUpdatesManager *manager, GError **error); void gsd_updates_manager_stop (GsdUpdatesManager *manager); G_END_DECLS #endif /* __GSD_UPDATES_MANAGER_H */ unity-settings-daemon/plugins/updates/gsd-updates-plugin.c0000664000000000000000000000202415172222611021220 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2011 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "gnome-settings-plugin.h" #include "gsd-updates-manager.h" GNOME_SETTINGS_PLUGIN_REGISTER (GsdUpdates, gsd_updates) unity-settings-daemon/plugins/updates/gsd-updates-refresh.c0000664000000000000000000004757715172222611021406 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2007-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include "gnome-settings-bus.h" #include "gsd-updates-common.h" #include "gsd-updates-refresh.h" static void gsd_updates_refresh_finalize (GObject *object); #define GSD_UPDATES_REFRESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshPrivate)) #define PERIODIC_CHECK_TIME 60*60 /* poke PackageKit every hour */ #define LOGIN_TIMEOUT 3 /* seconds */ #define SESSION_STARTUP_TIMEOUT 10 /* seconds */ enum { PRESENCE_STATUS_AVAILABLE = 0, PRESENCE_STATUS_INVISIBLE, PRESENCE_STATUS_BUSY, PRESENCE_STATUS_IDLE, PRESENCE_STATUS_UNKNOWN }; /* * at startup, after a small delay, force a GetUpdates call * every hour (or any event) check: - if we are online, idle and on AC power, it's been more than a day since we refreshed then RefreshCache - if we are online and it's been longer than the timeout since getting the updates period then GetUpdates */ struct GsdUpdatesRefreshPrivate { gboolean session_idle; gboolean on_battery; gboolean network_active; guint timeout_id; guint periodic_id; UpClient *client; GSettings *settings; GsdSessionManager *proxy_session; PkControl *control; }; enum { REFRESH_CACHE, GET_UPDATES, GET_UPGRADES, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (GsdUpdatesRefresh, gsd_updates_refresh, G_TYPE_OBJECT) static void gsd_updates_refresh_class_init (GsdUpdatesRefreshClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gsd_updates_refresh_finalize; g_type_class_add_private (klass, sizeof (GsdUpdatesRefreshPrivate)); signals [REFRESH_CACHE] = g_signal_new ("refresh-cache", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals [GET_UPDATES] = g_signal_new ("get-updates", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals [GET_UPGRADES] = g_signal_new ("get-upgrades", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void get_time_refresh_cache_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh) { PkControl *control = PK_CONTROL (object); GError *error = NULL; guint seconds; guint thresh; /* get the result */ seconds = pk_control_get_time_since_action_finish (control, res, &error); if (seconds == 0) { g_warning ("failed to get time: %s", error->message); g_error_free (error); return; } /* have we passed the timout? */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_GET_UPDATES); if (seconds < thresh) { g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds); return; } /* send signal */ g_debug ("emitting refresh-cache"); g_signal_emit (refresh, signals [REFRESH_CACHE], 0); } static void maybe_refresh_cache (GsdUpdatesRefresh *refresh) { guint thresh; g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); /* if we don't want to auto check for updates, don't do this either */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_GET_UPDATES); if (thresh == 0) { g_debug ("not when policy is set to never"); return; } /* only do the refresh cache when the user is idle */ if (!refresh->priv->session_idle) { g_debug ("not when session active"); return; } /* get this each time, as it may have changed behind out back */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_REFRESH_CACHE); if (thresh == 0) { g_debug ("not when policy is set to never"); return; } /* get the time since the last refresh */ pk_control_get_time_since_action_async (refresh->priv->control, PK_ROLE_ENUM_REFRESH_CACHE, NULL, (GAsyncReadyCallback) get_time_refresh_cache_cb, refresh); } static void get_time_get_updates_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh) { PkControl *control = PK_CONTROL (object); GError *error = NULL; guint seconds; guint thresh; /* get the result */ seconds = pk_control_get_time_since_action_finish (control, res, &error); if (seconds == 0) { g_warning ("failed to get time: %s", error->message); g_error_free (error); return; } /* have we passed the timout? */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_GET_UPDATES); if (seconds < thresh) { g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds); return; } /* send signal */ g_debug ("emitting get-updates"); g_signal_emit (refresh, signals [GET_UPDATES], 0); } static void maybe_get_updates (GsdUpdatesRefresh *refresh) { guint thresh; g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); /* if we don't want to auto check for updates, don't do this either */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_GET_UPDATES); if (thresh == 0) { g_debug ("not when policy is set to never"); return; } /* get the time since the last refresh */ pk_control_get_time_since_action_async (refresh->priv->control, PK_ROLE_ENUM_GET_UPDATES, NULL, (GAsyncReadyCallback) get_time_get_updates_cb, refresh); } static void get_time_get_upgrades_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh) { PkControl *control = PK_CONTROL (object); GError *error = NULL; guint seconds; guint thresh; /* get the result */ seconds = pk_control_get_time_since_action_finish (control, res, &error); if (seconds == 0) { g_warning ("failed to get time: %s", error->message); g_error_free (error); return; } /* have we passed the timout? */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_GET_UPDATES); if (seconds < thresh) { g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds); return; } /* send signal */ g_debug ("emitting get-upgrades"); g_signal_emit (refresh, signals [GET_UPGRADES], 0); } static void maybe_get_upgrades (GsdUpdatesRefresh *refresh) { guint thresh; g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); /* get this each time, as it may have changed behind out back */ thresh = g_settings_get_int (refresh->priv->settings, GSD_SETTINGS_FREQUENCY_GET_UPGRADES); if (thresh == 0) { g_debug ("not when policy is set to never"); return; } /* get the time since the last refresh */ pk_control_get_time_since_action_async (refresh->priv->control, PK_ROLE_ENUM_GET_DISTRO_UPGRADES, NULL, (GAsyncReadyCallback) get_time_get_upgrades_cb, refresh); } static gboolean change_state_cb (GsdUpdatesRefresh *refresh) { /* check all actions */ maybe_refresh_cache (refresh); maybe_get_updates (refresh); maybe_get_upgrades (refresh); return FALSE; } static gboolean change_state (GsdUpdatesRefresh *refresh) { gboolean ret; g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE); /* no point continuing if we have no network */ if (!refresh->priv->network_active) { g_debug ("not when no network"); return FALSE; } /* not on battery unless overridden */ ret = g_settings_get_boolean (refresh->priv->settings, GSD_SETTINGS_UPDATE_BATTERY); if (!ret && refresh->priv->on_battery) { g_debug ("not when on battery"); return FALSE; } /* wait a little time for things to settle down */ if (refresh->priv->timeout_id != 0) g_source_remove (refresh->priv->timeout_id); g_debug ("defering action for %i seconds", SESSION_STARTUP_TIMEOUT); refresh->priv->timeout_id = g_timeout_add_seconds (SESSION_STARTUP_TIMEOUT, (GSourceFunc) change_state_cb, refresh); g_source_set_name_by_id (refresh->priv->timeout_id, "[GsdUpdatesRefresh] change-state"); return TRUE; } static void settings_key_changed_cb (GSettings *client, const gchar *key, GsdUpdatesRefresh *refresh) { g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); if (g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPDATES) == 0 || g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPGRADES) == 0 || g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_REFRESH_CACHE) == 0 || g_strcmp0 (key, GSD_SETTINGS_UPDATE_BATTERY) == 0) change_state (refresh); } static gboolean convert_network_state (GsdUpdatesRefresh *refresh, PkNetworkEnum state) { /* offline */ if (state == PK_NETWORK_ENUM_OFFLINE) return FALSE; /* online */ if (state == PK_NETWORK_ENUM_ONLINE || state == PK_NETWORK_ENUM_WIFI || state == PK_NETWORK_ENUM_WIRED) return TRUE; /* check policy */ if (state == PK_NETWORK_ENUM_MOBILE) return g_settings_get_boolean (refresh->priv->settings, GSD_SETTINGS_CONNECTION_USE_MOBILE); /* not recognised */ g_warning ("state unknown: %i", state); return TRUE; } static void notify_network_state_cb (PkControl *control, GParamSpec *pspec, GsdUpdatesRefresh *refresh) { PkNetworkEnum state; g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); g_object_get (control, "network-state", &state, NULL); refresh->priv->network_active = convert_network_state (refresh, state); g_debug ("setting online %i", refresh->priv->network_active); if (refresh->priv->network_active) change_state (refresh); } static gboolean periodic_timeout_cb (gpointer user_data) { GsdUpdatesRefresh *refresh = GSD_UPDATES_REFRESH (user_data); g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE); /* debug so we can catch polling */ g_debug ("polling check"); /* triggered once an hour */ change_state (refresh); /* always return */ return TRUE; } static void gsd_updates_refresh_client_changed_cb (UpClient *client, GsdUpdatesRefresh *refresh) { gboolean on_battery; g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); /* get the on-battery state */ on_battery = up_client_get_on_battery (refresh->priv->client); if (on_battery == refresh->priv->on_battery) { g_debug ("same state as before, ignoring"); return; } /* save in local cache */ g_debug ("setting on_battery %i", on_battery); refresh->priv->on_battery = on_battery; if (!on_battery) change_state (refresh); } static void get_properties_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh) { PkNetworkEnum state; GError *error = NULL; PkControl *control = PK_CONTROL(object); gboolean ret; /* get the result */ ret = pk_control_get_properties_finish (control, res, &error); if (!ret) { /* TRANSLATORS: backend is broken, and won't tell us what it supports */ g_warning ("could not get properties"); g_error_free (error); goto out; } /* get values */ g_object_get (control, "network-state", &state, NULL); refresh->priv->network_active = convert_network_state (refresh, state); out: return; } static void session_presence_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, GsdUpdatesRefresh *refresh) { guint status; g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh)); if (g_strcmp0 (signal_name, "StatusChanged") != 0) return; /* map status code into boolean */ g_variant_get (parameters, "(u)", &status); refresh->priv->session_idle = (status == PRESENCE_STATUS_IDLE); g_debug ("setting is_idle %i", refresh->priv->session_idle); if (refresh->priv->session_idle) change_state (refresh); } static void gsd_updates_refresh_init (GsdUpdatesRefresh *refresh) { GVariant *status; guint status_code; refresh->priv = GSD_UPDATES_REFRESH_GET_PRIVATE (refresh); refresh->priv->on_battery = FALSE; refresh->priv->network_active = FALSE; refresh->priv->timeout_id = 0; refresh->priv->periodic_id = 0; /* we need to know the updates frequency */ refresh->priv->settings = g_settings_new (GSD_SETTINGS_SCHEMA); g_signal_connect (refresh->priv->settings, "changed", G_CALLBACK (settings_key_changed_cb), refresh); /* we need to query the last cache refresh time */ refresh->priv->control = pk_control_new (); g_signal_connect (refresh->priv->control, "notify::network-state", G_CALLBACK (notify_network_state_cb), refresh); /* get network state */ pk_control_get_properties_async (refresh->priv->control, NULL, (GAsyncReadyCallback) get_properties_cb, refresh); /* use a UpClient */ refresh->priv->client = up_client_new (); g_signal_connect (refresh->priv->client, "changed", G_CALLBACK (gsd_updates_refresh_client_changed_cb), refresh); /* get the battery state */ refresh->priv->on_battery = up_client_get_on_battery (refresh->priv->client); g_debug ("setting on battery %i", refresh->priv->on_battery); /* use gnome-session for the idle detection */ refresh->priv->proxy_session = gnome_settings_bus_get_session_proxy (); if (refresh->priv->proxy_session != NULL) { g_signal_connect (G_DBUS_PROXY (refresh->priv->proxy_session), "g-signal", G_CALLBACK (session_presence_signal_cb), refresh); status = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (refresh->priv->proxy_session), "status"); if (status) { g_variant_get (status, "u", &status_code); refresh->priv->session_idle = (status_code == PRESENCE_STATUS_IDLE); g_variant_unref (status); } else { refresh->priv->session_idle = FALSE; } } /* we check this in case we miss one of the async signals */ refresh->priv->periodic_id = g_timeout_add_seconds (PERIODIC_CHECK_TIME, periodic_timeout_cb, refresh); g_source_set_name_by_id (refresh->priv->periodic_id, "[GsdUpdatesRefresh] periodic check"); /* check system state */ change_state (refresh); } static void gsd_updates_refresh_finalize (GObject *object) { GsdUpdatesRefresh *refresh; g_return_if_fail (GSD_IS_UPDATES_REFRESH (object)); refresh = GSD_UPDATES_REFRESH (object); g_return_if_fail (refresh->priv != NULL); if (refresh->priv->timeout_id != 0) g_source_remove (refresh->priv->timeout_id); if (refresh->priv->periodic_id != 0) g_source_remove (refresh->priv->periodic_id); g_signal_handlers_disconnect_by_data (refresh->priv->client, refresh); g_signal_handlers_disconnect_by_data (refresh->priv->proxy_session, refresh); g_object_unref (refresh->priv->control); g_object_unref (refresh->priv->settings); g_object_unref (refresh->priv->client); if (refresh->priv->proxy_session != NULL) g_object_unref (refresh->priv->proxy_session); G_OBJECT_CLASS (gsd_updates_refresh_parent_class)->finalize (object); } GsdUpdatesRefresh * gsd_updates_refresh_new (void) { GsdUpdatesRefresh *refresh; refresh = g_object_new (GSD_TYPE_UPDATES_REFRESH, NULL); return GSD_UPDATES_REFRESH (refresh); } unity-settings-daemon/plugins/updates/gsd-updates-refresh.h0000664000000000000000000000361215172222611021371 0ustar /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2007-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GSD_UPDATES_REFRESH_H #define __GSD_UPDATES_REFRESH_H #include G_BEGIN_DECLS #define GSD_TYPE_UPDATES_REFRESH (gsd_updates_refresh_get_type ()) #define GSD_UPDATES_REFRESH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefresh)) #define GSD_UPDATES_REFRESH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshClass)) #define GSD_IS_UPDATES_REFRESH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_UPDATES_REFRESH)) typedef struct GsdUpdatesRefreshPrivate GsdUpdatesRefreshPrivate; typedef struct { GObject parent; GsdUpdatesRefreshPrivate *priv; } GsdUpdatesRefresh; typedef struct { GObjectClass parent_class; } GsdUpdatesRefreshClass; GType gsd_updates_refresh_get_type (void); GsdUpdatesRefresh *gsd_updates_refresh_new (void); G_END_DECLS #endif /* __GSD_UPDATES_REFRESH_H */ unity-settings-daemon/plugins/updates/updates-design.svg0000664000000000000000000010124015172222611020775 0ustar image/svg+xml Wait for refresh dueGetUpdates (typ. 1 day) GetUpdates() 'Auto download'checkbox set? Y N UpdatePackages(only-download) Any security orcritical updates? Y N Y N > notify threshold?typ. 1 week Y N 'Use Mobile'checkbox set? Y N On GPRS orCDMA? Notify the user aboutimportant updates Notify the user aboutregular updates unity-settings-daemon/plugins/updates/updates.gnome-settings-plugin.in0000664000000000000000000000024115172222611023572 0ustar [GNOME Settings Plugin] Module=updates IAge=0 Priority=300 _Name=Updates _Description=Updates plugin Authors=Richard Hughes Copyright=Copyright © 2011 Website= unity-settings-daemon/plugins/wacom/0000775000000000000000000000000015172222611015003 5ustar unity-settings-daemon/plugins/wacom/Makefile.am0000664000000000000000000001221315172222611017036 0ustar plugin_name = wacom plugin_LTLIBRARIES = libgsdwacom.la libgsdwacom_la_SOURCES = \ gsd-wacom-plugin.c \ gsd-wacom-manager.h \ gsd-wacom-manager.c \ gsd-wacom-osd-window.h \ gsd-wacom-osd-window.c \ gsd-wacom-device.c \ gsd-wacom-device.h \ gsd-wacom-resources.c libgsdwacom_la_CPPFLAGS = \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common/ \ -I$(top_srcdir)/data/ \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) libgsdwacom_la_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(WACOM_CFLAGS) \ $(AM_CFLAGS) libgsdwacom_la_LDFLAGS = \ $(GSD_PLUGIN_LDFLAGS) libgsdwacom_la_LIBADD = \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_PLUGIN_LIBS) \ $(WACOM_LIBS) com.ubuntu.unity-settings-daemon.plugins.wacom.policy.in: com.ubuntu.unity-settings-daemon.plugins.wacom.policy.in.in Makefile $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ gsd-wacom-resources.c: wacom.gresource.xml tablet-layout.css glib-compile-resources \ --target=$@ \ --sourcedir=$(srcdir) \ --generate-source \ --c-name gsd_wacom \ $(srcdir)/wacom.gresource.xml @INTLTOOL_POLICY_RULE@ polkit_policydir = $(datadir)/polkit-1/actions polkit_policy_in_files = com.ubuntu.unity-settings-daemon.plugins.wacom.policy.in polkit_policy_DATA = $(polkit_policy_in_files:.policy.in=.policy) # so it always gets included in the tarball usd_wacom_led_helper_SOURCES = gsd-wacom-led-helper.c EXTRA_DIST = $(usd_wacom_led_helper_SOURCES) wacom.gresource.xml tablet-layout.css if HAVE_GUDEV libexec_PROGRAMS = usd-wacom-led-helper usd_wacom_led_helper_LDFLAGS = \ $(BACKLIGHT_HELPER_LIBS) \ -lm usd_wacom_led_helper_CFLAGS = \ $(BACKLIGHT_HELPER_CFLAGS) else libexec_PROGRAMS = endif EXTRA_DIST += com.ubuntu.unity-settings-daemon.plugins.wacom.policy.in.in libexec_PROGRAMS += usd-test-wacom usd-list-wacom usd-test-wacom-osd usd_test_wacom_SOURCES = \ test-wacom.c \ gsd-wacom-manager.c \ gsd-wacom-manager.h \ gsd-wacom-osd-window.h \ gsd-wacom-osd-window.c \ gsd-wacom-device.c \ gsd-wacom-device.h \ gsd-wacom-resources.c usd_test_wacom_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DBINDIR=\"$(bindir)\" \ -DPIXMAPDIR=\""$(pkgdatadir)"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ -DSCHEMA_NAME=\""gsdwacom"\" \ $(AM_CPPFLAGS) usd_test_wacom_CFLAGS = \ $(PLUGIN_CFLAGS) \ $(SETTINGS_PLUGIN_CFLAGS) \ $(WACOM_CFLAGS) \ $(AM_CFLAGS) usd_test_wacom_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(WACOM_LIBS) \ -lm usd_list_wacom_SOURCES = \ list-wacom.c \ gsd-wacom-device.c \ gsd-wacom-device.h usd_list_wacom_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DBINDIR=\"$(bindir)\" \ -DPIXMAPDIR=\""$(pkgdatadir)"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ $(AM_CPPFLAGS) usd_list_wacom_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(WACOM_CFLAGS) \ $(AM_CFLAGS) usd_list_wacom_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(WACOM_LIBS) \ -lm usd_test_wacom_osd_SOURCES = \ test-osd-window.c \ gsd-wacom-osd-window.h \ gsd-wacom-osd-window.c \ gsd-wacom-device.c \ gsd-wacom-device.h \ gsd-wacom-resources.c usd_test_wacom_osd_CPPFLAGS = \ -I$(top_srcdir)/data/ \ -I$(top_srcdir)/gnome-settings-daemon \ -I$(top_srcdir)/plugins/common \ -DBINDIR=\"$(bindir)\" \ -DPIXMAPDIR=\""$(pkgdatadir)"\" \ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ $(AM_CPPFLAGS) usd_test_wacom_osd_CFLAGS = \ $(SETTINGS_PLUGIN_CFLAGS) \ $(WACOM_CFLAGS) \ $(AM_CFLAGS) usd_test_wacom_osd_LDADD = \ $(top_builddir)/gnome-settings-daemon/libgsd.la \ $(top_builddir)/plugins/common/libcommon.la \ $(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \ $(SETTINGS_DAEMON_LIBS) \ $(SETTINGS_PLUGIN_LIBS) \ $(WACOM_LIBS) \ -lm plugin_in_files = wacom.gnome-settings-plugin.in plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) EXTRA_DIST += $(plugin_in_files) README.config-storage CLEANFILES = \ $(plugin_DATA) \ gsd-wacom-resources.c \ com.ubuntu.unity-settings-daemon.plugins.wacom.policy \ com.ubuntu.unity-settings-daemon.plugins.wacom.policy.in @GSD_INTLTOOL_PLUGIN_RULE@ unity-settings-daemon/plugins/wacom/README.config-storage0000664000000000000000000000334315172222611020574 0ustar Configuration storage for Wacom tablets and styli Tablets ------- Configuration is stored on a per-device model basis, meaning that it's possible to use the same device, with same configuration on 2 machines with a shared home directory, or replace a malfunctioning device with the same model and have the same configuration. It does not allow having 2 separate tablets of the same model to have different configurations, whether on a single machine, or using a shared home directory. The configuration scheme is: schema: com.canonical.unity.settings-daemon.peripherals.wacom path: /com/canonical/unity/settings-daemon/peripherals/wacom/-/ where is the D-Bus machine-id for the machine, and is a unique identifier for the tablet. Stylus ------ Styli use a similar configuration scheme. The identifier for each stylus is the tool ID, for professional ranges, and a generic identifier for the consumer ranges that do not support tool ID. schema: com.canonical.unity.settings-daemon.peripherals.wacom.stylus or: com.canonical.unity.settings-daemon.peripherals.wacom.eraser path: /com/canonical/unity/settings-daemon/peripherals/wacom/// So each tool can be configured per tablet (so the compatible airbrush stylus will have different configurations on a Cintiq and an Intuos tablet) Buttons ------- schema: com.canonical.unity.settings-daemon.peripherals.wacom.tablet-button path: /com/canonical/unity/settings-daemon/peripherals/wacom//

&ᣳ>zI%ZC?.[TGYu*%lsɜł ^=l틱]wueٖ3|Y=%Y2k%}/H#Z6 w Ȣn9c"O )9㇋8E)\jfո !BSʀ'[.*Bѳwv,[^XNK-~zQ;/&i`jEUY|>]LjkVvӖ;bBlĨ nj!eduA3žxX1vzs阗GևɁOMZe.R;,e.p{P1{k `O:=Iee"dDL 11@Yj]6MXTںL^˹˴LuZJͽ]{-nteX&ϒ/U.nSUs.~w;y_kdwWM;BmA{Ia;=8@ӊzrIv2C;LP +y_yi*:bZi9pyFκb^(*,7x~K(c_Y'Z1֎uzrק W/fA22q\ `h>a;N`ݚ2pyAV&rr2yGvfo`^,%N!Tn(@&EHOpAAChFoܲl{x鏞xNs_o]XF ;G Cbu{jel&aܺ(1jꁷ bT4 י[g?~o&% Jm!eۨ}u*u/SAD. GlIZ"Cd-mdDG{XVll s{5 @H+>Rу6 J%ՐWGcje"gkIیaG5ԫ0۽kHH~ZGLDŽs: ,HX@, b{$K WSݍduN2&v7lCQ|a'ẏ@q+UqUu)Щv*"ctd!ó$J3 VɬWY3$ṳ̄vꚇȏ&Ú~"X&^'v1@Ux A|ϡ} {Ixqcjjj3{IzQeDzYqbA-.D}!l}hE5֟&s}4d! mw|,py! +qi~ ](=BZYZǝ4aUcE**u/! EOEoBAwCsP}=#N/TpUX\ V.1ыY7^+u%l|?E*AN$_$G< v)4 ~zD]ʼntKeiv{U?F~x_Ve'c2AC"ӭ]S3>?Aw# i;]b) EŚTHp&@sY# KXǟItGa3DɽrI&Z_&.cNΤwN@L8H .#I-߈hrEkq_$@oJ潜XQdʊ ^.o.KD=ofsWn-[$9 頀G#]|C2Һ+4i L-Le?Mֱ5qQ4y "?iqN-dwqώ0]c~d9atwr 20xI:`OinkU rCgq7p`i;Dr9L#c%~G=]Ј2& (*uh:u6˗TYgEEȭb*/߬.HoAB'ro43>vAM3{Yy@*[MGͶzf2k*kIqTt]ivwIҐ.g+B1G'+EӠIR{V) [:Bs %`ѩ:>D? ~lPKL25W ob_!O}3wyQOF]&а2rK\,Mh`c=Ufi%[FT{OoټK/?.E7 P7Toԝu2IE< }y:(3}<4#-W 3IH{K-/\9*tMSp8<W\Mi_g+=,N?IF i{|xbdr<=H=#I@Gij#Duq}x_>u&~&¨4@itXjB̙R[~u'7vrWxra_GfVVP֓`/,_)$auօnZnݭ}+WNVh ֖===q~ASL[-@}iPYy pW[vm7Π,?x$`h&jYh#E/ iMܮzV[7tXۣdPU>͛r'^&7`}h&B1)y6MV拢N3UBare }LPjG{9oZ7$ޅcz /=Ge{'~a?#^!Z/Az9'Iz|I80sr:q򬻾MrEvϵ^6 Mf$p}ɻDk55j>7g/Kn'>nсE^twnэan(:]/+f$z{d^HSe(TN/+bD*sg X!/`}{_)0Kv1$"ȠzwZ"Jɶ/۫8Խ97vȵ2^dl?RyX^'˫.Mܙx'䥠 nZpHXVS0xBqNH/xCza .''CG܅UzoCsX!<[;Q '`(/nJ,;`(F 9_,0[MyB9҈!Bq~l\N>xGq-fHn5E +yI 7 &,Xچ"_KyȜG֤ȁMí?&7gN89 #0XĹ)Q8JeL\ fxJFMO.xRl8 x} xŕWS!eɶZeI4ȶdd0ciI9lF,Wwf $v dr@pl cI^U_3#gF]U^zWzS_cBi[<PR,"kѠSÚpH kH8Xݧh1%\(u`0&UUJ555O]fw9I#"uc{"5?ti۠ՠ"j4Q{1/A-%")*)QE-Ґ'mQG5U d5@|kkU2 GV>z@lPjWB* ȽrP0kzXSP8ҧx5@:`x4&RKDS!emWë9 )1CP[ 5,wGg4$kT40zdXZƿukBCRu) `&lstYSˊ{䘜Na$u$%P5&1}"C_Fw6 %CG8)8@1[zCLéIaD1>}:@e~sd9 `8V9i׍l dxEc8άe%e7}XyH%UIk[HT`?YE~紂POCAUGdO_Zm@PZ괝C36YN]/@@EeM'ZZ/97\M학+ۀUzKn;u'Y_y"S?lkER,~@\^$ L̐v] َ^7zH#E+Q7ͪ]V;F %Y;LO tѣ@Ð7dϮZ "7 [A R 39%yL@DX40QWb% @8_ 5F}6X>1*1lH'rv+^t#]8ǠDB'W#\T?Gho}F6 UdCA<]~Pp״z@㣈Q4K6 p hԟ[[L r{^΄П1ib2T"{ԨB ^B[+菔.~uһ2$YKvun@v~R("WT,)4 y4ƣR(gݵD. $ּ+!KB2A`eN." dFK2CZ"-^F=sNQVUc p FK$΃3ڥE9)E '7X 2h wFXnH 4.G0oif׻ &˾6ʲ0 0|+Y^\OS/*fo/T5'_Dmj8St %7A3ߥz"Cǻpqe'3O-|nd:kY3%3KU^Ȳ =\S>GP`oW?֨|_DMIIf& ؏;ƞ W,R?d ]>766zD9^3n\{wAQpB 4!k?.@J" U!P%-%y!TB4;@sT(Ѕ^Ώ&?8P_/HC*$X˜E??7AM۴R4]?d~_CCL<֒I}ʹvF )IUӪg;35.Kypīta/*@[b+Kˉjq!ZZ+MA3Faݻ2/5/͋H?L;oBQ=Ɵ }y*ù*Q+eECIx+KAڴۦPꡕbadCWwh3^J, S@MFnGnFFt奣׈"jPZ=.:!ś`29١ZZP0*'zW՗e͙%wsaGŒzW#g^{ca;val[vHǑ kY!#9Ex"~PHBK!pF,zvPɢ誄QH4Q̨: q x79^qF |ؚOh/ATNT<]DQmD-$&fok j0ޣfP`ɡ%5/k'Z+-l0@JIPL^:8Hׅ͹B*QX^z09* ޭEMޱIP;䉥 % 9~>%4)hAA[g<߶X  Ha*k#z];[@Kx:~7PRIpI?IB=HJʪkJ5 ?Y'ܢ~XD 7g;2v(1р&Щ͐{!MYTQEAML&G F(rREwi:Ǎuߦ3j["Bo%\(T2n\ gK~z;܂IV,d)DGD-Z$H;&[;/pC*B W@դ$6˃엇e#%%B͐2l'cTu?S|xC4@<qld+B k/QÒ'-; UgiQB8ݎqG.]y 2E <K餝XֽHvΚ.ߨD!PM>]5ꖌS'ffgTh!m~0TB}j t1,efM!ol~{l~Ϲg#6EC +I!]j’P*/*h= 7NT|h?7U쵪i*:Fʋy#x5;h6,M;>F/[scoШG[$ĺutNc R"mX=ʁѣG-Y{뗌S'H[{Kw4XbA /9c9 0Bx<}MM,X% jARMKǭ1Եe6a&rWS"҂Icj\N@ TzeES;?v~ f,N}S;͊8Rj\xCi4wѭ~TUO# kt3@RO$ {TN>TC*g'3^%š$mu-<+ݽiv$ wuN0 2((`# w@?Ꮂ'6ρ"nU܂a\X11t"5M鋝jD ܊*qCI_TȬ^(S?+jI65q1xёB 쉑v1 $ٙ fPu.Ejs?ܣhLyYDPAְo/u.m$DxPU"yt?=[d{ 9:l<ą^?Zt$u|bxtrat?oF]Ȩj`o =+mH7'=D?ٻ9"PЯb&s;URcOzCC:guǹWByo1d1BBq4my ń@gqHw5L`0NgMCQ$<)쇕'V'ߩژv oxB}쟡_qš.@"d:N DJoI8!:잶FW&/d*# ^{;'hZ%#{рɺE_ۘ_O];3tCa@ [҂R TWtCF~XhGQ G!@uP9^n>M[)j}>nX2k< G]7|U5(Ȑx$;_B*bpT:הOH.!Tމ|߲"S`Ţ `; @Ћxt i70"8ۇ7o_ݝwٻzL}LjM&Д*^9a:wHxDDxBzhe׶>FZ)u_q &WQL(p# fEڽ@;h"$SX&j|=2HBWJG[G<żAR'@~3"TǤ(ɨNas ji?p^#P0`OYi׆E ^c4 <==WGЩ> ##d^haWiV8f#ч70^ғDPlE, a#|G H<H0*r(6 !NN$ U!lTĘsTfZ w.Q(ea4o@3S_kF0 spj@9*yWX֢L±AU(w/‘q #c+"U质ʃK<`+H1יUz\5\qzcS0VNy-F,zU:>~Gx-]:ü'0}R󧪍(F[D( @_; x:/4;TU@ `QJudF e)OU-Y]-föxtN1+h뫧띏hRTZj+W諩]NX/A?JiU k^#ȝ`T6ECO$plAy2G } 1,_Rls MAbns0ǩxvcc*J7BG4@؟|n-:W`cJ%D uZF.IQĝ4J/o<.Xѣo;.AҔr ya WW#ZS Ӱ|ƒ fYD*)wTo9(܇-~~^e"ʑu}V׊&ҧo5.Lwh!jmo"N>>XM)ǻ2='1O #CI¿kuOF6=O5* į6L݆z^:ҙt(#9& It X}3}j@;]:ʗ(h8ۣD/sx3j[/%si>]47&}K[QEygWʡK,?2ԠԎKzj}w>X0fL aU:]A%DxTU@=\NW7tJ3ONy+ևg>fܹЭlJqgDOԞj?_ʧ/Jْi*e&W/d'Q!+E"E#>*e)?tiel PGW9B'nL^̖;Kzm7nXe'N*gYI=_WOn|YYIzNln_Ռ{+2w8^+ْ&wR/+Y:N|^t +K_Wx MۙkҴ+KA*V>A25l邓@jxpoU;KSzf'EXYVhG߀v~bӊ _\sUF83Y (cMbԖF0N KԀT{I$(] ֱDёA > _9f ,"[;13bP0tPxr o WPߠ jS'a(zqsaU.YqlrWFviFc&5[ .\ [O61i\[Ax"VB{Mm`:w,5f8goEC$rM"v%-Ʊ~6F΄] MN2o%;7{.hVf UlcE3Ƈ)e6]o$!V0ܳ0S[:X@Sݾ=5-=tR6r[ٟ Rl6Za'51yky߶7X-Ͻ aUjE81W1wOԎcH@I DB썑S)* etf$-C8(*-e?Ʊ\Sp4ys96n9=/CjcR=0aB 4эҗg׍S h9(0gO]>)>!%=grHфurmejy)QnrYj=«BGB`b((fCғJ̖m+))eqGyX$,9Li^VgŴ@S'-l|f'_ؠ@i)7l'7lӯ$!?jiq3voxӒtge5ƨ-BtZPoųx"iYjꛌVgcj8SvuluFr@cHN-A\ m%USHx' ;lahRU&{lc'E$i&AV>BOD nd9?u*k2*.b7V#Dž/5<4.kȒv3RcU;)-{1V|eC]i3YE:aQ`4aE 1<8n bʛ.y{tA-L4-7^6k$&.E=>|k=gxhUlc%aBkg[L'5%XolamBr _(." Wd'L?_6 aƪAOxɟbRs^~LA;?t:6\ΪwLrKj9^a5QU,4vx`L\>nc{^I+EAHoSQr%+\Jȱ2=B'RȆ}qīX{rp%ͳ0.*KJ[9 %+jV:0As0w5+LA3|1} [a<]`LaSa aDH#UYE –4;~'lLpZeL3u26{D ƔX8_`ױg&4c3Fy]ulYȑ5FV: 旺GQ[y8Kɧy>2$G70l=j6b7y=R1]$q 7P?6_r#[8nǃ!<ϸF67-ʵې"&3jћXahV޽]#&Ͱ?*O} zYlDқ3> ~^]46<`|j̵ײ2c>8mC;Zt+; #?c x'""kXpUm^ti55d?͒uV#x"@'*/XoT+J4 ΏuEh@@%E9:,+uv5*\F&U%o"T<5o)[9H6Q/~mWqUcgU̞pFf-00Rխy^SʢO3BzMهbVE?+D=Ad{ѠM`wt r"qejw|CWgtx,ۣDRD_8ڑ?b3oq5 C4fl+ /B"+w05~4/~\.bN_-4&wQ0y#zB}hY_g^O}-f,N~ ͧbsD#IЬY C/:&x>E-XGg mrGYPے{;5wEׁm o:㓿x^+NȌ4r[dcyZR"b||_rv_ zaJsL>>,uLEeF⋬k>k+VBdҎȕe(fǝT+dGمl7_Lk Uq;vux珰uaJ1ѐ)@}M(N|H4fO$Y[`~ԘC]RJR%Xq?o421Vx|'M2~Ugvnyj%3ַXʌ St Xx0(u5po\j y!H_g+H9_=b޲ Vnŏ©ᠴQ}fUs'YPTcl ֽHt~6}Vn|܄Sm>견o6cR.vptn|%Ѹ´d~qm3eYVRz8[f3%uhE/e@ORw<)c#YL(qvMNgx-A۟kO1;1̠c1 iH©"%wن(rq.l tvlੜ]ja>Az໬X>x4~<__ɱAǾor=tmAڴ] ,q7ycB8ف}3<6x3EGVBcm>mm`[S)vGG](JMųu64m=˺kCI Fijq\m^Y\0!+c|Ͽȶ֯ 1QdA%*փ}uM{Ycxef"V-erk_iigA3J(]G^x%!ih,M”afG ]!߃̣)G( c^f[2ZZY3ĊrϓZMZh9?#?E ;ĩZiԤWDD$2 /ć!*)j6?;O֭b%AJ=?[Y?7vJGUR|x8.Ehy̳7rtȶS47ys̛b,>9q0;ƭh;_PK'ϲ'dGH]:u.d\L@b-w2F6ӓHcJ"kD{\<v<Ҡ{(-lpK7c&Lc%T X୞.NR0 =-d>߲RIvu*U@bUv^C5b.ؤG0C% 3RwN?1R߰e4cHNҟX`lx(wWZU%PO`&vT~VvA<8 =J\J)'`7_U‡{ڪD =QQ/=Rx猢d j4Sh)7iږMVf:+xխDv"qllnIJsSov W\;NFl^ѣy6MobMDnJϾԚwJ?ɤԪxٰ\)?[ra SllOLZwf[@C?$1{V/YpGJH$s7!N CXr0L_UލRwԅ  ȱQS"jț:d"ow,471}sfMEWAyf%S(l-YԖ1LOl3W4ug=rPyJQsnhx/LbkV_tV2$$աIlOT㰇oe:ZysBԹf߭t]W%?.0j3fU]0젰HTlų載bf* gayDJ|廵<.YIY*n^iW[<jFL21+5.{լ4e%o"Zy^7 o=TRb:{nqn[!gɤP*46>|>y (2KIķjG%~H  vt`7)osfxX`ϺmʃJ/;zodyLOTto|z]mB/H7>ۙ==x,/)I~/8{?Ny(0wmi|_D炫&p{+΂o+4^Q+w[Q[Q(hyaFv᰷h+n#}W Dqw#7\ .nuWVa [h~|v k Y7:=~ t=X",wT}v x)H7W7靋imד~މ&0 t3 33:f N{tfÇ~$tW͕^Sqd5ͯv;10܌KVȢ<0D+:I?oG;I~yuf\p?zIfԍҰM@ԥ4"z*r\07[ѝ8+>;̭\ ss0˧n bOժX/w7@Sᄬ3<< ^~i`|Py u3k_ X`;;ݨu-fi3V6݊8w`o9z0x2 =+~ֵ98 ̓~s7ފn3' `M݇uą yXTp 4ʶI"#t%bIqKWp k­߶HGq'[vVU:31gpĘ}ѾG`/i0ك<յg=U H3lZ G@ cA;X/>MfM 70]dՠOSvT:~KbZ/.4. V0VmpJEM ^ɀ.[ ?0q_~D޾/Ok$?U_e<.L).ؒ΍,OA5fNnTfcA'ʷKknV rF ElUbO@:RccH` Dp#/ 69<]|7l;"/Ga[A' 6pd޾x࣫@xgz5)58H "Q 4B!pQ.]'A57loaڻ2c ‡TO&"Fl#q 9qI>((fpX@> <"nEpaM@Б\ VԔy)xGٚk}XZ=HuXP+cbpk1kEȟodq$ٛ3;a;AO%ITM?"q>av5PqUp9s=$ LL]giě*/+OZWu4e-ԸqV8dESz)y)ڼ7(^͛rR<{iԺiRǬ/?-i@u.pOJNVpJ}ќߣ):x’v i6_}aI?ʞSDW ъ)&qXtx~$]ʯdy ',zVay tb%=5Z ;ۙ+ᇗXoXВgAq[%DMz[=h`)>Us[DfbO0ŘAJ|2xZf _*&mx Л(#߇_/mi+jDEn7 EGվ jZk`ʇ-Bߔ*8W7;|uY1Iu,@FI5${M;(sk_OAP$XSU;B8hSDIε/'`#7cs3`+O@QX8#nՒztIE eMrM>Qϣ.',2'An>h{뢼WQz!>Y UVHD'\<>aЭ֧rCՅu}7أ}ƢXh4\C0!xlCZ/ !f1R:$l]i l3M].=  Gצ7~?PSTR>J-+ȾEM/C'6!MYXZKyiJSrH%P֚n$6Fu)`%1<f rc9I12°_x^gWߧ6Ci[K7#^byQ2XXGHOV1=S<NgEEa_PMȎ^$$>X/7Med'cQrHEjbKYXGhպ{ʎĝ2.b\lE<M*ThJ  utʨ:֮FoE_!ygẒ4;{h}cD~,e !V8ލ[eIV+AґUZ9sE[O"v\IW72M ,Q~L9chCW7w՝ ;JIc)mR{`+cH⶟delb= oܣ{z7erjR!mx DY5+@g:qM&.™WlS]Mv@|i T/#R,y9ɝ^"*?mt»TP+,bb'{ae9}B%zGg| oJ>k=^k*["LPк9j&H2p:_PtFI/mK̟yEQ87-L=nj X(GwteScZ;XU+LxV[YXz=l[M)xqG!ݧPp5IRw0;TS(%:6r[AZ*>I5BSw$n7VI0hJ31% 78לnsWS- Հ_P%pn)knI $D.a\B;rDlI>\O\ubV^ܢ_EiBXDtBPd [QIZRon>q.[9AV *hI:; XGYj]bÉUBko||5yR/Pyr޼p}qI"Y!ԓmb/`ʘ |9b[?VPLP !=>#Shv\ fTtJ&Gc,I %CzĩLt3'4_9$PFf:ϴx'ۉ!7t-Ftal#Wӊ6~;~KDlgy$8~c.pdb Xr4CdwQDS p0Q׶(K~d[V *.QAsv]Y܁;*|忟KAȤ_0N+OZ%[h81 ql)I5L$8GVʄG*)L 8Ps/IتKRUe2t`|sOtpMp' ̸#A< mh8K (%?l~"‹$8 /*dX87@x#jaoOqkTr2"G1c+N6.vC&5 cn.NZw^,/k87I9 0Ϳ?^P`i $k]GQ䣋DJx5Om)43z/н:gIHlv[VQ8tq/Oᗧ ((ADR<8B&Tb\;oZu`zm@sy#dxy /0M%m,11xF#xG#vc|gs7jK؁Vg|4=ob,j&$3&gl{_L t hIfH( 6a`Μ vgYي 0鼭lhrΟ@F\8)AxRMTG6$ؤzFX'Wu}Hi '&]m|g??lj ˕DV;B\$r2f(5:k(nwIs޹&{'O&_>yYI51KHT. ehdK{" ޹IkwsfO>S<7WBR|Ht(]yI9P>$YtAH\?z2rN7dŒъhkZ|Cidfܓ!O߾8Q`>hLr9v?zrFe&\͵|}g5ί&EmLױ%)^r,su6M*|ne5#5區x3kMYLun *RsuneW[dw0sLVT7zE«iC~T0[GXnB/xwխy9 v>K.!}vSkct6]pzb/* U~:BDK_>gJފ&xZ VNu> YtݢXLR׶⍜bC.l E7j&/ nlD͜ wX*kt$0P *zG#9!d\YIwUIa8P穎%!xw =އ.=z'4sa$,wַ?xr~..:RILxTQ4((vmfPg:~HҼq60f6jz@+]HI@}ۘNKu!_lGf2<\:Hw.gU*qs{ڛX7/..̜` Ӛ? tq~nr$'0Gd7J߅ר"J>US%cec%{iĉ$D 1V8c;ml1E_NI&so +w ^,QZf HXffÒ1w%us\^(,K@Zv'(ƭ0g k|"$ @<>\Zǁ>d yv>i|ݚ`y'=u<02SBJo%~؆['O$'7'ͭ$?}cnprhgGǛqM $'SS?A8A11]O0du{~\&er>}~B0hϮ4;|eKYwG00>憩:XL_p[̏56[1ֆ5c]Vv@*TJ 2W*y|@:VP1.ؚ&J~5m;ЮY4GJ;6lAuXA(.kQudG_:}y;ԓ#ljaӪ'>sBs-]sɧ-LWɐ[B/-+i?S ,k"9ddGD }2-tZefUqQgy+q#^Oӎ>|)0ސ[tJsF0y;0SY/lFh>\vL Ϸ[Yp/(g7eL2ܾuڵ?ʜ66]j5r<ȓ%`/ʎ1YA=>UܓJշ&r/TJVk^\In˚2K*Yxġ6Hq1D}[yXT6nf, _O#TSÐep̹4ƠSuT>+t^?uRM͉;")* =Eߊf'c޾4.Oju\ГPMlڿS}5|7kytv=G Rih(# 7a=.0`{zs/'긒A'x{?'tE+zd "E j*f>ŝQ.]B\~U IpRnoòGJ7e(%y?I S`(z V `I¢XN`ikrl̇'QT t #00mvFQ ,}bUv'b;d(ڈS w%Dשk&lJB ͳCVK0@w[&'ʓrZ\fs ;Ub«I TC-EdA@8H:|3",xWn#2YrڈQArD'G0LV)`"֙_z;1uu`V#5VXi!|J$oEjy?34W[mΈcj"$f_Ks\}[>gqff,hn"C9ϸ-Y^t\/p2U2[q4|j5qW~@' !:"<*+Q朔o&3Nؒ5P0 jUv&ds<_qz>(YQ(42Q",OeSCo\DZ2o (p&PmY8Mlg3c;Ajsu e\ջ yK]DYaSBErChVs\>u$rp*$ U1'L0/)ƯQ"Nå6*P/f5+C#f7tTBD\ua6̺e,=Ҩ3}XJ[&n@gJ{}a-{HrOS,^`BQT74ځy WI.b?PyLٜ@ř)ڳx='=>ijn;Bߒ}@^ >h&i:w}ǂD/ZTzaϰ^-P!YKEV \u_8}44x aq'^W[X.i.ʭ_cצ`}6$#.C0n8?C |~s]?|UX3mvDaulhȊ4w$A' F&I2 jPaa'AbB|`ßlb,A,\uXUWayi,^u#]FUmBtAW?Q_];s`>˺+uΙ@F̍ 5/G;4iҭ\nh yu;FA`7vh] Yz~l c`T o ]|;TT@cjDnul`ɝ4CO|#P'A:__8zWf}[ZGMhme8 ۊf9={^.[CԹ+yy(z b9/Wj+c<7Wьftenl 8[P;Q./ުտH_;a^X*6aq.ΌaV[;%jUuxj3Og &|c'Ln .wN[+ \\N{V,CsWy~ FAM00Ũ8x-0 &onEmr復Dt܉2+' 6R mh ̛P1F-܉8 vu%AT{2b8M;63]੃iYN YCԻUhY9 ͜:ty8qx5ՎZF+!7a4pnqIzոډ5qTŅ0ӂ 'DԁF1e/ȈJ d?XX1+}djǬp m3,7DBV$fR>/1J8bOBMYX>RWm(2H(})%NvT2om74ӷyxqS.o[4~0 dbwV681>"u+eG΄~BEͬwW 0btϟ(6os^LxۗR ]-p|0.'pz62{xy=I l_(jPr/Qy+:b4>c &Yfhav9nao+nf"ElNL:|]2k }\1|>wQGO>8~Jۡȸ'ձ%Ym}1 {N;q]))~-[l [8!^85,hרu3t6Tw8(R>NO,FEJ"/D{c2̠-mLlJBC lw"m ~;G[Q3w5 *GN ^L7]RFcpM 0]^=EpQ{qXGD"ludekAWijѳc<A:< TKj7#CC[ɒu92z<8T9# a֢h}"N&#j8!q a̎|xawETEm|GXU}l\ ;#пXmY|W cH+b^kȃoT0{BXf腵07N,]0SkSUӯb%ĤYxG*!cAWmW_ڢ\gЎD[v̆= =GzGFAu{tQ0֟  Z$+Di,&2%Ѳdn,XK3OMj/C!p=,gZ.YCj/sXH RN1.6Xl`+oI;@!{`ZiAX{E }Ǿ xgM!#2gE;eBV_dKLr'Gbe`޺}MLMVjSsE,,FZ*t-Ld07 B&( #Iq[-871Nq^:;nZ@c={a֨ڢݔ7vK;ȼ@_l'4HSYme`4k+ζ^،`9"5 \}yt)  ܃~EFОyザL~ @7pUA<࿈4~6[c MI@W}`\ W'Ӂ4E7N7QOq䞖Qh|As%֮: Ϸ[Y^ &Dic2ȵ(]EN2}c#؊Rzy.vdݽyomO0zkcLYHba)bcm$q=.n`TyhvnlAܴy]Эm&z9ӞVG_NgDq v@@K,glH4P2E#FU`=OBdBK|]1"FЊ'ye-WZAD 4η46W%GJ;.l3ZgF 'DIHwaVK4aNiksg &0F=D<Qw=)v&yϠ Oӹ ͽ_mĀH>8@Q;0C#q`9v?v7wVHxp{?AtWtTj5@JOЃn;v޿O̼+,?|tql M /lێ^+{8/gOg wjV RD!(bj>[IEI^r {O_m}ppJn5(o6wg)-tW~@ĭScsP6D9=cF:ŢtGCcG5V`H¸\n2`|ޗHLDi3uL<ج3-|a9DYK)B%1uw{]aQ6NHiuƛ*fMF Qp'Lcg%L=aΏnPE4eq\!6\8~(s,D#:f_lJe8%z_6.󪌣$*Dq9?lyB/:ל[$YSp>[) R; ^|Av a#3 \ Žtz>]+EqjWcۈ}B5zWYn RKqAO1CӊR*~ _nnء8 N^&f Si`A}FqVnNR;/h|<] }|zH<TOͭQ,뇅zINSRo8ō:n HCa{:mg8D}v\ {Ɍ%Ӏl7CGt'c^# G>[+bt%5u8.hx,k{ϜvOw'f4s|_2}_\1,逃P +6:!zd?PЊxجc%ѝn(ƭ'z808qFdֹՁGzɚsf3ʲx=nnX5v '!T@w>L׃e_: 5\ mtu,(ܦKtkf9MD89,WXt'Ix~& >J~j͏cz[=_VєevFR6F !bxtn߳WWP7( LC`*` N>{JTIlbrvAkSN7 =KXAIwG VD'SgG,n"Ў6w,-.ym9d&,fQS3 l+P.$r1j,-,rP_m\Ag(ěHD0j`V!@4Yi 8nVv 4툕'4gkZLf BKņY UFle+Iއ4\Vxc= (=; ͤ p ˂xu4mA-gx0/(@ cb6>R^P579HM"K_[Fߏ$dZGdcwݝr?`mYi$!# nArђ-mVȥyY(rYgNgg\Ц0Udő/7]rek nJ1@\FLI􍿊(9MrvgHmԶ^^!C8xph`3~%(w[@`=hu_^؋vc%;\`xh<pWTGz<T#gXwL6hhl-F_\:Ft0 փk\W!֫_딚Q8GӟǠH·2mR 1o\-$W[\+S$KSu/YغCn1(33h'v٧F[vOJLL_р~Ȱ@|ކqS%o8$]1!Q&ƧX^@("EYp%Y]4X)Yr0HwLA(sʟrx*s6˔L4-b_\^0,2.bZ,rqU&XGݼX@f'ܝ*d}VJ+gRM ݎ":ͥ?ZTqI+ͤ?UK}Ƨ–IɲNM'뿞mae-%oc͢ Og@>Z󙙢(*M0<91`\ЊN5#%|& :SGeN1*5,ta5" t*spkEoxÍ5~)&Ǿb8qͨ5o"hC6EBYO-%8zQK+ðaPNyu22qTDT\~EE!^ݲ?"$ZNB-U}QxxNCUQa9Kޛ[ⵇWa:,TL9W7"&!@U"x+o)e]W.yw%hFw{,{EF)4Q-Fo" =yH-9H돜<#9bsQG*&2aۮ^Jљ뙲y`qt,YYPbxBaAXV1z̿`l-Jc3#[-aJ.W/ԝZGٲR.n9{d-87me m& mDoV2.>8x->;.dz4~o3֘J"=hle|A[٘]¡FA??73JZ|¢ˌ?8_8iDEi\_ǝaet>ZZ*$Vb b¼sK;1R!2 ZuFܲ`UCGv$3:v^ƣ Ut0] l.ȗm-X fS^v{d5pů|E%Fl[(Dv-(I!~Fّ?z~h5"x}sgCFj,|N8w?Qh<8dLmn~8&tDsr"Ν擭x=F08sAWEA09%*/ߣ9Nᦶ#![#Jg"̖jYYJ6qY~  HO))]ZƵZ X(:fhCg*p5*sL4jV3GIHN/EEBQRќV ӘZȨdLYmuɆa[Sxhv4Ǻ=FcjQ"١|ւba *iKK9V12 D'LG!Z [8!  ]"8ҥ /4`h74LE-Z1Jg9K,wElf{&V/D#&:3B^Xc5"7CU?D/k^(W2;A w3)&s!QI C@(sښB鐳B,v򸶢jvAȡWjSư86j,@FC7}NS_Ͽg\_}kBzQסl*o[nQ5BdZCVz_-%(ž4x -ŧ[]&|("Oxtڿf!rn}e`=Hэ܉ċ,Cɟ3E/uhGE]Ը&?dah+AS7~fS;콍l3IhAhʀ 2׻*:HOusGƾ;4ҷJ^o"yq_vh3ka8aMjeljs z%69$ @Ge7,E^QLchqkCηn@v:6pO^4dz1:RrG y=+X>s`Й,@9CLÔ`uĻaΚc(K萪tMsw{D#AʳP9|£}C16OuRA%RgPyآ^s<Â$m9r htaO<q7Ȁĭ| ()+%U,ZYeU@6$8QTx}3r醐 +x'TE- |zdfCvGZ&DVQTC/E5< LWD#/qF-Bā¾輜[j^S@6|^*UqB)ȰJAYǂeF L6<*n((OIToB&]ԢB?A²2ܦ](8~Ƚ0q[:?nw\|NG`uQCQWpAbZy5|#F+7ņK{.O˟ECju ;4D=\ɻzK޹Rzv ,eWԥspR4", $2Q'N~BUɌS2"Jʥ{p2iR G"QBv$g5C.Yz~='\C< Zt*TX7OT@U4v7O鰽 * (VU7FŹʇ "Y$q;L r| ]PA9ex`CLѠ8l~Q@ 1mG?' Q5]i.TSFϗnfw0`jΟpR;nncD.> P]/h_?jM0R,rJG\`ؿ uχe= ?>B~7J#[Eq SACپ>>Yp{{P}3AtwHǓt<_7.6Xs J i.5N/#سǽA S=<-U< 8As?)6f$謘9ZT"ӫXeql4Ϟ9@ȋXz:XK.H>fJ LͿ/8C0v;^A[0D :/)5 F5ϦzrԢ# k4h᫠% ݋C@6r0L4 0{ e5^`ݱUiz xK5yX ٷ_Hƶ }z;hl'@q{7Ԋ D4и8O_zawnSl?`?ytG{9ȢՐ`mŲG.nAĵMAqw'_(G8; CtP9a )Eڃnwsb;Z~˶1\Sg{֙m,vVmHEVu8D 7Ey;11ZŋJ?\чY'la+xFG)HG)VZ;s866[wBCÇa<&bM=|ZDquX+V-ۯ.'+} e#ޅ"pG$E,DM AŐy<ᨛNh K$5@gvT*Q)΋Q칄=r<о|O5d%R,*\8h/ 8Z/./  GоEWioe-GOn|vJkʗ:(6٧%\r# 3+fzف\a:g63UΣuPd˪Oܙ>¼eӁ <'AXg6tf?g4$FQ 7y8=B mv(o917#}QK9m3VORjXc<` c[2uF%'J@%S|hbvةgo5@fY>]::kH6d[Q{t•+;Z7w뙐c!τg(H/T;Ga7]sS8U"z+G=@}u{sT6D͂=ud^g:J]n(F؄-66L̾7f,R *ȤÁ$-j ́Feٜce+jD ѝ[X|m T9g(#Fy_PFn/( Sbb<v\oF)6UIYn2fEQXKʧTG~Ӌ): Q4qITKD^6lX%>(b38Ox@~|&ݖ!a*i&K;EpXh_lGrCH1{b yJ:c}7k뱵|hu/?9JB;t{4|vy}XWk3lv e:)N}0sW!>IV*&q}Q .A' d*\" B Kk)?1P$ra ;y;]cUyUgfBĩ}%Or"3s3*= aǗ9 0(w{h^#WAJ<*M0.Am'^nQQM֓s ;?K 4yO/_N+GTWJXv!T]"畫o=E*p:~oN A< iVR (<K4QǓ|oJ~ȢRikPC@EKNlDԾ^JU@x'#q+u٤#8ߣ&$$;wR,}r/TWu8x<<#AYv6w~S=m:`֦}.B+=>>Hv\?+t_|nYwk]h`UGa,|Jǁ԰A†S |)avj .SݨA}jǩ(f11ǾC_J%U^1C0u…uu4QeYCGR3' ${{{;A s:[gGr*GeZXC1bWS<B6 r,v$ۍH(d:WY;։O].bV8np>by* NcB.R/mNH$}1f+. "뛠Q+B!& ֩NTTIQGW-V]"\D6e]: _ ٙ¹FzzU'[7vUH+\1Pq=MBnSryA̘&;cÜN<{t' oT$+~;to#49`[шq g 1 :5ZtWzq$sG. 9$uTans4,cq(fp1W* 0 ^ N_w`z<[i7oټA[ǯ +ݲ7#Ҏdu8Vv8G!OI֣(MӁS}Z`w [4 %{ݱGwA'_vrJ-"IfÓMhVB*v%]=]jUV\f/!1$A#"%{ޏSIfwIU:y?!A=藂yN֔ FU Kt5-A?8O\9]>,SenvG=P ҿ@'-  Hz@oݼ=G?0vr3z>Ը4HVѼyb'[//'׍p|@ҷ/Ϻ+^YpYnpW;F<̯&kޤNQ,'J&Mz k`jݐ&JWl뱌5 $4h[q*ޞS|n*25B7 X,nWӐbr|\s靼5*I%#җ 3Ջ%(5|3"4&#=}It4or!TfȰlBZCu &&q5vHTmnR2x*,z(+kΖ8qZ5Y̟tMBYŷT(ߛtP';'o`(4pֶQb y;P%.SnMS2E ,`ۢ=[Ficwr1p"qӴcs" "u13,K:v x1UUZ5S:G5.T Tk҆Mn8]%TSa L-t@md}OmN$:ߏQM 䩧՚2)z5h qJI\H ??N-b?}:Bb1'iQRw1|iq@dr6? q$UGCOG:5MAY~+67ҍ rp7I|0tIѺ~ %~NX+}i9g-VLi/xcKiრnYRHMsDl:dA% sUC~wԑ <=[FP:acq›6k1~UZ{z K/bǼML"-{ekmPve#:})ahz(D۔I6qp.VkMP'H6C zhħdIa8xD~~[Iu @ր҄B9B2k$mPn@1s+C"jygJ'v,uy_pd,lS>F݂gR IjWGT1YTS>fh%0v:tԳP19x&{NzaR×t,|=o<`8#ێ_.peC"▃@kS-$Kʠ6KM2;r4l^0^x$hMZK.`)%j־두9//="SSZ\mau:wcu&_ݕ^CsH5$i->沂*hD9p[ʁNCON] NCyů %g0bs?)p |&h,*yVJ|˼WAf}Ҩ?(>0= QW\g<ٚަ8cT ;ǷNWs+\0|>BEn-·S9bX_E]Ep,tc a8沂pS[>V\֪Fɳx],S7L> 4s ީ6rw['5!" )P\[<>JA ?Rںe4yjkK_՞7+E% ttND#5|#DR* >})ې/q:}Q$'$p݋ b*8vTZgDRF8&@&n?LKN`PA` .#}#&Se蛱)Z!yhuWAi#hwӯ_7a j'>ڈz:lХ53$HT Q~`["FIThP]uS>sn/HFcc@3Ls4jN R,GՙρrA)GM|jbY5e?>wܷ\KAArY{!5=ƕ$S/%Q-t:$6P/þ.޸_z_wM  RBvס$Dijt鑐@坜䴲; 8,:_0@Yp07tbdO7q2#D`H> nWjү\L. ;s\bjwh3@y9H Ti!XǖN f&!@2~bvxcL MHON7*C=)icѡH-pB˒2A2z;1c"0A0*6xĊǣja%Bsp=9C_p#81e2_"lsƐY]=_?lb\.Z*W@.:FEOz}/ b}\|]3qHCɭ)&e\@}|R@*) 1g5Kш=F\a4 p몱=~f0Y)e Iv)gVQjlG&-ci$:U7 M;w|#ajih Cm5mwR'_a=݄S #?ڨzS>$jpW8TkVAus־4)T7 %͒ ۚab| aB=% "Qzx BGԶ0`q| ۀ:@^6Qwb]z)} .ZǶ;A]  VEנR2;u;N+UIzL 5Z,s|XJ_PE_!+wxac.ȏ<u0k |h8 jw`8Q|%LA 12-!O}q8pf)cnO u+B G\"yFn>VH#vZ6]p^W,_c %SK)v+k|乧L-CvZtrb)'42KZ)jHt%~uP;dlqJfCka'}'-t  AћjĝAmRӉ=b6[LpɥsQ |ves`|\Ǒ.eWmO;ܰ&)N*FMvg;ğ<#HFJjvd# 3^ccJ HQ7?Μ~xR-+y|;齰tb^C)S #yiO'U6xв{6Oy0$:O]NLg^>4[sC\s# hjeEcp昚Ѝ[;N8̻}0TٻT\JH8fAwj-I$tݥ߂%C"`+ײݒC@A;٠04&aDg1E$BykNQfM,Iѕ+s,^N_J@w(ܹSɃ_֓VBe0CO-F=g +%ZG#!lw5a,.Hy֫LfŃtNǭc. )-f +R[[(e 0Om>X$iӒR8kM03lp`~*,d4fQO<@nv|m~+wlb2֚yR(b:9@d %RnsE~n.o,dE0D>QN aRuT ]L RN$".|4 sKEd43AY^& D8iyOSwBͣK9/?1j?`M܄RZCWS -'x 03nsM_!YbVvI,sbM=ݘرK0Ӆ"n y*9C?Ō_i_ДH~CahdX2QPbo) _(}#5,9T+iH TP|F d<`ѻu !RKL$,K=X>:%[2&/}9(7+@H{C#e͊LX휘1?}8ڪ7WD SUH g 3[%mb11Ԅnq U^w:zd@^Ǭߡ 捱vf2jSސ1Bdal ՏCyޭ(,`͔<@>(xM*wM&F#¦DxBEUwܗh;z:S͛:Dž \EgzH mC5Z1 ai璮ָ7SS;u>j˴mc}Lf15gLpqXL;F5 |w6:p&](XHQK앨 h~.()ENC"4 "S=fhf|x }a@he MJ3 pV]RTUJiOa=ֱd=eo{$#ixK7i$C [ kRlKK|M_i٢?=.7wrOce9);Ƚb+jftbȾcCմd :U9X4VWr0lr UZML ptN:āSZKܿ#lVݟxOA=X֠ vkB#jj0<1{z,qUx1DXPmIEj̀$~ 1}kn[=ߡZKz4(!<xٔ+l%']V#_&K<| 1}K32 j! Q45eh͗Ɛ񸒢6WүQSQCӒ TWCV]Q;iyl3\3"5!p򰹍{s=I as}bA`T|wyG\:U1۔熪׷Y65?ϋ dD촗 S^gH'@رk;ӌ ^n'`{I<]cttX!1KCq к.MT@ N 8ǯfP 60K- HnyޭuWjw51.mwa)7̋ VE}F:$^ VnD7hm cP-s/)jNdq#a历nHr +Y`PS{;jyqC Z>VO6y9^.o#T@t й~#K(R5TBmv]km^G];'hnL0){<ԍ}j䬐V:Ȗ{>sbݽAwlLF_HȻ6nEwoqh\k{(>ؠ:LL-:.i"FyfHES4v1,vDPIIh/itSjw[A ڳ\6*zBP IL;63V)W6{a;J<λd1>Hqc\^=LJ{#;A,;W+ ON |eҘEzˏ44c7Y0͚<^i\tx1fK?wua)OhC3DvR+z] 2VrP`@qes䫅9"T BZ^rpHZA@-Ϛ~)+FMkeD81ϟ~AfV8[ ~CoTPDߴNzisRϝSj&awHZ|ukV c.h?t.ډƺpPhSX^BEZ&Î)=B,zca[gOa#jRfXz۰}d+2 Jab02'Gq_fa4ȽBkO6wpCo:*'4uܫ?*6rd$IQ6h5o1V<( kO0˳~UE̓50<o@ŶX87;NaoG,2,cP4: J0cPQ9{  lBH?j$RkVʨA~ eA-L @γǣj J}cMtGX%>Y1Ȩlc.X~D?Ϲ<.-2ݨo9G 4'E Ɵ;WZ RT>5]6E\bb=afj-k`*p; Uʼ]vr#4*dk:F,/HdB#I1r9yj';[C`yCa #A?1P} c0 ZԦQAn=`:9j/\s++1&Nuv;`?<<"rRmٺ"29{ǯ)-"iL7A6"ỵ"&u.&sf}%[?>;Fu äTktΪrS]TGpbGF -X)aЉLM7 >8 2ZU_@x߳҃SԽz]8^q+rf>r++gw|-uccKoN9BsԂHMOM;~4(C-o$ %Ⱥ/;?.(X~:c :Pt~%EJ D-io(M U :UUS&6晹:ԗh우9,q}IoIa~rX4LHP=*Dk((ʕ &W z~;>9P ZC)B-4'Zzce7N^sp߸"5ۆވV!H97,u6Di~B\_oD-7Ͷ/ vQ+撃9=xzw7|w7:"_UT%l7p. Sٖqˢd@rhB&,J * IM*b(\HXNomS?y.YЉ BP!Ǔ)>H-aM O9`{@CakMu5Y%LȘu[Oq40L0b gϞ;T6O/̫?CQGӧUH]3ʯTt7?aþ{̾( 즏h7xI(3*lGs⪡<NX8ΧD?U͚>coE-I t`W;yաz@(H0mk̼{jpDk~"UہrJZAgg ظ?MHd"p}Cl]Y@qs1$|:7NۖkԯH$9hq:U*29\Ki\*TgP^~-ς2F[^ԥp։4ugs|g xV?ʗ3Tz!ӀBfBxjh vDDv_ė jRysgEk@ur~H%jN aEуnT4Z6Imjт'QK5ZRxPQTZ%uK 7O,U`$ \2yTAO] ZQkuqE"P%7yMy_&K%CǒRъW&HGCUP:xVIޓ1v Kh=T mʘ] R'pj.X76!K'Xma]${0Aʹ(ܴڼͱM ]۬oǹPYxksWr ݿ^.%~0EJcCfa9p tUz>lH㸻!R2I]i@,/mr!R1oܓyާN^ ]}*3O^g:ϴ b15d۸ ~ #~)0 HE[QFLO ?u_qB#_~]'xn -:N] ܝ&=$$O 8 M/E^Ο;m};x|1>nIJ'nw^]/ߟv :?B/vצ.r%7;̪3z~v/gcO}Igv_,gwt;Q|)"VFwxd* z+o+A2Mt +=^ICމ AVgM/z7D]BʆR!{QO;tOg ??LO#g=ge鮗l`zg9K0}ܹK|yr^r~'?|q!w`?ǟ>v[8| i䐣D'B'Β=t(&mFqǛ (K?95 \(.9Y@A!B*͈:k,!}$ם$ R'Opwo~?@܅=|qK71=~xvGC\) _ |Dv?<;y*A`%%?* _{˓?"+?ϿFsDQ 2V?_|sW<.!SsDn p \`P ҽYN=]2 g?[ɗwmPp~}񻎿Esw ݌gg*d0]氫 EDv\ZmsR‚c5ydlIapBIli2ݬD>8~"@o;4 H7;D%*">UNv[L:Ү6.{q[0:.E '#<\nP=(tpsU%~'wRu8|0hn#^wMB{`EAcnq ہeňNݰh3=9(^EGso3 c'd1;<4`+Qtb 'չ-}t?w1e֚='԰_F)Gz&q ^?9ˌ#1#Yp͔]׏uM=tPګrt݇OcZ8}G#|3hu;MIAEPD>O07sROdI'$M=cN(e)LDQ.s9W;Z|?|OoՏjkd B#T ZXRtzD܈ܸZ}SdV0UT ]MD ـ<赲Vpο(]bBW0.jELX-nۧ\;eV`p< += ת8 W: +>My.[v.UrTzJ8n]tQ@$yz2MCBDD kW̷%y.՚GKEOõDr!tŲB5eOedOåJdbGu>٭tp0@ ]taC-#I~)x&,%.¡Ⴅ¡ZUa]bt¡e¡R%aMRS8ݮ O88y7^d]ȳ4bbhW00ƯB Kw#,n3hńNjt%@Fਣ uce⥊STιeE~AQ-3q-Lhƞ-+ jLYgo ȟs< XR( jX+|uEXb8R3.Q,ifp#$vjd M12*I3oG\tWZ!bJmXVቾvhJ$|e Kط9rt@1C wʀ?ߐ]VPUQy5z%VTPpRϜutvϠ6:t-@nOtFM(ڼ$o=wSd. xSrgXg? OҼ#D3 7ˬ} ]P<GYXeXzP^͎yk'k=+s(ՑsOi;X:q,yij LU!1mV`d7Afh H Eⱦ6f"~n[PaK8E5Yb.Mq9h7Ef fr]CC4v Br2]ɚZ -o>xU Z9EC^ j(2-L00_)e1ZF?qY8FY=; 4笈Uc54dD9/ zX#-/cK *D-΃f(Z< _z{P\ k;|(fR:J=Edǻ-P(A\-yqR) !DZR;)ZSS,VtT^(ہ]c@K]?V$]LDU,Rwu QEy>Od9V6 @s*n镚 KU=Aq XϝG'=chq-o:;e҄9V Yvb*]{oHtV,DߡwE^Yti+q\Ҙ`pN7Fꮻ8&OYdV LOXHMNSL4y ;h)<\EuK'Z )^>N 2>[89^A׎+xv2ɺz[QC((cPy^#(,8 sg$܎gip!v\w8k5pfNOz]Ƀ),.FrLԬKoy&(>#IrsCޚOZS@6J79 nqZ&F9E~`7 1w9K/H7u>R%oh|2w&#+ vUKɊ˜zqK &U$쒗m$?f!S||'KZ ϩ@-X*d?):1oc&PW;81PH{ YO $rw؉+[- 7aUcC9MYJ&E"6H t ]zO6EG8b[(TJQ.A?;9fPds9;Q B^Jdt,=N2-T#9z員p4l2+P#J8O3h)UZEӝ(^EKvMy GuP[3#S r4rGss:npEq'&OseYy-*lw( (PpWI>ec#~d"JqB:_=¥UJ(+UJз`}|2wLrjBp,`;;CێL =9|hlxg#vD.L/N6|s匯;:O-q Ybw]9|7FqEcE  aYrH*Ҍcf^a2 A#jXE`L~Bz #:ۆPr= ,mlP@:(Gq^upӆAoy5~ݽ aH7UlE9Dܐ2XW"]DOS^Vto&,M6~?ڂ:}cYǑ (HÜI.᫱C&^1SSsvr?`3~EœvE>4$hÐ|(awzzl }Ҥؿ{+4qw,[cB0M-N.ϗlq]ClswQPm#iM.^WK6u7{ 'ayI}%ojXA׫ly`"oq\x1͚LɪD,}74?dokx7dҷ;ѶW ^A{ xp~ ۃhuW)"LSgdUwipb6_-9ɃW^Lk̆fjua Oe7[7E r rM#xN?YRmJ CL̴~1e J-3g'o7_lٕYSCWh(YW|34b4&S?[ZؚGx=L݄"/"uT[ Q]HM$sBo=7lMݳ/ws6 u 9.^sõկN8JAZס6;d2}qzΝx妆Vlkx+=O9JPSϴSQ-V/ef[CaUER .YsKڎq Vl={jzFkmh v`rû(;0gً2g;$ ?b y2vkGu"@|k`Fe.[W;M'T I v7 hAԢEУkGJ Mv~#:svU$LK_]/]=GjdpB0'Sxvz>;WՅu!K# RN/ 9n ؊|OJa[6}6%jxedcO-ym: w$Ufu&l#>{1L]UMbA1 o"풕r\t74t661`vh_0Ŗ oVW>fkQأ]XI}^xqrrȵc>P(Rdv@q!]zfC ` $$RL8 u^qnRQ@;C/xQě+PG4zP)$ԅYIȯ5C^1| p:1h! r5ga8@-Q^S6c:!ԯF.W*wBQes9+ETZ0'RUԆ Z/=}Z 4pReQ)ʍ&FyT%l1VoN5BqEXr!XQy; Χ^ h=njmȋp,7LA'@p٩ Ea'ykffzfʞ.:$}ċ.άÓ9%]P7ȿ"hBg.FJCߗb-aX5 b;1Fk}~KYcfK[i\k TV%6Lu>YqHD $TRL"P[i2אz&JB3,2+iqԄ`da3Ma\H%qMv} Q! DF$JK,C65}3O7->)JovhoJi-C VzU?UsNM? {0PsupqC*H` oHKTP=K5pct\ ͭ@v9g  dnz)B-ucJG=}G`:<vąW ?~Fd|P:t};1&kǺ{$9ƹ!/$ ,UI"3ʪ3}B:l^Q&~IC/T2kZ+4Ot;$O\,~)q&(QS7[S`ZV+:ץ-%ġB$m($$Q?"y/WK U&U61o^RI=4=$[o"\"l\imclDLr[J'Ix!ߑ%1Uۙ)Ђӡdtav 3ڲD<>N 3ݨ~vn@my;~O! _e*~C"2\*FJoyS/첧m惢 d&&92 ]% 7(ɤweP_Hт\y*,fAfSI)GPc-KcD? oĠ!ӢFoM)ԅ0w՘Emrr{xPR!Ŵ*Lq5J 桷<'Dy ONDH[ɩK:n!6Wu# WTeK|frm4/z:Xs6M6FV*o Q뼞wgmIV$ϔyhFzd5=7NmUޮ9)I [5=u`? [>g2̓o툉|]➝}G> ~tbIoRa| >G-n㲙\'s߂J'YMC0<oI+Upx<ÃjDT_£-2F_,nNlI~7y'TAdv '̠(9KJ&ŎIN/3y$2J|H_sآ0(Ensm5@Hiܡ>R21זU <.8C2XOȡ^15)sC i*KɋL'Sc݅9.!En,֤ߑ*e) Vճ{퀶q%ʉ>A>-e˨/³ fIn9C~Cg"4Yru%qp-%lY-{X\h$IpSncyͺ[ ;]ҴGI62ŔqtG .r7'lr< <>6NsMhuã#ԥU'o(m#)аmsR+I /O\5j4;nٽ)>L״Av7@(ecy#ȯyIu$} Z[8q?eA9;%xh4j"l%)퓩[^Ly~eӁr}7URRbu!%c[] fy>ߊIO|[uV˪Myahg Dډs-C"?~6n?>)9W-`}-e&(dWu87YZ7~ۏ_ʳЇh&c 1RTʡE(/Z]D.HQ[<9}boqsU_cڠa&ƏĪyvy^\{E>" *m l"RFci~x=gyFʵlNJC +EX!A,,m+@{vs#`bRRG]Dg&N *Td@Q})n4PFv~m)ekK ëEZ1]l8S' ;4=둵d׆a8(< oy(7*y>0 %<adAEoaX:UgiA9W/ [QXelVV1Q|g`rbh'԰ͫqbճ!47^ǃ Rv \A(rIdz멚m&aυQPCC*";QŦwT (nu =V} Penxn¦ö31˲us:%ZC2)He[OH\_ WT]DLrSQU*wȡ2/ֻVM]D\h뗱,f@w 3C}CƬa`$`[NAsg Eqsqoi{¸. 8O6;c6BIds=ŭY."Ɵ5ED$ ]j AlAbhn@)p bYDMfӹ]=2$zϭ 7xf ?lX|h]Zo~w9s yQXZokjF2ҀRY[c+@d% ZsAJʡ؋{H3B:*Ew)ZXA.$L~d^Ds^-"Zc%XC؇pv~b9+x@ bC5#J\Ll˟AmȖgĞO;8@&…GKf>oX}@ZxRcy&PKp}w~w}/K JMLFEC,reo/06]\*OvL o@ dS{(s^p]?-!S})2si a?wZ|4_Eikח_ oHW~\a 8*_}i"g`O5LG{BÇ_”a1>;H4VnͼGUhA3ZtM[&'Aԅ߅lu)&\Ћ{^ZTyh"FqEX >sBNo0=:mM}!柷yu8:|r }4 kG笹Q&D/h_;tIK7}kžpI'Pyiu?q fA sWiYZ鋍Dl]  y<}l{oF>%"Fې0fͻZFykY{eeTRCא=HmyՀS16,kn3Et/lB7{N T&쪙Xt9H%ruԻ:SXVxU?Kټz]5NFMȳKtU0v1ula:|!nq 67;WΡF5ˑ*VFYG[KO$?qs WkmО{*hDs9C "=Xؤԟ{zJofX!K+Hם(dz=t}\ ymL&g ɍ==ޙ2tWCWDiqWuRn*DbGr-ۑn ѷ ۷&>֝3 R#gˮeA7ەBNr$ˆ a$67MoHf4!n6zkO+L5_ÜTY)zĝ!G1Jh^'ZŦ'z4q7nIKfe'w}?^gt0/r߅\w{F82&$Q{)ﳭXI X]ײ!0oLC(VPT?jI;JC}hٮ1+%qnM1`Uc^)ȧgqe!VlӡfXcSΠ3+GƩotӊYkz3 Qov~kVa7\IF-CdP"o ީ0J~Q_NDm[Yh+~KcB?:^ת29l6rJ~Cj| 1 7`h301 OI3QI{IsT7&/,,wP{v׏@%#1 7Um:(?y)v]' sQ8w37kVr7z΄gh9wI9\`X͎\%uɹNNSv:S}Oan+eY$q5kd"¬:_?AƺS5(0Z3C|( SԒ[©y SPg?ʳ3E(_+i6vAֲq"<"`&2䟵,W0m 7x[T>to<<,#eW|qǾY%\'iӮ>%Dzҕ57t3so+aEc/YժXd_+Fb(=9˅\4'< ٦\R8JabЇKȦ^b%;wd@IN0Kst_w '~mKxDՍ--/KG|tObڮ;`ciO/䱹B~= ͒M'nN!RHaE*fyRE!+l,a!N@} dd&PZt~֮۳%R" 92%ZËD-aYhQ{t?j'bƞ~S5Rbrc z6o,IM?f&Yؚ-Ϩs}䘐Oy%)PPX\IOm $JE.jEC@;$ww*GSm#3dժ' 9]\6T ʣVO-@y:e$2-Z ".+!*j:WPRr5Y'= ϒNgD:_z~0 WvNnT"jk`8[j}h%9!%VQ1o?B#Lj!Ac|Gd)QR)mm gS;˃cjG "Am f*TB:pz_VC(UGiB)oA@ {b9v\0' QlJ(c*+LEY]~+O ǽKbuZQműKYB,oK_f`cM]Hn>J.E]oxVӛs,rmUo=yQTqYH/b*唗D VC\ym@{#xEļzi̫QA `8_tnǯ̈SLx̸w,X78r+T pT%@=u[EmYibzѥ'M1#6x #փH6xâF]FCO<ך]̩+A}yQyCqbK{1z7";;25ݢ/\t.QI~czwD|;A$ -2 .+Eyyo:F2|%M6DLPz'l,˾WLG:LܫF}=7 ;Q=u@|N?6ـŦAFqWZVOl|{ Hɽnz0{k\^& '_~K "_?liN0xiB}<;KTٍK4ܴ.ɻ҄~j9dA p' 6dځ/J ]1ԛ!o#jPw[ejޡVp%:jJ+9*Q-ǒAM;6ҨysQ4ufѠC FkZ{`|rD T *mQx7o` ,٫Woڐc;p7xE?Iʱ <$+~^'0kG-ϊKa}kj^N9S`i%nc3M@Ľ@1} 2g@`-2[ڦn[K +w4ndܪKxtnPGM񐓌xxHh+"͢|wgцeJd |7NѺR"v˅mk\)VW \4Ve}ڬH/4ǫ+*.(&zWfA9.8Z]΁VpC7^́t^!-ڷ8׍HdPN-Ś[@0 bݬ&cх|PU+dY CN*d9xQ\`g^bB\j@ceP+@cDi1h &D8^!IK;(&Q,RB2c@L xuezNn2J 邴L#J%jjd\ź(VeHʄߦֆUb娜V\7&z2VF)K4fKrB/j%r822 6^!#9JrdCZo2`κA/5cŹB̙ ռjh;Caƞ㧉vVu }zZ<|1bk,XSӜՓ}l˿)yN{) ~J?O)WlӐk=ZEјe_894zEF!ҢwO5&wv UF:J#C{*#cGahKoq֝NOl>Q5A }ؾDCo),P$nq^&["֞~kPj+ZZ-! ȿjUIs'+w '[2֔?떖la^26b_(Y+;p5!9j%Py60 2 ʡ~PпÎǯE7(Ng5X-E`nXT|+0Dv~[_|ZKy^10;,,JJ(;X6c#DmqY #7ם4OZ[y1J 1~4N]j +M[{Q'GVPVӰ XzBުM97jab5~,p;;gfF8nwVZvxDIˏFҌ,LQI}չGj 2<Llc~K4u;=+ vVH>WNnM#`qch>TUTh%ޑL9)'7!Dt~EX6ۅ:y'gܤyjUO Gw)_{Vo#ѳ8ğ,3/ïU6H4t [:ӊϭW98=rTi<-b YىA}qlT+[ãJZl$'+_POA.DJÆ.Wm+vWJrG$wq?FmB K?.W3|0r,[k n+Y5lvv`l.;Iu¯Y? G1[VK<"/8}?0).R'qwi!'@S&6Dqoǣsp{u~3hs'z?sv{^lxG)f#sh~Sۨ *?Yy91B\|@,be`3ʹPH:P '!!^{<肓H eSCǍZ4˵sXq2OڥɘpBIWRˀW+@gv( hM(S?ٜ;J3@P=ȃuѻ9oPSRIq(yq_ZoWWwUK>4{._)bD!GBH56N\s `IJ B][3R;ہK'fZ)[DyZ(w]9MeAkܣd5$gxn*+VQZA7!aɅ051SiÅ<}S ~YcІb^R|><1-$0 W_{8(M+YτwaYǐ§Sj^4ٓKÝVhQx\0/?cJh*6C`(xtY"~̭[ +dg=0r1? [lF1ЪȰ|)2;C{ۛV:?G~ qѨZ> =ӛX%qLnew"ku! ◗*~)R󭬳aj\֑R%jS_ ?14(W=H'9E/i!C5T{Joj { UF+A]mCQd(:TQROP=+R:t$$aNRLDsdmBO<-4h_Z'ځb$K`N R /yTV,P5kAQy>5g31$ %tRjxq>GS~?/U^(Ðjftu`!!/ tSDxoXWGMnMG_R29_$` 3„ WѫB.:`\OcwOi8UNw>xlٮ \66tȖ"Z>67pBM USDf%KU*'hd]/EMquP ܢԹJצXNη:N77v;Vo H#tr2U']#'d`B[ےh7UzcɼՓzUIeH>e:*kh؛[ x<΁B-[g^wiZB@H{]9\kE40ɾf)QV ֲVLC捯qdk}l4\VS52}hM EVoۣ:_7Kqވ_h_UyͰ9D mzʹI&}:Y{a #wx=δu+ԴvVHe튊AT{ HU`nf 3tl 9>Dֲ>eB3 Ls/W1ZKz@RZ9Xf#rx\;E6ov KYg%׷fuVۡϢSOp[O+mМVa Zc\@İ١x݊i[!6"i/f+oPhҪC_X+bO$y99]W-l@g^vK^bcV&wPS6Lv]7Rq#S:PdfHFN]v9,sXr/Ғջښx6=fy3 <~껁$cFOJOǹ{(}!ͪ`5SL8˫@D9Ic|GR қPcE[> (qSyG)jA)}{!\Ϲ!渶Av(t~2"eM;=|TG'N)Ͳ(h')9,8?: %ӐsmDew}@JT @ Jcb+hxSG\;=l*aXv=ZFDxDӹ.qw a\C<%G)~ӏ٠FSQ-j6h ^m҆螄Qol{k*rްښ_K3RA h6Ej(qabe [q"ׯ5=6U?ȹH*~0?# ݮZ -6Se1crMm./79u-nK1=YIӱTI3< f&mp9!YQܪP8|LZ"V}S%%<,.%JqT2@@ħ+4AQmDY|(#~uUK*V+QvpIAF,'B% m.L?V:+M U>?Rt.zPv-OʺގŧUpEm)\LS M:= %ֽkrîvb>M-mdiJ:p7.K^@Jm)~rjVHa Xpn ch 7)"⊹L+|wq'(Ǚ}/KfTڿvEL(j2?(8{&. _чKCzQh6 7OzMqn rqF;}]־\>g\"Vӵ(OɸpMQ@S vmBID}''a-HY& _@*q cO I|/7:R^wt#()Z k mM,6!r iېn{!TKYo[QĎ8Ϟ]R?2N-1%[ sL: @þX^:i:W5F -sm h3r"J[Ɓry( ьK ,`,bfaӇ'd8f9E bGP c9 Bh^\NB*~ O5}CwV>.X\W9{ԌIzO #iJf'NB(FXV{X{ѿo=\6p΃19gRDbyu*Ћ݀Wg R^DeO<4u8:qS[,FQ3">j~_yy4+@nxz CafC-R˪fjP39%+g?Z;&֖mqK(oijyЈ,& C=W]/&,v_\ۊ- } ]GVf㿊XYfp0HsnFAힷ.z]5CEϰQƻq[!f0A)=ub~΋Ĭ1{L -R[nv.9I0+k=FMAQ5cMۃ;p t\srVêt#3숕g|1Lmzd<9o9\ephq=0/y0 sYKI;&'IfqFYLuc@b3>\KhEJYBKDHxWQAlejjؿe$xca-090Q6];.>(rbLޮ-TG7ժo?• d'sF1&ȔQ?8.}m@ НsZM_ͭ\ۮۉ 5E##^B>xC? J??%5vث[< x =+Շ>d#Z7m RZuz1T}M-Yz(ځmH%bk~ÉYkjóe#NM4hF[{vz|Cs+(pǰ Rz?2LnUw8y3d7עAWݩ_E x"CwJY1 J 6\;~@_naJL 2⛾`gDlC!ӡc6x`k>(gZǜB͆"rQ'N$OvȌM~B@, sn76uex^ %mcyѺAy[=Ws!!%I6`Iž(D6%REFZ_ @9Gh#vmX$n79v7S\뿄 Qg PѴ2gxM1D !&z:;~k*vDRtF-8a=;lUUI8#NL"|l-B̪GpVc]{Cuխ fN!5zm &W_EXʂEqqnv33kT ,OV,AZ 2YKOXs _Y+|7\u0j@ߝ>/#CS6h2bav ,񏙗A]X@IYj]?wb6w+zaJ]:}LC+ acw7\l P0$\.E%vSf/@%fK U]T9C{"9a]9MbpܮI.xڲ]4%WEAү4L,fA_S&~,$ AxϡɑӢ9mY.:lܹBs~˫zQ",-5]r/t~nFnOȑʧɭ"J)XNh @T26ਥkݵ"Pt-s- $CX7 YBWGDZyQ|"&A2lqѕzc2\ -vdLb@*S$ ݐSN'6pYZO)F,m^W~@,|)fR,I1]~&hY&Zk_Mb 9nx#_Qqnxz_S]"L,^ 2_Iel'"j(:خfc+/sۇppCN|0|Vq*4Z&A _ZATn-BwI 7>=n:{y xZى,wd w.U t讲ǛhaϤ GbU~SĆ1$1ű'* >]xCp_Po?/qh/Mt:POIݝ\?^!i_.$͉w% \ډ 4]CwC X}U+2&5ޥ9($6ŦDkx}1i@yᾍ0ho0i,8`|,T阠4Z2:("fg<gӚplWK51.hv^^w2;=T Bl3" $!%&{ud3c5CXJ^cg*%RF:jVtS]B_fBdLN aNA[- է5PX Z eMռGӋ Fخř$Ģu8 YCwv0D33E[Gn!ݒ鯚+B=-_7Is&O5-=G›UvCPs~nMXmBh o,9F aǦ^tTcPb40k~7Y>]@ɺny^Wij]H7ЀYoyc}wM(4 QR,a,9L} sG5^ ɘZF5fPM]R+EBsBlMGކƢ,Ve`U 4|p,ztXc5Dt5\bk2]!{m~R|X˘mCpK; rcavbS8TTSESo:]WIY7_jiZ`<7ץ[e<Utܬ5CZqk0](WdV#8!; ;?V!`Ο?㯅|o}|X.Y|YItT,A˫8 ez.I+ x ^(u|)" >7s`"Saɵ_aU׶-2zn1]+Ng3G}U&j0;(J<г EBni{t*xnÙ56 ~^|ftCWA?꺩+0V"BŴ+ӌM(^gGd]O+9A"L~3?|R|RwHۜ)dGIj?,dAXFK&. \*+nx5%bOQcjc2²CE&#%7sN09eZ]@QA\X&0yvU.Žfg(Oizk,FSQ m'/,o( m,LO |M V97#" z^'rx-I]ӯMd$"BH.v8/+ A(B8|*R$T {V>ǣLr *W#`V;/c+mֵ)C.S_Q6u=B̞zu>yId2L閟ylF4B'l&\(IJ6}0p)N ~P`E;? Vi§ a=5(]zؓ)(&9הd;a4}5XҼ>z]M-}(ǜO8VoNq!~=Kt߅}Kxg<%Qgʻ>3w h'hd_~qlA͛ݧ߰+h(-,x!#A\Ț'B«orSI9R(z9uY[4Wd ~ASv1#9”lf) J[M"wQtFE&UL/ڃ^2҆Tsܔa0e2k(Yy#Sti0!sInrtrvD HQlQ퇫qGz)Et4tOqM<މP4 d)Xr ʻk FT4t GJbXz=RsFT/sC*Ԧ鄕Pkl.f`h(ަyVGw P| P!oTc1ዅP)Vx~ETad QRQg0ւzra(KYքYT IKlfQ<ʼn]\ycR9q1/VdqBԿ7& *,ѯJkD1ug}rӦ[w3:5vUjzQ٪Vg^^L{ ~9r[yQmT!]8"h$Š4NλXnH G矛slKnאsI4s1˜ ꌉRuT/qsRB_P9]¼l@Ļs +tΣu!J6CôޙGȻ X2o.lOUjJjoq&A69eyQB>:;UaDSjO5bfʍ%tYdN=Tn:D;^:$P7#lS 2,tӜ0XQ֪vB)ډ L3]O :/+HGL2!vzqcq& KS^J-/Ao,^qu85:C: h6O.)ӯ@f@9>ghF!g\3Ƥ.? ԅ1#cFz00M0ar5M*0 Б'tE݃hPXμcQ!-j|ʫMa|. htcd bB"JKjsΜΘ,F')a8:_y)ܝ6F90s s7!@4J]yt\;Lt3{Zb>Qox}{|ő[lKmXl֮eƖ߶dYXDk,;32Kd!q !r/wyH.˃ .\rHWU=J6$޿wfr∦g9]˚)])FJ4sfZVܮg9e$eĖ8pJ:%+%)3۪qFRjTy1-bVOJ&>y铢vd6{m-mXv!J&K3ex)Eɍ+RSQ⬢d4&nhn7cX49E3ŬF'TP2x,U)i&nĘ5e\ (D[jUiIJ) I9g28()?؂oH0oa&DjH.L3kt]J TVJ&4\{_NUZ>%srnF=1un=]X;'SN36[ZΦ.6uvijmjHHp;BuNݴײ[U9> KNW7r\iI}x+$Ԙ)WOOFj(fU+'5qfa# w` 3;$jo;u6M.w˚,iIU.Dm('DɐMJ꘬*JsYj> (riJ0u% ԷxTD )7^T|QX/+bF1qli ]Շqc8'VZ1ațDSRDznXnVrDKՍ$ҫFq 4M3/>ə2U@lR%%3VӁ_ 4 Hj ӏc˦$Du8\b/-F#16P4KҵY(lX ƤBkMrz$jAJKei Ld`LA@y_98/J!" H !I SB&LiLW-ZbNPF6Sz2Qv]R.=Ubf+9 KY.G.myx!Ze&i)c *T *'I,t2:ԯr0zsI. 'q(sqNK$JIeW0E0(4{&e [=ttzޡᩴ &?K2E57jP &WY}Kz,]y(B h$637c2(խtkh>L)I>'4Q +gYYhҐ#> on5fV^Y jڀY2bv5LUe` 0eEs%XUQM=״Ge A0N8kGcg9iTHĩ|Aa+m\+}⫼GԤޡ?n- bLh:zIG8H / 훈&f "ryC&Sah8oƝ3_iyBjO  , rk ,`76 xcha3Y0͑ep}T0 /l@VQHa'2(ugmߐk'9HW|2_Su ^a:F pԆ[GU6ҧ”O`4\>K-OpE 'o k2w2 (h~~EEw{F-  u-]7+9%~T̢+Scݺ j[ǒ 4tMHm4,Ӕ>KO.Gh}(sJVe[%4G}i+| EeZ0曲5}yitpqFodȱB.F߸j^?p#8隒Φ(IE=Al-Ѯ2dj G6֢y;2ֲ]۟“ uFU,B}ٳ'qg _ԕVONWjGК2`=mgxSCvt3@-ƛa %w;75҂5?(E-g>RuλWtYh ~c$N4d{gh'Mܖŵ}>Ej p{{%"zT!WRlwAo"sÇşݝ&ښ^SSo Aw(3@d22fM&CEMQQ`ju>wsʢxٽ9cؖ$J:\oq˴ֹ+$0' 3׷S%7ok_=,U UF_Pi Y+Ab{SGuȻkM4yf"!;|5]ugݱ8~t@PG05~.! bPRRIa`X9p&TPspIF5r"U|)-MV*gh$Eooݕszþ? iXmxܺ첼ܽ-vTNQ`^r?+܂ܻkm*Ձ cBJ+(?t$fK9Kj_Py%$`d[P i贾s-)53(_P,\a$|jpYtgM:On}r/ʑ[I;??Mxįw|7~>8kR]$/Jms]\qqY?S=p^,*\Uzh}䣳*ʠB{mm=AǮ=E\@=SGCfa_ ?1 /vc[O:򖘘LmJSj?OBԊ2I06Me/>4s"crͫ &n䍲NT䑏>9gQ+Z=o͒c%7Bhh`,:c[!InS{vTziý{%x޷Wܶ@7 $*Z  w=cO;Kύry0n#\S@PmQ "<|.!F=n+v:uછ"P\\hT6.W[dEŨ(1g +ax#:Xn=UF t-ZY \ZAwǝ;w5&7P JiI4PdShW{(QT1)5V$ԋ%V{1FXSvũ">ӟ3HO5jaeE1%#r\Y%*(k-+b .tñ.%ٷ}ym-0)!kT))q[MPtߔq:'SeA"^TCՄ2/FQ<žOa>/|zCǀ;D) k2{ļ'D噣*a}yW}v&RsT"eUeY[F۾Aָ~[]W-w=W7.?z};}-(+޸q_Ѫa_^kW5,ןo_{1?/npmzϿe9] mPQ˽nWi;) C1JԽG6`DC55|>5~)) %V8rBiReFrRz՛4X8a1'-J h/ɍ1`UhIi;w=wݘِ u{yA%5*CA1*/y@ #cm7SVL\4Df*f0S< P㦢q3@R!0:n*`L.9KɾO;l^l?X60V_={[WJnTE^c}bK%]q&팮Tts'"fy>;9pӕ&tW}^Q)v-cľuqYoA͝OQ GL lMt>1#]5R2xV8:2VۭJVʇf7kad2oIjY r$@:Pp'ARQR4t4i2̪F4M<.hJϥy `js@`73o;oe[ƒk51XgfNqvʄIdEq') "-PqPҴi9GKL9wd::SxxˆM>-aJ}hi;g?Rfh Ssڳc.3ΆzRy|.- o iz@<9xs98-x;C|R ~3/+=YOhږ A/`V B83YLĔf10 ;} */.c= ~qBÒFRح9xzęa|;yFA7Mn%Fm9ۆbTH7]RUUSy(m]Ǡ~E 'WXd %lsI[꼼q.YĪnXdHĭB7Z7i }vsV,YZv )u-bvd>58j%n`ȋQɪ矾V?# {2qf%c?Yiel-99q J“[^c1pIAD^vs @~Gd<~ N|I\}|EaB"elBm?(VZaB=;8_5S;U p.b˝=l!9/qd FͮkyQ{->OIN6Άbƌ%|cKU. J>hVń'|kX˖, mnbOLƖ7ܝpI?'"pnboXĖ/Bb#IL6Vma1f6ȚY}!&•%$-_(dv 5ͽnXzhJ$14 i Y@+;|-q深eż7BG6zZKS9/#Bzg:ִ|/if/ʭYͫaZ]Y߹dwx{[Xο]&$:tuu=4X$|s&5f 0\{)T;K0&AcjaPibN7RFȖ7κ5h:b#;]HΟSf3d3dзXQOY#YgL㯙p-;#-YiXƮ7T\T#ke..e ` pu.V9;E5N>6]xsra^ %ezd_śT%*~!z w|2$o4ʲ60۝ZƋoI>OI.>8tHvk.,V`L=Ԑ\|Zg}c - 9@KYDp]ZNz:5b×NtlՌ0a۝aAgR Jﺂ( oWPkW94Srp݀bmnaP8-XC {'KWDQ(  ww'lEU!h-8=һOŻXB0J2[e"eyZVS9I.[nū#k2~|[]|kXHv=k, Ȑo`MY$ lYlUEx[OFݳ7`{lvCB#[XIzָt>r9|+/(PVvEep('ɇ`vz66:#1M7~ atɄ8V73ˉʃlֽa o_bRnaX20i}vE8iYUE,~,O-~;Ttm07lڝki_cB!9X4IU?~êAt4Z3}Bk]̘OD" 2Q5q@Gz®ܘ|0> kM2y~'? Fqf#+pyqx@esŽlO]w@oZ™=[SO@>t?ۗ#/<;Y+=/Mf΋4tlӚ]ᨦw^u8D"NgˋY"M|m/{?]lFvGpqo]{hvdt~pn8*+lߪ'u]UtLpS0~-$Ёb EP=AuAG%7^OwF_-V\{0Y 'h$11 w:>Î예V[ĹùQvdsɸڽdYJoZw64b;|ݨזNfM2tB%%5$h%يIW̙|TgxAڙ7>#&mMuf:ϳg4~pH/&/bIl_G}@NbZ~]*NfZs>= jssSJϖt44q}8}s+v+0:6)aӱ̨Mk睶$aeB?Om0hlkB7˝9t`סCHU˥-ǝ1`E:GRLn(7$g@p?8_*݇WߘɅAAT'9G~ԝ"v'ϼ¶^}&?~??(憑)'1qk[𫼷.klYG4m^=)UHDu+TsTA; '[=P1%*Qm_H5NX< ?,(=[1ˀr߳k+\xO ǹ\3LL[\f,TsV%>5/!~'vj&/)Go{K=~rR~.p_eqm8̈́o,I2`(u\6a+a?\?m Hn1_{ jޥфY?&-yf zgb!xwBմv4m]K>$6:+ 5 G]~ ygN\ة]kU@j# 9')W~kRO'ys2䄑1˕/ze|#كZH5:]Jp^W۠-@Aaм'ZʛmU.\ˠ Pq,7j{"i%O ;XU]a5N:HZt8Ukv,Z~L&8cAa ڦM`{jpTZ,lG޼BZ^E`d*aY)FpG&'D81tUwO_@R%%7&|N>!kr~])+T?&]&Lw>TRaMY -n~L{)Dl;аn&iO3@V\ۅ9h}NL*%*_` Q"0EmB/p>\y&)718:h3`w:km#0j̼b1>4]K rp8*VǁVK\h]Z'8'ꄚY]>$=ڹ Z)1" [jOR/bN*A<4 #+@H'V ZJgnpU/,_la;haD]@]"B^1s?&OV [knqY}/uNr X`RwۀgQ,=oTi `Ng ۜ' c۳9i0Tt: {1cBZȸ^Y$ :"lWb2Ua<<|IhX9 +aI&gH5ۑ]3ڙ(xW4y1E>d4NVeZUmGbNɕVkQՁ́n@ iq.o*@h¹Βvs}.wlvm]2@;B6ŀַs$/juB^SA)[ܧܹC(;-oa1),=(OOΜB3?38>?)d¢GG ]ޞ(TƺT-{w pf>ο\)Xmj"A-[s<ǽ{kp RRj7mVx K0{[_v6x6 į"q`\ UųI~݉,7kVwm |`AOmږQk C1ȸOw7 &G(,탸BJE!7}[㻄=GrJV3?6T&#jBwD)9W[@a-k"L=T>X e3/GG"ʻ|t|r~k(\R|na_jbOWoC(x\ωV6)bFʋ Vs\2'?8T]JOdDl%`G/4S8+B[6_s%UB]SMaETFGk3!i%RCA)-$]k% z㈑fڻnd/lи`|'&8/!rEMJ E.4G9f{߮e1K^/ԗWq%[ ~O~[,KQrog+Q.K@S ?g^,՛cx˛ȣ3q~"9׿]DيMwR_~Gy[ڗOu z-i 5(E)ߗ䯂8Po}{ZW4iE,.=Ih"W ]?_*?>w4{RE<^$2[)}vsz^x dro>1LWs9[RU|%2Ç" D|dyF\4 ˥ n+R%|Y T (A.8_I^!Hd9W ayJ)]q D#F Aao*N8Ԝ". 2r-fxvkRQ.q%' +b T@.q|*:Xo>yp ZK-`=\)8:X4'qY/.΅hu܉2@9D;'J+ " Y)feDeǠ.`,Ij~fSKM֓>Jw6][]r%e@mtD ş+po*m;>3 Z`uGM M66 i(Dj1G>' " ՙR8yJ-` Ϋ5*@qm"dV0dJ>ʫl(/u8Ĕ5BA^9pVq `}6iP"-Zo>!!7oQ ;C=V}[\c8ujyDY(!mV psᅒŚ>SЛtA")ρa/fXYm5(@D3YuŹV:"\7m2|7G;"ɁXmzH Zix&腆C.^,#ri.|hZ-(طx`^ '0lESO~ Ȃo>\ZgELEʕ~xE 0w'8#j4+d SjF{UHWXArVzUB]|m2zJ O@&Ry7h5~ )|1%E.P-$r[0azH~O{g3 D!@'eK]EF]`fd\co>L/U(:mUO Ϳg_f`_! `;sd؆s ,;ˠT<,O {}G%\f&f;B} V4I@tr-AS1VhhZH2"_Ec ^ce(~w$ORxpӃPbSONs0Zf:p0[f]s~ ј3ʵ@!Y]Q*.E7/?.'үr-:@P" RP9gwBz"U T8fJT9݉50vo`v Eg@{{7)مlN1=4ÿn>OA, tT nׅ]ٵ4Aa3if){F D!z!%s& Y&hV2.>5#n]IlYd^ >m>Zߛk:XaŘC"1KSmn ncm#G۴G׽4pcocgcwcUSJ"r"=K@eiZ@jvSˋo9JcbE`$LcXɴc$tc@%a$ȡz$H~Ƈ&Z5BhuW!P/–+n\;y"wo '#a#ڴO#cG۷GճG[n??ɡZMPFHD"ID?r%\,_]qe_5][C̊,JwFWY*ڕߝ*M]꺩bhlM''!p}L9cX.r),=xPw? Q<_""(,)|`r^fyQR*uυ Qaa ow/ӽ3? 5373=r=Ej fcnb|c%ʐ#jܵ 0ir]}jg!-7^%Gi:; Y`3Uûjs8i0>1DN䷙.;jcC .E2O igx;+j3Foo>,tP(N8&%"hBG72EKPگ42HxW =5k6XЃe;YaD"F kuix̉6  mskf `cj{ܷ]ЧKD1 5K K2^ݘ J 8K9K ֵZjL amу57zs#).Jn0/^cٍKTp\[=q/x]t3_Q?`Ky{H珁 ,4*W((ڑ O]^b+JT%Pغ:F~R0xNq5Mţ|]wC51%Kn܌΄_9'^&(,э .rA_0c7|]4\ChkqNaY#o mjS`U,/'n)`;PZ~abLƛcW:FUbD7Ժ> @s>%_ޟ'5fbvjDk@sbu#WCk"}ZqJ먳WrZIu~2AS@4/F1< Nd^9!6褃t-ے4^ic:O#^G&е7.U 6˜Sjd".]եz QOzu/~э>Œr@1`quAA,?\TI4؁Wv>󢤄 i>\j zi̽@%tx:` Pp:`N=4(sS&u'iMVNj_L~F|E7TIS 'l ,&3Onc(q#ꣅD\\ A/` >tbP1耯].ɀa\9|‚ :Be4 u |pZ ٪==kWS3L{ "ɩP4PR00 |GRJ(C +ATMPq CIp%9Q|h4kQ 4( dLxCCc%(hr-;Hc\8Lq"8 yH܉OHi/nԆRf8vߚjuAhpZFC|T%*[TNbx/d,F#oE{Bz#%5Ng5IpNLb>@!N/?#9AQGɠ[2r\T 4?{nK~!VdJA͝,EԢ"TV|J-:s:px VJS}Kh%:) bdgFE, <[d쪐 ,HZGS=<7ZNAs.FAO}bEVxk<ȃlzssU&#yzF'1JJtLSHp!$OEs8|%ߗXo>pzw75t#j-4Y@MF4PG r㍲MCa]eN(Ƙ |NzxD~BQL 4 'AYfE"]`ѩ|~Q ,\~rx5gī o]-䅪n}ȁhHndr&G92>8)a>eغU7r̅yrYo=֧}2 t=h_ [3ytv7ՂeNSH;9$:/H|7UwsRBӍ)цnr -0ښ鱛i(`~A<͚P@ 4=+ߝm' R4-| o>a6[k&YٖbE-x|=>AцYʊ ,gQtK>AZxc5zmw&MzLP'a'Z,!G \15sVPX?xڨ+G8k-t;|g XW19фÂ$^Spe1ݻkӂg ľ,Ln;u ZwG!ͱlk])տT.5Lο?|vu'ݰ׉ +9xM e e:䘳g4;W;xU!2:0ͪϱg>|AT)8sr̝40@ ?#{AeMphwr5MHr4:2. DÜ}wgĜk/SNWEZBa9y`l lK/|w h[n1wDrnh'G_ 1(,"a8N5!(8Jȵk|#=X4k}?f*p+w|b]OZNJi62E"p;y%T1(c'^mͲ ܳ&sy;DIF^ }|7;1WmՈ*g:pg?T Omstc:A4Y%Zic!Lj]ݣIcFrOT@ sBZZu6Y&dXe `ېw$&5&_嬢 'nc^kFsLQ_c&[q Β8vs4 jeƀIR:N0]  DH) ?Fhp^~I?<ء\MH[ZFo|H譱xɋ 7~."Lj*츸5/u8iH,⎘Mt&7aFu:ħ_0()5%j]PlaU>X@y@5+ѽ̫6y֨YlNb pxJ8mi0>fp?W1X~q甠}TXs\xÖyԍ޸ =ÎAߍS:6$\Jr7W/.ZŽ 1ΜQ}2 B Cd%V4т"]HS- )B+qk4`7/^~}O-2[YXUƪ\z2uT5:ޡ:4kYT7^p2.zgV ȕ)p`1r-*Տ~&RהYMnzGN!Vc{|p #]vx+:UK]w̽-gZ=duU DMAʰn#"OG '⧥_[9i)L 5D4C2;bF+\q)atM`m|y!?f,exA즧׽(]o &9C% `m8T;^`{BXKN=EU\f$#ypCrwT _ҧ F;|ޥb.mU͊ ꉽ|,M.d l W&a9ResWcˊ 3Y:(i|oVe#WHfeV¼BGFGT8W԰1c  Uuҽimܽ;_5߳®6",(5UZ+ЮU<[ }E^'X}9-jduU-} |S2ô`ɳMƼBz4k9Z1+MwhݤqP 2 >bwSFJrsَ"@%VDk% Vou%2׻r %wǻ}.sPGՅ<-]ow5VOzŁTܡR#4)+l0,b,CH{mj(aBE~*˱bJ7_QÆ3˨\˧?XChX* ln>PP~ܒu) EF?*xwKX0 *aP @#8MMo"F=Piݳ|&T+YraR`nݓxed@T"ck$+%5Uݻ! vca?]"H%3Ki@K^ x94>n ŮXz#Np0ODapFHp.Tw(b`E\xJ7K-$K*;./]ф'~Cv,۞XW15ݘvVNn^*‘):ߠlGՓѓ){xK6{`_!UAd6?~{b&GlFb.^=kDQj;u%ѠAPa1^[̅Ӓi{1_Wz !6mIxߘٷ GXw`L=1>y;> iE-l|k~15\z].Wlz?g+C2V=_Gs,+X52kċe~Mjk.WIbMRtED;D-Ei)r=30#}=C0aW%ާ(vFDqqgRqDZa K2i [09yg՜:C=vV+KN!8GqI[#й,ZvnYqr͋9/nN5}b> U*r,~sf2[wcw/jROA/r3veI.ٮDn@b1)50&¼`/a~\urHUH˼j⭰.߯A%>0wGU"=}/1[P ;ֳ?}~{8?3GIƾ67 uSa#(+uZSPhz\UIQ}*Mc8#r$\pHUT"s܄ra\0)&8sapR د! t)+q(5ݤ#(a{G:]?'j@Ys*!8@3?aEY8F\>bJ8a eTUt2s.pfxC[>xݶWGbzWik/!e#:<]y.8$~HlRA%h"ڭ=]XMB]vxɌ'qdz{sngr~8?T 2(2ҧ6ɃK&EEӗfMs)زNt^9D餆xߢ NX# 1kZ O0}ShP[++l`F+Gg*H$T:7Ac5&ڻ @wǍoW؀wl7 8'xdK/z)UͺNo.mS47߿a,+[G{f+W`.hF qL BjߤҙOKS0l}"TDī@Mabu(T=bljMYd5_+}׎0Akʳp t$7뜢Fa P0 Eb@צLF^/_~ϱp# X(ۤi5OgEe0vɘŕ<QgkNrۅ^CVvwMңi"/2?Îz9f^?tdy]=ZƸ,\*\> zbzp0ߵȌ[Fju7^<í= y;fYB5 L\{OON}Uvs|촟Wjt1kXPoE݈Ƶ M ) JT1X&J%㛳@嵾(VPԑK\5N#kp|O#Aπ8;џuW7maIT#d tZI[E$b UEk, S2-gXjyONŋWJ509q9ɃXbGa9¶Fȅ>ylԔ;{nf\~>7 rn ˑH9e-qX&uKJYt\8h/tڬJF `nDrw8"SG5QUEB' qAn($Q-ܜ]ڔlHYgUJp*CBߔL.Rcưbi,Wy坒~G ; TO(6z.)d i}V/*4'P3wEcr8(av͎Uz`gL!qd޼h;!Ji>!y,Q0UEBkr7o'B[踡Ba?s>p̮h[V 6b]UJj Lẗ́,J>/D75G)IJUޢj&.:`B⩾q$kߠ2>"{f8X3qy{bS"tXd[c*h^rt:򵀷8|? /S*3 &@}wD]an m.]=&/1T G] z=:Vߵ~gx7~y6KumB{)6RwNNR)xW"Bm<^chg+0{I&]>tq!*~/]*%S[BF􁓂xSI+6'&V cAćU5M.fb>7O{Q\cNģ%L+bb,5^P=n dϩ2H7^-8sTT_oN^J*x؞7¡*v1lA i-"WKu.1ln<wd =V N" yJau9sN-s1T {A`l*;wٕCD̡R>ԧީY;kuɧh_eE ` M$[ n8I.\hF:4,W\bFu[p{ 2iD,3țD87ÿ KqZ9IGO Hw8c2N/` ώހF,ýOFܣCz6 |=7JQ+kѝddbлs1qRab OWyxzu]="+)L6]J9<uLk)c6'7TT[>`tm" nna/迷Y Դm_If"cҞv#"klkbqA`|mwK8o?١gܬgvMm7)M)1ҩWbjЀ1V?4"?yy3$],\ |܂b%J@Ö7)vH3.:kU56^;/> 2jy==/] QklT hk"l\Y e:XYa6p6q =ovwTtȧ|xlz=ƉM|G+,72TdV㣰?@° b{"6_k3Np_*83AuLnZ5dYys\ ̭9vR1*Jnȵn:jA)przwrv NuAG@t% N4:>A3%0]ʺ7x`ן>^90 Ԇ^ޚrϝ4n4w)Wm=jjƎ2]4s9f '5AW^sXפ>:l%zJfoX;qud4VO8W&KeY;)mSwn/$vHozII;Gp=tۺ{&q/;VT4(aR.ڣKZ}HfX'|^)̦AF42ǙmW#^Pd3C$WLߍgrRn&,^~gJv9<肨0>X&{饓1>Xzh!YwxR@vj$qfДzI34j`&*NIRe6-8%m wziX`JhZvI7i'j{n˦XO=[EK4{9|bt 2u;FRzJTv,ժ ƫơqIQ#.A+c19ڄm{cXev>8T)^ҩү0p+a]R AImy6N0~+NeVZ*a ܩRTjz*^ K%pA v,9Өpd_K>$ *G z1 k eIp%g9rhxȃ`m8&|'gZ)^@ _*K.ߗ`ɢ-\Ǯ~B@ N$I?QFaU3'ҥ>WU@ {ZM{Un GpԁQC]T:- *vq)^]J_ORvҩ*DǓ>&`lV=؛ރ(uK 1rЬሳ ?qU_tS cF&jjdP_ߒZgq5nlr)R"Re-=^t+ oc|^Hn6dxvL/c ƀ魟Bu:P3s}AeFpqk5[R`+ՖNAOv/x7PQ bR<U^צ>Ro4Qx$K'i~|dΔI8Rn$#-J\.k h//W`RnGԴlo)uƻ^ݖ®cI_~05#KH[ɝ;spw<+fWzKv'Jߒn}d}2yrl+}:s,3f8zmUиŦ̭sSFtwrI6$ҵ [Pķ^,r^aBMD>^=ca#}#﾿Rd/t7QQ2ƒ#lc ,dwRoմ Y]V/ݷ:[½P%`OCﺓ0`oM lE:fgcztELoDtП@ɜ#  tL-x=omsbsCweo$Ƞ'ΝgHaml7%ܱ̣E,)Xė:QD@'(՘5{5-Ub*˂[)UJZLg N΍VL)_PT`o tGR"w [&С@ qcY9N]AUaZЭPKz(++~[~+Ip.hܨd>>o-) R%fԕ ^1W\Ͱt&b^뇪p,wzoSsq[ 7&nE ;U\AŢ.Ou nt/e96uy~WvfCu]squ0KuGw=s6 .qfwS?ޏbfᖘnO[p${(m u/7x?_]y~YqM \`[:?bo~sR#^U&']Io-aMpl"ZK𯜸p dj6䷫xl>?WKDPșd 9l6]#WTP3rsʃNKbxZGQtm"L322x[bdc"5-p}Oiςbљls4WlUjvA n#7ևvlxbRiF'rZN *n46.쳁 oo9V"E)a 9d|iTkVд`ಯ4)IPs E^fU,Ȅ+][qa]ayV8EVsqGc2[PgWr 5؛TCE -1 yTc*4ƅLZJEȪe9X]ڇ_&EZtD nn[ZϝkeK[yC6A0nT[֙@EIߤҋƠ`xq?xR=>_<Ҏ޶t{Vv㜵Jgn5i=={2gKt:C2mzU2bjS +a'젍]=."Bܓ%OZѷBvQ ](OGNlA++):DN`wռىH GFy{} /F#5#V`o޼@oDfe;HQ?i۲a<.Uzٰw bmt8Ǖr7 LdmsPq VMO*̩Ml3r4V5C7 -EOu~;>pB\gP!`]q~2g+iʱl-%;EAg qjև7/S$2VV)rBy\wagcZW"/CG$̿jG1rJy O՚%4Y΅`ak'SUVW K $% Uo]J[PstRS0h'U8̊$UV0E266L<L+fP#!?9^lg:n0d 1ũ+5p"!5G @5_4*9Gj(O25^OXDs?{e`e$dEn̩cD!g hh9Jwu4r!'^2HB}-kvZb+"-x5Qv.ƙ2*T}7Aw"xꈒz1P 6kQvvDj_ :m[`}!jC9(`9ƕO[I>] c9_WSKr x+8>芒j8Ayu$J{Wȶ7pɞjP9"Np~X&o9Rù\K Ϯ5|BV{Cc rS?v7OYI<#ZufNe7|phszE+%#fvӚd8Dav+rNV9q9VҀxXQwS(уY nmCA +XBǙ\aA 20x 0ȁ\Gq} " i*T@%@y,d~|Sq~X(.v.Lӥz D*̳E.V+$s-`(lgю n@퉭$àF_d,FxYIٳX*n 44}ߗ<i\,GBdme(>7"2ͰVV#NM hZ)xHrh 58UHV<*.bfvVm@!^ Gc֓ԣ,"V_`Z+ dGtyfi['=@t P]4N-B.>iEw(-F 7Dƭ^Mpغonm2{.n>/ ±ZS`b¯J7x,[?*(XX 49EKܶ,[ja. ZhVvڀDDi_;DY[q8ؓǖ? FSc?2Ya~cҧ2rR7rŇśǬ|UA8֭g`Cm ]/'<^BXT9ɳ9]Q`_֧{;iފm%gL^^,u"MחPhـΛ}~jM,^W{KP6\//]k&x[w +3zM2m7H-ܤ!B{zMeMsj"NVK Q!G.1gMP3#L4{}9\Kؖ~`C6e;GzMGJ\,yY~!a;1_=#o1 o;=لn۳ρ:>I'V|i4u9+W0[-rx<ҵe}t0}[usP(O )EQFc{"]Vy&0C#S_5+nzn9L/ߣ7]p]/sq*]2' yok')+X]oi蘧*3~WIBOقZ|ȳ_J;^mķj;+;Fot |Ps?FtMə@[죙bfg>hVUSRzZϨ</W-_Y~ry#2 K3=Ky )PI%y;B-Y5a&ƲjRyRYdgc彋z/=*YFh8rzvz^{͊LI)$'h Uk ^=dO~[wTV_X%5aj U2 *idy9Y[4,P/f ~G-M~2e$lN(jy)CS9[PKtd|3"\Oo>'̥u7 LXB#A&,0-BQtV cM* bfKkZ̴NK$ ,Dm5E̚hs5U7WohMi FREwC]*wgl+H:<VS)fր-Y2}XNi6h%G|h3?>wP MQ=k 弽'wnJ&,RU?&_0:,(*DCPRMҎkS6g4N-а@p5@ &px0$VwhmhŕE|YdpqDTi.G"mh+BQ+1 8VPjZ@Sunι榛g, +d:3{>ϖ5u恵X8pY[.,`:g'|y\M.:&$hD=R695Ѵ rFKhC)c0 9&sDF`GeM@?$5),$I2}D'A!0x#HJx5]QW' *& OTgO L' 0' `3ʃ2 ڥ 2PB޳j9;+y+ϯS߶V;NǖnP]K|$}"'J:FGoQ3RN%])ڸh;h7XI_9PI>ݠF} *7TDygWxJґoimhWq)#skɦ|z2&Tr~9/_e!uSS# 3J[~+r9àDNHWh7u,J6fIzBaآj=HNO h6:@6ᣮ %w|@6N`<2J5?|쪥0J-SIYutV w8΄&BpDl "9uDEWa=%z9h=?t[ږS"S.HV0(Z@?4|bH`.4on^Gp`C L;펞|=-?q}f!m]EށdxmIӭ7Q'Vм F7G$M{Em.)FRPYT󻻚'C󐦣4וeZǫ<3.'h%YiZe>.!]Pfc*QO\L§\[pi` pKEVI(mɂv@JAɫyե lϙ,M0{$g>&Wԭ+!= &̔pjo~?&o7-ioJ'"ėgMa{KS?%mC<F.9dZllJr.w׍,;Z, ^SݷtϨM86Lc@Ger$v% gdžk'ˬUF/| \9_H st)XcJrMJ 37/\ohj u ;FXäE06[%XWЉe+&U51|B  >O1 7ݬ &L&B!mP< l?^Mo_>Y8A8hb?<|5:q[;i{)eu- ;Lpu/\'xBKRȞ&Db1?vl/4R0Iȭ"'pz2fM_otݎW ?ƪ9;Jxo5uWM/r7#SQwx_^o1dϢٱ~8qfb[[-ռ*#)]9~k5q0R.c65H֘COvu%q`P_Q8):#X 9 b℧!G!;FTvΨ8R$ /!DMPб[^xwQzv!Zv}cT5)47t )Ɂ @7M,utc`xn\Ohغ![s"H~v.{AYHv0z`dq Y2p_3B ʵAr>ܹmmy|8WO i,j<(;{{"5 `ApTPe+7gMd(w%KM%:iD:AeP.) #מ5RzbBr,6KW[Anɥ;7wUUЕl$L~?,0;VW:4#Seq WM{xȱVQ1I8r!ˡ")E8%a62v:8-"r{ ==CӟbX>{ם~a˱Lb em-mݽ\Go`]4Lyʔݽx=yc,{kؔrJ;a6὏w :A8 _IC\πJ!1R8Mif6Em*!<%?QlR ,zؔч1hqa:_CHSP9q_Y*f9aV蹴hpp2_Ǭwmh(GQA[̈Aݎ24w-CGAPcȝ30~;,"~DD]O1Nd\L^j~h$FF;&`ehxfNƓ3k VH"GB$ȣea(`xj؂jZc-Q cL01b-x- HgewF' - ${]5/cDßZ_zͩLiNpf< }]( ~\ύ)D,kg)3I@K P=Rފ)G@~{)x=HB.<-IO$D͞JRԻ?y83O-0#1~;1 rqC9=e#l< ϹB]}x!Zk,a'|dPF?%M$#|b6B`ȏ!=EnQ#a6߿tW~aSQh2qlYpeu2ဘػQoUm04|g~֠t',fjf) [`sJI<ܴq%W{kpw<5S9P;DU4o( JMo~l՛}Bϧ|Iѧ"+{JPam T\ǫm:-2X/Y̐Iږ'h׿(XT04meɞ!=Xv@CW)&Ԓy6 F@!{js)v+"eno^q&xE\1p2Smi0u.B+ 7d94 mB8y(a\ͪU$)ߓ:0w@'$8z)U8A;>pT\BZ۶M1[sVTAϼǻȪܕdbqlBG&iXq2{+@Zn6,$ Go#Xt^hy#RX\[&V2u&7%;Pr>2ӏ/j42Ӳ6ӛV~w]^ ZySɬfeP- Efu~U5f&ВnbA ,,gJ!aniP?ƪ4[L)9D4+qL€HNKN^-x'*! s/TM * 'ZJXm:miq<(/zb ;153 lJMT(ꠈ_:s)80;٦xaU aQ/B_ :on~jxhAN{niWK,Yr;Lʡ~[rqI'΃))O3:۪1<B]1*ئ&]@m#5lomP Pm$PثYbI ;n\Sjq6,˅(Ko1)snfCRqnے2H '+'fܠgE)83fhy<!g݃()u? OzC5GȢwG{P9ٱH䩩;M/L{(׿]̱..^,a3IUfrF̷ybK€"7LLOƼ|}ԕY{xl$ɓp3t!jN ϭS ( @^{qHzc)(Zz-H\v]R}ϿbxW<`rL`&/1%%)3&&H^-vaj.fCLZhF E;悈*Y}r` o5R zH%<<}~?{z D#"zۋ#)7/ŭq&PAP;E b>p&i5HLqWg%Jl@~@N޾0͊r&m$ے!U&m %YBT2;r)!Q6KEm\`:cMdnrF:'ӓ>{Ž+c ?u>uE6 =,2q6xwmDeBԐ5Q:\v&n!3-wJ#wa,7؍͎RshIr[zsL,\gEaUћ) Լ*+^Dv|>VLKL@zFD 0f gn8c[/&Io `_.v 2E&gXthg31hM;qlw_F["{cp{fnaK(pPFU]TAѮ!y.=Ie\`R QEi"˅ Vã9ou0z{Qq {7Qb?I,/?\|E=+wURx4CY-I%/H"/O*FAHD>=|1DAɘ* 5r9Bjh`dKjdy \t?; iz&O RA F>:V1~#$0Ԅ`QR*l8}krB5Ϫ݄K!/D5~u-j~W,';AMͪ؝:|-zR۔YZvfsT椫.̪amUoltYsY)`)Z.S(W^@̀.݃Ǫ}-׾3C/tWv#o,o]~dIhɓEiceg((DϺ "dN^NJNYWAT6 hw :C_B/fAk`؉"Mҫi|)9JJM|8,C'6TnfS8yn1Ax/둗$7V?ǢٯcNx=!xZ2dgXttPAE\Ơ" &s' 麇t A{?_Cƞ-_Ǣq{p_GW.Y%2Tg.ΌEBUb$j,gR`ab ߞi=2?#2p!{ZV.:o>bL5ܞSWeȾe{Ӕh"fȽK!Ju8՘Nqz " h9[b eUqu@!qչ(M0NX^Y[\؎KÉ y{hH%S #!~0eVn_Z].,bd!ɃQs'-L$=h2VұtL( ràSe#^C%7T^MƩyGH^:oo(E6H3u ̐sFŸr 3 ɫM> ˗a/l3Ld}9ՓG.YKa.75r2skHp\J~f!Ia]EQ ĩRz0UsvJ+kjຈR$mi+ U/JY)*B ^s |8kzˍɽ3l3:0:D=5iG-ǿ~bݒJbYR3I(]yIګ(>:~tdp-g0Iiؼ E{ͤn(}( d~ع,pcG.O;8|f]9'ڬ5xl3RrgzY((ΰ잦јᔚ)F <#IJ_zfCoK Ё|bSe"33 2Efgl˥FxfF+YH<]9uD/ >+$`.gY(i0= 6rc0tP/(" > ـfkEvf#Q,@L!%(O΍BpftR6|J6tOgEgy|  ¸#TDʣ4bۮ#- e\.Ԝ?DN10&"0̯0#[`ψIzzU] =Z0nap`sގJ%#_d+j#;QS)Щ /HNr4/[]=]Nd\%ս0C LO[p4?-;mο=;{(tRDo.˿-W~w})=+G}F4OؿG\:m}\3S Kowղ J{䊚i^2癗ZVPn t%xdt";9c=nLm 5ڬy}6VF"]\I/Ç?7+# IV0-[Hg9+=/7s~Mn_Ͻ9vO?5=ă|O+P8ޥ;[)Ѩuo~MhJ ަ/-멨GM$1I_q})ڄ7s:%KNII)TyŶ) h95 &c\a%#S0Kh}7ZP3D9a(_G45B*Y 1k :ʰYmsj[@:HB @0?lҜ1u*DHh`MG {M1KslkP3:+^ʡ˝F |jZA{cPb ?rSnv !`o XDt`Q >1rI;}|ȓQ"]zWo (b? F$]9G)b_(󋥡rstԞEEW¦cI+%SV~.w>S kcCQGC'| {O,V7^0 ,v'-gOѴrE ]g֍Vb/]ff _`6[|BA1W-؃hp'^  Uj%~_%_;nNeW ]'ՊZt%[V YwU}ʔ'W:f JV 1bu]NuK ;{@VkӚzJ֍> )63qCԺn8do Y2"e}Jhc?2fz%;R-hYԲnЩqB=Uf &.yX7첆ua}g\/x"-5h^:ڍҭՌV|WC_*bCU,4 L) MGKYVăVE5o9'fĴP[oasfcDѽ,]em;Peb [jW+#s h((+ lub2"m8HVwJM;LpGkNcհQX x7( tzXYNTDVX TmeTtۯNZXSe3.>ĂV-rM~ࡦNǝߣ7vYLA(NRG-װeUX2fd}r>Aap$/G}?zS'źe-뫌4Jڷ\mTZdݽW:y o.d,q9Ayf7PyXˀ]) kuk*D{c2Z_ZԙEl emc0k|۬D<"I-㋅h)lZbv}A40NarUlspeg<.tY8j}E{ĽF:/*d!ЌZwʬdm{}Q~C{:z=וlme'Wr۸]Ktv!f{~5ͷ>(]g:zRTV_{^$)Zg[Fm=Z&Z ߄;7b`tYrƚ|6XM ֟@:[Z{źضx aKEG}qkS C5j&PsS,ƖX+ٟT۱FnG kZVS'c*La2{((q%]vZ($y7UVUkR{AVmq vu 7YBk-Pl¶u,և7MRNsYl\2 'ֳUueZX RWwrHbl lp'fD-ٹm`NޏuE4h /v44Օ ϿHY? e27[snġv A %RȰ+Vn`+:V[޽Mm_:XW|Wi[3ewv9!A5„̊{Xcuu%ceK#JBYtNQ_sG%QUD?eZ'֢u(׮,i8$`D]SY`=ya dk_e7،(/>yF86_@0?j*27c}-]9^9XzL8cN?Q;]qֺpMDU]7 wo2_C[{(V(uA#bZWɏ] zXmzб8^^dhᑮȆ3vO|[PǕlޗFL2BQtl1F*`<6qMl <Jgu'7C?{BEn0L/%&y3uYmf-%SfLB^չO;Gnړ{&9 naעxa kZ(5w~F*C2luV 6p^7"B}0LtI_l{4,2[_>6`>ĺeUv A^1^?FɊ)'5AS*[/ҧ'Y5 ʂmlwe,5ZSeaYbWX [پnbe*PV鵩b'#݃9;A\ṟzݝ?S33^𺭟-^4ԦXN9l"܀^>:6_BAiUT.fIl=|:vkE((w>Kvh5r. wTbX6¾m|u[,<&lgm8 =7V+L a6{XCKyVevXOGnVC޲O3"etFjE:Zl!p=읕H^ 9|/[^ZZp#"1;^VE wZ?VѿJ 3,*F~vҷ!{aQ_늕Jm0 ErY|ͦ0cVtBDD⡃li2uduAv2 5KQ;O x">:6EӜ|! hX!A> [+q #i[7;haY<]ɛ@#.R(ѿafIVDaGXg9bԗ~uˍ,YVX/ly ĕE}&VяObW6a9؆-[͞iwLo(̛<*/ڎBqj=)[~:"[ϓ)ăJ_q=̜>z WFvj= cu`F&2k̬G3 "m,U,Q:r@ݽOgG**g勓F HY<ΎDU,JIGVvS8G";~"$(ufR-_x֧Y8X` vKqZ83v>B_[m=vb~:wuYƤOE=leiHlCہg۟cۭ{56P &o hoPw:PKi}Nq}xYf\IYwpEq;hՌ4bՏ-D,o[F# 2xZfւwԽwփsA_:Fɛ0#2vCڐ}qCL0"H Is׿b35Im@({:2dg+Y"kNw';Ozcy^t4$vtlS9)QPvJ%2Ӧ2,nK߰AiO!IV+uO5Y5;Aĭ;Lfar' EPR+z_O -P1&tvu @{3[)q/`=HN7LDa$Sd};0{ &[ٝn2KF ڗ: yI*lǑ>tQ:ơK+y b %фGFT2 9ֲv*R6hYkJwcWBY}ƞ}4W5bý쮊P٪Ȗ cy̕؆z" +kNX8QNQӓ _rM &_6UzMnD) ;!+Vv$ϋ`;RktK*"wy֖;YC|yb>zVCoBzZmy':>|۸ѕ&V;OxSݼ2H:̵;EH;نCXt~F !O2yD+lyT+cNX B~w傷7Yiݺ'Ѡ{ҽlI XcmeοX{8~v۷ <.-r4˰+5kHIapyh˿~ c@EmSIPP3b!UF4IXlgEg6ȷwȑSF=,9Ǚ=cJ7}YxcZbu?gؚ֭%%,k,,tI<_JEqbBaցWl!?u_bk-̪C/?zxì~+0˼?k? ܉$ZB@zQ"&3G?b1Ͻ3qbx1Q}xZΎ4 NBo%$.Nk /5=A($va:,(f.Mə;(8U((z>AGSbo=>eGuL`r5БCAO=ɮ^A |̀>I>/ٮ'‚3tF[.4̒`(u bD1ց)~EVcyyoVcKaPH|ƺ%woY53Y5:g2>%`Q׫+ԟ>伍ȕ$:}0HeL%Q 6e͙}R˥gȧ|$Y>5h>vwz;aM*Ζu䄧 ,{:r|,tegWI/;ɰ,e3xy>"$k'-+{b7W)th?g ?B}2|ҤJ }I\ڳyvc%8}$@EV lgelc]XxsOIJX%"QksTR,j* >Xr fV@u@I0KluK0lŞfy{X,Ӱxzi 1wٔhSEmyp^2 Fv9SL'+-@*FEzKF|LtXkQGq%Qռ33ldPV/zy.3j+-G^ QzWyvQ-y<"yrx/B׻|I{Z{_-ytJA\KGR"Zz!~JRaICK˻$~sXq{ITl#@WѤbNʹHY=U车Oz˳Hxb+;Iu&=/,80+ThIIuSxO>|P#Bu@}QQJ)8*ppЖbؚcH9$ҳn)+N5՝f2)!ky+ *$?\'0.P'85yIXwO9 $;WHf+K6&gw!'.G?JfmR g5~u;ݽTE/qPOgAdzx421Y;KX|\_u6uo2F5v )Ǯ+%/v_@GAbR'aݒOcZI1o H %*B*@b]N@i7x^™izEśQtWl 93,їE52 sA)ۜ< >&׀نE6HUT3VAh:}ֳJ5|q ϝcUy_MIog>PVۻ**_2JBB WB]",Q Nx8De[ VY|4${+숗=ģ>\%ddDRP c}eDQK/H65gJv86Xˬ [ [QLuI+篰E :07Isow77+/z`tEQ IDS CM/3ncl𒚚& ?ָ}s9Ab"1$qI{?®-u|X +op1<Υyut+QkJk|P)# A8X(3$9jSr/3ScPibZJ=>dă;Z$"g\=ւOңgUL!uzXDsNI1rC q.i)+~#q li)bi6/L)U `Zx%%X")$Q'J>*Byc~Q@ l-ݰ *獔IU|,T$I(ܴb3I~.N]Ujy2!@ďà7’eW`8! )!g j79uҢ؆U.V{6:Pcm[ZNk}*A0&u,yE1.zE/~⚃\#*dI\? Dkj|jxEp X<:@ܣfqB ,S'pTP>.QMs(fLŃg-i Y5fRƛvh2]߯+dƤ9Y+:کS.7Sww?Y[1xx} xՑ,[%!%Y%$ߖO-- dL%1$ئ;IlBC$%6, !%M6YB_sf|$vkUիWUz?;?F荨)IEEHh YU  CZR"!+C$FUWX#VchpBhX(ikkk-@'ɕJ[HXZĤ⾋ m;]0+?tmjkokW 7dVfU8ז92-lf;gS=!֥C:45SvȮ o[""IM,kPjeڅB!s\$~΃sm[ĥ-~U ʉ^5 HE ̩CH&[q"iLZhi=i1d!CŔRQԮB5G I)$E LA+3?Q#*hF4QGBBQsQ "BhסPgKl' 1O"A* t6[Q$a9OÑS{LSjK ؍z 2`j>t W $Sl! ƕC*9h1bmM,H)diYŞ(ҿ^9 H>c1IA :Q S^D55` SjKL'm@ojaI#Gx.{ѫFK2Ȍd㎒U3z`m=C/ǥjzhůRLAG i8 AE@[Nq`!K"IEM-euBpM JM " T "er_>t^9NšaGIĥpR K5qHHE$ Ĉ,_EL: ]JHM Ԅ4Q?8g~L?]4ͯnAd4z#  d8 [TݳR2M Jqw ; &tvFMƣ> 4 ,_@XiYSڠS}eQw_̔@ho@}0,'43c)1.r$_T~oQdxB]20  EyQD>=pBP(?Kn fyĜSSG.(7; bH{{zv~h,D, ^ Nq")\1cGLӏOk=C N?]ߪw̜F󺲣M`tS]Lc1n]\ZRoOVM֛f_;3W#0`e2! F'4oӋV1=5p?FW覢KMЇZWhX]A z5 Ihf!`ۛkد́fX"UՐPŴY2ࡖ)0X0ݺm>7ΒB,#2 s!֛+8EYtr1]J CQlw<f~zm@XJt.1=zо":krn.ѿhLҖ Մ __8(͘(+5ͼV/VF(Ut뿚SU_hk7zqvs*BAxlIm\®,+ЍybXM[80N7`n ]k֯1#fIi<>hD 8:-&Ǔ1UIA)RD?NF ',C @V61AJNJ`D%U!-ǂ J: Ρh*mT l= 3jEy3"T́vdj<[.U . 1;@Ҷ}< 3ƼT5S˦7P2s q~V( 74&R"WfrXaI j[ҚCݚ5m٥|Yes= r#b GEFPQ. r:sA}M-LPAl?i^Pչf @8 @#2i܆O:/ C %ss3R$7K6?4NEGl3Kw(kO#kgg= 6;L;fw $tcK,`b"%]ڥ!As)/" ~-}Յ5UCŨ,);[ D4$l*)x42? XxdJl/Zh0Ϡ9!]P qXr[t%KVܙ܏$(pfZ3v* A8#MC;*VYQ 7$2ҊJ HNpjbO迾>\8H jRWHHS锖ff0AK.$"Y:Pf:/;ч27иFΡ?)b](WN(I¨^$*Ƙ8M?MI dYABȅtz: CFGl6W(Ti\hꦜ̓iO⊲Ep1B+Fc&?mRqo*?H^A Zpvg>1lYDZjDm ~7 W&M'$ E8:jzF1~!A'MPQ?,ږ)tJ S2yq%)1ԕ~u:@T(I 7ׄk'`7V>prK FښrdL]d"I:Hd5 =!z[yЕ2\ &FYgeɂjFv>Ω6BY2``F+c8&%c˖i1۪8"ScϻiK[`*&*ם7/ ݑ_<8H䂆\AcD Ex!9ϝjL%LbgjQ˸`ɪiU 8A>M{ͤ,KLlw\\ES23kaU]S;ͯr'CV:RgL5Ev&]7vp|f>?j&]VK:c-m n8!Ž'k!.ɸ?_.K ysv7:o+ ޛ"ӑY\獳%rL'G9Gзi\+ggziQFnӒkZ44.:)4Bbtb&D֜U ;" (rZ ⭗D6O3?Ȟj\Hr,$,!DʹoUNDMl.?8SzKW-p62VX}IF-5][&pgg[&'IVjoh0c߱wK`:CJni`XN^F]/a}Rl}7v5Rp"4uovjp@k$a+!oI f T|DUh@N r\ƧWw1u[wF-[7'Oe"\|#ǭ<"yYDExmgσ}SCs!ֿ[naySG+$y-# q1qR]h% Rb(Y_4N¥%B`Gai5:Q|Osj}O-SMKmFy,kHPY`65)2p9J v.)/#ɱt !u~~-M\k#GdMDj_E^ iTAWNyٖXVDCam&L^').O$S`99ch3*Vkj(-4OPR2B\Nhfg7pm+,̆|:;Ɩ< fIQ4TSXHeP!_,s%~@UiL[q*yPof+6>!Cw'"$6/f5AI`74nelP^Yju ѺLYRi.`N{|jDf|*=QU ;EA}8nSD,O˯6:~Gڕ I}]fIP J0Z[Xd_c2R?TcX+.k" IOg#~ :ÕX`'6}LEmw[VЪ?Zl32FqGS֩+e')7*1]ދSY嚂X"ZɰwW]m<$a@hf-h8cٶo 8A܁!^S~a T6=5wܬV׏ŰPSI%{W-wp5dC.!~|wB٪,z i~_|,9lܢǨB*{~~\ȝA6nOW.I D0b]:T=D}s.E;>X2}>ߦW-]#9%]bl`\a.^'dMz"7dIt= B' Ze37@9m*S~1er)GQu̱‘P}ɐD Ϯy+ꩄzhΔnZhm[ew'B19.Ofrڒ\cE=`Y?ri' /Xˑ)'d!%kTS£H$֨ sUFhYNFƇy7pby 5ewIMG.=.bw(2 0@q!wҶDks i3@liəpfr?v:&1XfS/]b?>hA֣zF–>CK&A:2k -7Yp+Ea zTD<X0żTՆRPH"*CRc c%`0T(qn`BSw/[,ٚZ Hb*dАL B=C !8Ok.̤cKߛq\RAp+?(%\.EZ_ VDL=ıFg#v ?Bg<̙-aiipC^1%aF>-l-gJiz}ꖵ:a`v> !T50j5<>U/EpUũdp^F::89e=@?-;֙`=5Ҙ^g!Dxpchi9[w zgͮ37 1T)] yT5B2C T\#I!ZoK'9Y`LSeʓ7'N꧛ FЂ=Mg1C+lkMBO`)^7֍3k㴒 YFYc-AZf"*tG1tWK|[q/-Vd.<}zr+Ecֳ8˟KKITT Q_lt~@,b3W_[zaF)qnm"-5k5LH9LDq,E!AݻQ1zZi]޾S[/|,[ڏiR۞b3:oJݬJOkۧOp{~w>&R0 Q{'~KQ}~iWS. k줻K>| )u>"H{ ҇YS Zr}O!cQ7YUTiX.+9rSO"ܬSʪ^RP3 תg&T7+ڣrXSw?jW|X[f>NêY|ئYjѬ T=ɪQmSe4׮~4h ҝӇ>>zMM3OI"ۀ`摁?<^!Z}bJKX?f[.=$>2=[H2%̝?&UDrgtR3}p?!KMg10 1٥dixK朔@C-2q>oW2;r2A5>(Uf" dxJV螂UcǫI8hZZb0 >o! `1" AMߪ!u,y,9%z[,E}sƘXK&^ĩ1FWMh%XWGڧz53#儡f8z>39`,R@F zh#\/[̔wfy;TH?Tj`= ؼXaA3i -ͤ& ͤ"D iaٻN|`4 a>PˢJf,a񗭤"m*'߶4n>iIlۀxB!ܐBԜG Im9ayE{j!i}O^q+ٕ-8^cZLܐ6T= 7ZL},L[G9A#ܲZP4A 5>&crݜx51kVIG.\yc]lOd1Ef,^$N-4]5둝cOF2z8QIVJa.QfZF>5Uzjǃ0}9 &4&Ft鬡{=5']OK+vHFrpBSm w𴜝Ⱥ*2JVxm6'S$`ln6wBlFM}Ӆx~@&I̹Df6`kDkĭe9ܲkܶxd'E9v !|09~c 9lZفqBqv<㷙d9&QǴ3@fz^s'֦ڄz$vC[ΣUXqCwM9FK^1+5nUHt?=ɔ5EsMo0Nn&ˍ64I=,g<FG)Z 1O{TdclJ]G}dTO:.wCҩFc"mnAtXHпFY_q>8L1^Bcߏ`*N*6u0,f4ˢa-` lI9_:I-(2 m!ђqUЯo'32XNp,5nOሰ366}Lvil]Rym|)-gCX7Zw WYeԘ&͆pu쪫rRhsˌ+o&EϮ!_7-6qiB|ڨToUKcEr-yVm[cy1U#_+FG@ g|zZ[avFMq:{d&&W}mD1 wAQ,W=(N=dvy6nD-zh0wljF"͈1Y ,O7Yev==eDcm''p5x-젫|,cZ3!V"UmIcu =EC$:XvwuD7|#&;i6?(GJ33[uѰZ(2n?N!_3x!AFj/#.+RqCy㳶f`xڳ4s$ FrwY֐aX6B~?#: kjU6wƚ&H GD؝ctWǝC?` {GA2kBIn ./O` LNA@ :2jwLvZkתE{dwXdC$Q u&|"5k}|Wլϑe=^^='/;/ u-iL5ƒ/ fAO|'3%vǗu]J4ĔDxX%2Yri.cԌ'4"WAv. %+Ub6eXof~.bB _%3ֻ!2Yw4$J~JQ:tWClݼC a; ݽ FeqaH5 /2}OooGFy_L#d\k !bâ-X1nu1װw)FbJdiB8>bV$^QUYoD.N7h_%SKk{H=5{H})5l,:[e'Ri*l.}=xښ>Z@s3/zax%rC|qEil6Y::/ovb)/}6u?-ͳ$e^e)X2zѼoöFmمr演c Ʊ?ṃ?>$)9\zg!s==amҪn~ ȍ*^BB4y&FIcRN109x#0$Ӓx2{]_ŮVY6;RN"8}|K # 7߱}輞 ,ƱکΖznԬ OU/Id<ڗ(8 WL\:~!6588IMy%)(|z<#ؖ3쓢>\s=klw%=:]-6MwU.!{\8=m{S?ĮXr|>SKϨ?͏Ah[o!B>5ӡ֘+;u9? wLIC)Ă}dHwzH dO/QF924a#ޣp/} (}̭'cĘ~kۃk&{|&Fd!>5 )BI2y,+[(VG/uZvD:*2OcdI5m?d)>^L֬=~f੯B>*/lx Jj7oHhyt13o^#]y e{2?0gR1nB-A qa_3Io~TjouT6xD2Z)lZÿDl,4/l|*807l$kwͩ7;9?cd` &YVu`S$(8SNXA} n7vhfN| ̤D_tvmb E.}Ag~ΟLFv7sϋLSÐ+MܥFW!|̟C;!pW3LK>=)ܶO'B YNs3+:؈C0~Y[ ۇdc3aAw6k.QƗNjȡ"{g;> n4~WҴ#qϻоʻdvc/QjڥՅⴓ;xrF(ڒge&jwȢݭerǭ, YL YJU9;|~~@o~#KZ+ *P ۳'7U2-W\.lo<~#Xc_ϱf,[l*T oP,D2JdcȃL|)d_}_X`A\" ƚwa.D\-%KD`.xI"Vae[x4_upn,&2fg!ϿX|| am;Gۻ썐*i^Hrє 2~q_D9E6g̘GOc,8Y D|#|T< N?N(e0B#AW ;&" ?2sKO?42yس<$ێuosp xR> ORrbQn??v "Wt_t= 93oo'NA<U,<]CDӣ`44b9+g\G"h?|~=8׭~~rTFr!) 2Q9O#F,36z; X,>| ('eȫ? \XfE06OAV0lviZȂ\2<^IwX,L9Oo2 v,'_//8 B+X8&0*@ox,.xp p~ $<<U7,W,5ǀB  J>t #?B㼾_q,KOa&SG)XΊ w!#tصzi*vs f('f._D`LثV3{%ODs`r^D?s{؏s;Sh-pם(\ 6  q|/q,e\7Q*Y2_2 E24'IAsJ)zc0^#x|ҥ2`\nX $ƙ%L3:DU䛭`l>( EB\XIL @qɧ+ `Z *PVZRDeN T8)BTʶT]RA5q(0*_(8+hOa/,xpݑXSF:v/9 I=H0 $wyu?)ћBF $uTR`Y| o^|RB5~-$jl&>LkZb&aB8LF-Y戓Lc1El~Z1yFyw6PIT 5 ۦ"}Ul K*?B"`l٩k7Ǚ]l 6l^/@nkOK829G1$, MC:_Q%yjY+bV=?LK#V4:v4ҩv:YYL.LO@?1?պGM@G[S E8zq0x,8;x"?4`5 0@ҮDex"#"G6ucEM.B@kj,Y 1֌GmÈm^^9ma<t֠8db/Azf׷n0oԜj|P nS1jUfvUsUkͪ9ںUsUw WuaVuϡ:Vuߑ:Wn49X"<mf8@3gZ0C5A41+6 zԩAzNBzB׮B 9l 9T )o*xGNSʗx =^B{zqs̃[r9nsuhw WwaVwϡ:VwOy^Gn-r? ^ZȚG`*c~k/L(gr$܆i`@`Yƙ]t9iXM?ER;޿["-eX;җD!EP7YH}9/(C.q9R[OR,ي]yct5޼ ;~ V#8C,r)lM*!5W V|R8.ی "jDfHzpCK^M0 8,/RgAb;2 N(gΆvC'2:ZtJhYp]ȧOnmL%(] <+ %l2#s UeTVUߊVlsY>ߥȂe<%`,V .olTlD6vy5WoAq_<=ō9έ8 ?8  p5Pp&̷L}w=}YI*ǟ*XP 40HQׁhL <\ E  n+?GR@ d郳 <[Yɦ{5gUҺ`:ڹ~+|-cX S$ .0֊n!wM}:c@7r w53b4 c&^i CM[EehP 6+QR!wa9 ̗M.J!T4& )V+ Q7;4Ɇd͞2PMT r+@r}ihz9Gm޸=H5_ ,r{lԲ .:(9BwV 0K`j d*& sa1cyX.u*9lк KDATۯԫx"1 sVlvn `yXvs=?v[3aϦA8E'uFSt0raɔw$*A鼍jOKΆ% gue && sxYjG'E% R ŠJK5q~(w|C`6ۇеiOsww}Tifp>l`Y_1eEg1=#Et=Pi8V1l#v(]P "".B{{j 4B\60F#J *V >褋ya glS¿oGcjm0POmH~v~-N~Yeq^+ĒE'~CtK{1veN[D fT0:aKV!sVrUD<)g$̝T#eb 1{%aha#H](2`0()*AκI܏ %>RYۀ;+'q4dR3ngS",:k8X#t3<_Q1t2ZX795(l|X4Xp&/Du=i8@ )W>˘Qgs%RXg>Hy ,ɀ2gaNRG҉ G\+Q,LMQ7x :لl?NxCI&.gOOh T4dx18j!?GLzD"r  ف:yS 0rN8o|i8u.)ZD2$43+!#Gul$r"% He%ƽ8T_j*^̾2 J8Q 7JCd*3d+iV'TKQi(xi FERD+A"Z7 )FI'.dY ڮ4Op!iq"1Y?pkS4z/Zv5ev\Qf:!(w0~#6&#+gU2dVEԋy:nK`.A'b(Z5hV L `4+mݫ_(7b((QU5˂ zzVJI@TX\2Ǎ1@ZQz!Rh,{!oɮOV*o5xz#b9M! g PȠXP++˛55A%JJ&et(IxbM캱@(7:DUy:Kskn~Lv't!A mIV$0UⰠ NU &\/%hmWR:GU17֘B9 ĉgמ :ܳW~nc̅EZɍI0!k-;?'t04^k(XKJr`5͊k0\CUq ^5hSQҞ}N6Ԫtߴ(۸Z6jc.dNR,yJWE^̆y*kmVX{R\%\ koP% yMΤV*ech|ہ ~T0NR3yU2l[FGf&uRn}.Xۤ66cxËLxYԔ4ˇ6eva`raHmGA:#toL: 鍓ԉey/ 䤀BQ^9N6Az":8fOyVrJYPZc(q Pc/)ӂ6mX!ա9xB<{H;+:#Can۲oj1pםuc Xd^oN/ [ҏd:lZ&~,Hv1IW@4kSCD\SIeSk$M6uI<]GQF| jvt%D1ao[* 6Rx<ǼHJUo5umEH]Y\Y`{lZtQ 9R@UpjbyF Uo,}Z %a7wTP:Oelm`n}$K *,N7:=,nHH?j0Φn)unfYUdj b%h MF3ʋMՖ@z=S$$dHDRP HldZ0StRO(# IWצ4lWbSp Kp5Ѩ'@73l$إ޹|[ K|',л Ylg5.nG 3NAhS%7#ekb*3J2}L%#J{Tc"2T0u1/X2ᦀ@smj@3 ۀ\Ϻ&Ɍ.Jc:tVNؒj{br΢ia"JF uH1v+va*c?i,pV]C҇5*W3W fNߊ(zVSa4`V3ϯ(9AU?L*+zAMҎ#[*!;, ,ÂXSUjr1Ev##}Urj? Guހ|0Na:70ތM"%TFL$~ogw ) ]=n Ȩó|S*,8BPΨ$58'&gP.p:Iec%dpkJH0i-tԴ*aXts.={m]48OAUW8KRA&]fYb_5vf̃gTbjj)h*6;;wvP(1VW7݁ OW,Zk30fiPu.)HNfWX%yꍻؾQĮ׺On;Q^*HB2aSI+'o8#s^!dLI RDLaLփزG @?[1`eB-ּ86BmjjPDpr Ȉ4/bhs?*J? :r 5/~OnO6ncYZ$wɉ2g on!Ѱnh>Aak|SB zh3COBۮ{Cϖ;.jAqoyM-f<`Q$'+@jNw[eKE# 0`U@S<ӹTAʟҖEҩ=e zĮ&Jqa\*G)eN2%!.iHe Նx8e*r"M}|e}aYTLS#o q"G{\) A{<?T[NeF3yK*aS,;?ڿػf[ѝ7"QUw4ǷA? ^nX;_:0[֚cH&a3m70@Ӫb6C)*A*UTiׂâݺBhAwg6 ߳{r[5Q7X=>yAٲ_brmL`pJ tuK9~B3.ʆ S:OGjOg{y)FKWc!J .zkz3b2# FFW'.sK6-Vcj0H;޳-}Iq3UcZƭp=3wG`-j W](Y0pUMe$ǪvOy-HPshV:E[Sjetr1kHM0JMy -}AOʤbYA(T0ٖc~KWK/f,/ЈK S#BDP)UCF; Ժ-sOpr]KjnJvY܋d8d )!)kz*tmh  ,09O"V6:wwyZ}WfR%cRSQBʌk 8d*|">*IRNb1z߁X#YDUX"2ؕ2*.+2k)>f8[^5ZGF*%gYR9XEGt,YbYY!Bgeqջ S/J?UI3m0X*Wي>"+ML^߱y}gBqZ:A5,PoXحYh锆D60Z ;Ɋj-G7@hQ漿|m I4R]pM ^?+1V-*W~,*6f/ ǻ)}.@Uz9o F>ssgfko\,L./lI#jF:3輇+>tRtZ㾠o.pTy ZcTbB[J !׃,ʍaz]ݪSˎ_`(Y,&~4x&.fיs΋8ÕQJ%1;_1Kf>Xz娈|:-'EyìfdR׋_},[&rɝH@qK7V*j/Be*W<y6J|ة)4;-U1 04$7*jB*UxfdR˵ 9<ޱ1?ϑ*~2=~i =ߤ<$Φ*뒺)̄/t@xEs]%M8`Y-y PԖ]:;P(*z̬O`z:zu8s6'}Rfc5Z2p E"0/Ċ7yYU\—CA„9l`l"LSd:G&iISZcec(qf::m*ꬭ̕ X le7xCyYm -2{"SҭSb?8Rd/jnMUu\~:/ܜ#4VbpUz,!J |FO1{r:9 R 09uUgET`ޭ5 > Tԋns.`zN]}_L>Ffx7]ҍ++ϳFT.mz\*_"qQS.U5>Rnaq1F~ըwb-0UT ]? vV@6kEە_g` Lx \`̫3l{ ȂE:|4dT&j)aN?j] &w㈲Hٝ]0бR}d3)9(/$yM_92٫pJ%4<5Hu Un  T]I M|P>quMŁQOdIJ!ZPl.:cHFʵ=zPvmvy}t¾֝~=˵_/p; Z`k*lw5{74]P`ᘂ0]Z8jw".7Qy(W[7z#zGc6 VBXVu~wBÇ#0tO!)[iP5`vcmq.7]gFw~ ٜ1тDO {hCO_~u<+꿮a4:{"ةCb4&X4~nR. {iw|ڠD)S"]6afL 9|Vq ?neVcAݙ"sf]m)+ J<_@t/FK)\4[֩V=G*I\t䔮ǤĨCSi#f Ak=(:6y+}+/U uR"uo( .QyeGFݰ~p`j!{mԕ(JyZ$V QRS`'H|!-EU ?"vRUuo$`]b6!Trq:j13A D"|c R}A{& <+ n7 ~LŊ>g*vP#,Jqï3??_vݟr :ZI-F۴{E3 `8B ds׬tva*?3p[y_vgy+ջA*GjQENd!S *jXz?g%öE2N3y*gpsN&Q^=Co{&t}dPQ|1 TN 3(28Ϊ e+䡏w9MU_AuŌK4,y;냽HF~ w:oA }aݳ}C!my?;s }3'rmu@1+b As<{ҽJ>hg2(Ƙ{Leee^YWn9Kx1rZ|S0BxGOz\e|{ψ͟D%Z-jõ}9+"Rr&*@!6ΞM |L}:Oԡ3{8OSU:CK9p$J6zdNns_Ȱ扃aziR1a]1Q=5<0*K]GKy&םl ϴ͉tM ן]p~mg 0Y˟zg. nj'z8*4wVՑ@W !͖`{? LAa$*d[3hJA5لeY>vRNga3<ag^{` Y?Qk}x|ĻP Lq9>Zw+ഞLt^^SF?;ѧ̯1מgVe9uSzjCM`B JV 荲ޤ<΄A͛zN_bT tGm]"?7 h%hl~Df>f lkʿswkv/q$G /^ ʏl&ITn>RZ:l:~ V#kFjY"jnM<);-ЩGֽugs#f4Z }oD7l3oVfjH".C-pޠ_%DȚd JZfH1#+@iB;8<˂fPpFlctZzPHDXU`m9|{Ӡ؝Y+8m\Oqkba9 E1)(MUٔ"ΑuWoRkBѰWa=9MeT#8LQ,Ӫk1hC7pzޗ־$LС m#U{b;KQºK-? }Sm~cVrPІ>\ZGDoPMgy!W[HVc3۩Lꪤ Ʈ-Q8,DA4O"雦lXvx_#E1 6<0wDxiV5y尹;fVCT\+o |[1E@oCոid|{zV~bp\_t˪˜ K/xZj.xqYv]t1[ܗT 1RE$L{#2WC!X1Y>e<ǂm@Ff587'͑\1CP hѱ.)uXR9b)T+vs(m3LU.f[n]*םU6$%)& FL '@\IY'LLET0bcd6^ĭʴpw"ÏR,5@ݙ|75[ Ȇc߬~^TH Td1`OpΨv:fB G~Fn'ѲQxeAmX#_y7F'JY15,]o@榩=ք#c( ?fP 5s:~G҃ޫCip>@!޵k=U[hY)J,fL5^87VZ^.Bau}oe]-wYd֔ι޴罓 q)MCtPa Zʸx &HB4T,A+5Q U4s Vg󺾮x8^J8 NP-qcuto!Nl tl98,qZ_kzp\$K{?n*5w3_HymiO:@%xkx -mgW}^n&&tZh6v=+nl pޔxgѡ$eǺky b 䵬wjy~٧0w'h1O#v-f7#簠~ᗚ#9]YXˆstﶂItSS0Eyepc,5ΩGc:Qq01DjjCUMmv-6\`S;6G 7ͷikȑ.UEᷯB>\Oj|}SXec- ٺ8-Nf7.ܷ=侁ySqCY#&unK>p)fKUKCꮡA6$* \I6m~R>3ErW87YQvְ[[h4kV0cKelS /Xݩ,xt0Y'd+6bݼ7#^\>.rX!X6zOs |l>]cs\Ѱ=j6NZDFTڷND Vh^I=|'_ =j%wHХhmf_-^K#&W#^th7t_Qpœo_<}o`O'xtm L0ZrbᬠSoҮXniOYə= ^q8\L &³؆fej! JS eŔ_.*~׀ʖ9MÌFx bQNǺb4=ǠDKckvJPzZ,ư?.{o5i٨޼e;;P?w׳iaAAG]j~pqa3tZ8HO%|ҾwHLз1!Ji{~IVb;Q.h']8˜緇AZuZ TÆ` tOG0{ps [{5RKyj 'Iރs "|Udx=l &`3 FG.Js#2%C^hxZ|[ԴeM92+ø~η+{Ur|PBC pkY𡌑v]\{ i6ף۔d968MY zZ9A-TcىTխ-hdD[ #25Qۏy[~maK AsڥUFX5U=2)D*TFfîaNRٿt(_=c(ݻݫ6;ww`KPYwu\ :WT=g’jh5ePKjK_}DshԼn0N M#Ư2>+Ru3Jo ZZet|R{NP~Co=EyIfvCP?j9>Zܮ9ײLݍwc ^~ _Л;0+sCoL$w>WzY[]婣gyk|6w ^ez`ˍc>P?e6y&Ed=btAimr:rVdEXfo<|csR<6߭L$UOWe#Rs!ow~7޳,Swq4?jD\\oF)ks`z4w!~LC<Jmu#NHHR(k$ .K4aZ={]5-9xIrGMtIbd\SZ> ]Xݻ[@cv6Q(3 ,}q,KWdϖo:(wb(˳"֧zO9ub?O͗AN\Q\U}LE΃FuG6j~spj(62z´Sk܀xC7h|;fqQU ֑OU8Y| :ܴE0ij$PzJ\;2ABA‹~`ncAe󗍨tf o~GXNXDM~}$<Û))F#:B ,ǣZ=\-EFVn@ 瑚l$ 3 bMRG{ӂQQh pbZ"FW0cmRE(i< {oOZY!xb`>+#9W!Y 4d4"Dqp vk@}KՀ|RǒE-T^S?VHuNv ڂ堬 I`rPq l%X& U_)y'LѦ';^zs VdsQsq馍Y:** ga)W\Fq<LTl,TԻlIvÕVՕ{rwl3q3 ͷ[2l]0=JU)Q|D2*M)ZpWʩ|Å/`CH341P\3|VCG,obrjt0T\i"nnU Y^I([8="-`AϰT2X~ˬa@y#o~Xy Ř̥n}ԗuՋ`Ϧ>"SfD犂U'&A`*')\S wP̴v=d-=(惇6;ouwo]GwiiVV 4P_jbEO; ݰB Eɧ)aj F䛫myI2 X!-VtWt?{{ay3^9 X]BA-2:LS/i'DH6@_5vp&("&BzfD^,i$#)Me%6ytdMjy'mi4]ݭꡭ#XI 0no61kTSX+$ :h0RݦPG˦XnzBcT Fvw4/@w:=彸58gyӲn0}I_/6S:REp@@KL ӹ7`"|L>荗Nq+jX&ReKEyUq՚t;X  TO*`e3fkxTʁB DE$dXR퇟թV0߿KSLV/k. 5t^N´Z%RC6A}jњA wOJaKP$wm_e_CH:59]0*Z9$,AW|}琹-'G*qRKԵrXoY{jV?%2(Q;ر{|v)V.QDuHèC?в²Y"HYCöu:V5Ȱiz,wX=r-\g9`P3"uD1mB!Au ?׭zq}/kDUplɖ2c{̊$$*퇹0}YSqFW\}:C7elx-<_OI^.\Tf$EAxOw.o,Ekdj_w}98*'1W?0;߉N'/DrAѢݯ{0Q@;&ҍnE8)X"L*6{?ncxۓ#l{i+. 㔭0e; :~@}B멦f8B)S Z&TP鿃Mvˏp]1UhWm,TO|jf3$D\KJBGQ­;Cu?=w-n*sXJ߫n`Oªh+..d}]p0&kv#LVF=3k{wetTRW|af, zQIYF뉮P|⢧OBWV1+iZFv̟_/,<忯;V9XZ2R9'9ʯzrQh  \)(\]m8Z !Nd&Sy1LfҦ8xŽ |G0Xe[eK#ɷ;|;dŲ9LKӚq@$!bX//ل/A +\!$!\?`{U=#nUUzշ??ERfdnion}RnLu mK˶5J+[[[?kmH=F}L6i)$ѓ`Z~US$ߔj٦JJ)iE"ijR-E-]X?$dFPN-*nLAژEWZl"j"Y)y5ͤI-#KJXx VlSJ&-Y rФчլ!mɚ[%F7]j-4GFΨlfE6ƶe {50La?mhr)n+m; UMU9Т@F/|H$9H9I{}o^XRl[攬d }IF)3̔iOZΜb^vlf*4ݏ7q֕R5kW`VuQIWO؄4#iS(g3Ihl}\47MT5cplpdR5])IF*6&#C!ę%cZ6Iօd!Į$匬4)C,N55aݢv)h#7Ly}#r ۆLdI9V[~wDnRd!L]8 }mA$`(m U:#v|$Y0sxXKӧFNN7 *zXw$o>}r (#?&&'4N HIı1` Y#'ۑ`>MI-MVRI8[ r$Ș[nj~h:caT f*!=?iuK?MJ1`+F0&pv=NX=f>ʹČ^q&\0GxD,MH~dt J9c;#CU$'* q̢arM7l,98?t#j"X6Jvϟ:mnyYTi,X 3}%>9z*"h`uHid}@U^ʂ겔 ?#Ct5a&/3WNPjjإk.TYS@>D(}m)KE MPMwzTɶ v&A)-_wwK41%h‰!e Cj-TG+>%PgaP/, ^;e{uGEd*8" vM, H@d$GUYmk0Q̑H.ooETz'Lx#ֿaL̬JW Sv!;s D j Ȱe;90(#dpI:dHGO) >'H5L@ =&kFֽp]ʹO[ռ]KeGԜ}}YJ=Ǖ.oq_=:= ƨ rrCd6oB>W߂8x~M}T#_7 Ġ &SX˼d&@M/榎> I[/HвRh9ky̎ :h-[+ | ;NǢ48rshgf=XGc[`Rh| A +l4TOc x$Lv?4|uUȐ~fb`)v6'|Tpemо(erc.5ϗ^[ i)W!E4u[JD!'RmD1 G%mhɆ䎾ô=#ɴd:VLT@iYնU5qռ4CRfaL9noz .~)p,;pJp3sD^ og`bFzDzmIb4+nU᱔eH8=C!ȒLJдb]:}nբT|X{]Pi=%UZu؉CB"epN}Nx'[1/ :4迌$Yp=}/g4Ƅt oXF@) ,7Nr_{gAT]A%~WG6UDp a.qh{jՄXD~aݼBh؍@Ʃ]c}C{ڇM4#`C#恾 K:8ț3"*ܥp*|:(!@S5l&݇8 P4pb%CUAXe6u|lLMp'^yk,S?Y6n^2'!>ܣJv/L܎z_Q`{k0 •[u7kY#onsȵ Km*$pP-W OjmLzV0R>ZF@Xhq+([6Lo:JzliJJ)CðQsgB'%` rlcF9=)r'x`v#kbKMO4 U)"B 'bFG;ZkP'lJ-rzϞ2qP^=І{ܛv[wUy{8G{'GO90hlN۽<_0~T.&)2E78#'* &zaLH27ɚ^[sPiLHGj V0&ޱ ikQ=Py=M|ĚGmw1:-e4NߛXIŲ nJ[~jow鈜A{ 7tcgpD`S.}ðNm#Ce + r I,<'YV}Pbc9ڴmV"cimVD!H&aĥJc|0PFUg3)B ~a?#3܌X)ɆQ6[E h1+cp [ R_۔Qes0ۻ`fh#U! C9f KG1.w_(b@+"KUJv0lh hrʉ(Um(3ʷ")vm2RGN X)6*&?x MIQn@/:DJ CgPJ N;d/;0ѽpI/} L'ШE"0YUjQጨ  G- h0q 4g@%|9CjZTũ %!DžRppœ½r?i~8A2Lu ÝSzߵ3[!7҅gC !%MZϴ}Lm\N[v!3XM*I{a]lSZx`9tY}ڑ.X ]ٱ1ܑiQV9[a5 %GyDSGwL9. <~ۡMgX0|5H0@DBJ@D0(0)"آQّ)5fbGD|ۍK CGo+:@T3n* CG?,/V5eF_Üǝtœ.T+q1B2ν[v9.㻓4ђ+SKI{K~J^StQD>iC;oڜAr@,)B7o5y*/>\9Xޒ\{8G>;ԂŇ9AD~4fݯfA#PXJTfb$?+3wqUڿp&:6~@588¸q3/igQZH0V1~3}CY 'p5(ګYUk3N%"0[x!Q^W3 +P# }ՌSJx1Ӷ25 epvږĠhkZjTݭzk϶6FM[A"1J_nURC6+V!+Zx#ANJ4ۙۺoGS˫ b|hGC @ Rfr109+D1rriԔ]UMyJ+vyҠpu=&à>jyf9TF}DZl.t5鐽⽗k=-TA[.7]b]+\[-(n8,heXaԟ(,[ZwSqM-ƅߋ R xCMX 莾aJ>G2"d~Pcꏄd sшodU[,8Uj"{M!*L9ٔ1[lD7;`dRb=@qc;V.͍;*vc:18X҂hqo—uo1JM5U1`W3$% 'Y%<}/$J?M qa8#&Ԁ&ۧ'͘2ܡ٥欑Z\YFYxR@tޔ''k DR GW΋fۦ@_^cse6mu#o{@Ø컃w^|޻s/mxWԞ!k =:GkNj7U[nsƙ{%LESW+89?) h >d**[jRڣ[?={dɎ_EV1Vlqɾۥ?YȪx ~5RHI8Ty33D'g2l+8]=ɝwnfTr!P 3|78!=#Y}N Kd s b5i2z& 0co07s&%Ӆ>~ֱ{N.|Ph({o:o@F?n,\dlJ8(Dqkǎo$!QU aC%+fo0nP``6L )X._?/R#'l1Gw0]eYSJ4h5s:d|WO$K۶wvTR~|'W@ƤxܧQyT tnp |‡oTXtu)eE[~:~MtL;3Ժ7f|a t`x#k Vƨvͫ'N9qĪK W KJbV[4#C2] X3Gڻ^3jۃk xC1a _1 C' zob]VshǍs#ÔZyFF6t/by(9%#wjfI0cǔKp?(s[Hu3B b<xwb@ J\g:M ͺ P17_q;O '6ֹ_HpǴg:c9:P~7$jG p|H17ݷ{{E]p摡b!~. dn 'Dc>TL~>0Ofb5- tq` VɤY>EOBRjIMCO,F Oag)L2D w89*9Քr(C JMFGFFX>2_2,Iˊw.SJؑVd[; )|TSz@Lo7-XHk"LH?⠵!B +: ,@Բn9}9+/[AϾmE.du@y@>G09Yb:cT WC!ioyAXÒ1g%U7HP a8d?Isl&~I~ Qg}C:5 bEXWN͟mr :ص#VP}a~sG3u-8WTL3:g1dr)$fhK'z*d6 hTLP3@h0|R3460wj zԹ /q_W -9MM6]UBw]1{<78ztѴ dPky*#0]nkf9N^ϟ-_i X(Y.hBo(i/n#Zz8"ot`jo(eFHw>KN{VnǹO+뾸z!9^F-0ʵɬ9<3 ꟝A?!Êz ods*Ȳ=v[ }A6}7'4{kZ76\[5$ʗ.6V;TQ//kjO6X<[T6t²2#'Q 6P>F( p$#L2iVOop5e• X$OeI\Ny={8U)6k"T=ժs7^9,¿̳wNkw#_٣6uM.9;s)kƕsϟz[Ӝ1HpDʞǞRyVN_)Z+WL겉L܋bKNAXsU_Amo\+F\uDgLJҖnTgҦJIߗ]Jйߚ92qw7E\X~׬:"6- ~qGNIe q=?aI5 PXlT"gؼ~xMGWe&I1sH >wxt1㔇($fEDPgf&׍׷$)_AkɾG /]?zt$7(-p(_WP]\A> Hl\K~R+s]}O-ÿAΛٍ7GNf}ACپ9{D]HdU5wÿ8Хwrs@$y@-*kʤ]p&{T%7iÌPN{^֌J6bGߖTGFc5S?RQlvl~U:h$og+h'\i_so|FxJ+{ :&łCeL_4 ndwxr<08w 9ib` 'ŮWX| Z( +-qy]gUfuV7~ѹFiah32R}?n}Hoϭes~j&L U3xq2]c/̺mNe}m}}C>^܋ _4s0o߷;_D,w9-_zs]w_nѴ|},XhagV_q;/8daWϹ3qwr^k?^?a҃~R m[U?(g"fL u?pga5p-42:}]=C2#1wi⼶u;O/u_nOPz*7LmP9ūV5%-i蝈r@T@?_|SP gj?Ο%58~wj?5N:ßd ?KSmV~2|i)b#9y7R4r2/ )JNڄ㯧`#{P<&g/Qf+c(P(};ݵCF^$bA9GW |<,HIETK9TRsFFO9NOU45>TA"Er4'MXev@SoH1xeAߣ.扐H+&_}1\" Ej/'m:%FoXaںE N:s_]VwRI:$z%5 \.'&pfeykξf_PkV|U,A⿯vo‰~_ny2iVO(5kيYUMo%" :Um׻gEyk}u[DUO(K\w_o*7S2&w0&Ɲ0@+Ic)1EXw8k`ǵ0#Ils]7rb_+?^2m;\t^~2;8➥T6dvEElӵSy^ 6v\*Q?LMe_D)\ /vy6<͙6wⷋ.e_?`{)aM-LW~L?kS"KَDG2 g_GǹYCOixQXu@H[.G%;8GLz2c`1bqutcȓy팃<D'a&0=fipo+<4mx"1j!X*f!ϲ]]Ud4,Eo/JU^YY,4&2xdruJY])<@<ëډ)[|TQR˱O{AMRYӿ~d+؉(еa\޼nXoQIMM"⁀D{2uI؃^7zt zߣDo/9TF. p(F4[ GSw*WWt9[p)9 '/gvR՟FԹep*wP{x!op!da>.%SAc *Az+0Pz,=_(U^>M Y>ɖv__VhǑv"׎CE,Qi.fŴMvlZv].n`V**\-m-aխyR(^RlP%el=el+kdK'#U#[1R(%#-Dl Ml쨖"&4MͬM@qf-i6ۼ |^v ikoj-i ۼf˵RrϬ*BPkѴ+V%sJ\W)Xk]%obqR,qQwVe3VjP[VT|^rp-[Z_-𾼖}vvVy.|S*nerz{C$r$ CC;FN! Q{a* `*>[c񼸔QE{~W|'- 闦{ϰ =uy(9Hw,dQ@;qpv f/8H9ArkƱT193M`}b#]EZ6->v!w>IxPHOͬoxS?  ~3@2 xԧa ?na}sEf`?)»N\>Kl'qKPn񾿍]Կ?DxJnf.&oo۪3!36NG1W}q۸L`ϖE#}Lwv?u7;R1 lQ?O׏guxXޑ!xEE{52U({sMJ._=I{k B5N2Ћ: y#倮U@ۄןc+&pL]rv?rd{,މuR>eyV}(%Y|y_IZ\p*F뫆׆ΝlŶLmbK^p{mveo;ao x٥^n*V4D{n6ۜg O:_⧤~(#] ڿm6谉4% Dpmce (q `xEmvO Dz^L6`Ȟf~E`r7K-/W`2s7'& `{C|+Ǔne-s }~ hzDG7SyU13^_b7YD iowb"h$ l҃FJxϽ9 ZNΩ5|7v&Mc?x==|D\B9-zMՒu65J)لizo~3`r0P-c1ȖZ>Gwz.FADO]1I.2Ff{wl2>h+<Ly};VØrGv۴ # \D$ ZF{]~vͭ!l_9>ĕةw>u;::)M`gx\fNw7)y,P^U R].7Ƚ@ 0l=V:z{3E -5=4PeDܐGxU&u߼_n+WYjOmgͳYELW-(?_ؼc?舰"H*(ʬ093~^5}wLA;T)W Tݱ_1"f7QtY#ͅ]!ct$< O7]R>.y]l fL/BV?&Ν`OVA.'s3G'U}4RЂd#DN5wJz%bC}˲d~My}cIG4]i@qR5'O]C5f7yJ7^~G]3!((U0RX*%|pU GJj}AvT)ӈe_RJϔv! F7 =<t,!kxZ2K,!(e6cVwx}ryA LR&1`@lm[Һuuٰ9XYլFFuil:j^=>I̾zd+y|;T%-I|Rp=oSEn'XKu`P9v'M;'K&;" g)bǃCnBUߟbu8.MWDe ?_"ՓkX;PAxPs}sZUVwٗ׉Lψ${xd/x_mzܩo݊!WEG!DjiS߀a_ƔY}%j3XDDqf>?{q?f&?oޕcNʌ'm>ػU6eݢk5bR% ]{l]~]_8Jg">ܧB1}VV LD]/.z TZEZit"+ @n 3)c [#赈xҸ{iv1k֧O6{(9Q9 0i E ev}lm">n{RC_dŧ¡u~m \O os2&ym">zqS>{aL2R#H}iCGLx^b lbdQÓc#քxhp5#feK詨>^>؋^.KJ $TC|m!=z~Hrt}5 ,J6ll~]_<48 (?Y>m/Xv[mD}-vo!kǠ<[~/xՠ |{eP4˾boe6'\7nMزd0@y+/煺_[eݡ$>#6ԃre7\M(UNfL%3X9mҡe8&e "2,4'=EMMIt{TWn#"kme ab+Twt)!`j'ӈ@> L00D8je¼j8kfBmT')i<3"-IWRO+Z*R5hZSǸ)͈({1u^w&7R$ҹ ۵})xùsFlMĢsGzaq.C!}꫓KxxR8XxS?TgS."WM!V3fnWbZ' ߤ+3UXq@:ljzqEրC=^R; `J-ihM%e/9NӋ$ ﵛޘWd h3 (|IvNbG*MVm:(܋%,cJtl fN lQҲ^`5džY+6 ?_6ƢT$hZe1 0VyQZR,iV%0>DZ /J`3QE DCԛ6b0ɤ#aiƱzzNrF/FD]|u߳G9mxIvB d9_7- ./\^J ZJz% (֡Gy&TV.ۙ+0#[ q8+LLWCd|>!!"0T+ o2^9M RުaeciXi6#c/;&=Q:3ş!*8($(9AeYCJCnD4j ŀ#R-@i+#a;w,>||*%!0ot_Im{w 5G^jk¸xӺ9`xq! 74NdcK1X q@ݝªg?v>M3BWf="cW7N|[5\;6Kc!.Bk` [t㜰v3j 0*5i;2iw`_acڀgrȂufHb; i%U,ژ/֏߉чۥ4e kj"8'1ʤpI) ;ha؂,ă؃צۊկ5 oG"*np,¬[xHh @P^~\L(őhro#ς;8ihYMmO'*6S aUpi `R&u6X7,$XZU`0jz`*RCk?:]*6n8P?K~a$F(zC}A\?Q= _ rbb=TvLJ # 6UEʜh=(BB.;ݭ[Y坲.>*9r^tP(jZS_{Nb.s'51qT<p0Pi;,pJa 秩d<`؊!x/=V+U%؃مNǜҭ̋ĿA^|cϙ`T7 Ke7ԔCƂ~Ǹt6Z9SNVp(>w1K 5q1(>HUcT1tS+*~Z"@/;,K}J{l) Z`qag[8k Ƅ3$ jpw {KQ#"Y{d%Yh`+ZΗ^A|x_XBVt{͍H+B:'Jp61 ([ң3\ٖL*nLHA # đ/6{ /??i[>]|EUcRum^),ókY*2?.TwrV܍Pk&~AVW u 3r*#' %W+&W Ŋ&^ z$IRAr4V-U\~H6 L̟s5[亓?Ձ89q 阬ڰ1J^@?MJkj)_ݔohXcZzZ\* `87=ޙ|3zqS3Cu c3vӻJs>t]5nˣJHr4]◢TXZNC?0 hX"dZEHB:NXXAGpŽAwr`0j~ SmKҎ.ߝd n7µ}]L0%)rqt3LQ|?V|rUqRu^B\ZGe*R0<,~Do$҉\*w=bh49Mx 9>wGgRv r<~_B;""=RY jO+|)Ev̡JlwRBy;iLW-0tv4&jŪH IX—DBW`X7N*. BܜAH}cŔCb(th\ wxǏ?G#  0ڽ[q@O}Ƨ?`u4yScfȖQ-vZ `:M%g6jX*ó- %;MvV'AQ`r@T`au_K?kp=RK Lp F %{^xV% `Iƒ6(ME^9cPn$96 筤b-K绖4hF鎤J6'U"Ok׵C|{('fS g(ԣuD%.Ɖ\#jVbb?[*:*RD8;J A0MGױU-Ʉt7 d^ -AAqB|H Ɛ1BT\] |aJ 1^JJy= !xSD TCDVǘU5=HP=`rSRdZh95yƛX||\GF9r/,艏kXӒ-c*' Gyxe~t3dբjxϔ\NI/ 4(A##|h@L5&+ت \QՖr.(H7~q.tч_u4_y6Xѷ|N7!@jSgx}{|UձoE^B <I›<$QBB9;a9{>'|DVRw~ՊZ^>8Zжֶ[>Yk h?D8{֬Yf͚5k_ gUKSeMJf&䴪kgJUKZ뤅MM ?jXZR˩S5)KޗL6)Ÿ#?#KrB[$G⊩ & W7di륔%9djJ֧I96D('N46^ve4Qє4fѤ)倴1{< [e%3Z\PbWXQj@Y( )6(=šUХUITT5[C"r l4b٣j߷?9_NRl ikFT:C1eh%HLOvKϥPxs5o9E5=Dt]F.#G4VEKC"u+}h0b t?8fqUs0H2 ݓ1ui=L/LʄEz f8{A_} R?V㪂Z/c&$oV7%缙:r{-ӟ"[lYlj)l†-T.Z.hrwjUEUaXv-:8jzc6ENHD@CIkOxJXcJ)rbGVeZߗQaN2tduIJɞȦLlOJT=x:xъSY] 25Z-ֻ9Xp*Z,E ͈X)CNz" HZu܅~ݤe۔d,I]ōE;(&T Ig=r~;'ZL|^hŴ@ZL|.aL4E.h^3% ثC]#{2j6(LbA42%S "Kb PS*E&YA~ \KED㲵3S{h 6*vjNA 0az(r\ǭƤ44͢II0c8GpBiΤb# QF4)DDYbGUɅ^#Ϥq9h2|isq|Aqmr(L+L>Clz@J0{H)@{¹ǿRfIS+XӐDΣ!<UrPLLM`m`o#mVGU;*ˤ%=ivh=0n*9P[.FHkT>蘸bOSÍ.SIA 8Bn_7v!jϤIr WU0DѦ-%='ΕL3shl3K X>wSYuy٭!v a !Ad3{`a'$릆6y8$):ᠽH_PagL6H3ĩ*裸L;>;k!?7VCvoƱb9cvJ 6+~Cpk$YDos5/wE4 c w PAdG7ԝj !l }d\/ySHbTdf ͢d@ɅEss{jO.:< 94  <iIWQ-RRN)2Mf,}h,mjaQDѣ7Ԧђ;Sv^j8,z#E;vVKޟH凫Ifb%tJEUˬo,t"a'zO>سxx׮ E:uQNSR}"k&LdʂA5{]+^[QW6e'Ȳz+- 0p J*6]  8.ü.C+E+kjByCjƓvٝ7ϧp)+KӫՆ3#뼑<"\[%VA^3*3euPGo=fּ0 +IKPrI{;H# ݸ~Um0`f!Q`+0@n:{cB! CT(ɹ=%E ZMЍ[3MiR~*n9{ݼ)/gY<e_6Ƶ^:'=mȦXj7:'ӓ*iZ`um]DfDfhOvmm30W7=C}" x_ij&48Q~I-@Nܴמ &dDO C<ߴv4W20rr7KN/;] I\JRlV7MOS_B\R~>ɪ$q_!i 㩜q(8،i~z (H&HSQ(p2,=4Xҹ@1(h cUȀj[dI]-K9<\znWfk$]w d#(Oʃ31bX 04b.uGjz֦}Cyr6J-0|zm|f W>F3΢BF4_$ź(3Y}̶%˺&aI}#4&tBbT7=3rR- B#7G>5 Q-fK&j Ιg7ڭNlus"Oi}z5y̒MX&ALs|+j-1;v ze]̞ P  cd`N@taC v}pZ;U%~"}EVE w0#?{9:c笙ސ4y@%0}0'=MJvN4<y7YSM}zE1;UY^<~>^GKfǭ|CR"N]ӚG"jRziw.E2xXI|8+{V]>bܒ·MAq[|Rq=J~8ѝ׆k"]OMw0BB5>Dbv"Y/MGi;r$?2so^#.o-*^1cb=ȺmO}HŋbcBwZ9X6:vԉb ʜP-ۻ>dAH<>*INV(ϕ!xL94L]ų(9{BOW͡fsQɭr*1Bs\Yxpv*kWfrYʹ2zeKB-[ ;G*)NdRBjaZVkeB3t`#4̇ZKFEKcgy F~z֔/]18!]_!ĨI9{rjn2>u͊}7-r怫>Q@9j0UG9q<?_0ljxGfǽk~e F ic%<693= `(tZlsEs^͔";%tET/c* hin4Q:Gp_ hZfj.tj޺"| 1$)}>w-~c޹tj(Î17Tu) x"hi=t 54"$.G:Eog3P߽Sxb4z\zԄNJӐ/A' 0 +FaQ&nmiG+B3ώ=jPZFuz0#- oxk~.? %֥yW|*/iG4!p`BGCcr۹d5[CNFĩ'LS e,K2'<4c2hi}c= ajȣn'PGΔo쑢]K1ݤ.|?nO͖qSWݡꭇyy9̝W(R؝ }(rB`bޮYh/L~'[.<6H邔&jUq[DkJ{ƞֶW"2 &XGwWtc"R 珠HśR ?\f ~;M)q5Èow:5or#u&9B(bktĤ]ì;Xc uHF-X֪S>\QO`,Q:F`lJ}*-owm'4} Դf<ƽKFX?Bvo.kꖑ֢L~<#)AWfM;Z{(#DZO t{A `fe]lkwiZQ] ԏ8c9^:hύZ+4g ZibDBlCh߅ߌ½2\.) kA:E'u:@Hp{jyQ3(4+{ꉄBx9*XI7E'P ф% )&tt9-}ž d_a-6#m8.Zx`i LYER+*;D:I[n_Cx۠ߐòN:`Cb17@ፕUF5Z %ӛT 'ҍͭmu.v/,?DHr:S`;e IgU})gx!CO䧙P1}ŜLEٗI$xS[9OьÂtՄ;r|DGa%tJԽq}x8PxO߫wLCo4~w9(Z餽bֶs( 2d , \T0]˛4OwjE2  Ԁ'覫ˁhe~Ya9ry5cWtpQe(WܞpA8e|ֻ__& @E+ ^&ȯw:iբVc~85$+8C; e z^(? -\uԘ=]BG#F{;E 2i8"5(G7 ˿$Ƣrei ol-^ϩ@7%jU6Mw[7'Z/nF%Pix+D2]|*|` M{֪}(%'eg\O1?Т`Cg`cr P,' ,GJYH"<w<ͥҩ5<)P?Pa~gYX"JR@6,~G1d*Sq訊фIjrHprLڿ-fc}|p拥*. o]2B\"o-XBD#!rCCe!y} ;o?^g߹vlgZ&#_ޙm]n'gTcp>fflwf}r}7=~)~,X9-&b"r,4hQ˻ulQwǩ[b:|9/Ej}Y욂+쮱`Q]<͚Ҩ\`31l}cX,!2 ql(EǫcٮŋƲi2FO%q'cRi}8VYƱ^C Y]2Mp.@,^aof=/囌  OOل KG_h?=I%+tǷ=?߮֯]nmMq }z7E`DAP `Lqobnç'*{"'N>U}d}7*8־}dEE ϱq2n&M ju6&Mv Ž=H2}yF&չX@{r=˙k%I좒:8-ہNd)Z9h6acboMRHpY O%ז-@NSlF?mI37g8"agb Ku]<|d+cgqll6kt4QL30F{c9[3q` kU֎`clX'R#s mRN0~$4J윢 n(Į9K LR%x<•؟dLb;ƻ$=7Ubww?f)|V y 1z Z簲3:~V>9FkK9lxb8_SNӹbNl }eq\>*cΌe㜺skYj9C.BtA>t!çf;:2`Yl`pg؞@ i?Uǎ⧦Ρ+Gv>]  Xiރ&Ht1 G/ fwn4ɮzvA%B(dXRk) 6&"@f PM2`L{m߈0pVuCȪtѤ"炼6fx=d/ƽ/ 6٣{ CNټa1$P$'|?mKT,Yٯعc'%Qx[q#sl+i90N4Pweߴ휽Af4^VŬyvG~a3p\lq"Ђ%,2=xpmKXӌ0OCKYKM(za[]2*9oU@sXXI1L߹ۓV0e ɏ`{J;) ΁j{j 7JRb%g+^j-VL*6ŁS{fYՖqYDPs_׌<0bҸUu;kق4oc y!kOcEۀnz(.FYCecRl^"s8ӦzV7/ @_.60>&Cmx YOڼb~Jc^OoyS&|b ltpS f9`n9.=lvhmImHAogQO{St /3BChub߷ \E:&̼O7: l^M\\`Z&uu9M]2ыRUrT1:#6aѣ{PI\؊2eJonCx}f.fM0{70iG;؍IeD\x$L;T&)}iE$Tuk`گwf aҀy5>l,t nvrV3*Arڛz7xm!:mle>_p,?y=8qvaV z`0hw|w)չyFL/&o+iԔA fH+|4^dܧ%kj"Rp0Dy抉z"z 5{T9H C%U ǶӢ +h{5CêEʥ 7DΣ 5dh$~Js:>AuwJ0p>- ҳ9jtk>95+X.%Gw!lek9I$AqWKy#^&i糇`{)Z ~|Jv&*^ye_{%(sGٿ5P_^*ּ*Z/SQ@W3vV^!׊=.j>ό}'%l!X_լnP ٣xK9*-;Y%dSG"J`GAvL7_ek'^w- abq E<=A}̌`x_>@y~hiW Ao+b %bp=Npq eײSЊTs`bìkYńm7 UoL5qq١ ?,eEݫ㌞Ivm\+ۍۭ{:XJ}Cl4朁K,0 ֯y`Lr!_'g7S,c{Ol<|lB6w}U79S]s!}}ml̍iZ`d8 _=^ +FYd|n<}u^X#^֜&ڏ{->B}Z$ҭ0 0ߟ&CObRe[< %N\l7Fy9^w 6Noҁ` iL4lDI|}\GPb:>;6'Ev38aо+g*2ܩ:FobDq_=t;,$Z aՓ<3ΗZ͝gؾb "`' h;S|`ĔDۯdJ} t-ـKJO KO#X"&UQE~|l}?Ca kv[ Ξi:->Oz!MuP?= 40T^kjD4 u{A#"r_4>([dW-›-d =L9F:ߺu AϬ 4mA CT`X߃A̠Dž<͉jyӚTe E\LwH;O푷`"0RTVr}A&o6s )ޓw+H_s۬jgگ>jZ+,M>0 ]/zF[VeO8ƪ*$IGأcl+%>'p-POi~Fȭ/7 ~J͈X$Ƅ=Vl,D1J)^yP"v/+˯"&Z~Eu ttP0=zevN z1sM͠#fLE5o,{dR?2P7Vn`2Gs#l|>Iaor (f9vc+YȺWՅ|1p=n9c7 (dZ[\b+%~_i+ZځIx0SMɦJ1|O,ӔNj|p򦻲]=$lZCg]g^R8evrj Wa>&5|UC̅X+,R\ѳ :~0|݊V!tU!}KofģEFu|ɽO$:z5 T*b!z[;}nS$檧ٕ;N,Z{.0`eP1adGɞjw3W/ɁNڇ)ׄ,tkIvT̝< EϰO@@{+Ko' Pgwgw. r@DŽiM;@WoeN鳤)pW ~;l&_#Tx Se_a1рS=eD=bXm\P|}0;ƝJyv#P0;Avf6>v L*Q2j0SRisl)`fM "7j=R.}%٢2zNZKډG|{珘6ڂ͛"[<=R|uV[Cw\c7y+OR 6ޙ@%RL^bjC2/NWi hcJ}OY˼ 7leU [۵/IW۝?cVV`J34E|}33)n!ї'~v9M܇#;Mc?glX8]@xl?̑|z(rlb+r$_a+Wjx´ƱE^D&=ԫKۄ=xB1N7ݰDO?u_Jrbb/dV~aP<u]3nO I(47`u+gܮ;VwJxO!4dyE튙![5n|"F^g wuC@boӖӂ?dҕ4;*cXgMoq'`gqT^GFif4:F%"Ҿ[yCi|̔֔aQvsXy7 l_ʃޕQeiwf.5fƣ~3d3wԺBbKdUc7$EWIV)OdB#&<'9gq9booQ1Ap>p"U]!Ug¬4߳~*P~ҫ`e//_e穻 V( |dq +x @#?Kk!CKJc ^q Gvk^)QMh( 35#^GiVЉY8Xn KB~?W`fHvXՂ7V=QbQBsz+;U5)[lzy.X+ FTf%nmVVڶ=vlڜ`؀|ֶɫ{AXrZ6& diu ;_.+;=%aR$ hY4tC}`FmX;'Ҋ]{t``zu-v+ju*H Cn?TՇ MfF\yީzsn8brָhyf-5=IQA>C(ASjBK9fO@wy'hv^? P$P1GYz画Ļ(+#E$ F<<?]PY jKvR&~wt,Rz?!e|;jhgF"Lx} xT3A%n pr!$$wUn"aI6ɚd7nP\xE $l-kk~Zik[jb̜3s.{#^9UuWS+uBa;묨vf47/_}e+: !p@OW@uDNCf8s{byjN!>VRuf/x|E}͜4]3BL!/c:j.ܲIlEu͟N{Ēo}[O"lw'ЄXLѡ1|nCxxmW$҆is ᐰuOVА@EQvUB8~`}dҪ i0Az7҆4isRX黷}6<:?$E~D$ui ۆPQ1 uV@=h|P lEpCX.^Ҭx~n^eI'y<HF"i5鴂ʈp&HQ2WQDAzQY {֬^ Xk"|/=V)LpUs|p݂ &+Jgc+.37,dBh V0Fma?j@B^qك&9LW.e]p2DE[rn05,Je=D$pI\ XR3!rqv u*W`giz|\![p[jYB~e Ί*+zjk5(R>OvIQs.u"Ty  G#\ yM!*LiT`&9 AL/!A `{Ρo1:(߾NӁձүnh=-DW(qw-/VJ+;k\ IAVU1 X'"b. N~HX8B( 21y4F $*7 =H R)"5i=P:3*Dx&?V*2b!fXQM9/@$\3C6mnabJ\MT&8D/+3IA;'.! *%EÞE1gv$<+3h 僴ܖ#5zI}PI~51ANCژRSZ@ "zݩ2$'crƖF A'jHIoX'p&2⁼ SiO.Dڕ+e槬6U6"i>ESK5- ~-9lAV Xm"q~[GX9Z9Slf}7c2 䀶dRg.Ig f(_8~=Nre.:"*`Ů5GFI剈^fc(nֹ r:!dd9';-WGx* poMyqwYkQJm(0{b9 cH̯% %{*l,SL166yDsC^MZ0 ,cW6M%]1RGA^.ȲݻtFs*4C$j:4xydQgBNyEhoufiA6~ǩuCZ CUy6)+#+t|K[nP)X>^J*-Z>>͹DYV{7"v70m Hq#؅FRDEF+Ddcg{# XX΅MK*ᘦM % |\a8嬎^DN"pw8RlLȼt zGSp{%ä}wU6 jWP;L5O%plDs0eff-=mnt Q?^M+񡐔V8iO&"NTm:odE* f'_3Y$.V{[ FD:Z}H34XTUmFiݢ@9E'9of"a}:fu.vM2̫ r(CC\d+4(I7[yK[\ ٤g֍zٕoV#pfsҦ;+%X?)a}2bW\2.P,G%@DTX[:K3،chܛMhqogb!ȍ=rWvUt*VN[poS& 6KSZlꄵ4 }j6iNy0w.5,:jչ$YEz. 8چ(5d B Hz,ruG-$򗐎nmxڷ6[9IM0LP Eӈ$FT N3ؘ2Y/TnJ8m7 5ީ튓TfX罵0ѸYqқyL]lOT{ZTS<Ã8il1Ld[6}sNXu=Dt>#q(E&WJIm=O^ {*ЌBtzA9u jtQ*K[3$>A NNk)g"ZH7hZ!~m+c٬ c'0"["mͭQm m#wȸ\duYވv:0`jqg3QlqxaRogm*䴢73Kͧ)YJBKuK͋.^orUHOl,rLR<CA<%Yr*]h16N7 IkL+9>ъ"X>z)8T:Cd_}9c0#mn3gK*1Y3?X\}gu4!DF):r{ &l :8Q1yr5oF1F *b*қR῅S",jM_P=RiP+@:eJ5EE+_£j|uI.p7 #py⎐¾L{6Pȉ[cfI9Qi1K ~j06QyKgqH~4?7jRS{i^?K<#i:9q(~gH>' Qrn؟NsvѬWO$+&MJP*m~ Z}mH}KҷK8'͓Ӷ0{<vxtoZfko+'K#ykO{t9nsQX&}0oISITϽ(*ѫA1?6r 2b~|i 46<&'sw$| i+1~uߍaF9(M1ۛ/ĿP~aDrwX2 nQ>Θ,2W&hlIcfAh鑎yiEtSUh…ٌ=:74\f` چlP(YיrD1WQaҋ .-4!GĴ%aiR^*2;|H[ ^Ѩfhc ;2ӲiwҺ]ѩa*d2C"fͪ-yfJWWĵEHBpk ]Nxڭ5UCwmW=7x1 #n$Įl%Na@=gs9ߜRtD6A"AnASX>\X$kq;77H72"V0[_TxETy>XQOGVu2>QQ} DJoNWC Ƅ Z6ڼU[ F|A]v|Վk@(d!nr6D"1> L骥+p%s.5͎Ҿ)C|8 j} C{G- V > xTZpImΌ~.67c,R)G#6#*NNB2flUҝ \d[_eM. Q-^ޒBjaM<d BM+D|M=2emu WCYɾH$234,ɞ)S[Ǩ!+P3Uh`P@r:Z*)ŵڨrti }=C^]MmqiEJErMCxF0ۤ:X2Iw.ɘya9JI|+"Q&vKHN0<`OUG.Zǹ"72qYj9CTz.I;L8]X@%n]!\ȣXSdy( |⥹M6zov`WS2r!%FhZDk0jOe7|@e~)_o}cfٲkq xJ3zᭉoLO3M=23Y*y3Wmz7ѯXp==OmQ,; eBB7!'}`ɸy˪fR UDfac2qfT{IL?&,je\<pS\5Tz)&inysmqպ6)a҈_$$YFItɶW2Wob^Hzr-V I&.m҇_=57уm6Z'NrY90W3j!ٓ<S+\n>z0oꧨLiK/}W8}#)F:m-{Mհ{(٘-P<=$Gex'M}K_7x%]XZ͒vXybN⬿n*'ԝK,Zŧmcg)տk̒}.}GjsbwjRX&eil1(Ɔ?D [YPBC A%gWzu?8[jKȖiVTF[ƔXQ*uXk1[fp 49ҷ_/~#i>n6y6'?1 +6E9%`vv9n|N;(fWR%a MzQ{2!h]EP~8/BB:xku6ScE>])vr~2mr/q2vdf2{|Ntzr&׭ח/Rѡ 4C/y`>}w#$l[jM)Vcfʶ`H/Q(v5^ ʑ$~"4Xj1Iy!5u G~m بrPkMf2FU#f2? =5U?Zbi9ENq@44qM |CIЙkmF.ڴd(|F'=N#5+nJǩGgA<|c3 ^hijǙoIʫ!UZcj&?,6BgAKP0\kQK]XI4C3Dau9"ǝ@-Uo_#W8D5B `մ9~`s?VjM"`'WO$`Na =$0x2&y1`VJA%1*p LZYRf7ƂR+% T'!3!Pl+C.V%VL{PMHl]ys|B(g<;dہ( MS7rMI86y1`#v;]~:#DUc1\OͲ[nThJ#D"uPEr/4퇧P "LVg"gxV "D`,`uFa᫶ex%ULU>m" XB &M>6.F#S,-vWFg̗.=j`!{ؼq]0 >p?3u?&"`k7Zn,}Jqʾ]`98f%H;)W!iV1@,s6NB95pc 9KB(C '5{W/*? / %ybEp+`,}A9Z ^,"ۖ~܃vI> bWtk Ⱥ:y7#eu'8^&oFYہ}0{%81XM'~{XKVem<je.'Xr7J1'1ODyl+/{9l+*)}4Z pφ^=Vƈ6a& ~0-Pj7wJRfv]\ o8dtWN+vgQ\yQ0H  B8]gLf+L+ѐ%Xʗn8Q`"ˊɈd1@e¥H6 \7 ,s2a1peSxKNjr>b.ԭAݏo2 hgNɮP8ĹARwQ`d)'dC<f m !=VҺ"'_P\'K`Obptjp(= {$h:pmla(QU^'9x\3; `R6z 6F|sB2|'Uj%HJ0b$)KB^=b=v)N?> w)a"׎pjQ gyAhlUStD1rq΂mnOς;ڧ1j43[Wp;|xv[> #F}vVW4`8F<)9bӖ 7!M`w07V}# Ds`\zɶ`ȗx,$A2b'b0=( `SO~Gʩ=J/QDi(ltֱ[ԝ0HRP墋hW,B8Cl i4#"^+DK0[W.ۜj -w$W|@;p@w:@<&sx0Tu)q#-Q^S4V=+XH`$~+?_+乗{x)c wf悗Cb m0#JKUJ4Ѻ|2hu5r_TFDL`Vc-&W\WϾsBݺJ:fܥ^fK2X#l}+Q"SkV_!._IrOt6P[$^*d~r@u>X/oR8#? W>,K*f|jEvp;<^50*xԽ ˃-;w^N\nKuaq:)ԟp`"7bh yh+:Z%o,yܮM\-0Q ?/tcA|'xdnJP=&( dcԟi4@n[>U?֟r_%4{&-ɪ.ohw6 r,Cq W,Zfn/AY>׵}y-0N>k0@.8LfCJB"`|/Qﰪv'f˄>P6(,^z|N2m0-Ԋ"!gA<~ Zӱ߁rCq7o\m|r/F+V@-*ųٚ)Z| M8`y ҃!~jS0X97-Bbq3TA{ {z%rl{fQ_6Lω-XW3'yzn<4)Y,[Fd<@H Hμ),.g1P9#-a,ǿ܈@|kHIa2Ą>)zY!ȠEnsI~bc[H?`ù@TN8Jbh"?72Y4Yka4]~\39kVG/T&I O!)l`d8(-dBt,%l`dh LP_hgi йft`rA 83t[oPP[҇ I+lxSش~ܸZ}NBq6*Z]@".\^1z@k] J{ި&j@1:ݎ-N*\>Ͱ y1% v1׍y–gж)V6Rp{NX1 v '窭8WuV ZQryEaQ]u=FA\nv k7>l*=`wy т҃@09hGxx"G|[P1^+ S YRB+Nۊs|>m{^=W٧01,4̬t{HHj'P5uO6<=>fx?Y~xޅNvq &GbV~QKE%:< ~PpDWXTcS^N|>.m{BpDNM$y~u:nlƑG|6@]zWs&. pA'MfT"Od 3fXfdrW%{ p(lRũ*lQB^2HȨ |PY f*E˴n~Q{sl=&,"pQ{ fvM ;O(ZC9^#"0DȠ;-8k҃ SW4'dBmI(4XHk0Y! fSvOArN bF0uk#ZԍfיDoJ+ě>*zH_ejG_ r_AA1dlfe dMSԍ'Lߍ /$4 xvȓ?DSYê?!:C;h`wfDy!0ɉ #IC绹[|e5JZ]!+E~o`XzzY]Y1fR `uWo sap k姨w88" OljX1%Gn2!eK X%ȡjpf'םm$|?cr46dEwFYFk%y?D /(TclRtljlChBUӗ2^b'\ n/GB&t(RDF ԍb#Yj#61jdCU՘Ԉ;=$ڿmJfѧ訨K#=uNS[O U3im^"o xgj@٪a䫄17pa7ȟ|'f=ub΍$zn4,rL\wl8 krF(٣јQ A34# &jƀfD+`m1Q+6$x]g!&3wU 8<{"Jz-V\Vˏ|jU+ ߶U-S+B":-▘"]٥4E}Aá8$/Iߘ| v~-ՠ6 a0F{~d,yƌ. ۢEnI !jQ> ư(ABz/C@> :lF u  c8R!u<'a]k. U`Z$5DWjS~/Fd5 f?)/jƁPj|nݤ E YD"#Cc]$L,[c3_4҄2+?Kl~L4[cFqy2?,5:b&8%jX=bo]KO0ԦI)Ynesp-<sXh/\y0x'DȘ}DP5՞ ~X hY71t^bOCm*'At4[r;j:U٨tn:x M`:BK)o=.߇vW$@G}}wyhR$޶;Ў=4*`%{Q\j9#ٯH:\NI+<ޗyjuݎd./)a.|$f 1g]rOg@diq0./oZWІ F?JJ /KKJ5V>K[HF0t\$ydGle ?Nk]'"*\ԟ-" ?No6cYhW0mˎuDcR9@r;L2(#:#s &L-}(vh91)@$~Sv0d Hϰ,Qb}W9}0L:6.+]U ʷ&8 R&?V_swsi5h榥~,O!!'G_Ť)y#"3u p 7W>0FLb "~/$v[QnFĔX.J]|д&|%>)9 #%蘹|NFa9LL QK1?CG':{V#7V@hNe]c<r6X啒̩S0Ҹ&F;´dET!weaaq%.RDDcô\X򹓘C^D,,wj x{/\hh~(^0{_GÞ8/^ q!i$NXQ΋X[&a'q?frQn||}=o' }Z7Ϗ 'xo7b9cױy[]}߫ ]; ˹ܥr1]`۟-]#qsW2S?wܙ ϝ:w|xNֳ͝`)v gSg7¢[xԖ!NJ(_Õ\8yɼ~G|Ʉ_.e'zX%zͫ^DžZ 1>PF˓$߱Js޷}Xi7~'.qSa&sײ_\`@|,~w =NQ帗^(pN~Ϳ]`'{a "+ "يF, zR8L |b_ +:@daEq WeK"Q-]\{ci{S0>PvWrN!z&3 >I 4 CL}/Z)VQQgءeRPCNf!fM!^q2|Pܴzyn&b3 4fVd:yVD=4 )]AXdW;>={$:K/\:C~hxy" s3˒N^[:ɭWYW7t[92ˆRO)k(>9səNL>Q*$ܥ,H rYw]b<7xq/S·AV-솠Oȯ#|^_w{ZvJηY o6,ռbvQa^jco-/''f3[Ġ(hQf7t(Z ~{(e5?ULlZ퓙MA eNǚ7jڟ @] 3ֳ49Ӊu&2%_ y'r "H#ۊ4qfy&Cwg4B t&lbcvOs~@Y@~Lh̜KC[IjySԷ-ʄu (!f̷9lէ#{1?<|[G3Y̯P9yRMQo6 ooX0ZP?E=m,G44Bh Lr/B_M؜9X;?bޖ|f A-%s)~AA2rpLSmp,Ɣ_F^JxtWPm4(fc;DmAwK"S+5;B<Ү1SDxoGj4(-l)7kx> ϱs`,,vvl Vl.Ngd63@ֳdkηJ-cO:m Efw+F  a0;ߋ{K |Ŵ7? H~X9_}HIv>:JwOv>:||"r qAxg1,pbEI `8؍W$3.kJ V ո{,_wͳYQĝ$ba2 DŽc3hdoY;'\>GUodekRw𼳃yTp 50m7KDa0+)X|38A2T)Q}S fB~G H7l/b 0/qc 9SB\,hy6L>)U `~o)sa!9g0I9g|A%!͠LܛTdzly-oTdh65oi)7 MjixQC~Us3i`}< sOD~9 (iʩgu~lҎ!] S0UM}$C JS ,T*f1]3Y@PL?}(s&9 & gB' /k0sL%h9ّ@: /MWQ? f? ٔ}&q)8,f?{yifrRHՋou!4*dشÝ|9K o)ϖVb"͒,T2b"|8>>ni_o\ȧrjP@%hz.azYcEof.}aF΁9*,̋Ƿ`e  bq2!:Q2.|g>}\uaz6L= e[H5P}':ypeYF/z 1OsV`˰(z"BPͅx$ s^102 b%ěj#R<:!YuK|q-\̫;'<&VflP!iXR(B׮gJcekc2ӭ,Z{dΊə˱O#5UD<2pj*M&H@"BmPG'J $bV4? Z)pX?h˸{o{L@}3vX[5 Sӽs$ANO^Ly$oA>u3c`})<[kÜ9{>7'e.;+· Cf4qCEf3qEԭniK6>: '?<psN7"ZdY^2!3,-(k:)TiԡQ|ut1>׈BIMAV=W9yL8w=\+ƟKq:4SFKB//`S}޿ uWɣwo2"Lg?WwΘ\`øgEӠNYɺPbH3,_yQFIKi_qq9Q*^nd1Դov?熊9Іaj)z65SB%>Sߺ[NlI_T4oürOVmA2ki∄F^'gc[OpVΙJ8x[ q,[M8@@kQd']BGYHpBiOZ#bSs MbFu̩3SWqeM;&o=p#S(aDe4]x1$:wO+sݏP%R@ Q2z,ZRjoi7_qջ\e o_Za`łTWg'E51A?ۈ a*PZ$րl'=X Pϵ!Uu t"VD"{:53%P'z^ˡm%h(:.ksIf›sjPLhRY(.E$@&T_crP$!L^+PG9ks:EƀNC~[5^Sl-"nsdU]WpW2 Y{bHWykx'C`Dv|>{QAǔVX27cWl5UmG){jw7iDAWQNy^)i[0 ˸X)$qQPGEJR#Ha/T-1d(6)[F̕2,㞢(;Ԋ2q+ ̵)p]C'f)oB-0c}#>tlr 4Xz/7=Nnj/QlJJq4iP:ƭW֨pUD)88f[Ҵw 牂Q14@}:clU"xBY˧2qunYā2Q\9n}h"f_dCJ&7GƗzBP?$p7/l9:6ޡ0Y-2[O;;C:B??,3-<[U=q~NolRutö2I%YJU*!z9̻|avB\tiSdwWZCv6@ .[* @a)~ ?%ehN8I#UHȶ42褟A?kkY1C:yx-fYMMU!_zU륟ʃG' b|N&hG_J#}Ou_iω]G`ǚ˸WڀӰ= iZEO8E^@AaʙR"ƛMOܰ6C$0h${k5*334,,-3.5}`0qWM Ei~G,7{:'#ł~)6.|^1oexM w.Ab}UˀFni EʿXB^r#;Yd\ #] ǁsZi cE#.>f,)fHUX6T)D'Lxgo49j~ SrtW.٬ݯ:AW]0s:e(٦S3rcJ`|R 9~8eTP20pa}|SF``ym |`?3Z6u2.W) E7]BaO1@1A430ƨ[~f ?og_O|*'Ď Ɠ3R@U#=@Nwl)=x9qDtj!3{֡6fƅ=5"gb,Yڶ 3]ˈ/${\h7cIsU15twG!U.s?< :͐wLv̫\y2^pWǰE tG O%qF@w/qNRL?|Ϸ{Q`;r^h$դpgGL-${tjK_\݁aW3hJ9͈}\>/ò`rAxmY$ʹ "ՄVeànJ=c@N9spjkEo}m[aPvMŕ8A8 .Y<{뗃m?/1,ܲܞl쾻#{cnabI>=q"L8:sC(fN"Bn1 R-Ew"P[7@;!U4Ra,cz08AM No WPZ eXF'oY݈O:ih^Rd\;gtEҀ+o>@yt|:8IܽxqJK&BϼR..ɡ>Q9{b#N$V`UYEM46#_q4_de *^M㨫7o4l؜"yFFn|=l P=ƽd5 UF*d,$ U)$sj rl3.֩/? #C֘H@A*16wi6,f5W'' " ;YSbM7w"Cl 39ځrn+cf7"9S y%@L-o3ah&jqX[j(r}J VWnC|K%ćׄn_>WP],-!gnۢm`_*ELS/I90Xʱ.)\-Nؽ> ֮?IӇa6VTe6 WpvW9##ҙPMIvz9֫$ *XK + #]F(("sJrnQDK(p=F<{(Sp-n Vy&G7r[|+[ylkͫ.'#-.oekC3D_a2ᔤjaH?y`I3p>ƫ[+iQA|kN+mAkT@wR#=iB7j)э,. +p4Q8m5B&S>0nuA|qVBnGzQmB mi{ _"Z\ -DJRh`ב5p"ɦYFB9riy&=rVuKS3|E ]w'yUXNJSU}S,y犖%r{} 7݊0[ J|pȜ.EW 2 ߛ:j o}]j-jP]BkzY fW˚K[\ďo}vjA K$M9Ҏ;_`LlZwRŴ@j(@Һ.rT&:BGQ5h?q_W:);4׷oMѦ^isj@c֎aC-bQװ`NĴڴD"4K=!ZР6$hO9t uFU #tZRիas::SH\ty @cO/1.F("7 D#lqa-.W2GIihB ๥KF̷:=G2:٦1 uLZፔ)44=ɹ.A4`WH@56 )͕S6T? Bk 0XM`y%1CD Ljyǿb4ayw3Vj~Gn)-/'Mj۾ӿiA|"20دEрŘh]2*tm,b}6?,˱IӇlm%JYi1\`vBO釦]$;Vi&JbٲdT~?Kq~-@̋]*& 2.޸zƂLTeXV=D[4-pT4';SD>9d%A腗? (cdQLp{!TWYWNtW;JaCʹ12״d)/x eAG:L/\5D0I;%{2-q 2Ho?,md;ݯD'?\t]%zBso&H#}Kf?Pԁut(RB(aV ;Eסܖ0fśW&ІgYgE8AbIIύ&4V3jw2J $ZŶV[ :qe*M'+OgMW{[Z9ʂ9]E K*44x3 a_bE^⣠nlSxlr* urnj-pqDo91®JxI}\G-](~Lo218RKAd%aZ6_mrEE!^²MѮ9 #3ad&ELp>T?}qYeݠvC6vՏ082R;G#Өeq4q1Tܭ?]#?`ЭΦ]*R 3c߹C!:`F96>ZEҢ 2A'""ٳ]1 Q)M^80r@p_EC !*p*U~%$2so&~5$AUʩtԈߘO2ZeVӵf:5m(Ogk i{K+M#4JW11^}U^=ါ4*J 6kC6\t`]^j]iyDg,.:8YD^У3gTylkfyP?N.20ГE( p$X4N6CwzK[ W'Md48Y ґ"}a"aDʰs<QF Z,2neJ[hGXÎgP5P'UڿGL܁Vk_3}(C`ϭ\ [(J+|t(SRb(𠩰_Ņst3.o,·.G/ry7mJr/#fCSGWSAl'Q_-täz?^Q_^ˆYUڰ[ZMp+:~_Mqz\}tG qOYQ љJ\),T! |pBRQ%e'mU4b\Pjxu[gTUvPT_ڠ6}$cPᲺSz ][x >Q\O!\^ 8Q[nKQZU7-%xp:f^jʮ=Ho[Ml5 B0oL^&inϛz?Tu_y ]?IwxZJ ҂7I= ^wGoYZ&!M䘸ހ$#cY{1N(m] ;hap2V\N@7LٿݴsIw2{' :EH2i>hUB %,HgR[}(;Jp֮_KH5`&9'.CG=m(Q~}ߊB()eНQདྷv>k<\S?}Pש.dgmFJ%Pa7ߑ֥7e|y5k+ ;To߸|pC6T񊩒S3tt'!.,q6\tfWvJ͐R;ȦX7.~y{`_,KuQDf,YͤaZ}^!tT\43˒7r6ҸæHRG2dN\ׂ_z[Mv$m(Lʢ3O{b}>xŦ+nl-jXT3@oy0/.߱f|=~=.Q|^s펳AZZ?\b\yRGtU\ ڹl~a>q9xuP`cq*/;?}H%;bfL[0hA" 71v˝hvӕgq?$IvߏzlM4$wss S?v[ܩ+dlt7ݏ 4QfѳX{\wnFxzҬg}#zWJny%$vp[[Lyƶ|ky[W6 Z9&Z==4/~2F("@.H7} @0#=*"s cЪ.fe̩zaҷ /* ӔqS]=)uh=,eh|Vv)KN&oGrO\}Uo(6p.%1*bXE/V+hS%[e-0M<R>ҜVfy)MA6mloN Ui 0IoXY2R՘7V*fN; gۈ09Լrqo呎*W4yLͪe46'[Yh}w2#IVrl%z(֜x(ĺa p tDn0v@VtuC1N̕ps_bğ߹nM?)4b_;וߝ2͝FlxZ=3-K;e!\Ŭf (_Zv-ߥO '`Hǵh6v+>DO#d,~3 5){"7G~k"XB.cDʲYu#ʰ8|0]_r.{-;T@,GHu`\Z(|ETQz-PO#Y((x9X k+qw>< q/N828MeջdMw*ئi٣]EQG%F49Lȗw穊4%_cpzQ fܕcb p`a2n ]Q+]-mI%@\J3TJ'eKߞQV ªWqZu:JP_ݓKL9AvYymzeO>jC.̄i0 P:b!»lcHis d ףж! 4vPkQFMXA >tH>ngP}uvqdеFh!vg@wifT~ar|t;|2u鎚\NE@6H+ӄڀ0(ǜk]+qՔ)R8#EIEjb)@jꂴICN y=}؄NG=E{lP#M{s6߳&O:̪A!C.m{qqNO-jE\ C7f*azU.U!s/^b)6o:WFRE,ˑ$kTrF'p\cqMAɾRoֿjMVR\(fF%fiՉ|ȇ'V _)ծ0a^qVWc׮`<M覑.M-ևs :-h'ɴ$=mr͚ṵwZr,dMEJZδi`@C|uإ<[+Ь%x eCג˺2RIBCOԵ ND@&kpF0[4-AUu77&yj;bR.]WL0JwGqM[{d1Q> 3hewJ)eȤ7`{<^%TΚ} 1-qa'LŘF]kaʸPPI?D$v#!O $vjw ENJ#w Iaz&-VqWRc$Z[_yX}W ߉Ô-DiCܞkuxL +lզv05|&X~[AM N9V{yxqֽn-O_F6|fk}o?Va;5xog?2-?B;OAOۖO(w[jEۂ cƍ{QHW \YO7l.z}j[ylxC2ŕ!8 ixNl]ĭJW5|Q#**,} |figM \peG򾇹n%"),D14:wOw肝8U7k55ja>]mG,> `$:nV}xDBP!\Ed8ĎǵѾ ivBW_JםgחD 7hP>𦈺q8\D6pSsCPiz]cfVV74KyUT둵FT {^kk=Jd^<-b8vc{Ez,͝ZƕLV׳fRjPeW_v1VPZt o弩 ġLT57+1r.HG~u w)_t;T4-~ŀ˵ :ԋ ;\Jh{b*v`WT Q7h^~ero`¾kth]CX$MU*o*<3yWɬB-3IQVd2=`%Q*7W}U:Gя}Bo$2pTMkzodLrbzFI v>ۉ\}{[guC8I) +0tSHM@ SV~N FaH/_)BO\8/LP?h)5RƎ9-8ER+{F"%"4mmZyA1U@g?C@Sṳ/cNCv|hQZ2dGk({! .*=C׀k}F[G *c2UG tN+_vջP5^?H nEGz roڅ7֊߷c҄6j+@A+x_q*"rZ f"Nnw,=siPγ5̱^ DZ iPh`c[ +lYLc=p=C4ϮaLDH١`Kqxbjhk'$YVͳk"IQ)% ƙXk f(]I6-.^tkb9_c7X%HaB0E 5eMe=~.3p}52:y%ȱf4ojK98 0qXHzm]MGq \fdo*lH3'WAȪ2i'v( NF7L jc>)K<nP.gS"H*&5N؃ӿ 8{0Ѣw*䑡'~w`VLcSVgd\ocf.N^14:V[-F~o( }ۍپW#ѽ7nRnOpO0OypӱE"X ̀P(02b":r[`"i (mwsS뒐UD=U(69͝vRNDvU Ǧt"SǸB%Aޟ@Q_^3-Ŕh.ֻm=q@k\됓tvU/Aath 0n^ $.x].;U=Sy yF,Oz4\w,ۥő&Z~~$1y^r3Ā?dN]Ÿ7i;$F.=)w%V~%4dK-U;Bg9t *=q Z&u-y W[ʥIB&KۢRzU|k#ͪl۶Q{L?{+aYʗEQYOu8TJL<@iŽؓ rQ^ x pk Ks u W $K|yO"&h.v[1[~+*vw~Tiwu>d-Jy] 8-&ד(~@ClR {ԑcGUJG;" 7TtPo(ٍ/?*=Q٬MECvcڝ}NL pm; , 0lo﵁[Ga9Z|P@;ğ)ÆYpza E.Nl($ Hb&߹AT.(0GniF,.F"ǮDe;RTx^a|ڵ5#5#pg10=إ("դ6W{"P bE [&n '%4EŽt{h_}](SY7i8*wLYA, ܝt4m))WMDcvFS+ _0 yK68mhսuRWL8\v9,_XfA}-8o {KKw! `voK^R-$)NN+d}V؂6c'?E.vz `X ,Zg1{WD& }kfJ]ٚh= U!(8T*q5隿 U]z!9{r'Xl WrmS!*`8#UR>L?,y:yfBՀ) ]JS*Ȅob0}&җ+JOt((jWRK}}79#t': ,L];DcV?ŞO5j/@pFP(TpJL>4hEJ.#Z8ZnXvW,LzKf'-F,{*+d؏Z ]m̀dF n)6Rÿd^;h70k긡 o`޼ 6i2v'vn- $"2O@co+Yw =TaMn"e}"@(kqQJQO4"/LD W\='@Gqޯj+\/ݳG0y7ϏO<:fSixPYbJ$4 ֊̖5yYL*bew*KO I2qn~m6?O#Ueh h뜠=CNS-'82IOs(.qڄM%"܉ !JnE]-e1 SM}riT0/cZ"t'`E&N뇜d/SbS;^iÅlmgi7>eH~AyuEc]f|~:Lݏ 'W?cPdml{@L7T߼UgQ- Eܖ)`g*7Jh#MO *H/%W 5rF:w*ۇ9φBXf zšgA!ȣe~X 9A`X$Qtd^2rWok1Zۂ"UjP뵎6Ce՚܇ I1]{ q~[euX2N[u < } <% ߌSciر}dI†{u;Pp2/iD\:F̩*t9`W 4,A8bBW嚆F2}e (oRCꆨT:+aIYkW UCuZ@$-`zԓ9PU%ҚqpfoM̲ad7R>Ev(PDEJ})m;TsĘ eat8̞aGnnnAOOX@$%ٝtLύp1jO'3l\Ss! JTAy? y[DSZ.MM"1L<$aflli[]VP;)?j\5Bn3_XFmÝR1eUۚigFmb>^$eiM%e4#6},Y B~+a&G(gT\^*J_hsxi(L.'ɑi;s]123)MRV ^ᔮ5x܄ϲ/l.q戴s/Dw9TDe~0 tDü^NI3, ~G\D:n9\՜TFI(6PƊIގinMjF8m;d0N2ц/?Q|/d" ?(T3<-s=G`Daȍo|Ӷ;*U#?Ԍ)6%"4[:f5ɠ.f4g .v܂'4ne$s1z%v&l MAjBgY*ީY F#A7!U j"c 44R!*(`~eOg݉+U x3?~l?r@A,tfA: {=ls1Ey.yRTuZXFxoXŞ y?O+G9Ƶ.e/׈"esz$B Րi3D쇫I^2_Į748{I`蹳$LdZ慓L\l&+cF7ػuB&NN7[g?0¿!9f}aP@$zkG3g=w?pV\Y}uC{?xm&m2@'1M=^m*UcZ(}?8CxtƎ^SQ/0@}\ Ut^ sWO8"ToN{<.bwx@CJ8,|M1͠-4}GkEp$Fk%: K>wRN_`CzJ*n0ށa;9կ}D޶`M.X+d*$G6q\/L>8wo[+bNdMs4fĶd3bSt"K_c+ pq2of?f๿W^؆݃o?7߼85ŸFR9 BmĎ`_xmsW }3RKb6Oaww'TUJ̚, uLL& <fױ,kZV`Z(D_K{y%pl̺EUs=~~H QHUF}24גɎԏ[ak4"?x?!9 `SO_E'KW_|uW߼:xW^<=xW{v&0ʜm~ JIk-iw׺e\{q7p FxuOKA>z cm}QSM+ipR*ܣ' 'Bק'&_>c(Fq۟Ek0D <Е,d~FWP'Tmv垤0ӯ ]!JF^2Dԫ;@&7{u?R*f$%(^bk#9Ϳ{⋗w-?ō=[s)x :ZA!#|!{a}@t u[c ݁e5NJ $5| N C9?ؓ'9\=~kFmF7q6d]EhHކO%HIOqIT^E{';0Dt=J!$6Tr$/k|"2ߓ xKƈw>ҷQPx̞8`?Qg;s1d׍Pz}mfv\6_e)EN ʖR@~ڍ:${T ǀ#T#39n02߾)]hP$5^}Ĺ#-b Egű+SdcJjP#KC@l E)KpkvT b~zCsҧ'զ%㵟nF_Tվ ű~yq́{VUXGWrټ%K:#65Q%W)vu9x.֎4mqΔjBee1Lg#VPȏ|z$/;'_bn$'i8Rh2 vyKw"wjlPm햟VWE)}D^U@&jz9nsCk㘪ԨlK|>pA)C<$Tb']i ؤ^~)+,3NcPwه18BcΎQэMCG?eRA폴.DC`Q&(I}=b<@آ oOJ(gxCЋ5Qh&d %Qb;:͎1 " 2i\f-aꢀVBs$ &=ݨg/DSkԇM޿ c ¶Oo(a4z@++0Pw4SV\kwt&P!7Rgt:WiJbBGwtS.wo m =|w \SE4iB # `h%I@?H_MQز ]F[ _;(4_I/*SBMx(<c8 +䌲MHf|rec\R|Z*?RǭRdB8w^z< w{8pӨOhOmMMn| 6O miGDj?f3+#TR/AT7\:MB)IQOuAD}SCA{ |z7 0R;XS5U=gQ^gg^t%wELg=,lo@*10P7.ޱ-/C|7!Wߕ;LdrOuG3@WKl$GO`Nb0ajG(nb!w]}S+wXwova5 AL-I*mF~#K݈$mvlh;pd8)ZV?mRM C͊ k勂 U5-5*uW*YC  {G9Au<IJ:r#-uJݦB cC5Հ|9Ts!wa&LZehYIT|ITwER&K"隼t-0^k#&tg*Bzظ$ Z5a*5* U5-5*5XP,Ver,1CrJ)yz˾3u %)ȼT'>|3؇0*pxmL0 S;QrmQ?̀Mퟻe4,.=J.jngᄅ.3A~sR4 F2d$✜ 'ۛ'tt؇$>VExtmǏ!dl5Lω=٦\gׂʰ ʸ mMR7 Ɨ,0#QL;ِgHV}/ƅ|s !Sz6GӂL"-1"'.fTۺtreqX@}KqG.ƑnEba-A>܋}lZ^u|xݦAԕ>%%z9O6U)xz^z<]ϓU}/^& VykSk80,i/*fؒBC"x~[Sn1ISF;3PD~EXbf~7 \VW86^ɽ)ݘXs%/q:CyI3>KeHi-4Z/C^xi s0p\f„߰:/$޲;D]k*:2<kioR ?\maGt34OTkg .H]Ș`| r~cU9yP=]_QhZI* Ι\炝8$߁CzX}f?}p+]Vc>[yLZ4524^i\U;kl͎Ш2{.S*],gC=iL8}a5$DwXs/by8qm]Ⴚ`a!u~Fl(N*2˰ͪ\x?T$C8IE!&NANeQGL;C,y3sȅ7h_P1;ŚcyvNF2˜/%s،zY(*!PE B;`5!I#K~^o0bmrQN|-lj󯽨X/KM҅0Cpܖ>l^+AM5aK^=d̒oˁ`盢}ƴשa=āH~XTUtHMiQYtP>,'MϞ'T`~O8Bu\S%KadU#C&檶@x희Pg<>ڐ0}++YHcMeZOZgܓ.#siM۹cάz웬J@)PqMHzSz~iT\K.KvVfh!w4p|+>R; ZFC]yvi%=U?tRŸ\^ vi  *&\`郈};oiV>vEUMT_ qH ;Uϲe2n{ , k*dzyv*YN]ݱ=.!=҉Qt. ǿ%RБ9p "MRR\j$iǹK3s7)lw' DΐDAGf1|ٹ=3m0 ijiD3?4'j[&%(yڽ`ʂGbz7G"1ODž +HI ^S*Pw2U#w͛[.e[*վb9L '鯸2O,oHɜ3ư8v]cN){kadR'G*'~}F-8N3eUcŸFpQ3c/XQ2/C53o+w׼;KD$GK)aIhʌ&z׵y.KxNYy9] )!' ~1# jͥP9+n^iT0mr)!/rlMi%es)̺[>ټyְ?PBVgji wڿ@,Nޙhe__FQvUJÑFhU'R}>Xcե]rFV.dmDz}u| uqg a%´Vу zEOȘ8I1X#hXJ|{݂׊oPSihl*Wěwjz5KC&#h(dɟ7VUa/a6~J;4h~ˢ/nqz؛Gjħ? ͋?I -׳GalEĨW#8'؁vO+.cq*}$h(ڟ5鐙ÈteC*F"bߵ@~ uޑ=Z|^Z(> 8`V>Gc8G<KT@q0Sak9'cq2뭛Y9ͬ~y~ _msH*ӢQ CBTvbRLmt%b1>}4[觀=SC5 .ј2~>[)|p ?mAħA'=U4V&ƨ܏w pׯo/0["~OdqH_AIzʗB=) 6{Es#MqJ)ѧ?OU9͕̥* ׵^9zȡ|1̏zRIђǪ)W6vm*}ק,|mXI)lB ,`t}$듬'J}%{as2}>zMx=$({1wh"n:(J0S{8FQ J&B{}-tW6 vn59!{YA@zD^IR?b ImIz΁Z͞ ]l8DʓbA_Zl̴ Cf3(;yuR wRI0p/K䄖,8q?įy̞)DuK/"'2i2I5'$6k[vզ°,\*lo]UXAm@ߋ/$2~yV)&,x#v)MiLpr݀_Z2Bj+bTh&i` "xE·&)z޾&dDt9l~O K`nV)ta[J/H~G I#!G'sCVVC1D=ζ| OUE[\MbH PFEpꚕx4s w)c&/#uiKmUu:PZ (t,g+E.?8t~+?{82qj n;)iᾆLF$$<).c&@7"{Ͳ4S^ zD3O0:^CF|6<Ȉ2Ny&;]ae<9-x1ɾEP."U>!A$*۽a''$2IH'63/cVK^#B~ٿeEDţmр$wqѧ'~鉂:Ȝ&zn4.At)tط; ?g*a3/DSq0zR@!ڜ Rf=+mD~dhy,{A^km \f|)jc="Jp?MA_&5 }gᑩ/,BLaύfa. BTLɐ+f]&PPCE'<B,Vd_ ?s!ʥ1sݥ3JWa cd\\Ugdk@+1qoxb;zAj%fhqq& 6WMA%⺿ȒOBV[ .F5>K[Ŭ YI҅Bډm `,-ɢ]v&f2_Z'(T M8348bv?L"Ȗ]ww_ԕwtfC,vW)]T$9%xOl;)^2v]?A9Jc`X I1g <%r@ݓ%ִYp p|i:C*(5=KB߫5't[/bqbt}&.u!Kxl 6Q^9[$jƆ4[h!haY7ԾPO 7Mw8J4 9`#Rމ}퀝4`)T?r׿3̱uḺ)fEIy.Lx/64~nRu+5jk1^9RcSjz]$dY A.frFƊkx$I"@+>=xGÕAp128(9bLBܡULpQޘǂ15_pSW(V8}z4^$H) )iv[ht>=1!! {BIrk*VpYw$!bpG¤+xzU(]RyF &K]K,V'2-"8#>Hj.b z^MW+TfS7 ~D⥾9^O-'J"'Q !''b! ~O(~ 4NySa \P;z\cUr7oqIeN^t5#[+`'d&95i( IN7'ϕ9_X7jQuK&t+#'Np!F[AհQ%Nc A ]cu_!]_?VKF*0kݫ;v'H޻GHGUS[ Is'Tn b?FN 1$&9 '*z@lL8F1ff(IhUdGO7AHy\OE)mbyi y@]uESd}.T$C5}f XEҽ!Gka2dp1BC TФ5:bnD{g&.n=dA `-uJ|D9t&-6{Mg礈N+õ5`6Ogڡ_c*^3ȎDTUSHT|P 38x>ɀ0I]䉼x6YRS){ZtW';2kqg8`eqZE֤hme?2Hm,H~☌ 2z lnOyH JAu <3i|2Bo͏)̞6r/&0p&J] @H(2c0PY~ ]ey4$қ:#K! jh&SX>@70}v/%eV}/ƾh8mabɬ2&CqP+.-B;*oieOݵD8;M<&3Z/g"/8ɖ&6MPRbP[pB N}K`e+Z*L (Լga߰gTQa$TDjQiM"hgsj$["MxpwmD]c u7AF/Y@r׷ 4ҀK e@$ގ/BE:xF0Nxc*1uUy$)q*F7N)pg/nF{z3B7]p/7#`x)6%T`ZƷ՜v[UZr+Q[P.d13pD8 "Utv>Q1aޛ/!-4򂨜p(ij}z*ZJD?GSglk (_09/ΎCE~pyR U[̏pgiB}j~^zwf'$c ȴ>tAHeb$`%VśYo클bQC jWikW}k]]>EsAWwXSVE%aEHﵞ_Txm(ʘ=1Ak\ja 5A0iz“o%'6+ȈҲGs*х) (:Y Oɣxa}" ͠%@, IL3s 5^{~t" W,_FT2 uN,B_M\z)lQ،4*0BR Bnii8{O=ɢ_Uh-wͷA'#;!Pk} $+:H8MD|zmIv/y[JFxRGe\~XޡouٿFv|d2>Ĵ]7&@#l'J>= +|%V#{uؕ ,7gm=E!Ma#cQ (ɕ-HIc/ڮ i.DRđ(RU)DYΧ[H>}!wT6;;|dM=rxs$w4pPVP{YmNl`;3:IEkSy VM1C[wLåi3AءG7IԤR=R-1,ubɹL@@? ~ဏ* am)d