packages feed

movie-monad 0.0.4.0 → 0.0.5.0

raw patch · 41 files changed

+2849/−1007 lines, 41 filesdep +bytestringdep +haskell-gi-overloadingdep ~gi-gtkdep ~haskell-gidep ~haskell-gi-base

Dependencies added: bytestring, haskell-gi-overloading

Dependency ranges changed: gi-gtk, haskell-gi, haskell-gi-base

Files

CHANGELOG.md view
@@ -2,6 +2,38 @@  ## CHANGELOG +-------------------------------------------------------------------------------++### 0.0.5.0++#### Added++- Repeat mode+- Custom icons for new bottom controls+- Custom styling for new bottom controls+- Added a one second fade in animation for the bottom controls+- Added extra error checking around window width combo box selection+- Mac install script++#### Changed++- Tooltips+- Use a SVG icon instead of PNG+- Fixed video info being changed before selecting a video+- Use play and pause image widget names to determine state of the play pause button+- If the user sets the window to a custom size, select nothing in the window selection combo box+- Set timeout for hiding the bottom controls to seven seconds instead of five+- AppImage meta data+- AppImage install script+- Snap packaging+- AUR packaging++#### Removed++-++-------------------------------------------------------------------------------+ ### 0.0.4.0  #### Added
README.md view
@@ -1,43 +1,47 @@ ![Movie Monad](https://i.imgur.com/gdsyIMv.png) -# Movie Monad--A free and simple to use video player built with Haskell.--## Screenshots+# Movie Monad? Another video player? Really? -### Linux+Yes really.   -![GUI showing "Caminandes 3: LLamigos" from the Blender Foundation](https://i.imgur.com/aYf6XOB.png)+Movie Monad is a free and simple to use video player made with Haskell.+Originally it was a proof of concept to add video playback to+[Gifcurry](https://lettier.github.io/gifcurry/) (another great app—check it out).+Nowadays it's a lightweight yet mighty media player used all over the+[world](https://snapcraft.io/movie-monad#js-snap-map)+everyday. -![GUI showing "Sintel" from the Blender Foundation](https://i.imgur.com/UBNYbER.jpg)+Movie Monad is cross platform so you'll never have to compute without it.+You can play files on your computer or stream videos from the web.+Play, pause, seek, repeat, resize, expand, and turn it up—Movie Monad gets out of+the way so you can watch the videos you love. -### Mac+So put down your copy of mpv, VLC, or Elmedia and try out Movie Monad—it's FREE! -![GUI showing "Big Buck Bunny" from the Blender Foundation](https://i.imgur.com/Tgmk7SW.png)+## What does Movie Monad look like? -![GUI showing the About window as seen on the Mac](https://i.imgur.com/pTJLQdM.png)+![Movie Monad](https://i.imgur.com/0zjy4xz.gif)+![Movie Monad](https://i.imgur.com/0SvqTpp.gif) -## Features+## What can I do with Movie Monad? -* Local or Remote Video Playback-    * `file://`-    * `http://`-    * `https://`-* Window Size Quick Select-* Responsive Window Resizing-* Fullscreen Mode-* Seek-* Play and Pause-* Volume-* Subtitles-    * Disable-    * List and Pick from the Available Languages-* Command-line Play+* You can play video files from your hard drive or stream videos from the web.+    * To play web videos, click the file open button, paste the URL into the text box, and click open.+    * Movie Monad can handle `file://`, `https://`, and `http://`.+* You can play and pause.+* You can seek/scrub through the video.+* You can put the video on repeat.+* You can turn subtitles off or on and pick your language.+* You can turn up, turn down, or mute the volume.+* You can expand the video to fullscreen.+* You can quickly resize the video to standard sizes.+* You can resize the video to a custom size by resizing the window.+    * Movie Monad will responsively adjust the video size to fill the window.+* You can play videos from the command line.     * `movie-monad ./path/to/video/file.mp4`     * `movie-monad http://www.domain.tld/path/to/video/file.mp4` -## Keyboard Shortcuts+## What are the keyboard controls?  * Mute/Unmute     * `m`@@ -46,6 +50,8 @@     * `f` * Show Controls     * `c`+* Toggle Repeat+    * `r` * Volume Up     * `ArrowUp`     * `AudioRaiseVolume`@@ -60,152 +66,111 @@     * `Space`     * `AudioPlay` -## Tested On--### Linux--* [Ubuntu 17.10](https://www.ubuntu.com/desktop)-* [Ubuntu 16.04](https://www.ubuntu.com/desktop)-* [Ubuntu 14.04](https://www.ubuntu.com/desktop)-* [Linux Mint 18.2](https://linuxmint.com/)-* [Deepin 15.4.1](https://www.deepin.org/en/dde/)-* [Manjaro 17.04](https://manjaro.org/)-* [Antergos 17.10](https://antergos.com/)-* [Fedora 27](https://getfedora.org/)-* [Solus 3](https://solus-project.com/2017/08/15/solus-3-released/)--### Mac--* [macOS Sierra 10.12.6](https://en.wikipedia.org/wiki/MacOS_Sierra)--## Dependencies--### Run--* [GTK+ >= 3.10](https://www.gtk.org/download/index.php)-* [GStreamer >= 1.0](https://gstreamer.freedesktop.org/download/)-    * [GStreamer Good Plug-ins](https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)-    * [GStreamer Bad Plug-ins >= 1.8](https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)--### Build--* [Haskell](https://www.haskell.org/platform/prior.html)-    * GHC == 8.0.2--## Install & Run--### Linux+## How do I get a copy of Movie Monad? -#### AppImage+Movie Monad works on Linux, Mac, and most likely Windows.+Make sure you have GStreamer and GTK+ installed on your machine.+To find the latest version of Movie Monad, head over to the+[releases page](https://github.com/lettier/movie-monad/releases). -##### Download & Run+### I use Linux. -```bash-# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)-# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)-# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)-# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)-# Install Wget (https://www.gnu.org/software/wget/)-# Visit https://github.com/lettier/movie-monad/releases-# Download the latest AppImage movie-monad-0.0.4.0-x86_64.AppImage-wget https://github.com/lettier/movie-monad/releases/download/0.0.4.0/movie-monad-0.0.4.0-x86_64.AppImage-chmod a+x movie-monad-0.0.4.0-x86_64.AppImage-./movie-monad-0.0.4.0-x86_64.AppImage-```+If you use Linux then the easiest way to grab a copy of Movie Monad is by downloading the+[AppImage](https://github.com/lettier/movie-monad/releases/download/0.0.5.0/movie-monad-0.0.5.0-x86_64.AppImage).+After you download the+[AppImage](https://github.com/lettier/movie-monad/releases/download/0.0.5.0/movie-monad-0.0.5.0-x86_64.AppImage),+right click on it, select permissions, and check the box near execute.+With that out of the way—you're all set—just double click on the AppImage+and Movie Monad will pop up. -##### Install+You can also download and install the+[AppImage](https://github.com/lettier/movie-monad/releases/download/0.0.5.0/movie-monad-0.0.5.0-x86_64.AppImage)+using the handy+[AppImage install script](https://raw.githubusercontent.com/lettier/movie-monad/master/packaging/linux/app-image/movie-monad-install-app-image-script.sh)+(right click the link and select "Save link as...").+Download the script, right click on it, select permissions, check the box near execute, and double click on it.+You should now see Movie Monad listed alongside your other installed programs. -```bash-# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)-# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)-# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)-# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)-# Install Wget (https://www.gnu.org/software/wget/)-wget "https://raw.githubusercontent.com/lettier/movie-monad/master/scripts/sh/install-app-image.sh" -O "movie-monad-install-app-image.sh"-chmod +x "movie-monad-install-app-image.sh"-./movie-monad-install-app-image.sh-```+#### I use Arch/Manjaro/Antergos/pacman. -#### [Arch/Manjaro/Antergos](https://aur.archlinux.org/packages/movie-monad/)+If you'd rather install Movie Monad via `pacman` then copy the following into your terminal.  ```bash-cd-# Install Git (https://git-scm.com/downloads)+cd "$HOME/Downloads" sudo pacman -S git-# Install Movie Monad from the AUR (https://aur.archlinux.org/packages/movie-monad/)-mkdir -p movie-monad-tmp-cd movie-monad-tmp+mkdir -p build-movie-monad+cd build-movie-monad git clone https://aur.archlinux.org/movie-monad.git cd movie-monad makepkg -sic+cd "$HOME/Downloads"+rm -rf build-movie-monad cd-rm -rf movie-monad-tmp movie-monad ``` -### Mac+#### I use Ubuntu/Mint/Debian/Deepin/snap. -```bash-# Install Homebrew (https://brew.sh/#install)-cd ~/Downloads-brew update && brew upgrade-brew install git-git clone https://github.com/lettier/movie-monad.git-cd movie-monad-brew cask install haskell-platform-brew install pkg-config libffi libav libsvg librsvg libogg libvorbis openh264 theora \-  gobject-introspection cairo gdk-pixbuf gsettings-desktop-schemas gtk+3 gtk-mac-integration \-  gstreamer gst-libav gst-plugins-base gst-plugins-good-brew install --with-gtk+3 gst-plugins-bad-stack setup-stack install hsc2hs-stack install-export PATH=$PATH:"$HOME/.local/bin/"-movie-monad-```+Movie Monad is available as a snap from [Snapcraft](https://snapcraft.io/).+If you don't already have `snap`, go ahead and install it using the command `sudo apt install snapd`. -### [Hackage](https://hackage.haskell.org/package/movie-monad)+You can install the+[Movie Monad snap](https://snapcraft.io/movie-monad)+right from your browser or via the command line.+For the command line route, paste the following into your terminal.  ```bash-# Install GObject Introspection (https://wiki.gnome.org/action/show/Projects/GObjectIntrospection)-# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)-# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)-# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)-# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)-# Install Cabal, GHC == 8.0.2 (https://www.haskell.org/platform/prior.html)-# Install Cabal Install (https://www.haskell.org/platform/prior.html)-cabal install movie-monad+snap install movie-monad+sudo snap connect movie-monad:mount-observe+sudo snap connect movie-monad:removable-media+sudo snap connect movie-monad:raw-usb movie-monad ``` -### [GitHub](https://github.com/lettier/movie-monad)+### I use Mac. +Mac users can download and run the+[Mac install script](https://raw.githubusercontent.com/lettier/movie-monad/master/packaging/mac/movie-monad-mac-install-script.command)+(hold down control, click the link, and select "Save Link As...").+After running the install script, a shortcut to Movie Monad will be on your desktop.++### I'm a Haskell developer.++If you develop Haskell programs then the easiest way to build Movie Monad is with+[Haskell Stack](https://docs.haskellstack.org/en/stable/README/).+Copy the following into your terminal.+ ```bash-# Install GObject Introspection (https://wiki.gnome.org/action/show/Projects/GObjectIntrospection)-# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)-# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)-# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)-# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)-# Install Git (https://git-scm.com/downloads)-# Install GNU Make (https://www.gnu.org/software/make/)-# Install Haskell, GHC == 8.0.2 (https://www.haskell.org/platform/prior.html)-# Install Haksell Stack (https://www.haskell.org/platform/)+cd "$HOME/Downloads" git clone https://github.com/lettier/movie-monad.git-cd movie-monad/-make-make install-make run+cd movie-monad+stack update+stack setup+stack install alex happy+stack install haskell-gi+stack install+stack exec -- movie-monad ``` -## Developer Documentation+## What dependencies does Movie Monad use? -[Let's make a GTK Video Player with Haskell](https://lettier.github.io/posts/2017-08-30-haskell-gtk-video-player.html)+### To run Movie Monad. -## License+* [GTK+ >= 3.10](https://www.gtk.org/download/index.php)+* [GStreamer >= 1.0](https://gstreamer.freedesktop.org/download/)+    * [GStreamer Good Plug-ins](https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)+    * [GStreamer Bad Plug-ins >= 1.8](https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html) +### To build Movie Monad.++* [GObject Introspection](https://wiki.gnome.org/action/show/Projects/GObjectIntrospection)+* [Haskell Stack](https://docs.haskellstack.org/en/stable/README/)++## What is the license?+ See [LICENSE](LICENSE). -## Copyright+## Who wrote Movie Monad?  (C) 2017 David Lettier   [lettier.com](http://www.lettier.com/)
makefile view
@@ -3,50 +3,63 @@  .RECIPEPREFIX != ps -STACK=stack --allow-different-user-STACK_SNAPSHOT_INSTALL_ROOT=`$(STACK) path --snapshot-install-root`-STACK_SNAPSHOT_INSTALL_ROOT_BIN=$(STACK_SNAPSHOT_INSTALL_ROOT)/bin-STACK_PATH_LOCAL_BIN=`$(STACK) path --local-bin`-STACK_GHC_EXE=`$(STACK) path --compiler-exe`-STACK_GHC_BIN=`$(STACK) path --compiler-bin`-STACK_PATHS=$(STACK_PATH_LOCAL_BIN):$(STACK_GHC_BIN):$(STACK_SNAPSHOT_INSTALL_ROOT):$(STACK_SNAPSHOT_INSTALL_ROOT_BIN)-CABAL=env PATH=$(PATH):$(STACK_PATHS) $(STACK_SNAPSHOT_INSTALL_ROOT_BIN)/cabal+_NAME="movie-monad"+_STACK=stack --allow-different-user+_STACK_SNAPSHOT_INSTALL_ROOT=`$(_STACK) path --snapshot-install-root`+_STACK_SNAPSHOT_INSTALL_ROOT_BIN="$(_STACK_SNAPSHOT_INSTALL_ROOT)/bin"+_STACK_PATH_LOCAL_BIN=`$(_STACK) path --local-bin`+_STACK_GHC_EXE=`$(_STACK) path --compiler-exe`+_STACK_GHC_BIN=`$(_STACK) path --compiler-bin`+_STACK_PATHS=$(_STACK_PATH_LOCAL_BIN):$(_STACK_GHC_BIN):$(_STACK_SNAPSHOT_INSTALL_ROOT):$(_STACK_SNAPSHOT_INSTALL_ROOT_BIN)+_CABAL=env PATH=$(PATH):$(_STACK_PATHS) "$(_STACK_SNAPSHOT_INSTALL_ROOT_BIN)/cabal"+_CABAL_SANDBOX_DIR=".cabal-sandbox"+_APPLICATIONS_DESKTOP_DIR="$(_CABAL_SANDBOX_DIR)/share/applications"+_ICONS_HICOLOR_SCALABLE_APPS_DIR="$(_CABAL_SANDBOX_DIR)/share/icons/hicolor/scalable/apps"+_PACKAGING_LINUX_COMMON_DIR="./packaging/linux/common" -export PATH := $(PATH):$(STACK_PATHS)+export PATH := $(PATH):$(_STACK_PATHS) -all: setup build+all: install  setup:-  $(STACK) setup && \-  $(STACK) update && \-  $(STACK) build alex && \-  $(STACK) build happy+  $(_STACK) update && \+  $(_STACK) setup && \+  $(_STACK) install alex happy && \+  $(_STACK) install haskell-gi -build: setup-  $(STACK) build+cabal_update: setup+  $(_CABAL) update -install: build-  $(STACK) install+cabal_sandbox_init: cabal_update+  $(_CABAL) sandbox init -run: install-  $(STACK) exec -- movie-monad+cabal_clean: cabal_update+  $(_CABAL) clean && \+  $(_CABAL) sandbox init && \+  $(_CABAL) sandbox delete && \+  $(_CABAL) sandbox init -build_sdist:-  $(STACK) sdist+cabal_install_dependencies: cabal_sandbox_init+  $(_CABAL) --require-sandbox install --dependencies-only --force-reinstalls -j -w $(_STACK_GHC_EXE) -cabal_update: setup-  $(STACK) build cabal-install && \-  $(CABAL) update+cabal_configure: cabal_install_dependencies+  $(_CABAL) --require-sandbox configure --enable-relocatable -w $(_STACK_GHC_EXE) -cabal_clean: cabal_update-  $(CABAL) clean && \-  $(CABAL) sandbox init && \-  $(CABAL) sandbox delete && \-  $(CABAL) sandbox init+cabal_build: cabal_configure+  $(_CABAL) --require-sandbox build -j -cabal_install_relocatable_executable: cabal_clean-  $(CABAL) sandbox init && \-  $(CABAL) --require-sandbox install --dependencies-only --force-reinstalls -j -w $(STACK_GHC_EXE) && \-  $(CABAL) --require-sandbox configure --enable-relocatable -w $(STACK_GHC_EXE) && \-  $(CABAL) --require-sandbox build -j && \-  $(CABAL) --require-sandbox install --enable-relocatable --force-reinstalls -j -w $(STACK_GHC_EXE)+cabal_install: cabal_build+  $(_CABAL) --require-sandbox install --enable-relocatable --force-reinstalls -j -w $(_STACK_GHC_EXE)++applications_desktop:+  mkdir -p $(_APPLICATIONS_DESKTOP_DIR) && \+  cp $(_PACKAGING_LINUX_COMMON_DIR)/$(_NAME).desktop $(_APPLICATIONS_DESKTOP_DIR)/++icons_hicolor_scalable_apps:+  mkdir -p $(_ICONS_HICOLOR_SCALABLE_APPS_DIR) && \+  cp $(_PACKAGING_LINUX_COMMON_DIR)/$(_NAME)-icon.svg $(_ICONS_HICOLOR_SCALABLE_APPS_DIR)/++install: cabal_install applications_desktop icons_hicolor_scalable_apps++build_sdist:+  $(_STACK) sdist
movie-monad.cabal view
@@ -1,13 +1,13 @@ name:                 movie-monad-version:              0.0.4.0+version:              0.0.5.0 synopsis:             Plays videos using GStreamer and GTK+.-description:          A free and simple to use video player built with Haskell.+description:          A free and simple to use video player made with Haskell. homepage:             https://github.com/lettier/movie-monad license:              BSD3 license-file:         LICENSE author:               Lettier maintainer:           Lettier-copyright:            2017 David Lettier+copyright:            (C) 2017 David Lettier category:               Application                       , Multimedia                       , Multimedia Player@@ -21,10 +21,19 @@                       , stack.yaml                       , ./src/dev/Paths_movie_monad.hs                       , ./src/data/gui.glade+                      , ./src/data/style.css+                      , ./src/data/style-3-18.css+                      , ./src/data/style-3-20.css                       , ./src/data/movie-monad-logo.svg-                      , ./src/data/movie-monad-icon.png+                      , ./src/data/movie-monad-icon.svg+                      , ./src/data/about-icon.svg+                      , ./src/data/play-icon.svg+                      , ./src/data/pause-icon.svg+                      , ./src/data/repeat-icon.svg+                      , ./src/data/fullscreen-icon.svg                       , ./src/Records.hs                       , ./src/Constants.hs+                      , ./src/Reset.hs                       , ./src/Window.hs                       , ./src/CommandLine.hs                       , ./src/Keyboard.hs@@ -40,13 +49,22 @@                       , ./src/VideoInfo.hs                       , ./src/Playbin.hs                       , ./src/Uri.hs+                      , ./src/CssStyle.hs                       , ./src/Utils.hs                       , ./src/ScreensaverAndPowerManagement.hs                       , ./src/c/gst-ffi.h                       , ./src/c/gst-ffi.c data-files:             data/gui.glade+                      , data/style.css+                      , data/style-3-18.css+                      , data/style-3-20.css                       , data/movie-monad-logo.svg-                      , data/movie-monad-icon.png+                      , data/movie-monad-icon.svg+                      , data/about-icon.svg+                      , data/play-icon.svg+                      , data/pause-icon.svg+                      , data/repeat-icon.svg+                      , data/fullscreen-icon.svg data-dir:             ./src/  source-repository     head@@ -54,8 +72,8 @@   location:           https://github.com/lettier/movie-monad.git  executable            movie-monad-  main-is:              Main.hs-  default-language:     Haskell2010+  main-is:            Main.hs+  default-language:   Haskell2010   build-depends:        base == 4.9.*                       , filepath == 1.4.*                       , system-fileio == 0.3.*@@ -65,18 +83,21 @@                       , process == 1.4.*                       , MissingH == 1.4.*                       , network-uri == 2.6.*-                      , haskell-gi == 0.20.*-                      , haskell-gi-base == 0.20.8+                      , bytestring == 0.10.*+                      , haskell-gi == 0.21.*+                      , haskell-gi-base == 0.21.*+                      , haskell-gi-overloading == 1.0                       , gi-gobject == 2.0.*                       , gi-glib == 2.0.*                       , gi-gdk == 3.0.*                       , gi-gdkpixbuf == 2.0.*                       , gi-gst == 1.0.*                       , gi-gstvideo == 1.0.*-                      , gi-gtk == 3.0.18+                      , gi-gtk == 3.0.*   other-modules:        Paths_movie_monad                       , Records                       , Constants+                      , Reset                       , Window                       , CommandLine                       , Keyboard@@ -92,9 +113,10 @@                       , VideoInfo                       , Uri                       , Playbin+                      , CssStyle                       , Utils                       , ScreensaverAndPowerManagement-  hs-source-dirs:       ./src/-  includes:             ./src/c/gst-ffi.h-  c-sources:            ./src/c/gst-ffi.c+  hs-source-dirs:     ./src/+  includes:           ./src/c/gst-ffi.h+  c-sources:          ./src/c/gst-ffi.c   ghc-options:        -rtsopts -with-rtsopts=-N -threaded -Wall -freverse-errors
src/About.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -14,26 +14,21 @@  addAboutHandler :: R.Application -> IO () addAboutHandler-  R.Application {-        R.guiObjects = R.GuiObjects {-              R.aboutButton = aboutButton-            , R.aboutDialog = aboutDialog+  R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.aboutButton = aboutButton+          , R.aboutDialog = aboutDialog           }     }   =-  void (-      GI.Gtk.onWidgetButtonReleaseEvent aboutButton (aboutButtonReleaseHandler aboutDialog)-    )+  void $+    GI.Gtk.onWidgetButtonReleaseEvent+      aboutButton+      (aboutButtonReleaseHandler aboutDialog) -aboutButtonReleaseHandler ::-  GI.Gtk.AboutDialog ->-  GI.Gdk.EventButton ->-  IO Bool-aboutButtonReleaseHandler aboutDialog _ =-  void (-      GI.Gtk.onDialogResponse aboutDialog (\ _ -> GI.Gtk.widgetHide aboutDialog)-    ) >>-  void (-      GI.Gtk.dialogRun aboutDialog-    ) >>+aboutButtonReleaseHandler :: GI.Gtk.AboutDialog -> GI.Gdk.EventButton -> IO Bool+aboutButtonReleaseHandler aboutDialog _ = do+  _ <- GI.Gtk.onDialogResponse aboutDialog (\ _ -> GI.Gtk.widgetHide aboutDialog)+  _ <- GI.Gtk.dialogRun aboutDialog   return True
src/CommandLine.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} 
src/Constants.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -11,10 +11,13 @@ import Data.Text  hideOnScreenControlsInterval :: Integral a => a-hideOnScreenControlsInterval = 5+hideOnScreenControlsInterval = 7  invalidVideoWidgetName :: Data.Text.Text invalidVideoWidgetName = "invalid-video-widget"  keyboardShortcutSeekAdvanceBy :: Double keyboardShortcutSeekAdvanceBy = 1.0++windowMinimumSize :: Integral a => a+windowMinimumSize = 448
+ src/CssStyle.hs view
@@ -0,0 +1,121 @@+{-+  Movie Monad+  (C) 2017 David Lettier+  lettier.com+-}++{-# LANGUAGE OverloadedStrings #-}++module CssStyle where++import Prelude+import Control.Monad+import Data.Word+import Data.Text+import qualified Data.ByteString+import qualified GI.Gdk+import qualified GI.Gtk++import qualified Records as R++import Paths_movie_monad++cssPriority :: Word32+cssPriority =+  fromIntegral GI.Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION :: Word32++applyCss :: R.GuiObjects -> IO ()+applyCss+  guiObjects+  = do+  maybeScreen  <- GI.Gdk.screenGetDefault+  provider     <- GI.Gtk.cssProviderNew+  styleFile    <- getDataFileName "data/style.css"+  styleFile318 <- getDataFileName "data/style-3-18.css"+  styleFile320 <- getDataFileName "data/style-3-20.css"+  isGtkVersionGte310  <- isGtkVersionGte 3 10+  isGtkVersionGte318  <- isGtkVersionGte 3 18+  isGtkVersionGte320  <- isGtkVersionGte 3 20+  case ( maybeScreen+       , isGtkVersionGte310+       , isGtkVersionGte318+       , isGtkVersionGte320+       )+    of+    (Just screen, True, False, False) -> do+      GI.Gtk.cssProviderLoadFromPath provider (Data.Text.pack styleFile)+      GI.Gtk.styleContextAddProviderForScreen+        screen+        provider+        cssPriority+      setScaleSizeForLegacyGtk guiObjects+    (Just screen, True, True, False) -> do+      styleFileContents    <- Data.ByteString.readFile styleFile+      styleFileContents318 <- Data.ByteString.readFile styleFile318+      let totalStyleFileContents =+            Data.ByteString.concat+              [styleFileContents, styleFileContents318]+      GI.Gtk.cssProviderLoadFromData provider totalStyleFileContents+      GI.Gtk.styleContextAddProviderForScreen+        screen+        provider+        cssPriority+      setScaleSizeForLegacyGtk guiObjects+    (Just screen, True, True, True) -> do+      styleFileContents    <- Data.ByteString.readFile styleFile+      styleFileContents318 <- Data.ByteString.readFile styleFile318+      styleFileContents320 <- Data.ByteString.readFile styleFile320+      let totalStyleFileContents =+            Data.ByteString.concat+              [styleFileContents, styleFileContents318, styleFileContents320]+      GI.Gtk.cssProviderLoadFromData provider totalStyleFileContents+      GI.Gtk.styleContextAddProviderForScreen+        screen+        provider+        cssPriority+    _ -> return ()++setScaleSizeForLegacyGtk :: R.GuiObjects -> IO ()+setScaleSizeForLegacyGtk+  R.GuiObjects+    { R.window    = window+    , R.seekScale = seekScale+    }+  = do+  GI.Gtk.containerForall+    window+    (\ windowChild -> do+      windowChildName <- GI.Gtk.widgetGetName windowChild+      when (windowChildName == "GtkPopover") $ do+        maybePopover <- GI.Gtk.castTo GI.Gtk.Popover windowChild+        case maybePopover of+          Just popover ->+            GI.Gtk.containerForall+              popover+              (\ popoverChild -> do+                popoverChildName <- GI.Gtk.widgetGetName popoverChild+                when (popoverChildName == "GtkBox") $ do+                  maybeBox <- GI.Gtk.castTo GI.Gtk.Box popoverChild+                  case maybeBox of+                    Just box ->+                      GI.Gtk.containerForall+                        box+                        (\ boxChild -> do+                          boxChildName <- GI.Gtk.widgetGetName boxChild+                          when (boxChildName == "GtkScale") $ do+                            maybeScale <- GI.Gtk.castTo GI.Gtk.Scale boxChild+                            case maybeScale of+                              Just scale -> GI.Gtk.rangeSetMinSliderSize scale 15+                              _          -> return ()+                        )+                    _ -> return ()+              )+          _ -> return ()+    )+  GI.Gtk.rangeSetMinSliderSize seekScale 15++isGtkVersionGte :: Word32 -> Word32 -> IO Bool+isGtkVersionGte major minor = do+  major' <- GI.Gtk.getMajorVersion+  minor' <- GI.Gtk.getMinorVersion+  return (major' >= major && minor' >= minor)
src/ErrorMessage.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} 
src/FileChooser.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -9,6 +9,7 @@ module FileChooser where  import Control.Monad+import Data.Maybe import Data.Int import Data.Text import Data.IORef@@ -19,8 +20,8 @@  import qualified Records as R import Constants+import Reset import Window-import PlayPause import ErrorMessage import VideoInfo import Playbin@@ -29,125 +30,108 @@  addFileChooserHandlers :: R.Application -> IO () addFileChooserHandlers-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.fileChooserButton = fileChooserButton-            , R.fileChooserDialog = fileChooserDialog-            , R.fileChooserWidget = fileChooserWidget-            , R.fileChooserEntry = fileChooserEntry+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.fileChooserButton = fileChooserButton+          , R.fileChooserDialog = fileChooserDialog+          , R.fileChooserWidget = fileChooserWidget+          , R.fileChooserEntry  = fileChooserEntry           }     }-  =-  void (GI.Gtk.onWidgetButtonReleaseEvent fileChooserButton (fileChooserButtonClickHandler application)) >>-  void (GI.Gtk.onDialogResponse fileChooserDialog (fileChooserDialogResponseHandler application)) >>-  void (GI.Gtk.onFileChooserSelectionChanged fileChooserWidget (fileChooserSelectionChangedHandler application)) >>-  void (GI.Gtk.onEntryIconRelease fileChooserEntry (\ _ _ -> GI.Gtk.entrySetText fileChooserEntry ""))+  = do+  void $+    GI.Gtk.onWidgetButtonReleaseEvent fileChooserButton (fileChooserButtonClickHandler application)+  void $+    GI.Gtk.onDialogResponse fileChooserDialog (fileChooserDialogResponseHandler application)+  void $+    GI.Gtk.onFileChooserSelectionChanged fileChooserWidget (fileChooserSelectionChangedHandler application)+  void $+    GI.Gtk.onEntryIconRelease fileChooserEntry (\ _ _ -> GI.Gtk.entrySetText fileChooserEntry "") -fileChooserDialogResponseHandler ::-  R.Application ->-  Int32 ->-  IO ()+fileChooserDialogResponseHandler :: R.Application -> Int32 -> IO () fileChooserDialogResponseHandler-  R.Application {-        R.guiObjects = guiObjects@R.GuiObjects {-              R.videoWidget = videoWidget-            , R.seekScale = seekScale-            , R.playPauseButton = playPauseButton-            , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox-            , R.fullscreenButton = fullscreenButton-            , R.fileChooserEntry = fileChooserEntry-            , R.fileChooserButtonLabel = fileChooserButtonLabel-            , R.volumeButton = volumeButton-            , R.errorMessageDialog = errorMessageDialog-            , R.fileChooserDialog = fileChooserDialog-            , R.playImage = playImage-            , R.pauseImage = pauseImage+  application@R.Application+    { R.guiObjects =+        guiObjects@R.GuiObjects+          { R.window                           = window+          , R.videoWidget                      = videoWidget+          , R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText+          , R.fileChooserEntry                 = fileChooserEntry+          , R.fileChooserButtonLabel           = fileChooserButtonLabel+          , R.volumeButton                     = volumeButton+          , R.errorMessageDialog               = errorMessageDialog+          , R.fileChooserDialog                = fileChooserDialog           }-      , R.ioRefs = R.IORefs {-              R.isWindowFullScreenRef = isWindowFullScreenRef-            , R.videoInfoRef = videoInfoRef-            , R.previousFileNamePathRef = previousFileNamePathRef+    , R.ioRefs =+        R.IORefs+          { R.isWindowFullScreenRef   = isWindowFullScreenRef+          , R.videoInfoRef            = videoInfoRef+          , R.previousFileNamePathRef = previousFileNamePathRef           }-      , R.playbin = playbin+    , R.playbin = playbin     }   responseId   = do   GI.Gtk.widgetHide fileChooserDialog-  handleResponseType GI.Gtk.ResponseTypeOk-  where-    handleResponseType :: (Enum a, Ord a) => a -> IO ()-    handleResponseType enum-      | enumToInt32 enum == responseId = do-        _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull-        filePathName <- GI.Gtk.entryGetText fileChooserEntry-        let filePathNameStr = Data.Text.unpack filePathName-        (_, fileNameEmpty) <- setFileChooserButtonLabel fileChooserButtonLabel filePathName-        isWindowFullScreen <- readIORef isWindowFullScreenRef-        videoWidthSelection <- getSelectedVideoWidth videoWidthSelectionComboBox-        setPlaybinUriAndVolume playbin filePathNameStr volumeButton-        handleFileName-          fileNameEmpty-          filePathNameStr-          isWindowFullScreen-          videoWidthSelection-      | otherwise = do-        filePathName <- readIORef previousFileNamePathRef-        _ <- setFileChooserButtonLabel fileChooserButtonLabel filePathName-        GI.Gtk.entrySetText fileChooserEntry filePathName-    handleFileName ::-      Bool ->-      Prelude.String ->-      Bool ->-      Int ->-      IO ()-    handleFileName True _ _ _ = atomicWriteIORef videoInfoRef R.defaultVideoInfo >> resetWindow guiObjects-    handleFileName-      _-      filePathNameStr-      isWindowFullScreen-      videoWidthSelection-      = do-      retrievedVideoInfo <- getVideoInfo videoInfoRef filePathNameStr-      maybeWindowSize <- calculateWindowSize guiObjects videoWidthSelection retrievedVideoInfo-      GI.Gtk.widgetSetSensitive seekScale True-      if R.isSeekable retrievedVideoInfo-        then GI.Gtk.widgetShow seekScale-        else GI.Gtk.widgetHide seekScale-      case maybeWindowSize of-        Nothing -> do-          resetWindow guiObjects-          runErrorMessageDialog-            errorMessageDialog-            (Data.Text.pack $ Prelude.concat ["\"", filePathNameStr, "\" is not a video."])-        Just (width, height) -> do-          videoWidgetName <- GI.Gtk.widgetGetName videoWidget-          if videoWidgetName == invalidVideoWidgetName-            then do-              resetWindow guiObjects+  if enumToInt32 GI.Gtk.ResponseTypeOk == responseId+    then do+      filePathName  <- GI.Gtk.entryGetText fileChooserEntry+      maybeFileName <- setFileChooserButtonLabel fileChooserButtonLabel filePathName+      case maybeFileName of+        (Just _) -> do+          let filePathNameStr = Data.Text.unpack filePathName+          videoInfo           <- fromMaybe R.defaultVideoInfo <$> getVideoInfo videoInfoRef filePathNameStr+          desiredWindowWidth  <- getDesiredWindowWidth windowWidthSelectionComboBoxText window+          maybeWindowSize     <- calculateWindowSize guiObjects desiredWindowWidth videoInfo+          case maybeWindowSize of+            Just (width, height) -> do+              videoWidgetName <- GI.Gtk.widgetGetName videoWidget+              if videoWidgetName == invalidVideoWidgetName+                then do+                  resetApplication application+                  runErrorMessageDialog+                    errorMessageDialog+                    "Cannot play the video. Please install the bad plugins, version 1.8 or higher, for GStreamer version 1."+                else do+                  isWindowFullScreen <- readIORef isWindowFullScreenRef+                  setupWindowForPlayback+                    guiObjects+                    (R.isSeekable videoInfo)+                    isWindowFullScreen+                    width+                    height+                  saveVideoInfo videoInfoRef videoInfo+                  resetPlaybin playbin+                  setPlaybinUriAndVolume playbin filePathNameStr volumeButton+                  void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying+            _ -> do+              resetApplication application               runErrorMessageDialog-                errorMessageDialog-                "Cannot play the video. Please install the bad plugins, version 1.8 or higher, for GStreamer version 1."-            else do-              GI.Gtk.widgetShow videoWidget-              GI.Gtk.widgetShow playPauseButton-              GI.Gtk.widgetShow fullscreenButton-              setPlayPauseButton playPauseButton playImage pauseImage True-              unless isWindowFullScreen $-                setWindowSize guiObjects width height-              void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying+                errorMessageDialog $+                  Data.Text.pack $+                  Prelude.concat ["\"", filePathNameStr, "\" is not a video."]+        _ ->+          resetApplication application+    else do+      filePathName <- readIORef previousFileNamePathRef+      fromMaybe R.defaultVideoInfo <$>+        getVideoInfo videoInfoRef (Data.Text.unpack filePathName) >>=+          saveVideoInfo videoInfoRef+      _ <- setFileChooserButtonLabel fileChooserButtonLabel filePathName+      GI.Gtk.entrySetText fileChooserEntry filePathName -fileChooserButtonClickHandler ::-  R.Application ->-  GI.Gdk.EventButton ->-  IO Bool+fileChooserButtonClickHandler :: R.Application -> GI.Gdk.EventButton -> IO Bool fileChooserButtonClickHandler-  R.Application {-        R.guiObjects = R.GuiObjects {-              R.fileChooserEntry = fileChooserEntry-            , R.fileChooserDialog = fileChooserDialog+  R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.fileChooserEntry = fileChooserEntry+          , R.fileChooserDialog = fileChooserDialog           }-      , R.ioRefs = R.IORefs {-              R.previousFileNamePathRef = previousFileNamePathRef+    , R.ioRefs =+        R.IORefs+          { R.previousFileNamePathRef = previousFileNamePathRef           }     }   _@@ -157,17 +141,17 @@   _ <- GI.Gtk.dialogRun fileChooserDialog   return True -fileChooserSelectionChangedHandler ::-  R.Application ->-  IO ()+fileChooserSelectionChangedHandler :: R.Application -> IO () fileChooserSelectionChangedHandler-  R.Application {-        R.guiObjects = R.GuiObjects {-              R.fileChooserWidget = fileChooserWidget-            , R.fileChooserEntry = fileChooserEntry+  R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.fileChooserWidget = fileChooserWidget+          , R.fileChooserEntry  = fileChooserEntry           }-      , R.ioRefs = R.IORefs {-              R.videoInfoRef = videoInfoRef+    , R.ioRefs =+        R.IORefs+          { R.videoInfoRef = videoInfoRef           }     }   = do@@ -177,12 +161,17 @@     Just uri' -> do       let uri = Network.URI.unEscapeString $ Data.Text.unpack uri'       local <- isLocalFile uri-      video <- R.isVideo <$> getVideoInfo videoInfoRef uri+      video <- R.isVideo . fromMaybe R.defaultVideoInfo <$> getVideoInfo videoInfoRef uri       GI.Gtk.entrySetText fileChooserEntry (if local && video then Data.Text.pack uri else "") -setFileChooserButtonLabel :: GI.Gtk.Label -> Data.Text.Text -> IO (Data.Text.Text, Bool)+setFileChooserButtonLabel :: GI.Gtk.Label -> Data.Text.Text -> IO (Maybe Data.Text.Text) setFileChooserButtonLabel fileChooserButtonLabel filePathName = do   let fileName = fileNameFromFilePathName filePathName   let fileNameEmpty = isTextEmpty fileName-  GI.Gtk.labelSetText fileChooserButtonLabel (if fileNameEmpty then "Open" else fileName)-  return (fileName, fileNameEmpty)+  if fileNameEmpty+    then do+      GI.Gtk.labelSetText fileChooserButtonLabel "Open"+      return Nothing+    else do+      GI.Gtk.labelSetText fileChooserButtonLabel fileName+      return $ Just fileName
src/Fullscreen.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -31,8 +31,8 @@   R.Application {         R.guiObjects = R.GuiObjects {               R.window = window-            , R.fileChooserButton = fileChooserButton-            , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox+            , R.fileChooserButton                = fileChooserButton+            , R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText           }       , R.ioRefs = R.IORefs {             R.isWindowFullScreenRef = isWindowFullScreenRef@@ -43,11 +43,11 @@   isWindowFullScreen <- readIORef isWindowFullScreenRef   if isWindowFullScreen     then do-      GI.Gtk.widgetShow videoWidthSelectionComboBox+      GI.Gtk.widgetShow windowWidthSelectionComboBoxText       GI.Gtk.widgetShow fileChooserButton       void $ GI.Gtk.windowUnfullscreen window     else do-      GI.Gtk.widgetHide videoWidthSelectionComboBox+      GI.Gtk.widgetHide windowWidthSelectionComboBoxText       GI.Gtk.widgetHide fileChooserButton       void $ GI.Gtk.windowFullscreen window   return True
src/Keyboard.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -21,37 +21,38 @@  addKeyboardEventHandler :: R.Application -> IO () addKeyboardEventHandler-  application@R.Application {-    R.guiObjects = R.GuiObjects {-        R.window = window-      }+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.window = window+          }     }   =   void $ GI.Gtk.onWidgetKeyPressEvent window $ keyboardEventHandler application -keyboardEventHandler ::-  R.Application ->-  GI.Gdk.EventKey ->-  IO Bool+keyboardEventHandler :: R.Application -> GI.Gdk.EventKey -> IO Bool keyboardEventHandler-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.volumeButton = volumeButton-            , R.seekScale = seekScale+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.volumeButton      = volumeButton+          , R.seekScale         = seekScale+          , R.repeatCheckButton = repeatCheckButton           }-      , R.ioRefs = R.IORefs {-              R.videoInfoRef = videoInfoRef-        }+    , R.ioRefs =+        R.IORefs+          { R.videoInfoRef = videoInfoRef+          }     }   eventKey   = do-  videoInfoGathered <- readIORef videoInfoRef-  let isVideo = R.isVideo videoInfoGathered-  let volumeDelta = 0.05-  oldVolume <- GI.Gtk.scaleButtonGetValue volumeButton-  keyValue <- GI.Gdk.getEventKeyKeyval eventKey+  videoInfo   <- readIORef videoInfoRef+  oldVolume   <- GI.Gtk.scaleButtonGetValue volumeButton+  keyValue    <- GI.Gdk.getEventKeyKeyval eventKey   eventButton <- GI.Gdk.newZeroEventButton-  rangeValue <- GI.Gtk.rangeGetValue seekScale+  rangeValue  <- GI.Gtk.rangeGetValue seekScale+  let isVideo = R.isVideo videoInfo+  let volumeDelta = 0.05   -- Mute Toggle   when (keyValue == GI.Gdk.KEY_m || keyValue == GI.Gdk.KEY_AudioMute) $ do     let newVolume = if oldVolume <= 0.0 then 0.5 else 0.0@@ -59,6 +60,10 @@   -- Play/Pause Toggle   when ((keyValue == GI.Gdk.KEY_space || keyValue == GI.Gdk.KEY_AudioPlay) && isVideo) $     void $ playPauseButtonClickHandler application eventButton+  -- Fullscreen Toggle+  when (keyValue == GI.Gdk.KEY_r && isVideo) $ do+    repeatVideo <- GI.Gtk.toggleButtonGetActive repeatCheckButton+    void $ GI.Gtk.toggleButtonSetActive repeatCheckButton (not repeatVideo)   -- Volume Up   when (keyValue == GI.Gdk.KEY_Up || keyValue == GI.Gdk.KEY_AudioRaiseVolume) $ do     let newVolume = if oldVolume >= 1.0 then 1.0 else oldVolume + volumeDelta@@ -68,12 +73,12 @@     let newVolume = if oldVolume <= 0.0 then 0.0 else oldVolume - volumeDelta     GI.Gtk.scaleButtonSetValue volumeButton newVolume   -- Seek left-  when (keyValue == GI.Gdk.KEY_Left) $+  when (keyValue == GI.Gdk.KEY_Left && isVideo) $     void $ GI.Gtk.rangeSetValue       seekScale       (clamp 0.0 100.0 (rangeValue - keyboardShortcutSeekAdvanceBy))   -- Seek right-  when (keyValue == GI.Gdk.KEY_Right) $+  when (keyValue == GI.Gdk.KEY_Right && isVideo) $     void $ GI.Gtk.rangeSetValue       seekScale       (clamp 0.0 100.0 (rangeValue + keyboardShortcutSeekAdvanceBy))
src/Main.hs view
@@ -1,11 +1,13 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} -{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE+    OverloadedStrings+  , ScopedTypeVariables+#-}  module Main where @@ -24,6 +26,7 @@  import qualified Records as R import Constants+import Reset import Window import CommandLine import Mouse@@ -38,6 +41,7 @@ import SubtitleSelector import Playbin import ScreensaverAndPowerManagement (disable, enable)+import CssStyle import Utils  import Paths_movie_monad@@ -54,30 +58,31 @@   _ <- GI.Gtk.init Nothing    gladeFile <- getDataFileName "data/gui.glade"-  builder <- GI.Gtk.builderNewFromFile (pack gladeFile)+  builder   <- GI.Gtk.builderNewFromFile (pack gladeFile) -  window <- builderGetObject GI.Gtk.Window builder "window"-  fileChooserButton <- builderGetObject GI.Gtk.Button builder "file-chooser-button"-  fileChooserButtonLabel <- builderGetObject GI.Gtk.Label builder "file-chooser-button-label"-  fileChooserDialog <- builderGetObject GI.Gtk.Dialog builder "file-chooser-dialog"-  fileChooserEntry <- builderGetObject GI.Gtk.Entry builder "file-chooser-entry"-  fileChooserWidget <- builderGetObject GI.Gtk.FileChooserWidget builder "file-chooser-widget"-  fileChooserCancelButton <- builderGetObject GI.Gtk.Button builder "file-chooser-cancel-button"-  fileChooserOpenButton <- builderGetObject GI.Gtk.Button builder "file-chooser-open-button"-  videoWidgetBox <- builderGetObject GI.Gtk.Box builder "video-widget-box"-  bottomControlsGtkBox <- builderGetObject GI.Gtk.Box builder "bottom-controls-gtk-box"-  seekScale <- builderGetObject GI.Gtk.Scale builder "seek-scale"-  playPauseButton <- builderGetObject GI.Gtk.Button builder "play-pause-button"-  playImage <- builderGetObject GI.Gtk.Image builder "play-image"-  pauseImage <- builderGetObject GI.Gtk.Image builder "pause-image"-  volumeButton <- builderGetObject GI.Gtk.VolumeButton builder "volume-button"-  videoWidthSelectionComboBox <- builderGetObject GI.Gtk.ComboBoxText builder "video-width-selection-combo-box"-  subtitleSelectionComboBox <- builderGetObject GI.Gtk.ComboBoxText builder "subtitle-selection-combo-box"-  fullscreenButton <- builderGetObject GI.Gtk.Button builder "fullscreen-button"-  bufferingSpinner <- builderGetObject GI.Gtk.Spinner builder "buffering-spinner"-  errorMessageDialog <- builderGetObject GI.Gtk.MessageDialog builder "error-message-dialog"-  aboutButton <- builderGetObject GI.Gtk.Button builder "about-button"-  aboutDialog <- builderGetObject GI.Gtk.AboutDialog builder "about-dialog"+  window                           <- builderGetObject GI.Gtk.Window            builder "window"+  fileChooserButtonLabel           <- builderGetObject GI.Gtk.Label             builder "file-chooser-button-label"+  fileChooserEntry                 <- builderGetObject GI.Gtk.Entry             builder "file-chooser-entry"+  fileChooserWidget                <- builderGetObject GI.Gtk.FileChooserWidget builder "file-chooser-widget"+  videoWidgetBox                   <- builderGetObject GI.Gtk.Box               builder "video-widget-box"+  bottomControlsGtkBox             <- builderGetObject GI.Gtk.Box               builder "bottom-controls-gtk-box"+  seekScale                        <- builderGetObject GI.Gtk.Scale             builder "seek-scale"+  fileChooserButton                <- builderGetObject GI.Gtk.Button            builder "file-chooser-button"+  fileChooserCancelButton          <- builderGetObject GI.Gtk.Button            builder "file-chooser-cancel-button"+  fileChooserOpenButton            <- builderGetObject GI.Gtk.Button            builder "file-chooser-open-button"+  playPauseButton                  <- builderGetObject GI.Gtk.Button            builder "play-pause-button"+  fullscreenButton                 <- builderGetObject GI.Gtk.Button            builder "fullscreen-button"+  aboutButton                      <- builderGetObject GI.Gtk.Button            builder "about-button"+  repeatCheckButton                <- builderGetObject GI.Gtk.CheckButton       builder "repeat-check-button"+  volumeButton                     <- builderGetObject GI.Gtk.VolumeButton      builder "volume-button"+  playImage                        <- builderGetObject GI.Gtk.Image             builder "play-image"+  pauseImage                       <- builderGetObject GI.Gtk.Image             builder "pause-image"+  windowWidthSelectionComboBoxText <- builderGetObject GI.Gtk.ComboBoxText      builder "window-width-selection-combo-box-text"+  subtitleSelectionComboBoxText    <- builderGetObject GI.Gtk.ComboBoxText      builder "subtitle-selection-combo-box-text"+  bufferingSpinner                 <- builderGetObject GI.Gtk.Spinner           builder "buffering-spinner"+  fileChooserDialog                <- builderGetObject GI.Gtk.Dialog            builder "file-chooser-dialog"+  errorMessageDialog               <- builderGetObject GI.Gtk.MessageDialog     builder "error-message-dialog"+  aboutDialog                      <- builderGetObject GI.Gtk.AboutDialog       builder "about-dialog"    logoFile <- getDataFileName "data/movie-monad-logo.svg"   logo <- GI.GdkPixbuf.pixbufNewFromFile (pack logoFile)@@ -87,17 +92,18 @@   GI.Gtk.dialogAddActionWidget fileChooserDialog fileChooserCancelButton (enumToInt32 GI.Gtk.ResponseTypeCancel)   GI.Gtk.dialogAddActionWidget fileChooserDialog fileChooserOpenButton   (enumToInt32 GI.Gtk.ResponseTypeOk) -  isWindowFullScreenRef <- newIORef False-  mouseMovedLastRef <- newIORef 0+  isWindowFullScreenRef   <- newIORef False+  mouseMovedLastRef       <- newIORef 0   previousFileNamePathRef <- newIORef ""-  videoInfoRef <- newIORef R.defaultVideoInfo+  videoInfoRef            <- newIORef R.defaultVideoInfo -  let ioRefs = R.IORefs {-        R.isWindowFullScreenRef = isWindowFullScreenRef-      , R.mouseMovedLastRef = mouseMovedLastRef-      , R.previousFileNamePathRef = previousFileNamePathRef-      , R.videoInfoRef = videoInfoRef-    }+  let ioRefs =+        R.IORefs+          { R.isWindowFullScreenRef = isWindowFullScreenRef+          , R.mouseMovedLastRef = mouseMovedLastRef+          , R.previousFileNamePathRef = previousFileNamePathRef+          , R.videoInfoRef = videoInfoRef+          }    playbin <- fromJust <$> GI.Gst.elementFactoryMake "playbin" (Just "MultimediaPlayerPlaybin")   maybeGtkSink <- GI.Gst.elementFactoryMake "gtksink" (Just "MultimediaPlayerGtkSink")@@ -114,73 +120,82 @@   Data.GI.Base.Properties.setObjectPropertyObject playbin "video-sink" maybeGtkSink   Data.GI.Base.Properties.setObjectPropertyBool   playbin "force-aspect-ratio" True   GI.Gtk.boxPackStart videoWidgetBox videoWidget True True 0-  GI.Gtk.widgetSetHexpand videoWidget True-  GI.Gtk.widgetSetVexpand videoWidget True+  GI.Gtk.widgetSetHexpand   videoWidget True+  GI.Gtk.widgetSetVexpand   videoWidget True   GI.Gtk.widgetSetSensitive videoWidget True    turnOffSubtitles playbin    playbinBus <- GI.Gst.elementGetBus playbin -  let guiObjects = R.GuiObjects {-        R.window = window-      , R.fileChooserButton = fileChooserButton-      , R.fileChooserButtonLabel = fileChooserButtonLabel-      , R.fileChooserDialog = fileChooserDialog-      , R.fileChooserEntry = fileChooserEntry-      , R.fileChooserWidget = fileChooserWidget-      , R.fileChooserCancelButton = fileChooserCancelButton-      , R.fileChooserOpenButton = fileChooserOpenButton-      , R.videoWidget = videoWidget-      , R.bottomControlsGtkBox = bottomControlsGtkBox-      , R.seekScale = seekScale-      , R.playPauseButton = playPauseButton-      , R.playImage = playImage-      , R.pauseImage = pauseImage-      , R.volumeButton = volumeButton-      , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox-      , R.subtitleSelectionComboBox = subtitleSelectionComboBox-      , R.fullscreenButton = fullscreenButton-      , R.bufferingSpinner = bufferingSpinner-      , R.errorMessageDialog = errorMessageDialog-      , R.aboutButton = aboutButton-      , R.aboutDialog = aboutDialog-    }+  let guiObjects =+        R.GuiObjects+          { R.window                           = window+          , R.fileChooserButtonLabel           = fileChooserButtonLabel+          , R.fileChooserEntry                 = fileChooserEntry+          , R.fileChooserWidget                = fileChooserWidget+          , R.fileChooserCancelButton          = fileChooserCancelButton+          , R.fileChooserOpenButton            = fileChooserOpenButton+          , R.videoWidget                      = videoWidget+          , R.bottomControlsGtkBox             = bottomControlsGtkBox+          , R.seekScale                        = seekScale+          , R.fileChooserButton                = fileChooserButton+          , R.playPauseButton                  = playPauseButton+          , R.fullscreenButton                 = fullscreenButton+          , R.volumeButton                     = volumeButton+          , R.repeatCheckButton                = repeatCheckButton+          , R.playImage                        = playImage+          , R.pauseImage                       = pauseImage+          , R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText+          , R.subtitleSelectionComboBoxText    = subtitleSelectionComboBoxText+          , R.bufferingSpinner                 = bufferingSpinner+          , R.errorMessageDialog               = errorMessageDialog+          , R.fileChooserDialog                = fileChooserDialog+          , R.aboutButton                      = aboutButton+          , R.aboutDialog                      = aboutDialog+          } -  let application = R.Application {-        R.guiObjects = guiObjects-      , R.ioRefs = ioRefs-      , R.playbin = playbin-      , R.playbinBus = playbinBus-    }+  let application =+        R.Application+          { R.guiObjects = guiObjects+          , R.ioRefs = ioRefs+          , R.playbin = playbin+          , R.playbinBus = playbinBus+          } -  addWindowHandlers application [playVideoFromCommandLineIfNeeded]-  addPlaybinHandlers application-  addFileChooserHandlers application-  addPlayPauseButtonClickHandler application-  addSeekHandlers application-  addVideoSizeSelectorHandler application-  addSubtitleSelectorHandler application+  addWindowHandlers                 application [playVideoFromCommandLineIfNeeded]+  addPlaybinHandlers                application+  addFileChooserHandlers            application+  addPlayPauseButtonClickHandler    application+  addSeekHandlers                   application+  addVideoSizeSelectorHandlers      application+  addSubtitleSelectorHandler        application   addFullscreenButtonReleaseHandler application-  addMouseMoveHandlers application [fillWindowWithVideo]-  addAboutHandler application-  addKeyboardEventHandler application-  addErrorMessageDialogHandler application+  addMouseMoveHandlers              application [fillWindowWithVideo]+  addAboutHandler                   application+  addKeyboardEventHandler           application+  addErrorMessageDialogHandler      application    let operatingSystem = System.Info.os   screenAndPowerManagementActions <- ScreensaverAndPowerManagement.disable operatingSystem +  applyCss guiObjects+   GI.Gtk.widgetShowAll window+   GI.Gtk.main +  resetPlaybin playbin+   ScreensaverAndPowerManagement.enable operatingSystem screenAndPowerManagementActions -builderGetObject ::-  (GI.GObject.GObject b, GI.Gtk.IsBuilder a) =>-  (Data.GI.Base.ManagedPtr b -> b) ->-  a ->-  Prelude.String ->-  IO b+builderGetObject+  ::  (GI.GObject.GObject b, GI.Gtk.IsBuilder a)+  =>  (Data.GI.Base.ManagedPtr b -> b)+  ->  a+  ->  Prelude.String+  ->  IO b builderGetObject objectTypeClass builder objectId =   fromJust <$> GI.Gtk.builderGetObject builder (pack objectId) >>=     GI.Gtk.unsafeCastTo objectTypeClass+
src/Mouse.hs view
@@ -1,8 +1,9 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -}+{-# LANGUAGE OverloadedStrings #-}  module Mouse where @@ -18,43 +19,51 @@  addMouseMoveHandlers :: R.Application -> [R.Application -> IO ()] -> IO () addMouseMoveHandlers-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.videoWidget = videoWidget-            , R.seekScale = seekScale+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.videoWidget = videoWidget+          , R.seekScale = seekScale           }     }   onMouseMoveCallbacks-  =-      void (GI.Gtk.onWidgetMotionNotifyEvent videoWidget mouseMoveHandler')-  >>  void (GI.Gtk.onWidgetMotionNotifyEvent seekScale   mouseMoveHandler')+  = do+  void $ GI.Gtk.onWidgetMotionNotifyEvent videoWidget mouseMoveHandler'+  void $ GI.Gtk.onWidgetMotionNotifyEvent seekScale   mouseMoveHandler'   where     mouseMoveHandler' :: GI.Gdk.EventMotion -> IO Bool     mouseMoveHandler' = mouseMoveHandler application onMouseMoveCallbacks  mouseMoveHandler-  :: R.Application-  -> [R.Application -> IO ()]-  -> GI.Gdk.EventMotion-  -> IO Bool+  ::  R.Application+  ->  [R.Application -> IO ()]+  ->  GI.Gdk.EventMotion+  ->  IO Bool mouseMoveHandler-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.window = window-            , R.fileChooserButton = fileChooserButton-            , R.bottomControlsGtkBox = bottomControlsGtkBox+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.window               = window+          , R.fileChooserButton    = fileChooserButton+          , R.bottomControlsGtkBox = bottomControlsGtkBox           }-      , R.ioRefs = R.IORefs {-            R.isWindowFullScreenRef = isWindowFullScreenRef-          , R.mouseMovedLastRef = mouseMovedLastRef-        }+      , R.ioRefs =+          R.IORefs+            { R.isWindowFullScreenRef = isWindowFullScreenRef+            , R.mouseMovedLastRef     = mouseMovedLastRef+            , R.videoInfoRef          = videoInfoRef+            }     }   onMouseMoveCallbacks   _   = do   isWindowFullScreen <- readIORef isWindowFullScreenRef+  videoInfo          <- readIORef videoInfoRef   unless isWindowFullScreen $ GI.Gtk.widgetShow fileChooserButton-  GI.Gtk.widgetShow bottomControlsGtkBox+  when (R.isVideo videoInfo) $ do+    GI.Gtk.widgetShow bottomControlsGtkBox+    styleContext <- GI.Gtk.widgetGetStyleContext bottomControlsGtkBox+    GI.Gtk.styleContextAddClass styleContext "movie-monad-fade-in"   setCursor window Nothing   timeNow <- getPOSIXTime   atomicWriteIORef mouseMovedLastRef (round timeNow)
src/PlayPause.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -18,26 +18,31 @@  addPlayPauseButtonClickHandler :: R.Application -> IO () addPlayPauseButtonClickHandler-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.playPauseButton = playPauseButton+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.playPauseButton = playPauseButton           }     }   =-  void $ GI.Gtk.onWidgetButtonReleaseEvent playPauseButton (playPauseButtonClickHandler application)+  void $+    GI.Gtk.onWidgetButtonReleaseEvent+      playPauseButton $+        playPauseButtonClickHandler application  playPauseButtonClickHandler ::   R.Application ->   GI.Gdk.EventButton ->   IO Bool playPauseButtonClickHandler-  R.Application {-        R.guiObjects = R.GuiObjects {-              R.playPauseButton = playPauseButton-            , R.playImage = playImage-            , R.pauseImage = pauseImage+  R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.playPauseButton = playPauseButton+          , R.playImage = playImage+          , R.pauseImage = pauseImage           }-      , R.playbin = playbin+    , R.playbin = playbin     }   _   = do@@ -51,22 +56,20 @@       void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying   return False -setPlayPauseButton ::-  GI.Gtk.Button ->-  GI.Gtk.Image ->-  GI.Gtk.Image ->-  Bool ->-  IO ()+setPlayPauseButton+  ::  GI.Gtk.Button+  ->  GI.Gtk.Image+  ->  GI.Gtk.Image+  ->  Bool+  ->  IO () setPlayPauseButton playPauseButton _ pauseImage True = do   GI.Gtk.buttonSetImage playPauseButton (Just pauseImage)-  GI.Gtk.widgetSetTooltipText playPauseButton (Just "Click to pause")+  GI.Gtk.widgetSetTooltipText playPauseButton (Just "Click to Pause") setPlayPauseButton playPauseButton playImage _ False = do   GI.Gtk.buttonSetImage playPauseButton (Just playImage)-  GI.Gtk.widgetSetTooltipText playPauseButton (Just "Click to play")+  GI.Gtk.widgetSetTooltipText playPauseButton (Just "Click to Play") -isPlayPauseButtonPlaying ::-  GI.Gtk.Button ->-  IO Bool+isPlayPauseButtonPlaying :: GI.Gtk.Button -> IO Bool isPlayPauseButtonPlaying playPauseButton =   GI.Gtk.buttonGetImage playPauseButton >>= getImage >>= getName >>= getMatch   where@@ -75,7 +78,7 @@     getImage (Just widget) = GI.Gtk.castTo GI.Gtk.Image widget     getName :: Maybe GI.Gtk.Image -> IO (Maybe Text)     getName Nothing        = return Nothing-    getName (Just image)   = GI.Gtk.getImageStock image+    getName (Just image)   = Just . Data.Text.strip . Data.Text.toLower <$> GI.Gtk.widgetGetName image     getMatch :: Maybe Text -> IO Bool     getMatch Nothing       = return False-    getMatch (Just text)   = return ("gtk-media-pause" == text)+    getMatch (Just text)   = return ("pause-image" == text)
src/Playbin.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -14,6 +14,7 @@ import Data.Bits import Data.Text import Data.Maybe+import Data.Int import Data.GI.Base.Properties import Data.GI.Base.ManagedPtr import qualified GI.GLib@@ -21,7 +22,7 @@ import qualified GI.Gst  import qualified Records as R-import Window+import Reset import PlayPause import ErrorMessage import Uri@@ -31,69 +32,72 @@  addPlaybinHandlers :: R.Application -> IO () addPlaybinHandlers-  R.Application {-        R.guiObjects = guiObjects@R.GuiObjects {-              R.volumeButton = volumeButton+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.volumeButton      = volumeButton+          , R.repeatCheckButton = repeatCheckButton           }-      , R.playbin = playbin-      , R.playbinBus = playbinBus+    , R.playbin    = playbin+    , R.playbinBus = playbinBus     }-  =-  void(-      GI.Gst.busAddWatch playbinBus GI.GLib.PRIORITY_DEFAULT (-          pipelineBusMessageHandler-            guiObjects-            playbin-        )-    ) >>-  void (-      GI.Gtk.onScaleButtonValueChanged volumeButton (volumeButtonValueChangedHandler playbin)-    )+  = do+  void $+    GI.Gst.busAddWatch playbinBus GI.GLib.PRIORITY_DEFAULT $+      pipelineBusMessageHandler application+  void $+    GI.Gtk.onScaleButtonValueChanged+      volumeButton+      (setPlaybinVolume playbin)+  void $+    GI.GLib.timeoutAddSeconds GI.GLib.PRIORITY_DEFAULT 1 $ do+      rewindPlaybackIfVideoEndedAndRepeat+        playbin+        repeatCheckButton+      return True -pipelineBusMessageHandler ::-  R.GuiObjects ->-  GI.Gst.Element ->-  GI.Gst.Bus ->-  GI.Gst.Message ->-  IO Bool pipelineBusMessageHandler-  guiObjects@R.GuiObjects {-        R.seekScale = seekScale-      , R.fileChooserEntry = fileChooserEntry-      , R.fileChooserButtonLabel = fileChooserButtonLabel-      , R.volumeButton = volumeButton-      , R.errorMessageDialog = errorMessageDialog-      , R.bufferingSpinner = bufferingSpinner-      , R.playPauseButton = playPauseButton-      , R.subtitleSelectionComboBox = subtitleSelectionComboBox+  ::  R.Application+  ->  GI.Gst.Bus+  ->  GI.Gst.Message+  ->  IO Bool+pipelineBusMessageHandler+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.seekScale                     = seekScale+          , R.fileChooserEntry              = fileChooserEntry+          , R.fileChooserButtonLabel        = fileChooserButtonLabel+          , R.errorMessageDialog            = errorMessageDialog+          , R.bufferingSpinner              = bufferingSpinner+          , R.playPauseButton               = playPauseButton+          , R.repeatCheckButton             = repeatCheckButton+          , R.subtitleSelectionComboBoxText = subtitleSelectionComboBoxText+          }+    , R.playbin = playbin     }-  playbin   _   message   = do   messageTypes <- GI.Gst.getMessageType message-  let messageType = case messageTypes of-                      [] -> GI.Gst.MessageTypeUnknown-                      (msg:_) -> msg+  let messageType =+        case messageTypes of+          []      -> GI.Gst.MessageTypeUnknown+          (msg:_) -> msg   entryText <- GI.Gtk.entryGetText fileChooserEntry   labelText <- GI.Gtk.labelGetText fileChooserButtonLabel-  when (-      messageType == GI.Gst.MessageTypeError && (-        (not . Data.Text.null) entryText ||-        labelText /= "Open"-      )+  when+    (  messageType == GI.Gst.MessageTypeError+    && ((not . Data.Text.null) entryText || labelText /= "Open")     ) $ do       (gError, text) <- GI.Gst.messageParseError message       gErrorText <- GI.Gst.gerrorMessage gError       putStr ((Data.Text.unpack . Data.Text.unlines) [text, gErrorText])-      GI.Gtk.entrySetText fileChooserEntry ""-      GI.Gtk.labelSetText fileChooserButtonLabel "Open"-      _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull-      setPlaybinUriAndVolume playbin "" volumeButton-      resetWindow guiObjects+      resetApplication application       runErrorMessageDialog-        errorMessageDialog-        (Data.Text.concat ["There was a problem trying to play the video \"", entryText, "\"."])+        errorMessageDialog $+          Data.Text.concat+            ["There was a problem trying to play the video \"", entryText, "\"."]   when (messageType == GI.Gst.MessageTypeBuffering) $ do     percent <- GI.Gst.messageParseBuffering message     isPlaying <- isPlayPauseButtonPlaying playPauseButton@@ -102,7 +106,9 @@         GI.Gtk.widgetHide bufferingSpinner         GI.Gtk.setSpinnerActive bufferingSpinner False         GI.Gtk.widgetSetSensitive seekScale True-        when isPlaying $ void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying+        when isPlaying $+          void $+            GI.Gst.elementSetState playbin GI.Gst.StatePlaying       else do         GI.Gtk.widgetShow bufferingSpinner         GI.Gtk.setSpinnerActive bufferingSpinner True@@ -112,41 +118,72 @@   when (messageType == GI.Gst.MessageTypeStreamStart) $ do     turnOffSubtitles playbin     nText <- getTextStreamCount playbin-    GI.Gtk.comboBoxTextRemoveAll subtitleSelectionComboBox+    GI.Gtk.comboBoxTextRemoveAll subtitleSelectionComboBoxText     GI.Gtk.comboBoxTextAppend-      subtitleSelectionComboBox+      subtitleSelectionComboBoxText       (Just "-1")       "None"-    _ <- GI.Gtk.comboBoxSetActiveId subtitleSelectionComboBox (Just "-1")-    GI.Gtk.widgetHide subtitleSelectionComboBox+    _ <- GI.Gtk.comboBoxSetActiveId subtitleSelectionComboBoxText (Just "-1")+    GI.Gtk.widgetHide subtitleSelectionComboBoxText     when (nText > 0) $       mapM_ (\ i -> do         (_, maybeCode) <- getTextTagLanguageNameAndCode playbin i         case maybeCode of           Nothing -> return ()           Just code -> do-            GI.Gtk.widgetShow subtitleSelectionComboBox+            GI.Gtk.widgetShow subtitleSelectionComboBoxText             GI.Gtk.comboBoxTextAppend-              subtitleSelectionComboBox+              subtitleSelectionComboBoxText               (Just (Data.Text.pack (show i)))               code         ) [0..(nText-1)]+  when (messageType == GI.Gst.MessageTypeEos) $+    rewindPlaybackIfRepeat playbin repeatCheckButton   return True -volumeButtonValueChangedHandler ::-  GI.Gst.Element ->-  Double ->-  IO ()-volumeButtonValueChangedHandler playbin volume =+rewindPlaybackIfVideoEndedAndRepeat :: GI.Gst.Element -> GI.Gtk.CheckButton -> IO ()+rewindPlaybackIfVideoEndedAndRepeat playbin repeatCheckButton = do+  maybeDurationAndPosition <- queryPlaybinForDurationAndPosition playbin+  case maybeDurationAndPosition of+    (Just (duration, position)) ->+      -- Position may never be >= duration even though an EOS event has occurred.+      -- Allow for a half second tolerance.+      when (position >= duration || ((duration - position) < 50000000)) $+        rewindPlaybackIfRepeat playbin repeatCheckButton+    _ -> return ()++rewindPlaybackIfRepeat :: GI.Gst.Element -> GI.Gtk.CheckButton -> IO ()+rewindPlaybackIfRepeat playbin repeatCheckButton = do+  repeatVideo <- GI.Gtk.toggleButtonGetActive repeatCheckButton+  when repeatVideo $+    void $+      GI.Gst.elementSeekSimple playbin GI.Gst.FormatTime [ GI.Gst.SeekFlagsFlush ] 0++setPlaybinVolume :: GI.Gst.Element -> Double -> IO ()+setPlaybinVolume playbin volume =     void $ Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" volume +setPlaybinUri :: GI.Gst.Element -> Maybe String -> IO ()+setPlaybinUri playbin (Just uri) =+    void $ Data.GI.Base.Properties.setObjectPropertyString playbin "uri" (Just $ pack uri)+setPlaybinUri playbin Nothing =+    void $ Data.GI.Base.Properties.setObjectPropertyString playbin "uri" (Just "")+ setPlaybinUriAndVolume :: GI.Gst.Element -> Prelude.String -> GI.Gtk.VolumeButton -> IO () setPlaybinUriAndVolume playbin fileName volumeButton = do-  uri <- addUriSchemeIfNone fileName+  uri    <- addUriSchemeIfNone fileName   volume <- GI.Gtk.scaleButtonGetValue volumeButton-  Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" volume-  Data.GI.Base.Properties.setObjectPropertyString playbin "uri" (Just $ pack uri)+  setPlaybinVolume playbin volume+  setPlaybinUri playbin (Just uri) +queryPlaybinForDurationAndPosition :: GI.Gst.Element -> IO (Maybe (Int64, Int64))+queryPlaybinForDurationAndPosition playbin = do+  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime+  (couldQueryPosition, position) <- GI.Gst.elementQueryPosition playbin GI.Gst.FormatTime+  if couldQueryDuration && couldQueryPosition && duration > 0 && position >= 0+    then return (Just (duration, position))+    else return Nothing+ getTextTagLanguageNameAndCode :: GI.Gst.Element -> Int -> IO (Maybe Text, Maybe Text) getTextTagLanguageNameAndCode playbin streamId = do   nText <- getTextStreamCount playbin@@ -160,15 +197,17 @@           else do             tagList <- wrapBoxed GI.Gst.TagList tagListPtr             tagListAsString <- fmap (fromMaybe "") (GI.Gst.tagListToString tagList)-            (successName, name) <- if "language-name" `Data.Text.isInfixOf` tagListAsString-                                    then GI.Gst.tagListGetString tagList "language-name"-                                    else return (False, "")-            (successCode, code) <- if "language-code" `Data.Text.isInfixOf` tagListAsString-                                    then GI.Gst.tagListGetString tagList "language-code"-                                    else return (False, "")-            return (-                  if successName then Just name else Nothing-                , if successCode then Just code else Nothing+            (successName, name) <-+              if "language-name" `Data.Text.isInfixOf` tagListAsString+                then GI.Gst.tagListGetString tagList "language-name"+                else return (False, "")+            (successCode, code) <-+              if "language-code" `Data.Text.isInfixOf` tagListAsString+                then GI.Gst.tagListGetString tagList "language-code"+                else return (False, "")+            return+              ( if successName then Just name else Nothing+              , if successCode then Just code else Nothing               )     else return (Nothing, Nothing) @@ -198,13 +237,17 @@  getTextStreamCount :: GI.Gst.Element -> IO Int getTextStreamCount playbin =-    Data.GI.Base.Properties.getObjectPropertyInt playbin "n-text"-  >>= \ x -> return (if x < 0 then 0 else fromIntegral x :: Int)+  Data.GI.Base.Properties.getObjectPropertyInt playbin "n-text" >>=+    \ x -> return (if x < 0 then 0 else fromIntegral x :: Int)  getCurrentTextStreamId :: GI.Gst.Element -> IO Int getCurrentTextStreamId playbin =-  Data.GI.Base.Properties.getObjectPropertyInt playbin "current-text" >>= \ x -> return (fromIntegral x :: Int)+  Data.GI.Base.Properties.getObjectPropertyInt playbin "current-text" >>=+    \ x -> return (fromIntegral x :: Int)  setCurrentTextStreamId :: GI.Gst.Element -> Int -> IO () setCurrentTextStreamId playbin streamId =-  Data.GI.Base.Properties.setObjectPropertyInt playbin "current-text" (fromIntegral streamId :: CInt)+  Data.GI.Base.Properties.setObjectPropertyInt+    playbin+    "current-text"+    (fromIntegral streamId :: CInt)
src/Records.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -11,67 +11,74 @@ import qualified GI.Gtk import qualified GI.Gst -data VideoInfo = VideoInfo {-      uri         :: Prelude.String+data Application =+  Application+    { guiObjects :: GuiObjects+    , ioRefs :: IORefs+    , playbin :: GI.Gst.Element+    , playbinBus :: GI.Gst.Bus+    }++data GuiObjects =+  GuiObjects+    { window                           :: GI.Gtk.Window+    , fileChooserButtonLabel           :: GI.Gtk.Label+    , fileChooserDialog                :: GI.Gtk.Dialog+    , fileChooserEntry                 :: GI.Gtk.Entry+    , fileChooserWidget                :: GI.Gtk.FileChooserWidget+    , videoWidget                      :: GI.Gtk.Widget+    , bottomControlsGtkBox             :: GI.Gtk.Box+    , seekScale                        :: GI.Gtk.Scale+    , fileChooserButton                :: GI.Gtk.Button+    , playPauseButton                  :: GI.Gtk.Button+    , fullscreenButton                 :: GI.Gtk.Button+    , fileChooserCancelButton          :: GI.Gtk.Button+    , fileChooserOpenButton            :: GI.Gtk.Button+    , aboutButton                      :: GI.Gtk.Button+    , repeatCheckButton                :: GI.Gtk.CheckButton+    , volumeButton                     :: GI.Gtk.VolumeButton+    , playImage                        :: GI.Gtk.Image+    , pauseImage                       :: GI.Gtk.Image+    , windowWidthSelectionComboBoxText :: GI.Gtk.ComboBoxText+    , subtitleSelectionComboBoxText    :: GI.Gtk.ComboBoxText+    , bufferingSpinner                 :: GI.Gtk.Spinner+    , errorMessageDialog               :: GI.Gtk.MessageDialog+    , aboutDialog                      :: GI.Gtk.AboutDialog+    }++data IORefs =+  IORefs+    { isWindowFullScreenRef   :: IORef Bool+    , mouseMovedLastRef       :: IORef Integer+    , previousFileNamePathRef :: IORef Data.Text.Text+    , videoInfoRef            :: IORef VideoInfo+    }++data VideoInfo =+  VideoInfo+    { uri         :: Prelude.String     , isLocalFile :: Bool     , isVideo     :: Bool     , isSeekable  :: Bool     , videoWidth  :: Int     , videoHeight :: Int-  }+    } +data ScreensaverAndPowerManagementActions =+  ScreensaverAndPowerManagementActions+    { disabledPowerManagement     :: Bool+    , disabledXScreensaver        :: Bool+    , disabledCinnamonScreensaver :: Bool+    , disabledGnomeScreensaver    :: Bool+    }+ defaultVideoInfo :: VideoInfo-defaultVideoInfo  = VideoInfo {-      uri         = ""+defaultVideoInfo  =+  VideoInfo+    { uri         = ""     , isLocalFile = False     , isVideo     = False     , isSeekable  = False     , videoWidth  = 800     , videoHeight = 600-  }--data GuiObjects = GuiObjects {-      window :: GI.Gtk.Window-    , fileChooserButton :: GI.Gtk.Button-    , fileChooserButtonLabel :: GI.Gtk.Label-    , fileChooserDialog :: GI.Gtk.Dialog-    , fileChooserEntry :: GI.Gtk.Entry-    , fileChooserWidget :: GI.Gtk.FileChooserWidget-    , fileChooserCancelButton :: GI.Gtk.Button-    , fileChooserOpenButton :: GI.Gtk.Button-    , videoWidget :: GI.Gtk.Widget-    , bottomControlsGtkBox :: GI.Gtk.Box-    , seekScale :: GI.Gtk.Scale-    , playPauseButton :: GI.Gtk.Button-    , playImage :: GI.Gtk.Image-    , pauseImage :: GI.Gtk.Image-    , volumeButton :: GI.Gtk.VolumeButton-    , videoWidthSelectionComboBox :: GI.Gtk.ComboBoxText-    , subtitleSelectionComboBox :: GI.Gtk.ComboBoxText-    , fullscreenButton :: GI.Gtk.Button-    , bufferingSpinner :: GI.Gtk.Spinner-    , errorMessageDialog :: GI.Gtk.MessageDialog-    , aboutButton :: GI.Gtk.Button-    , aboutDialog :: GI.Gtk.AboutDialog-  }--data IORefs = IORefs {-      isWindowFullScreenRef :: IORef Bool-    , mouseMovedLastRef :: IORef Integer-    , previousFileNamePathRef :: IORef Data.Text.Text-    , videoInfoRef :: IORef VideoInfo-  }--data ScreensaverAndPowerManagementActions = ScreensaverAndPowerManagementActions {-      disabledPowerManagement :: Bool-    , disabledXScreensaver :: Bool-    , disabledCinnamonScreensaver :: Bool-    , disabledGnomeScreensaver :: Bool-  }--data Application = Application {-      guiObjects :: GuiObjects-    , ioRefs :: IORefs-    , playbin :: GI.Gst.Element-    , playbinBus :: GI.Gst.Bus-  }+    }
+ src/Reset.hs view
@@ -0,0 +1,97 @@+{-+  Movie Monad+  (C) 2017 David Lettier+  lettier.com+-}++{-# LANGUAGE OverloadedStrings #-}++module Reset where++import Control.Monad+import Data.Int+import Data.IORef+import Data.GI.Base.Properties+import qualified GI.Gtk+import qualified GI.Gst++import qualified Records as R+import Constants+import Mouse+import VideoInfo+import PlayPause+import Utils++resetApplication :: R.Application -> IO ()+resetApplication+  R.Application+    { R.guiObjects = guiObjects+    , R.playbin    = playbin+    , R.ioRefs     = ioRefs+    }+  = do+  resetIoRefs     ioRefs+  resetPlaybin    playbin+  resetGuiObjects guiObjects++resetIoRefs :: R.IORefs -> IO ()+resetIoRefs+  R.IORefs+    { R.videoInfoRef            = videoInfoRef+    , R.previousFileNamePathRef = previousFileNamePathRef+    }+  = do+  void $ resetVideoInfo videoInfoRef+  atomicWriteIORef previousFileNamePathRef ""++resetVideoInfo :: IORef R.VideoInfo -> IO R.VideoInfo+resetVideoInfo videoInfoRef = do+  let videoInfo = R.defaultVideoInfo+  saveVideoInfo videoInfoRef videoInfo+  return videoInfo++resetPlaybin :: GI.Gst.Element -> IO ()+resetPlaybin playbin = do+  void $ GI.Gst.elementSetState playbin GI.Gst.StateNull+  void $ Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" 0.0+  void $ Data.GI.Base.Properties.setObjectPropertyString playbin "uri" (Just "")++resetGuiObjects :: R.GuiObjects -> IO ()+resetGuiObjects+  R.GuiObjects+    { R.window                           = window+    , R.fileChooserButton                = fileChooserButton+    , R.fileChooserEntry                 = fileChooserEntry+    , R.fileChooserButtonLabel           = fileChooserButtonLabel+    , R.videoWidget                      = videoWidget+    , R.seekScale                        = seekScale+    , R.playPauseButton                  = playPauseButton+    , R.repeatCheckButton                = repeatCheckButton+    , R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText+    , R.subtitleSelectionComboBoxText    = subtitleSelectionComboBoxText+    , R.fullscreenButton                 = fullscreenButton+    , R.playImage                        = playImage+    , R.pauseImage                       = pauseImage+    , R.bottomControlsGtkBox             = bottomControlsGtkBox+    }+  = do+  desiredWindowWidth <- getDesiredWindowWidth windowWidthSelectionComboBoxText window+  styleContext <- GI.Gtk.widgetGetStyleContext bottomControlsGtkBox+  GI.Gtk.widgetSetSizeRequest window windowMinimumSize (-1)+  GI.Gtk.windowUnfullscreen window+  GI.Gtk.widgetHide videoWidget+  GI.Gtk.widgetHide bottomControlsGtkBox+  GI.Gtk.widgetHide seekScale+  GI.Gtk.widgetHide playPauseButton+  GI.Gtk.widgetHide repeatCheckButton+  GI.Gtk.widgetHide fullscreenButton+  GI.Gtk.widgetHide subtitleSelectionComboBoxText+  GI.Gtk.widgetShow fileChooserButton+  GI.Gtk.widgetShow windowWidthSelectionComboBoxText+  GI.Gtk.setToggleButtonActive repeatCheckButton False+  GI.Gtk.entrySetText fileChooserEntry ""+  GI.Gtk.labelSetText fileChooserButtonLabel "Open"+  GI.Gtk.windowResize window (fromIntegral desiredWindowWidth :: Int32) 1+  GI.Gtk.styleContextRemoveClass styleContext "movie-monad-fade-in"+  setCursor window Nothing+  setPlayPauseButton playPauseButton playImage pauseImage False
src/ScreensaverAndPowerManagement.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} 
src/Seek.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -8,7 +8,6 @@  import Control.Monad import Data.IORef-import Data.Int import Data.GI.Base.Signals import GI.GLib import GI.GObject@@ -16,73 +15,87 @@ import qualified GI.Gst  import qualified Records as R+import Playbin+import Utils  addSeekHandlers :: R.Application -> IO () addSeekHandlers-  R.Application {-        R.guiObjects = R.GuiObjects {-              R.seekScale = seekScale+  R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.seekScale = seekScale           }-      , R.ioRefs = R.IORefs {-              R.videoInfoRef = videoInfoRef-        }-      , R.playbin = playbin+    , R.ioRefs =+        R.IORefs+          { R.videoInfoRef = videoInfoRef+          }+    , R.playbin = playbin     }   = do-  seekScaleHandlerId <- GI.Gtk.onRangeValueChanged seekScale (+  seekScaleHandlerId <-+    GI.Gtk.onRangeValueChanged seekScale $       onRangeValueChanged         playbin         seekScale         videoInfoRef-    )-  void (-      GI.GLib.timeoutAdd GI.GLib.PRIORITY_DEFAULT 41 (-          updateSeekScale-            playbin-            seekScale-            seekScaleHandlerId-        )-    )+  void $+    GI.GLib.timeoutAdd GI.GLib.PRIORITY_DEFAULT 41 $+      updateSeekScale+        playbin+        seekScale+        seekScaleHandlerId -onRangeValueChanged ::-  GI.Gst.Element ->-  GI.Gtk.Scale ->-  IORef R.VideoInfo ->-  IO ()+onRangeValueChanged :: GI.Gst.Element -> GI.Gtk.Scale -> IORef R.VideoInfo -> IO () onRangeValueChanged   playbin   seekScale   videoInfoRef   = do-  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime-  when couldQueryDuration $ do-    percentage' <- GI.Gtk.rangeGetValue seekScale-    let percentage = percentage' / 100.0-    let position = fromIntegral (round ((fromIntegral duration :: Double) * percentage) :: Int) :: Int64-    void $ GI.Gst.elementSeekSimple playbin GI.Gst.FormatTime [ GI.Gst.SeekFlagsFlush ] position-    videoInfoGathered <- readIORef videoInfoRef-    -- When playing over a network (not local),-    -- sending too many asynchronous seek requests will cause GStreamer to error.-    -- Block until this seek request finishes which will block the main GTK main thread.-    -- Note that by blocking here, the seek scale will not slide.-    -- The user will have to point and click on the scale track.-    unless (R.isLocalFile videoInfoGathered) $ void $ GI.Gst.elementGetState playbin GI.Gst.CLOCK_TIME_NONE+  maybeDurationAndPosition <- queryPlaybinForDurationAndPosition playbin+  case maybeDurationAndPosition of+    (Just (duration, _)) -> do+      percentage <- clamp 0.0 1.0 . flip (/) 100.0 . clamp 0.0 100.0 <$> GI.Gtk.rangeGetValue seekScale+      let position =+            clamp 0 duration $+                doubleToInt64 $+                  int64toDouble duration * percentage+      void $ GI.Gst.elementSeekSimple playbin GI.Gst.FormatTime [ GI.Gst.SeekFlagsFlush ] position+      videoInfo <- readIORef videoInfoRef+      -- When playing over a network (not local),+      -- sending too many asynchronous seek requests will cause GStreamer to error.+      -- Block until this seek request finishes which will block the main GTK main thread.+      -- Note that by blocking here, the seek scale will not slide.+      -- The user will have to point and click on the scale track.+      unless (R.isLocalFile videoInfo) $+        void $+          GI.Gst.elementGetState playbin GI.Gst.CLOCK_TIME_NONE+    _ -> return () -updateSeekScale ::-  GI.Gst.Element ->-  GI.Gtk.Scale ->-  Data.GI.Base.Signals.SignalHandlerId ->-  IO Bool updateSeekScale+  ::  GI.Gst.Element+  ->  GI.Gtk.Scale+  ->  Data.GI.Base.Signals.SignalHandlerId+  ->  IO Bool+updateSeekScale   playbin   seekScale   seekScaleHandlerId   = do-  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime-  (couldQueryPosition, position) <- GI.Gst.elementQueryPosition playbin GI.Gst.FormatTime-  when (couldQueryDuration && couldQueryPosition && duration > 0) $ do-    let percentage = 100.0 * (fromIntegral position / fromIntegral duration :: Double)-    GI.GObject.signalHandlerBlock seekScale seekScaleHandlerId-    GI.Gtk.rangeSetValue seekScale percentage-    GI.GObject.signalHandlerUnblock seekScale seekScaleHandlerId+  maybeDurationAndPosition <- queryPlaybinForDurationAndPosition playbin+  case maybeDurationAndPosition of+    (Just (duration, position)) ->+      when (duration > 0) $ do+        let percentage = 100.0 * (int64toDouble position / int64toDouble duration)+        GI.GObject.signalHandlerBlock seekScale seekScaleHandlerId+        GI.Gtk.rangeSetValue seekScale percentage+        GI.GObject.signalHandlerUnblock seekScale seekScaleHandlerId+    _ -> return ()   return True++hideOrShowSeekScale :: GI.Gtk.Scale -> Bool -> IO ()+hideOrShowSeekScale seekScale True = do+  GI.Gtk.widgetSetSensitive seekScale True+  GI.Gtk.widgetShow seekScale+hideOrShowSeekScale seekScale False = do+  GI.Gtk.widgetSetSensitive seekScale False+  GI.Gtk.widgetHide seekScale
src/SubtitleSelector.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -17,12 +17,12 @@ addSubtitleSelectorHandler   application@R.Application {         R.guiObjects = R.GuiObjects {-              R.subtitleSelectionComboBox = subtitleSelectionComboBox+              R.subtitleSelectionComboBoxText = subtitleSelectionComboBoxText           }     }   = void (         GI.Gtk.onComboBoxChanged-          subtitleSelectionComboBox+          subtitleSelectionComboBoxText           (subtitleSelectorHandler application)       ) @@ -30,12 +30,12 @@ subtitleSelectorHandler   R.Application {         R.guiObjects = R.GuiObjects {-              R.subtitleSelectionComboBox = subtitleSelectionComboBox+              R.subtitleSelectionComboBoxText = subtitleSelectionComboBoxText           }       , R.playbin = playbin     }   = do-    maybeActiveId <- GI.Gtk.getComboBoxActiveId subtitleSelectionComboBox+    maybeActiveId <- GI.Gtk.getComboBoxActiveId subtitleSelectionComboBoxText     nText <- getTextStreamCount playbin     case maybeActiveId of       Nothing -> return ()
src/Uri.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -49,14 +49,16 @@         else if hasHttpUriScheme filePathName then filePathName else "http://" ++ filePathName  isLocalFile :: Prelude.String -> IO Bool-isLocalFile = Filesystem.isFile . Filesystem.Path.CurrentOS.fromText . Data.Text.pack . removeFileUriScheme+isLocalFile =+  Filesystem.isFile . Filesystem.Path.CurrentOS.fromText . Data.Text.pack . removeFileUriScheme  toAbsoluteUri :: String -> IO String toAbsoluteUri uri = do   cwd <- getWorkingDirectory-  let cwd' = case toText cwd of-              Right x -> x-              Left  y -> y+  let cwd' =+        case toText cwd of+          Right x -> x+          Left  y -> y   isLocal <- isLocalFile uri   if not isLocal     then return uri
src/Utils.hs view
@@ -1,11 +1,9 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} -{-# LANGUAGE ScopedTypeVariables #-}- module Utils where  import System.Exit@@ -13,6 +11,7 @@ import System.FilePath import Control.Monad import Control.Exception+import Text.Read import Data.List import Data.Text import Data.Int@@ -24,12 +23,36 @@ enumToInt32 :: (Enum a, Ord a) => a -> Int32 enumToInt32 enum = fromIntegral (fromEnum enum) :: Int32 +int64toDouble :: Int64 -> Double+int64toDouble i = fromIntegral i :: Double++doubleToInt64 :: Double -> Int64+doubleToInt64 d = fromIntegral (round d :: Int) :: Int64+ isTextEmpty :: Data.Text.Text -> Bool isTextEmpty = Data.Text.null . Data.Text.strip -getSelectedVideoWidth :: GI.Gtk.ComboBoxText -> IO Int-getSelectedVideoWidth = fmap (\ x -> read (Data.Text.unpack x) :: Int) . GI.Gtk.comboBoxTextGetActiveText+getDesiredWindowWidth :: GI.Gtk.ComboBoxText -> GI.Gtk.Window -> IO Int+getDesiredWindowWidth windowWidthSelectionComboBoxText window = do+  maybeSelectedWindowWidth <- getSelectedWindowWidth windowWidthSelectionComboBoxText+  case maybeSelectedWindowWidth of+    Just selectedWidth -> return selectedWidth+    _                  -> do+      (windowWidth, _) <- GI.Gtk.windowGetSize window+      return (fromIntegral windowWidth :: Int) +getSelectedWindowWidth :: GI.Gtk.ComboBoxText -> IO (Maybe Int)+getSelectedWindowWidth windowWidthSelectionComboBoxText = do+  activeId <- GI.Gtk.comboBoxGetActive windowWidthSelectionComboBoxText+  if activeId == (-1)+    then return Nothing+    else do+      string <-+        Data.Text.unpack <$>+          GI.Gtk.comboBoxTextGetActiveText+            windowWidthSelectionComboBoxText+      return (readMaybe string :: Maybe Int)+ linuxProcessIsRunning :: String -> IO Bool linuxProcessIsRunning processName = do   (_, out, _) <- safeRunProcessGetOutput "pgrep" ["-f", processName]@@ -39,23 +62,25 @@ spawnLinuxProcessAndDisown processCommand =   void $     System.Process.spawnCommand-      (-              "nohup "-          ++  processCommand-          ++  " </dev/null &>/dev/null & disown"-        )+      (  "nohup "+      ++ processCommand+      ++ " </dev/null &>/dev/null & disown"+      )  safeRunProcessGetOutput :: String -> [String] -> IO (System.Exit.ExitCode, String, String) safeRunProcessGetOutput processName args =-  catch (+  catch readProcess' catchError+  where+    readProcess' :: IO (System.Exit.ExitCode, String, String)+    readProcess' =       readProcessWithExitCode         processName         args         ""-    ) (\ (e :: Control.Exception.IOException) ->-        putStr (show e) >>-        return (ExitFailure 1, "", "")-      )+    catchError :: Control.Exception.IOException -> IO (System.Exit.ExitCode, String, String)+    catchError e = do+      putStr $ show e+      return (ExitFailure 1, "", "")  clamp :: Ord a => a -> a -> a -> a clamp minimum' maximum' el
src/VideoInfo.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -19,58 +19,64 @@ import Uri import Utils -getVideoInfoRaw :: Prelude.String -> IO (Maybe Prelude.String)-getVideoInfoRaw uri = do+getRawVideoInfo :: Prelude.String -> IO (Maybe Prelude.String)+getRawVideoInfo uri = do   (code, out, _) <- safeRunProcessGetOutput "gst-discoverer-1.0" [uri, "-v"]   if code == System.Exit.ExitSuccess     then return (Just out)     else return Nothing -getVideoInfo :: IORef R.VideoInfo -> Prelude.String -> IO R.VideoInfo-getVideoInfo videoInfoRef filePathName = do-  videoInfoGathered <- readIORef videoInfoRef-  uri <- addUriSchemeIfNone filePathName-  cacheDo (R.uri videoInfoGathered == uri) videoInfoGathered uri+processRawVideoInfo :: Maybe Prelude.String -> Prelude.String -> Maybe R.VideoInfo+processRawVideoInfo Nothing _ = Nothing+processRawVideoInfo (Just str) uri = do+  let text      = Data.Text.toLower $ Data.Text.pack str+  let textLines = Data.Text.lines text+  let videoInfo =+        R.VideoInfo+          { R.uri          = uri+          , R.isLocalFile  = hasFileUriScheme uri+          , R.isVideo      = "video: video/" `Data.Text.isInfixOf` text+          , R.isSeekable   = "yes" == getField seekableField textLines+          , R.videoWidth   = getDimension R.videoWidth  widthField textLines+          , R.videoHeight  = getDimension R.videoHeight heightField textLines+          }+  Just videoInfo   where-    widthField :: Data.Text.Text-    widthField = "width: "-    heightField :: Data.Text.Text-    heightField = "height: "+    widthField    :: Data.Text.Text+    widthField    = "width: "+    heightField   :: Data.Text.Text+    heightField   = "height: "     seekableField :: Data.Text.Text     seekableField = "seekable: "-    cacheDo :: Bool -> R.VideoInfo -> Prelude.String -> IO R.VideoInfo-    cacheDo True  videoInfoGathered _   = return videoInfoGathered-    cacheDo False _                 uri = do-      videoInfoRaw <- getVideoInfoRaw uri-      processVideoInfoRaw videoInfoRaw uri-    processVideoInfoRaw :: Maybe Prelude.String -> Prelude.String -> IO R.VideoInfo-    processVideoInfoRaw Nothing _ = do-      let videoInfoGathered = R.defaultVideoInfo-      atomicWriteIORef videoInfoRef videoInfoGathered-      return videoInfoGathered-    processVideoInfoRaw (Just str) uri = do-      let text      = Data.Text.toLower $ Data.Text.pack str-      let textLines = Data.Text.lines text-      let videoInfoGathered = R.VideoInfo {-              R.uri          = uri-            , R.isLocalFile  = hasFileUriScheme uri-            , R.isVideo      = "video: video/" `Data.Text.isInfixOf` text-            , R.isSeekable   = "yes" == getField seekableField textLines-            , R.videoWidth   = getDimension R.videoWidth  widthField textLines-            , R.videoHeight  = getDimension R.videoHeight heightField textLines-          }-      atomicWriteIORef videoInfoRef videoInfoGathered-      return videoInfoGathered     getDimension :: (R.VideoInfo -> Int) -> Data.Text.Text -> [Data.Text.Text] -> Int-    getDimension f field lines' = fromMaybe (-        f R.defaultVideoInfo-      ) (readMaybe (Data.Text.unpack $ getField field lines') :: Maybe Int)+    getDimension f field lines' =+      fromMaybe+        (f R.defaultVideoInfo)+        (readMaybe (Data.Text.unpack $ getField field lines') :: Maybe Int)     getField :: Data.Text.Text -> [Data.Text.Text] -> Data.Text.Text     getField field =-      Prelude.foldl (\ acc l ->+      Prelude.foldl+        (\ acc l ->           if not $ Data.Text.null acc             then acc-            else if field `Data.Text.isInfixOf` l-              then Data.Text.replace field "" $ Data.Text.strip l-              else ""-        ) ""+            else+              if field `Data.Text.isInfixOf` l+                then Data.Text.replace field "" $ Data.Text.strip l+                else ""+        )+      ""+getVideoInfo :: IORef R.VideoInfo -> Prelude.String -> IO (Maybe R.VideoInfo)+getVideoInfo videoInfoRef filePathName = do+  videoInfo <- readIORef videoInfoRef+  uri       <- addUriSchemeIfNone filePathName+  if R.uri videoInfo == uri+    then return $ Just videoInfo+    else do+      rawVideoInfo <- getRawVideoInfo uri+      case processRawVideoInfo rawVideoInfo uri of+        (Just videoInfo') -> return $ Just videoInfo'+        _ -> return Nothing++saveVideoInfo :: IORef R.VideoInfo -> R.VideoInfo -> IO ()+saveVideoInfo = atomicWriteIORef+
src/VideoSizeSelector.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -8,42 +8,76 @@  import Control.Monad import Data.Text+import Data.IORef+import qualified GI.GLib import qualified GI.Gtk  import qualified Records as R+import Reset import Window-import VideoInfo import Utils -addVideoSizeSelectorHandler :: R.Application -> IO ()-addVideoSizeSelectorHandler-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.videoWidthSelectionComboBox = videoWidthSelectionComboBox+addVideoSizeSelectorHandlers :: R.Application -> IO ()+addVideoSizeSelectorHandlers+  application@R.Application+    { R.guiObjects =+        guiObjects@R.GuiObjects+          { R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText           }     }-  = void (-        GI.Gtk.onComboBoxChanged-          videoWidthSelectionComboBox-          (videoSizeSelectionHandler application)-      )+  = do+  void $+    GI.Gtk.onComboBoxChanged+      windowWidthSelectionComboBoxText $+        videoSizeSelectionHandler application+  void $+    GI.GLib.timeoutAddSeconds+      GI.GLib.PRIORITY_DEFAULT+      1 $+        setToCustomIfNeeded guiObjects  videoSizeSelectionHandler :: R.Application -> IO () videoSizeSelectionHandler-  R.Application {-        R.guiObjects = guiObjects@R.GuiObjects {-              R.videoWidthSelectionComboBox = videoWidthSelectionComboBox-            , R.fileChooserEntry = fileChooserEntry+  application@R.Application+    { R.guiObjects =+        guiObjects@R.GuiObjects+          { R.window                           = window+          , R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText           }-      , R.ioRefs = R.IORefs {-              R.videoInfoRef = videoInfoRef-        }+    , R.ioRefs =+        R.IORefs+          { R.videoInfoRef = videoInfoRef+          }     }   = do-  filePathName <- Data.Text.unpack <$> GI.Gtk.entryGetText fileChooserEntry-  videoWidthSelection <- getSelectedVideoWidth videoWidthSelectionComboBox-  retrievedVideoInfo <- getVideoInfo videoInfoRef filePathName-  maybeWindowSize <- calculateWindowSize guiObjects videoWidthSelection retrievedVideoInfo+  videoInfo         <- readIORef videoInfoRef+  desiredWindowWidth <- getDesiredWindowWidth windowWidthSelectionComboBoxText window+  maybeWindowSize   <- calculateWindowSize guiObjects desiredWindowWidth videoInfo   case maybeWindowSize of-    Nothing -> resetWindow guiObjects+    Nothing              -> resetApplication application     Just (width, height) -> setWindowSize guiObjects width height++setToCustomIfNeeded :: R.GuiObjects -> IO Bool+setToCustomIfNeeded+  R.GuiObjects+    { R.window                      = window+    , R.windowWidthSelectionComboBoxText = windowWidthSelectionComboBoxText+    }+  = do+  (windowWidth', _)  <- GI.Gtk.windowGetSize window+  maybeSelectedWidth <- getSelectedWindowWidth windowWidthSelectionComboBoxText+  let windowWidth    = fromIntegral windowWidth' :: Int+  case maybeSelectedWidth of+    Just selectedWidth ->+      when (windowWidth /= selectedWidth) $+        GI.Gtk.comboBoxSetActive windowWidthSelectionComboBoxText (-1)+    Nothing -> do+      let windowWidthText = Data.Text.pack $ show windowWidth+      present <-+        GI.Gtk.comboBoxSetActiveId+          windowWidthSelectionComboBoxText $+            Just windowWidthText+      if present+        then return ()+        else GI.Gtk.comboBoxSetActive windowWidthSelectionComboBoxText (-1)+  return True
src/Window.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} @@ -21,66 +21,67 @@  import qualified Records as R import Constants+import Reset import Mouse import PlayPause-import Utils+import Seek  addWindowHandlers :: R.Application -> [R.Application -> IO ()] -> IO () addWindowHandlers-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.window = window-            , R.videoWidget = videoWidget+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.window      = window+          , R.videoWidget = videoWidget           }-      , R.ioRefs = R.IORefs {-              R.isWindowFullScreenRef = isWindowFullScreenRef+    , R.ioRefs =+        R.IORefs+          { R.isWindowFullScreenRef = isWindowFullScreenRef           }-      , R.playbin = playbin+    , R.playbin = playbin     }   onWidgetRealizeCallbacks-  =-  void (-      GI.Gtk.onWidgetRealize videoWidget (-          windowRealizedHandler-            application-            onWidgetRealizeCallbacks-        )-    ) >>-  void (-      GI.Gtk.onWidgetWindowStateEvent window (widgetWindowStateEventHandler isWindowFullScreenRef)-    ) >>-  void (-      GI.Gtk.onWidgetDestroy window (windowDestroyHandler playbin)-    ) >>-  void (-      GI.GLib.timeoutAddSeconds GI.GLib.PRIORITY_DEFAULT 1 (hideOnScreenControls application)-    )+  = do+  void $+    GI.Gtk.onWidgetRealize videoWidget $+      windowRealizedHandler+        application+        onWidgetRealizeCallbacks+  void $+    GI.Gtk.onWidgetWindowStateEvent window (widgetWindowStateEventHandler isWindowFullScreenRef)+  void $+    GI.Gtk.onWidgetDestroy window (windowDestroyHandler playbin)+  void $+    GI.GLib.timeoutAddSeconds GI.GLib.PRIORITY_DEFAULT 1 (adjustWindow application)  windowRealizedHandler-  :: R.Application-  -> [R.Application -> IO ()]-  -> GI.Gtk.WidgetRealizeCallback+  ::  R.Application+  ->  [R.Application -> IO ()]+  ->  GI.Gtk.WidgetRealizeCallback windowRealizedHandler-  application@R.Application {-        R.guiObjects = guiObjects@R.GuiObjects {-              R.videoWidget = videoWidget-            , R.seekScale = seekScale+  application@R.Application+    { R.guiObjects =+        guiObjects@R.GuiObjects+          { R.videoWidget = videoWidget+          , R.seekScale   = seekScale           }     }   onWidgetRealizeCallbacks   = do-  let eventMask = enumToInt32 GI.Gdk.EventMaskAllEventsMask+  let eventMask = [GI.Gdk.EventMaskAllEventsMask]   GI.Gtk.widgetAddEvents videoWidget eventMask-  GI.Gtk.widgetAddEvents seekScale eventMask-  resetWindow guiObjects+  GI.Gtk.widgetAddEvents seekScale   eventMask+  resetGuiObjects guiObjects   mapM_ (\ f -> f application) onWidgetRealizeCallbacks  widgetWindowStateEventHandler :: IORef Bool -> GI.Gdk.EventWindowState -> IO Bool widgetWindowStateEventHandler isWindowFullScreenRef eventWindowState = do   windowStates <- GI.Gdk.getEventWindowStateNewWindowState eventWindowState-  let isWindowFullScreen = Prelude.foldl (\ acc x ->-          acc || GI.Gdk.WindowStateFullscreen == x-        ) False windowStates+  let isWindowFullScreen =+        Prelude.foldl+          (\ acc x -> acc || GI.Gdk.WindowStateFullscreen == x)+          False+          windowStates   atomicWriteIORef isWindowFullScreenRef isWindowFullScreen   return True @@ -90,53 +91,59 @@   _ <- GI.Gst.objectUnref playbin   GI.Gtk.mainQuit -hideOnScreenControls :: R.Application -> IO Bool-hideOnScreenControls-  application@R.Application {-        R.guiObjects = R.GuiObjects {-              R.window = window-            , R.fileChooserButton = fileChooserButton-            , R.bottomControlsGtkBox = bottomControlsGtkBox+adjustWindow :: R.Application -> IO Bool+adjustWindow+  application@R.Application+    { R.guiObjects =+        R.GuiObjects+          { R.window               = window+          , R.fileChooserButton    = fileChooserButton+          , R.bottomControlsGtkBox = bottomControlsGtkBox           }-      , R.ioRefs = R.IORefs {-              R.videoInfoRef = videoInfoRef-            , R.mouseMovedLastRef = mouseMovedLastRef+    , R.ioRefs =+        R.IORefs+          { R.videoInfoRef      = videoInfoRef+          , R.mouseMovedLastRef = mouseMovedLastRef           }-      , R.playbin = playbin+    , R.playbin = playbin     }   = do-  videoInfoGathered <- readIORef videoInfoRef-  let isVideo = R.isVideo videoInfoGathered-  mouseMovedLast <- readIORef mouseMovedLastRef-  timeNow <- fmap round getPOSIXTime+  videoInfo            <- readIORef videoInfoRef+  mouseMovedLast       <- readIORef mouseMovedLastRef+  timeNow              <- fmap round getPOSIXTime   (_, playBinState, _) <- GI.Gst.elementGetState playbin (fromIntegral GI.Gst.MSECOND :: GHC.Word.Word64)   let isPlaying = GI.Gst.StatePlaying == playBinState-  let delta = timeNow - mouseMovedLast+  let delta     = timeNow - mouseMovedLast+  let isVideo   = R.isVideo videoInfo   when (isPlaying && isVideo && delta >= hideOnScreenControlsInterval) $ do     GI.Gtk.widgetHide fileChooserButton     GI.Gtk.widgetHide bottomControlsGtkBox+    styleContext <- GI.Gtk.widgetGetStyleContext bottomControlsGtkBox+    GI.Gtk.styleContextRemoveClass styleContext "movie-monad-fade-in"     setCursor window (Just "none")     atomicWriteIORef mouseMovedLastRef timeNow-    fillWindowWithVideo application+  fillWindowWithVideo application   return True  fillWindowWithVideo :: R.Application -> IO () fillWindowWithVideo-  R.Application {-        R.guiObjects = guiObjects@R.GuiObjects {-              R.window = window+  R.Application+    { R.guiObjects =+        guiObjects@R.GuiObjects+          { R.window = window           }-      , R.ioRefs = R.IORefs {-              R.videoInfoRef = videoInfoRef-            , R.isWindowFullScreenRef = isWindowFullScreenRef+    , R.ioRefs =+        R.IORefs+          { R.videoInfoRef          = videoInfoRef+          , R.isWindowFullScreenRef = isWindowFullScreenRef           }     }   = do-  isWindowFullScreen <- readIORef isWindowFullScreenRef-  unless isWindowFullScreen $ do-    videoInfoGathered <- readIORef videoInfoRef-    (width, _) <- GI.Gtk.windowGetSize window-    maybeWindowSize <- calculateWindowSize guiObjects (fromIntegral width :: Int) videoInfoGathered+  isWindowFullScreen   <- readIORef isWindowFullScreenRef+  videoInfo            <- readIORef videoInfoRef+  when (R.isVideo videoInfo && not isWindowFullScreen) $ do+    (width, _)      <- GI.Gtk.windowGetSize window+    maybeWindowSize <- calculateWindowSize guiObjects (fromIntegral width :: Int) videoInfo     when (isJust maybeWindowSize) $ do       let (windowWidth, windowHeight) = fromMaybe (0, 0) maybeWindowSize       setWindowSize guiObjects windowWidth windowHeight@@ -145,67 +152,68 @@ calculateWindowSize :: R.GuiObjects -> Int -> R.VideoInfo -> IO (Maybe (Int32, Int32)) calculateWindowSize _ _ R.VideoInfo { R.isVideo = False } = return Nothing calculateWindowSize-  R.GuiObjects {-        R.fileChooserButton = fileChooserButton-      , R.bottomControlsGtkBox = bottomControlsGtkBox+  R.GuiObjects+    { R.fileChooserButton = fileChooserButton     }   desiredWidth-  R.VideoInfo { R.videoWidth = videoWidth, R.videoHeight = videoHeight }+  R.VideoInfo+    { R.videoWidth  = videoWidth+    , R.videoHeight = videoHeight+    }   = do-  fileChooserButtonIsVisible    <- GI.Gtk.widgetGetVisible fileChooserButton-  bottomControlsGtkBoxIsVisible <- GI.Gtk.widgetGetVisible bottomControlsGtkBox+  fileChooserButtonIsVisible <- GI.Gtk.widgetGetVisible fileChooserButton   fileChooserButtonHeight    <- GI.Gtk.widgetGetAllocation fileChooserButton >>= GI.Gdk.getRectangleHeight-  bottomControlsGtkBoxHeight <- GI.Gtk.widgetGetAllocation bottomControlsGtkBox >>= GI.Gdk.getRectangleHeight-  let videoWidthDouble = fromIntegral videoWidth :: Double+  let videoWidthDouble  = fromIntegral videoWidth  :: Double   let videoHeightDouble = fromIntegral videoHeight :: Double-  let ratio = if videoWidthDouble <= 0.0 then 0.0 else videoHeightDouble / videoWidthDouble+  let ratio =+        if videoWidthDouble <= 0.0+          then 0.0+          else videoHeightDouble / videoWidthDouble   let desiredWidthDouble = fromIntegral desiredWidth :: Double-  let topMargin = if fileChooserButtonIsVisible-                    then (fromIntegral fileChooserButtonHeight :: Double)-                    else 0.0-  let bottomMargin = if bottomControlsGtkBoxIsVisible-                        then (fromIntegral bottomControlsGtkBoxHeight :: Double)-                        else 0.0+  let topMargin =+        if fileChooserButtonIsVisible+          then (fromIntegral fileChooserButtonHeight :: Double)+          else 0.0+  let bottomMargin = 0.0   let height = topMargin + (desiredWidthDouble * ratio) + bottomMargin-  return (Just (fromIntegral desiredWidth:: Int32, round height :: Int32))+  return $ Just (fromIntegral desiredWidth:: Int32, round height :: Int32)  setWindowSize :: R.GuiObjects -> Int32 -> Int32 -> IO () setWindowSize-  R.GuiObjects {-        R.window = window+  R.GuiObjects+    { R.window = window     }   width   height   =   GI.Gtk.windowResize window width (if height <= 0 then 1 else height) -resetWindow :: R.GuiObjects -> IO ()-resetWindow-  guiObjects@R.GuiObjects {-        R.window = window-      , R.fileChooserButton = fileChooserButton-      , R.videoWidget = videoWidget-      , R.seekScale = seekScale-      , R.playPauseButton = playPauseButton-      , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox-      , R.subtitleSelectionComboBox = subtitleSelectionComboBox-      , R.fullscreenButton = fullscreenButton-      , R.playImage = playImage-      , R.pauseImage = pauseImage-      , R.bottomControlsGtkBox = bottomControlsGtkBox+setupWindowForPlayback :: R.GuiObjects -> Bool -> Bool -> Int32 -> Int32 -> IO ()+setupWindowForPlayback+  guiObjects@R.GuiObjects+    { R.window               = window+    , R.videoWidget          = videoWidget+    , R.bottomControlsGtkBox = bottomControlsGtkBox+    , R.seekScale            = seekScale+    , R.playPauseButton      = playPauseButton+    , R.repeatCheckButton    = repeatCheckButton+    , R.fullscreenButton     = fullscreenButton+    , R.playImage            = playImage+    , R.pauseImage           = pauseImage     }+  isSeekable+  isWindowFullScreen+  windowWidth+  windowHeight   = do-  videoWidthSelection <- getSelectedVideoWidth videoWidthSelectionComboBox-  let width = fromIntegral videoWidthSelection :: Int32-  GI.Gtk.windowUnfullscreen window-  GI.Gtk.widgetHide videoWidget-  GI.Gtk.widgetHide seekScale-  GI.Gtk.widgetHide playPauseButton-  GI.Gtk.widgetHide fullscreenButton-  GI.Gtk.widgetHide subtitleSelectionComboBox-  GI.Gtk.widgetShow fileChooserButton   GI.Gtk.widgetShow bottomControlsGtkBox-  GI.Gtk.widgetShow videoWidthSelectionComboBox-  setCursor window Nothing-  setPlayPauseButton playPauseButton playImage pauseImage False-  setWindowSize guiObjects width 0+  GI.Gtk.widgetShow videoWidget+  GI.Gtk.widgetShow playPauseButton+  GI.Gtk.widgetShow repeatCheckButton+  GI.Gtk.widgetShow fullscreenButton+  GI.Gtk.setToggleButtonActive repeatCheckButton False+  GI.Gtk.widgetSetSizeRequest window windowMinimumSize 100+  setPlayPauseButton playPauseButton playImage pauseImage True+  unless isWindowFullScreen $+    setWindowSize guiObjects windowWidth windowHeight+  hideOrShowSeekScale seekScale isSeekable
src/c/gst-ffi.c view
@@ -1,6 +1,6 @@ /*   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com */ 
src/c/gst-ffi.h view
@@ -1,6 +1,6 @@ /*   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com */ 
+ src/data/about-icon.svg view
@@ -0,0 +1,267 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<svg+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:xlink="http://www.w3.org/1999/xlink"+   width="30"+   height="30"+   viewBox="0 0 30 30"+   version="1.1"+   id="svg8">+  <defs+     id="defs2">+    <linearGradient+       id="linearGradient5445">+      <stop+         style="stop-color:#57ace3;stop-opacity:1;"+         offset="0"+         id="stop5441" />+      <stop+         style="stop-color:#57ace3;stop-opacity:0;"+         offset="1"+         id="stop5443" />+    </linearGradient>+    <marker+       orient="auto"+       refY="0"+       refX="0"+       id="Arrow1Mend"+       style="overflow:visible">+      <path+         id="path10335"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         style="fill:#57ace3;fill-opacity:1;fill-rule:evenodd;stroke:#57ace3;stroke-width:1.00000003pt;stroke-opacity:1"+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />+    </marker>+    <marker+       orient="auto"+       refY="0"+       refX="0"+       id="marker10589"+       style="overflow:visible">+      <path+         id="path10326"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         style="fill:#57ace3;fill-opacity:1;fill-rule:evenodd;stroke:#57ace3;stroke-width:1.00000003pt;stroke-opacity:1"+         transform="matrix(0.8,0,0,0.8,10,0)" />+    </marker>+    <linearGradient+       id="linearGradient10200">+      <stop+         id="stop10196"+         offset="0"+         style="stop-color:#57ace3;stop-opacity:1" />+      <stop+         id="stop10198"+         offset="1"+         style="stop-color:#e0437f;stop-opacity:0.89019608" />+    </linearGradient>+    <linearGradient+       id="linearGradient8935"+       osb:paint="solid">+      <stop+         style="stop-color:#373737;stop-opacity:1;"+         offset="0"+         id="stop8933" />+    </linearGradient>+    <linearGradient+       id="linearGradient5282">+      <stop+         style="stop-color:#814dd2;stop-opacity:1;"+         offset="0"+         id="stop5278" />+      <stop+         style="stop-color:#b46bd3;stop-opacity:0.89019608"+         offset="1"+         id="stop5280" />+    </linearGradient>+    <marker+       orient="auto"+       refY="0"+       refX="0"+       id="Arrow1Lend"+       style="overflow:visible">+      <path+         id="path4997"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />+    </marker>+    <marker+       orient="auto"+       refY="0"+       refX="0"+       id="Arrow1Lstart"+       style="overflow:visible">+      <path+         id="path4994"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"+         transform="matrix(0.8,0,0,0.8,10,0)" />+    </marker>+    <linearGradient+       xlink:href="#linearGradient5282"+       id="linearGradient5284"+       x1="-119.13808"+       y1="53.642838"+       x2="-64.290207"+       y2="53.285694"+       gradientUnits="userSpaceOnUse" />+    <linearGradient+       xlink:href="#linearGradient5282"+       id="linearGradient5300"+       gradientUnits="userSpaceOnUse"+       x1="-119.13808"+       y1="53.642838"+       x2="-58.218777"+       y2="55.071407" />+    <linearGradient+       xlink:href="#linearGradient5282"+       id="linearGradient5352"+       gradientUnits="userSpaceOnUse"+       x1="-119.13808"+       y1="53.642838"+       x2="-58.218777"+       y2="55.071407" />+    <linearGradient+       xlink:href="#linearGradient5282"+       id="linearGradient5354"+       gradientUnits="userSpaceOnUse"+       x1="-119.13808"+       y1="53.642838"+       x2="-64.290207"+       y2="53.285694" />+    <linearGradient+       xlink:href="#linearGradient10200"+       id="linearGradient5260"+       x1="61.251041"+       y1="250.69791"+       x2="128.98438"+       y2="250.69791"+       gradientUnits="userSpaceOnUse"+       gradientTransform="matrix(1.1521699,0,0,1.1943224,-10.9053,-54.269335)" />+    <clipPath+       clipPathUnits="userSpaceOnUse"+       id="clipPath5388">+      <g+         id="g5394">+        <path+           style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.23003563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"+           d="m 125.5315,249.78764 c -3.34965,-1.30393 -6.69931,-2.60787 -10.04896,-3.9118 5.21848,-2.15262 10.43696,-4.30525 15.65545,-6.45787 -0.92835,-2.01253 -1.85669,-4.02505 -2.78504,-6.03758 -6.83922,2.90641 -13.67843,5.81282 -20.51763,8.71921 0.0104,2.54721 0.0208,5.09442 0.0312,7.64163 6.86079,2.8724 13.7216,5.74479 20.58242,8.61717 0.90892,-2.11466 1.81783,-4.22931 2.72675,-6.34397 -1.76975,-0.68894 -3.53951,-1.37789 -5.30926,-2.06683 m -2.62477,-4.90221 c 3.04901,-1.25752 6.09801,-2.51505 9.14702,-3.77257 -0.92751,-2.01274 -1.85501,-4.02549 -2.78252,-6.03823 -2.59416,1.10259 -5.18831,2.20519 -7.78247,3.30778 m 5.56493,-1.53082 c -5.40972,2.29966 -10.81943,4.59932 -16.22916,6.89899 0.0117,2.54697 0.0234,5.09394 0.0352,7.64091 6.86463,2.8717 13.72924,5.74341 20.59384,8.61511 0.91009,-2.11486 1.82018,-4.22973 2.73027,-6.3446 -5.23684,-2.04024 -10.47368,-4.08049 -15.71053,-6.12073 0.75831,-0.31271 1.51662,-0.62542 2.27492,-0.93812 m -14.17992,-7.36348 c -0.76309,-1.65493 -1.52619,-3.30987 -2.28928,-4.9648 -6.839321,2.90343 -13.678636,5.80688 -20.517944,8.71032 0.01054,2.5462 0.02107,5.0924 0.03161,7.6386 6.860547,2.86946 13.721102,5.73892 20.581664,8.60838 0.90903,-2.11556 1.81807,-4.23112 2.72711,-6.34668 -5.23993,-2.04195 -10.479853,-4.08389 -15.719771,-6.12583 3.538493,-1.46115 7.076989,-2.9223 10.615481,-4.38345 m -9.578034,6.75815 c -0.379995,-0.14802 -0.759989,-0.29603 -1.139983,-0.44404 5.220982,-2.15291 10.441957,-4.30583 15.662927,-6.45875 -0.54602,-1.18498 -1.09203,-2.36995 -1.63805,-3.55493 m -30.75959,4.52156 c 2.327107,-4.2e-4 4.654213,-8.4e-4 6.981318,-0.001 4.72e-4,-2.42569 9.42e-4,-4.85139 0.0014,-7.27708 -5.608879,-0.001 -11.217765,-0.002 -16.826659,-0.003 4.62e-4,2.42483 9.24e-4,4.84967 0.0014,7.2745 5.611028,-9.8e-4 11.22205,-0.002 16.833063,-0.003 4.54e-4,-2.42568 9.07e-4,-4.85135 0.0014,-7.27703 -1.723988,-3e-4 -3.447976,-5.9e-4 -5.171966,-8.9e-4 m -2.024007,22.444 c 2.816132,-10e-6 5.632262,-2e-5 8.448391,-3e-5 4.56e-4,-2.64572 9.1e-4,-5.29144 0.0014,-7.93716 -5.637754,-2e-5 -11.275514,-5e-5 -16.913281,-7e-5 4.48e-4,2.6457 8.94e-4,5.29139 0.0013,7.93709 5.639668,-2e-5 11.279329,-5e-5 16.918984,-7e-5 4.39e-4,-2.64571 8.77e-4,-5.29143 0.0013,-7.93714 -0.03972,0 -0.07944,0 -0.119166,0 m 27.325493,-18.3087 -17.328909,7.36254 m 21.261659,1.45287 -0.93476,0.39715 m 0.92531,12.30443 14.19828,5.93971"+           id="path5390" />+        <path+           id="path5392"+           d="m 650.1385,82.874465 c -10.14856,3.782654 -20.17926,7.700083 -30.11698,11.72366 3e-5,-0.006 -0.20482,33.232065 -0.20478,33.226075 10.46549,4.53108 20.80642,9.17856 30.98016,13.96537 M 633.88611,89.913445 c -4.37599,1.711249 -8.73217,3.445238 -13.07064,5.199586 10e-6,-4.22e-4 -0.0731,11.184859 -0.0731,11.184439 m 0.3725,-3.80674 c 2e-5,-0.002 -0.17666,25.85227 -0.17665,25.8502 14.60689,6.33968 28.96767,12.90811 42.96621,19.76778 m -31.32028,-14.07007 c 25.19819,11.26699 49.55187,23.27873 72.44648,36.3659 1.42471,-2.72961 2.86128,-5.45544 4.31003,-8.17738 m -6.9747,6.68407 c 0.92932,0.52537 1.85629,1.05248 2.78088,1.58133 4.58589,-8.78001 9.29471,-17.52088 14.13698,-26.21901 -6.95333,-3.77163 -14.01978,-7.44184 -21.18454,-11.01929 m 1.28755,-0.18569 c -14.81139,-7.42465 -30.04545,-14.44997 -45.57119,-21.15245 12.62262,-4.62919 25.39834,-9.03993 38.37684,-13.17341 m -18.736,22.83496 c -6.26352,-2.87301 -12.58606,-5.68603 -18.95852,-8.44437 23.14013,-8.47831 46.79246,-16.218619 71.2638,-22.85755 -0.22881,-0.662606 -0.45833,-1.325109 -0.68856,-1.987508 M 654.01463,113.139 c -2.7e-4,-1.2e-4 -0.7157,-0.30906 -0.71597,-0.30917 23.13517,-8.5031 46.78037,-16.274199 71.2423,-22.950019 -2.81543,-8.107892 -5.73743,-16.200324 -8.75838,-24.277065 m -26.0906,33.266668 C 700.9826,95.2376 712.42531,91.81337 724.05294,88.63561 723.6003,87.337599 723.14495,86.039985 722.6869,84.742768 m -0.61698,6.067377 c 0.81695,-0.226028 1.6348,-0.450842 2.45357,-0.674428 -3.17915,-9.162957 -6.49443,-18.306184 -9.93482,-27.429347 -0.62065,0.179639 -1.24074,0.359926 -1.86026,0.540855 m 11.24057,25.511777 c -3e-5,7e-6 0.25989,-0.07102 0.25987,-0.07101 -3.19279,-9.161294 -6.52126,-18.302817 -9.97442,-27.424233 -10.91387,3.159213 -21.65318,6.518244 -32.24401,10.04705 m 11.85645,-2.486221 c -23.89063,7.594747 -46.99669,16.092552 -69.6095,25.158099 m -0.43504,1.234896 c -0.86163,0.346106 -1.72255,0.693034 -2.58277,1.040765 0,-6.34e-4 -0.0817,11.715582 -0.0816,11.714952 m -1.1452,-4.62256 c 2e-5,-0.003 -0.15748,25.97022 -0.15747,25.96764 19.67826,8.52466 38.91018,17.46103 57.41168,26.96201 m -5.18017,-4.09637 c 11.17724,5.62986 22.1038,11.4573 32.71864,17.51516 1.06549,-2.04103 2.13762,-4.07996 3.21651,-6.11673 m -16.16776,-0.69646 c 4.49775,2.43586 8.94607,4.90905 13.34063,7.42189 4.58695,-8.78083 9.2969,-17.5225 14.14034,-26.22142 -13.91794,-7.55008 -28.28862,-14.69392 -42.99342,-21.50079 m 3.21074,0.98686 c -8.79479,-4.11181 -17.71249,-8.10054 -26.7275,-11.98114 9.58226,-3.52312 19.25253,-6.92117 29.03252,-10.1684 m -6.29117,3.40887 c 16.00699,-5.451542 32.29632,-10.509544 48.965,-15.0591 -2.7328,-7.869445 -5.56598,-15.724327 -8.49254,-23.564436 m 9.71391,23.600286 c 0,0 0.0757,-0.02053 0.0757,-0.02053 -3.16863,-9.16775 -6.47406,-18.315717 -9.90529,-27.443567 -14.81942,4.262317 -29.3167,8.895683 -43.55719,13.824889 m 47.96342,-1.486613 c -1.4697,-4.050884 -2.96505,-8.097851 -4.48508,-12.14087 -10.36572,2.9834 -20.57391,6.148352 -30.64696,9.469099 m 34.56573,1.426708 c -1.47522,-4.049947 -2.97598,-8.095973 -4.5013,-12.138051 -19.92422,5.742688 -39.26545,12.153458 -58.18225,19.049877 m 27.30054,-7.799146 c -7.20357,2.383909 -14.33829,4.847277 -21.41236,7.380658 m 13.91885,-6.240903 C 658.33096,80.00152 640.22123,86.8241 622.41471,93.993846 M 522.52817,91.33976 c -3.71543,1.71506 -7.42434,3.436 -11.12792,5.16192 -5e-5,-0.0011 0.51202,11.70155 0.51197,11.70043 m -1.1665,-9.974259 c -2e-5,7e-6 -0.1003,0.04677 -0.10032,0.04678 -4.8e-4,-0.01106 1.45486,33.189159 1.45438,33.178099 14.55619,5.39325 29.02314,10.86367 43.33703,16.46536 m -44.30747,-34.95594 c -1.2e-4,-0.003 0.7663,17.43323 0.76618,17.43044 2.49473,0.92408 4.98688,1.85041 7.47614,2.77928 m -7.7994,-15.73106 c -6e-5,-0.001 0.55121,12.57744 0.55114,12.57602 16.53443,6.12668 32.95588,12.35293 49.17089,18.75796 m -49.99946,-25.64531 c -2e-5,-4.2e-4 0.29602,6.72016 0.296,6.71974 21.69281,8.03096 43.19288,16.23183 64.28933,24.78141 m -55.73533,-22.29122 c 16.28128,6.07809 32.43879,12.26569 48.38274,18.6389 m -29.93723,-10.07554 c 13.09037,4.99891 26.07571,10.08848 38.90831,15.30914 4.92668,2.00718 9.8291,4.03142 14.70284,6.07511 m -42.55877,-18.2672 c 9.34563,3.62215 18.63091,7.2968 27.83828,11.03885 8.29429,3.37568 16.52059,6.79982 24.65785,10.28374 2.01069,-4.82106 4.0379,-9.63863 6.08313,-14.45221 m -27.09237,6.5496 c 6.76797,2.77515 13.48798,5.5838 20.1485,8.43215 3.83273,-9.20444 7.72504,-18.39642 11.68744,-27.57238 -2.66279,-1.06701 -5.33349,-2.1269 -8.01145,-3.18005 m -17.67348,24.80831 c -4e-4,-1.7e-4 0.71089,0.29523 0.71049,0.29506 m 0.1423,0.48985 c 4.49734,1.87003 8.97142,3.75596 13.41882,5.65962 m -10.07756,-3.99132 c 3.3045,1.3838 6.59589,2.77646 9.8728,4.17875 3.83071,-9.20427 7.72094,-18.39609 11.68121,-27.57188 -4.68156,-1.87698 -9.38775,-3.73191 -14.11494,-5.56693 m -3.47113,28.46889 c 2.5033,1.05562 4.99884,2.11653 7.48603,3.18308 3.84259,-9.20093 7.74586,-18.38896 11.72032,-27.56052 -12.40258,-4.98562 -24.97809,-9.81439 -37.65896,-14.52577 -3.82029,-1.41856 -7.65021,-2.82596 -11.48865,-4.22321 m 48.53743,21.60948 c -1.7e-4,3.9e-4 0.39562,-0.91482 0.39545,-0.91442 -12.31989,-4.95543 -24.81309,-9.75643 -37.41315,-14.4418 0,0 0,0 0,0 -0.002,-6.7e-4 -1.5944,-0.59165 -1.59619,-0.59232 m 14.92841,5.28033 c -4.43048,-1.68898 -8.87723,-3.36174 -13.33731,-5.02001 -10.81095,-4.01704 -21.70034,-7.94452 -32.64285,-11.80547 3.60406,-1.59938 7.21381,-3.19151 10.83032,-4.77558 m 3.29087,8.88546 c -4.50086,-1.62052 -9.01254,-3.22799 -13.53326,-4.82404 10.49312,-4.65332 21.03521,-9.24496 31.65268,-13.754409 6.66805,-2.833165 13.36682,-5.635506 20.10392,-8.398021 m -42.45579,26.47275 c -2.78093,-0.99529 -5.56581,-1.98581 -8.35423,-2.97194 3.53011,-1.56467 7.06571,-3.12228 10.60782,-4.67206 m -6.28217,1.12112 c 8.75211,-3.85687 17.54116,-7.66857 26.38242,-11.423276 6.20558,-2.636402 12.43772,-5.246109 18.70256,-7.821867 M 565.235,104.41462 c 1.69001,-0.73028 3.38168,-1.45864 5.07513,-2.185 m -3.7095,0.27093 c 3.32978,-1.43549 6.66623,-2.863461 10.01016,-4.283286 12.05562,-5.120857 24.21185,-10.14093 36.5136,-15.007053 -3.81958,-8.195982 -7.69977,-16.37731 -11.6316,-24.543711 m 7.66441,15.992954 c -2.66865,-5.659947 -5.36479,-11.312843 -8.08546,-16.958599 -6.13403,2.520537 -12.22664,5.07595 -18.28339,7.659824 m 21.84963,0.238651 c -1.20001,-2.513838 -2.40514,-5.026273 -3.61513,-7.537296 -5.45027,2.240821 -10.8679,4.509159 -16.25681,6.80051 m 12.33523,-6.475731 c -6.71383,2.781303 -13.37891,5.602978 -20.0026,8.456552 m 5.22342,-1.425141 c -2.06169,0.880321 -4.11923,1.763923 -6.17285,2.650552 -21.36486,9.204436 -42.34641,18.729808 -63.15655,28.416385 m 73.147,-32.390491 c -3.33946,1.415917 -6.66778,2.840803 -9.98587,4.27359 -14.08986,6.07131 -28.0133,12.282249 -41.83112,18.58698 m 34.13476,-15.102029 c -13.55068,5.91156 -26.95662,11.945573 -40.2726,18.06074 m 39.16746,-18.497686 c -10.0099,4.372426 -19.94106,8.811076 -29.81557,13.299296 m 19.59876,-7.374448 c -15.5269,6.890006 -30.88255,13.927354 -46.15087,21.048813 -1e-4,-0.0022 0.70303,16.025174 0.70293,16.022934 m 0.87606,-18.197656 c -1.8e-4,8.6e-5 -0.35811,0.166728 -0.35829,0.166814 m 1.0845,0.822688 c -0.004,0.0019 -1.6924,0.788526 -1.69655,0.790459 -1.3e-4,-0.0029 0.8415,19.229225 0.84138,19.226345 m 0.27161,-20.309876 c -7.4e-4,3.43e-4 -0.7139,0.332478 -0.71464,0.332822 -4.1e-4,-0.0093 1.44551,33.189744 1.44511,33.180454 11.28037,4.18384 22.50704,8.41503 33.65029,12.71877 m -35.32335,-28.4736 c -1.1e-4,-0.002 0.69833,15.95299 0.69823,15.95058 17.67847,6.5524 35.2262,13.2193 52.52889,20.09755 m -13.02772,-5.47913 c 6.6484,2.58631 13.26536,5.19988 19.84453,7.84608 m -14.54076,-5.47895 c 3.37538,1.32474 6.74215,2.65692 10.09948,3.99724 m -5.39576,-1.55957 c 5.19891,2.05665 10.37627,4.13181 15.52899,6.22812 7.99932,3.25904 15.93464,6.56309 23.78707,9.92231 3.57334,-8.58229 7.19846,-17.15376 10.88388,-25.71151 m -48.34699,8.62713 c 4.56751,1.81107 9.1183,3.63669 13.65027,5.47863 8.54576,3.47808 17.01964,7.00763 25.39866,10.60104 1.91828,-4.59494 3.85169,-9.18667 5.80151,-13.77474 m -41.52622,0.53198 c 3.46016,1.38089 6.91028,2.77041 10.34944,4.16935 8.32169,3.38981 16.57422,6.82834 24.73632,10.32703 3.83666,-9.20168 7.7334,-18.39069 11.70074,-27.56344 -5.91972,-2.37789 -11.87907,-4.72026 -17.87072,-7.03142 m 13.95401,4.36254 c -0.002,-8.8e-4 -1.79942,-0.71399 -1.80164,-0.71487 m 0.2527,1.27065 c -10.383,-4.11626 -20.88016,-8.12817 -31.45225,-12.05866 -10.56518,-3.92547 -21.20529,-7.76542 -31.89671,-11.54133 -0.0133,0.006 3.635,-1.60838 3.62171,-1.60249 m 48.06573,20.84643 c -4.71759,-1.82299 -9.45546,-3.6265 -14.21001,-5.41264 m 2.40102,-0.24272 c -2.66027,-1.00343 -5.32589,-2.00128 -7.99623,-2.99393 -10.42273,-3.87217 -20.91774,-7.66119 -31.46237,-11.38766 -0.0155,0.007 3.94408,-1.74398 3.92858,-1.73711 m 20.40457,11.06315 c -7.93034,-2.90965 -15.89953,-5.77414 -23.89767,-8.60246 5.07406,-2.24838 10.15954,-4.48219 15.25944,-6.69909 m -13.61623,6.67486 c -0.009,-0.003 -3.05456,-1.0798 -3.06326,-1.08288 10.62529,-4.71174 21.30067,-9.36051 32.05354,-13.925016 7.17818,-3.048345 14.3921,-6.060956 21.6512,-9.026612 m -8.83851,3.867272 c 7.88156,-3.275909 15.81224,-6.50137 23.80435,-9.661803 -0.90946,-1.951272 -1.82236,-3.901714 -2.73857,-5.851321 m 2.26344,3.123577 c -3.69749,-7.913834 -7.45102,-15.813948 -11.25251,-23.700094 -8.52807,3.498878 -16.97554,7.065434 -25.35735,10.682462 -4.89403,2.107372 -9.76789,4.231576 -14.62411,6.370693 M 445.26039,104.95921 c 8.95388,-0.41892 2.48979,-0.11655 11.44367,-0.53548 m -10.32304,0.17021 c 17.33763,-0.81148 34.68486,-1.62857 52.04397,-2.35972 0,2e-5 -0.46265,-11.003332 -0.46265,-11.003312 m -45.86181,13.509922 c 10.91924,-0.51039 21.84207,-1.01902 32.76909,-1.50304 m -10.72124,-0.82499 c 8.06799,-0.36738 16.13864,-0.72541 24.21221,-1.06487 0.002,0.0443 -1.33278,-31.644013 -1.33091,-31.599662 -6.59015,0.277373 -13.17046,0.56677 -19.74107,0.863273 m 2.25648,0.535649 c -7.33994,0.328149 -36.12847,1.680751 -43.46841,2.0089 m 35.77564,-0.870908 c -10.87947,0.497595 -31.75687,1.489268 -42.63634,1.986863 m 3.35972,-1.504318 c 0.3926,-0.01824 -9.26877,0.428031 -8.87616,0.409785 -0.001,-0.02231 1.44585,31.619878 1.44483,31.597578 0.10319,-0.005 5.20958,-0.23887 5.31278,-0.24357 m -0.204,-30.764537 c 0.20259,-0.0094 -6.92127,0.318259 -6.71869,0.308893 -9.8e-4,-0.02167 1.4404,31.616444 1.43942,31.594774 0.18506,-0.008 6.8961,-0.31721 7.08117,-0.32567 m -6.69282,-6.800653 c 0,-4e-6 0.31803,6.962623 0.31803,6.962613 0.24334,-0.0111 7.70728,-0.35517 7.95063,-0.3663 m -8.35399,-1.37173 c 0,0 0.0827,1.80758 0.0827,1.80758 3.05198,-0.1396 22.3444,-1.0416 25.39639,-1.1812 m 20.54411,-1.2031 c 8.98415,-0.412 17.97129,-0.81375 26.96173,-1.19252 0.002,0.0378 -1.33278,-31.63929 -1.33119,-31.601527 -10.17041,0.427735 -20.31779,0.884055 -30.44258,1.350874 m 30.68618,-0.727576 c -20.40162,0.859073 -40.71202,1.833698 -60.93492,2.777862 m 28.41956,-1.684043 c -4.22241,0.195401 -19.86403,0.929934 -24.08644,1.125334 m 22.1757,-1.068146 c -22.67755,1.053109 -16.70814,0.783245 -39.38568,1.836354 -1.5e-4,-0.0032 0.53526,11.761592 0.53512,11.758434 M 456.1832,71.641038 c -107.36134,5.003653 74.40662,-3.471827 -32.95473,1.531826 -1e-4,-0.0021 0.45249,9.905361 0.45239,9.903239 m 25.13451,-10.51949 c 11.4671,-0.537186 -36.69231,1.710473 -25.2252,1.173287 -10e-4,-0.02348 1.44302,31.62008 1.44195,31.5966 6.6279,-0.30246 28.48629,-1.33026 35.11418,-1.63271 m -34.01894,1.55836 c 13.40919,-0.61298 30.78484,-1.43956 44.19403,-2.05254 m -9.57076,1.21557 c 12.84616,-0.59866 25.69743,-1.18654 38.55477,-1.72643 0.003,0.0687 -1.20262,-28.704057 -1.19974,-28.635325 m -20.19182,84.780915 c -0.21095,0.01 8.4496,-0.38049 8.23866,-0.3709 m -8.41928,0.49644 c 7.79043,-0.35497 15.56308,-0.70026 23.31815,-1.02742 0.007,0.17634 -1.454,-34.6511 -1.4466,-34.47476 -7.23283,0.30431 -14.47011,0.62392 -21.71203,0.95211 m 9.43944,34.49334 c 4.35639,-0.19382 8.70719,-0.3835 13.05244,-0.56757 0.003,0.0658 -1.45774,-34.5418 -1.45496,-34.47597 -0.0566,0.002 -5.57856,0.23811 -5.63518,0.2405 m 7.67487,28.58015 c 0,0 -0.41001,-9.7569 -0.41001,-9.7569 m 0.84075,6.75642 c 0.001,0.0345 -1.11266,-26.54189 -1.11121,-26.50737 -17.97928,0.75466 -35.9856,1.60511 -54.02154,2.44839 m 55.02012,23.80444 c 0.006,0.15291 -0.85594,-20.44976 -0.84954,-20.29685 m 0.21926,1.51521 c 3.2e-4,0.007 -0.35057,-8.37981 -0.35026,-8.37231 -10.56586,0.44235 -21.14047,0.91781 -31.72435,1.40548 m 9.07711,1.51928 c -17.08329,0.77653 -35.79512,1.67755 -52.8784,2.45408 -10e-4,-0.0288 1.56889,34.50005 1.56758,34.4713 0.0578,-0.003 4.17177,-0.18968 4.22958,-0.1923 m -4.9898,-19.88838 c -3.9e-4,-0.009 0.87703,19.28511 0.87665,19.27657 18.52645,-0.84154 35.36,-1.65485 53.88645,-2.49639 m 11.79881,0.19044 c -0.15813,0.007 8.99192,-0.38652 8.83379,-0.37961 0,-8e-5 -1.43645,-34.11648 -1.43645,-34.11656 m -1.69544,33.35022 c -0.0262,0.001 3.81656,-0.16211 3.79034,-0.16098 0.0154,0.36787 -1.45891,-34.8442 -1.44351,-34.47633 -0.0214,9e-4 -3.51047,0.14833 -3.53187,0.14923 m 4.61961,19.10903 c 0.004,0.0846 -0.7849,-18.76637 -0.78136,-18.68176 -24.53906,1.02942 -49.13067,2.23808 -73.78157,3.36404 m 73.39732,-3.66621 c 0,0 -0.0474,-1.127 -0.0474,-1.127 -8.93561,0.37444 -17.87754,0.77245 -26.82607,1.18138 m 15.15017,0.12669 c -0.22973,0.0101 -9.6171,0.43046 -9.84682,0.44058 m 1.52062,0.345 c -16.3477,0.7365 -38.85642,1.81571 -55.20412,2.55222 -0.001,-0.024 1.47399,32.4516 1.4729,32.4276 m 40.34206,-35.16508 c -25.57791,1.18495 -15.88789,0.74325 -41.4658,1.92819 -7.8e-4,-0.0171 1.20903,26.53287 1.20826,26.51578 m 24.69612,-28.18016 c 9.38054,-0.43806 -35.6539,1.65382 -26.27337,1.21576 -10e-4,-0.0299 1.57081,34.49549 1.56944,34.46557 0.0759,-0.003 4.73497,-0.21628 4.81082,-0.21973 m -2.79194,-33.16411 c 0.024,-10e-4 -2.59955,0.11863 -2.57551,0.11753 -3.8e-4,-0.008 0.81071,17.75552 0.81033,17.74722 m -1.05401,-3.95996 c -4.1e-4,-0.009 0.893,19.58434 0.89259,19.57526 0.0996,-0.005 5.38625,-0.24533 5.48582,-0.24984 m -0.33746,0.29461 c 18.09098,-0.82865 28.05353,-1.30984 46.14451,-2.13849 m -30.04522,0.96991 c 1.36603,-0.0638 6.13168,-0.28688 7.4977,-0.35072 m -6.93486,1.30994 c 17.84352,-0.83316 35.59379,-1.67094 53.25327,-2.41376 10e-4,0.025 -0.89264,-21.27401 -0.89159,-21.24898 M 645.80356,40.256829 c -23.8913,8.70051 -47.01068,18.108537 -69.65321,27.884575 -12.80286,5.515966 -25.46813,11.14719 -38.04142,16.859298 m 110.06361,-0.565846 c -1.94967,0.731567 -3.89505,1.468057 -5.83632,2.209266 m -8.16639,48.076008 c 27.78565,12.47688 54.52593,25.87031 79.39341,40.62548"+           style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"+           transform="matrix(0.23003563,0,0,0.23003563,-34.32847,220.35427)" />+      </g>+    </clipPath>+    <linearGradient+       xlink:href="#linearGradient5445"+       id="linearGradient5447"+       x1="194.11444"+       y1="171.69249"+       x2="208.0477"+       y2="171.69249"+       gradientUnits="userSpaceOnUse" />+  </defs>+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     id="layer1"+     transform="matrix(0.41323205,0,0,0.41323205,-25.73224,-69.525257)"+     style="display:inline">+    <rect+       style="display:inline;opacity:1;fill:url(#linearGradient5260);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.31037128;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"+       id="rect5250"+       width="77.735458"+       height="77.735466"+       x="59.818722"+       y="206.27705"+       ry="2.3587098"+       clip-path="url(#clipPath5388)"+       transform="translate(2.9514358e-6,-40.596579)" />+    <path+       style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2a144d;stroke-width:0.23003563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"+       d="m 125.5315,209.19106 c -3.34965,-1.30393 -6.69931,-2.60787 -10.04896,-3.9118 5.21848,-2.15262 10.43696,-4.30525 15.65545,-6.45787 -0.92835,-2.01253 -1.85669,-4.02505 -2.78504,-6.03758 -6.83922,2.90641 -13.67843,5.81282 -20.51763,8.71921 0.0104,2.54721 0.0208,5.09442 0.0312,7.64163 6.86079,2.8724 13.7216,5.74479 20.58242,8.61717 0.90892,-2.11466 1.81783,-4.22931 2.72675,-6.34397 -1.76975,-0.68894 -3.53951,-1.37789 -5.30926,-2.06683 m -2.62477,-4.90221 c 3.04901,-1.25752 6.09801,-2.51505 9.14702,-3.77257 -0.92751,-2.01274 -1.85501,-4.02549 -2.78252,-6.03823 -2.59416,1.10259 -5.18831,2.20519 -7.78247,3.30778 m 5.56493,-1.53082 c -5.40972,2.29966 -10.81943,4.59932 -16.22916,6.89899 0.0117,2.54697 0.0234,5.09394 0.0352,7.64091 6.86463,2.8717 13.72924,5.74341 20.59384,8.61511 0.91009,-2.11486 1.82018,-4.22973 2.73027,-6.3446 -5.23684,-2.04024 -10.47368,-4.08049 -15.71053,-6.12073 0.75831,-0.31271 1.51662,-0.62542 2.27492,-0.93812 m -14.17992,-7.36348 c -0.76309,-1.65493 -1.52619,-3.30987 -2.28928,-4.9648 -6.839318,2.90343 -13.678633,5.80688 -20.517941,8.71032 0.01054,2.5462 0.02107,5.0924 0.03161,7.6386 6.860547,2.86946 13.721102,5.73892 20.581661,8.60838 0.90903,-2.11556 1.81807,-4.23112 2.72711,-6.34668 -5.23993,-2.04195 -10.47985,-4.08389 -15.719768,-6.12583 3.538493,-1.46115 7.076989,-2.9223 10.615478,-4.38345 m -9.578031,6.75815 c -0.379995,-0.14802 -0.759989,-0.29603 -1.139983,-0.44404 5.220982,-2.15291 10.441954,-4.30583 15.662924,-6.45875 -0.54602,-1.18498 -1.09203,-2.36995 -1.63805,-3.55493 m -30.759587,4.52156 c 2.327107,-4.2e-4 4.654213,-8.4e-4 6.981318,-0.001 4.72e-4,-2.42569 9.42e-4,-4.85139 0.0014,-7.27708 -5.608879,-0.001 -11.217765,-0.002 -16.826659,-0.003 4.62e-4,2.42483 9.24e-4,4.84967 0.0014,7.2745 5.611028,-9.8e-4 11.22205,-0.002 16.833063,-0.003 4.54e-4,-2.42568 9.07e-4,-4.85135 0.0014,-7.27703 -1.723988,-3e-4 -3.447976,-5.9e-4 -5.171966,-8.9e-4 m -2.024007,22.444 c 2.816132,-1e-5 5.632262,-2e-5 8.448391,-3e-5 4.56e-4,-2.64572 9.1e-4,-5.29144 0.0014,-7.93716 -5.637754,-2e-5 -11.275514,-5e-5 -16.913281,-7e-5 4.48e-4,2.6457 8.94e-4,5.29139 0.0013,7.93709 5.639668,-2e-5 11.279329,-5e-5 16.918984,-7e-5 4.39e-4,-2.64571 8.77e-4,-5.29143 0.0013,-7.93714 -0.03972,0 -0.07944,0 -0.119166,0 m 27.32549,-18.3087 -17.328906,7.36254 m 21.261656,1.45287 -0.93476,0.39715 m 0.92531,12.30443 14.19828,5.93971"+       id="text10004" />+    <path+       style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2a144d;stroke-width:0.46007127;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"+       d="m 115.22655,198.82177 c -2.33453,0.87014 -4.64195,1.77129 -6.92798,2.69686 1e-5,-0.001 -0.0471,7.64456 -0.0471,7.64318 2.40744,1.04231 4.78622,2.11139 7.12654,3.21253 m -3.89008,-11.93336 c -1.00663,0.39365 -2.00871,0.79253 -3.00671,1.19609 0,-9e-5 -0.0168,2.57292 -0.0168,2.57282 m 0.0857,-0.87568 c 10e-6,-4.6e-4 -0.0406,5.94694 -0.0406,5.94646 3.36011,1.45836 6.6636,2.96933 9.88376,4.5473 m -7.20478,-3.23662 c 5.79648,2.59181 11.3987,5.35494 16.66528,8.36545 0.32773,-0.6279 0.65819,-1.25494 0.99146,-1.88109 m -1.60443,1.53758 c 0.21377,0.12085 0.42701,0.24211 0.6397,0.36376 1.05492,-2.01971 2.13811,-4.03043 3.25201,-6.03131 -1.59952,-0.86761 -3.22505,-1.71188 -4.8732,-2.53483 m 0.29618,-0.0427 c -3.40715,-1.70793 -6.91152,-3.32401 -10.483,-4.86582 2.90365,-1.06488 5.84253,-2.0795 8.82804,-3.03035 m -4.30994,5.25285 c -1.44084,-0.66089 -2.89525,-1.30799 -4.36114,-1.9425 5.32305,-1.95032 10.76393,-3.73086 16.39321,-5.25805 -0.0526,-0.15243 -0.10543,-0.30483 -0.15839,-0.4572 m -16.346,5.71656 c -6e-5,-3e-5 -0.16464,-0.0711 -0.1647,-0.0711 5.32191,-1.95602 10.76115,-3.74365 16.38827,-5.27932 -0.64765,-1.86511 -1.31982,-3.72666 -2.01474,-5.58459 m -6.00177,7.65252 c 2.59724,-0.83545 5.22948,-1.62315 7.90424,-2.35414 -0.10412,-0.29859 -0.20887,-0.59709 -0.31423,-0.8955 m -0.14193,1.39572 c 0.18793,-0.052 0.37606,-0.10371 0.56441,-0.15515 -0.73132,-2.1078 -1.49395,-4.21107 -2.28537,-6.30972 -0.14277,0.0413 -0.28541,0.0828 -0.42792,0.12441 m 2.58573,5.86862 c -1e-5,0 0.0598,-0.0163 0.0598,-0.0163 -0.73446,-2.10743 -1.50012,-4.2103 -2.29447,-6.30856 -2.51058,0.72674 -4.98101,1.49943 -7.41727,2.31118 m 2.7274,-0.57192 c -5.49569,1.74707 -10.81091,3.70187 -16.01266,5.78726 m -0.10008,0.28407 c -0.1982,0.0796 -0.39625,0.15943 -0.59413,0.23942 0,-1.5e-4 -0.0188,2.695 -0.0188,2.69485 m -0.26343,-1.06335 c 0,-6.9e-4 -0.0362,5.97408 -0.0362,5.97348 4.5267,1.96098 8.95073,4.01666 13.20673,6.20223 m -1.19162,-0.94232 c 2.57116,1.29507 5.08466,2.63559 7.52645,4.02912 0.2451,-0.46951 0.49173,-0.93854 0.73992,-1.40707 m -3.71917,-0.16021 c 1.03465,0.56033 2.05792,1.12925 3.06882,1.7073 1.05517,-2.01991 2.13862,-4.0308 3.25279,-6.03186 -3.20163,-1.73679 -6.50739,-3.38013 -9.89002,-4.94595 m 0.73858,0.22701 c -2.02311,-0.94586 -4.0745,-1.86341 -6.14827,-2.75609 2.20426,-0.81044 4.42876,-1.59211 6.67851,-2.33909 m -1.44719,0.78416 c 3.68217,-1.25405 7.4293,-2.41757 11.26369,-3.46413 -0.62864,-1.81025 -1.28037,-3.61715 -1.95359,-5.42066 m 2.23455,5.42891 c 0,0 0.0174,-0.005 0.0174,-0.005 -0.72889,-2.1089 -1.48926,-4.21326 -2.27857,-6.31299 -3.40899,0.98048 -6.74388,2.04632 -10.0197,3.18021 m 11.03329,-0.34197 c -0.33808,-0.93185 -0.68206,-1.86279 -1.03172,-2.79283 -2.38449,0.68629 -4.73274,1.41434 -7.0499,2.17823 m 7.95135,0.32819 c -0.33935,-0.93163 -0.68458,-1.86236 -1.03546,-2.79218 -4.58328,1.32102 -9.03245,2.79572 -13.38399,4.38215 m 6.2801,-1.79408 c -1.65708,0.54838 -3.29832,1.11504 -4.92561,1.69781 m 3.20183,-1.43563 c -4.26843,1.45184 -8.43432,3.02127 -12.53045,4.67057 m -22.97746,-0.61053 c -0.854682,0.39452 -1.707863,0.7904 -2.559818,1.18742 -1.2e-5,-2.5e-4 0.117783,2.69178 0.117771,2.69152 m -0.268337,-2.29444 c -4e-6,0 -0.02307,0.0108 -0.02308,0.0108 -1.1e-4,-0.003 0.33467,7.63469 0.33456,7.63215 3.348442,1.24064 6.676356,2.49903 9.969061,3.78762 m -10.192384,-8.04094 c -2.8e-5,-6.9e-4 0.176276,4.01026 0.176248,4.00962 0.573877,0.21257 1.147161,0.42566 1.719779,0.63933 m -1.79414,-3.6187 c -1.4e-5,-2.3e-4 0.126798,2.89326 0.126782,2.89293 3.803508,1.40936 7.581027,2.84161 11.311057,4.315 m -11.501658,-5.89934 c -4e-6,-9e-5 0.06809,1.54588 0.06809,1.54578 4.990119,1.84741 9.935901,3.7339 14.788836,5.70061 m -12.821111,-5.12777 c 3.745274,1.39817 7.462077,2.82154 11.129754,4.28761 m -6.88663,-2.31774 c 3.011252,1.14993 5.998343,2.32071 8.950298,3.52165 1.133312,0.46173 2.261042,0.92737 3.382172,1.39749 m -9.790029,-4.2021 c 2.149828,0.83322 4.285773,1.67852 6.403797,2.53933 1.907982,0.77652 3.800322,1.5642 5.672182,2.36562 0.46253,-1.10901 0.92886,-2.21723 1.39934,-3.32452 m -6.232212,1.50664 c 1.556872,0.63838 3.102712,1.28447 4.634872,1.9397 0.88166,-2.11735 1.77703,-4.23184 2.68853,-6.34263 -0.61254,-0.24545 -1.2269,-0.48927 -1.84292,-0.73153 m -4.06553,5.7068 c -9e-5,-4e-5 0.16353,0.0679 0.16344,0.0679 m 0.0327,0.11268 c 1.03455,0.43018 2.06375,0.86401 3.08681,1.30192 m -2.3182,-0.91815 c 0.76015,0.31833 1.51729,0.63869 2.27109,0.96126 0.8812,-2.11731 1.7761,-4.23175 2.6871,-6.34251 -1.07693,-0.43177 -2.15952,-0.85847 -3.24694,-1.28059 m -0.79848,6.54886 c 0.57584,0.24283 1.14991,0.48687 1.72205,0.73222 0.88393,-2.11654 1.78182,-4.23012 2.69609,-6.3399 -2.85303,-1.14687 -5.74585,-2.25766 -8.6629,-3.34145 -0.878803,-0.32632 -1.759821,-0.65007 -2.642799,-0.97149 m 11.165339,4.97095 c -4e-5,9e-5 0.091,-0.21044 0.091,-0.21035 -2.83402,-1.13992 -5.7079,-2.24432 -8.60636,-3.32213 0,0 0,0 0,0 -4.6e-4,-1.5e-4 -0.366769,-0.1361 -0.367181,-0.13625 m 3.434061,1.21466 c -1.01916,-0.38852 -2.042074,-0.77332 -3.068051,-1.15478 -2.486904,-0.92406 -4.991852,-1.82752 -7.509019,-2.71568 0.829062,-0.36791 1.659434,-0.73416 2.49136,-1.09855 m 0.757017,2.04397 c -1.035358,-0.37277 -2.073205,-0.74255 -3.113132,-1.1097 2.413792,-1.07043 4.838848,-2.12667 7.281244,-3.164 1.533889,-0.65173 3.074841,-1.29637 4.624621,-1.93185 m -9.766347,6.08968 c -0.639713,-0.22895 -1.280335,-0.45681 -1.921771,-0.68365 0.812051,-0.35993 1.625365,-0.71824 2.440177,-1.07474 m -1.445123,0.25789 c 2.013297,-0.88721 4.035092,-1.76404 6.068896,-2.62776 1.427505,-0.60646 2.861118,-1.20679 4.302258,-1.7993 m -6.920229,3.15085 c 0.388763,-0.16799 0.777907,-0.33554 1.167461,-0.50263 m -0.853317,0.0623 c 0.765968,-0.33022 1.53347,-0.6587 2.302693,-0.98531 2.773222,-1.17798 5.569582,-2.33278 8.399432,-3.45216 -0.87864,-1.88537 -1.77123,-3.76736 -2.67569,-5.64593 m 1.76309,3.67895 c -0.61388,-1.30199 -1.23409,-2.60236 -1.85994,-3.90108 -1.41105,0.57981 -2.81257,1.16765 -4.205833,1.76203 m 5.026193,0.0549 c -0.27605,-0.57827 -0.55327,-1.15622 -0.83161,-1.73385 -1.25376,0.51547 -2.5,1.03727 -3.73965,1.56436 m 2.83755,-1.48965 c -1.54442,0.6398 -3.077627,1.28889 -4.601312,1.94531 m 1.201573,-0.32783 c -0.474262,0.2025 -0.94757,0.40576 -1.419976,0.60972 -4.914679,2.11735 -9.741183,4.30852 -14.528256,6.53678 m 16.826411,-7.45096 c -0.76819,0.32571 -1.533822,0.65348 -2.297101,0.98307 -3.24117,1.39662 -6.444057,2.82536 -9.622648,4.27567 m 7.852211,-3.474 c -3.117139,1.35987 -6.200983,2.7479 -9.264133,4.15461 m 9.009911,-4.25513 c -2.302633,1.00582 -4.587154,2.02686 -6.858643,3.05931 m 4.508413,-1.69638 c -3.57174,1.58495 -7.104087,3.20379 -10.616344,4.84198 -2.3e-5,-5.1e-4 0.161722,3.68636 0.161699,3.68584 m 0.201525,-4.18611 c -4.2e-5,2e-5 -0.08238,0.0384 -0.08242,0.0384 m 0.249474,0.18924 c -9.2e-4,4.4e-4 -0.389313,0.18139 -0.390267,0.18184 -3e-5,-6.7e-4 0.193575,4.4234 0.193547,4.42274 m 0.06248,-4.67199 c -1.7e-4,7e-5 -0.164222,0.0765 -0.164393,0.0766 -9.4e-5,-0.002 0.332519,7.63482 0.332427,7.63268 2.594887,0.96244 5.177421,1.93576 7.740766,2.92577 m -8.125629,-6.54994 c -2.5e-5,-4.6e-4 0.160641,3.66976 0.160618,3.6692 4.066678,1.50729 8.103281,3.04091 12.083516,4.62316 m -2.99684,-1.2604 c 1.529369,0.59494 3.051506,1.19616 4.564949,1.80488 m -3.344893,-1.26036 c 0.776458,0.30474 1.550935,0.61119 2.32324,0.91951 m -1.241217,-0.35875 c 1.195935,0.4731 2.386912,0.95046 3.572221,1.43269 1.840131,0.74969 3.665531,1.50974 5.471871,2.28248 0.822,-1.97423 1.6559,-3.94598 2.50368,-5.91456 m -11.121527,1.98454 c 1.05069,0.41661 2.097534,0.83657 3.140048,1.26028 1.965829,0.80009 3.915119,1.61201 5.842599,2.43862 0.44127,-1.057 0.88602,-2.11326 1.33455,-3.16868 m -9.552508,0.12237 c 0.79596,0.31766 1.589611,0.6373 2.38074,0.9591 1.914288,0.77978 3.812658,1.57076 5.690228,2.37559 0.88257,-2.11672 1.77896,-4.23052 2.69159,-6.34058 -1.36174,-0.54699 -2.73261,-1.08582 -4.1109,-1.61747 m 3.20992,1.00354 c -4.6e-4,-2.1e-4 -0.41393,-0.16425 -0.41444,-0.16445 m 0.0581,0.2923 c -2.38846,-0.94689 -4.80318,-1.86977 -7.235138,-2.77392 -2.430368,-0.903 -4.877973,-1.78633 -7.33738,-2.65492 -0.0031,0.001 0.836179,-0.36999 0.833122,-0.36863 m 11.056826,4.79542 c -1.08521,-0.41935 -2.17509,-0.83422 -3.268804,-1.2451 m 0.552314,-0.0558 c -0.611951,-0.23083 -1.225138,-0.46037 -1.839412,-0.68871 -2.397599,-0.89074 -4.811825,-1.76235 -7.237466,-2.61957 -0.0036,0.002 0.907279,-0.40118 0.903714,-0.3996 m 4.693778,2.54492 c -1.824261,-0.66932 -3.657459,-1.32826 -5.497316,-1.97887 1.167215,-0.51721 2.337056,-1.03107 3.510215,-1.54103 m -3.132218,1.53545 c -0.0021,-6.9e-4 -0.702658,-0.24839 -0.704659,-0.2491 2.444195,-1.08387 4.899913,-2.15325 7.373456,-3.20325 1.651238,-0.70123 3.310698,-1.39423 4.980548,-2.07644 m -2.03317,0.88961 c 1.81304,-0.75358 3.63737,-1.49555 5.47584,-2.22256 -0.2092,-0.44886 -0.4192,-0.89753 -0.62996,-1.34601 m 0.52067,0.71853 c -0.85056,-1.82046 -1.714,-3.63777 -2.58848,-5.45186 -1.96176,0.80486 -3.90498,1.6253 -5.833093,2.45734 -1.125801,0.48477 -2.246963,0.97342 -3.364066,1.46549 m -26.743025,7.15179 c 2.059712,-0.0964 0.572741,-0.0268 2.632452,-0.12318 m -2.374667,0.0391 c 3.988273,-0.18667 7.978754,-0.37463 11.971968,-0.54282 0,1e-5 -0.106426,-2.53116 -0.106426,-2.53115 m -10.549851,3.10776 c 2.511814,-0.11741 5.024455,-0.23441 7.538059,-0.34575 m -2.466268,-0.18978 c 1.855925,-0.0845 3.712463,-0.16687 5.569671,-0.24496 4.6e-4,0.0102 -0.306587,-7.27925 -0.306156,-7.26905 -1.51597,0.0638 -3.029675,0.13038 -4.54115,0.19859 m 0.519071,0.12322 c -1.688448,0.0755 -8.310835,0.38663 -9.999283,0.46211 m 8.229672,-0.20034 c -2.502666,0.11447 -7.305212,0.34259 -9.807878,0.45705 m 0.772856,-0.34604 c 0.09031,-0.004 -2.132148,0.0985 -2.041833,0.0943 -2.3e-4,-0.005 0.332597,7.2737 0.332362,7.26857 0.02374,-0.001 1.198389,-0.0549 1.222129,-0.056 m -0.04693,-7.07694 c 0.0466,-0.002 -1.592138,0.0732 -1.545538,0.0711 -2.25e-4,-0.005 0.331344,7.27291 0.331118,7.26792 0.04257,-0.002 1.586349,-0.073 1.628922,-0.0749 m -1.539587,-1.5644 c 0,0 0.07316,1.60165 0.07316,1.60165 0.05598,-0.003 1.772949,-0.0817 1.828928,-0.0843 m -1.921715,-0.31555 c 0,0 0.01902,0.41581 0.01902,0.41581 0.702064,-0.0321 5.140008,-0.2396 5.842074,-0.27172 m 4.725877,-0.27675 c 2.066675,-0.0948 4.134037,-0.18719 6.202159,-0.27432 4.6e-4,0.009 -0.306587,-7.27817 -0.306221,-7.26948 -2.339557,0.0984 -4.673816,0.20336 -7.002878,0.31075 m 7.058915,-0.16737 c -4.6931,0.19762 -9.365216,0.42182 -14.017203,0.63901 m 6.537511,-0.38739 c -0.971305,0.045 -4.569434,0.21391 -5.540739,0.25886 m 5.101201,-0.24571 c -5.216645,0.24225 -3.843468,0.18018 -9.06011,0.42243 -3.4e-5,-7.4e-4 0.123129,2.70558 0.123097,2.70486 m 7.426843,-3.24953 c -24.696934,1.15102 17.116174,-0.79865 -7.580762,0.35237 -2.3e-5,-4.8e-4 0.104089,2.27859 0.104066,2.2781 m 5.781832,-2.41986 c 2.637842,-0.12357 -8.440538,0.39347 -5.802694,0.2699 -2.3e-4,-0.005 0.331946,7.27375 0.331699,7.26835 1.524654,-0.0696 6.552862,-0.30601 8.077513,-0.37559 m -7.825568,0.35848 c 3.084591,-0.14101 7.08161,-0.33115 10.166201,-0.47216 m -2.201616,0.27963 c 2.955075,-0.13771 5.911325,-0.27295 8.868971,-0.39714 6.9e-4,0.0158 -0.276645,-6.60296 -0.275983,-6.58715 m -4.644838,19.50263 c -0.04853,0.002 1.943709,-0.0875 1.895186,-0.0853 m -1.936735,0.1142 c 1.792077,-0.0816 3.580063,-0.16108 5.364006,-0.23634 0.0016,0.0406 -0.334472,-7.97099 -0.33277,-7.93042 -1.663809,0.07 -3.328641,0.14352 -4.99454,0.21902 m 2.171407,7.93469 c 1.002125,-0.0446 2.002964,-0.0882 3.002526,-0.13056 6.9e-4,0.0151 -0.335332,-7.94584 -0.334692,-7.9307 -0.01302,4.6e-4 -1.283268,0.0548 -1.296293,0.0553 m 1.765494,6.57446 c 0,0 -0.09432,-2.24444 -0.09432,-2.24444 m 0.193403,1.55422 c 2.3e-4,0.008 -0.255952,-6.10558 -0.255618,-6.09764 -4.135875,0.1736 -8.27797,0.36923 -12.426879,0.56322 m 12.656588,5.47587 c 0.0014,0.0352 -0.196897,-4.70418 -0.195425,-4.669 m 0.05044,0.34855 c 7.3e-5,0.002 -0.08064,-1.92765 -0.08057,-1.92593 -2.430525,0.10176 -4.863062,0.21113 -7.297731,0.32331 m 2.088058,0.34949 c -3.929765,0.17863 -8.234153,0.3859 -12.163916,0.56453 -2.3e-4,-0.007 0.360901,7.93624 0.3606,7.92962 0.0133,-6.9e-4 0.959655,-0.0436 0.972954,-0.0442 m -1.147832,-4.57504 c -9e-5,-0.002 0.201748,4.43626 0.201661,4.4343 4.261743,-0.19359 8.13406,-0.38068 12.395803,-0.57426 m 2.714147,0.0438 c -0.03638,0.002 2.068462,-0.0889 2.032086,-0.0873 0,-1e-5 -0.330434,-7.848 -0.330434,-7.84802 m -0.390012,7.67174 c -0.006,2.3e-4 0.877945,-0.0373 0.871913,-0.037 0.0035,0.0846 -0.335601,-8.01541 -0.332058,-7.93079 -0.0049,2.1e-4 -0.807534,0.0341 -0.812456,0.0343 m 1.062674,4.39576 c 9.21e-4,0.0195 -0.180555,-4.31693 -0.17974,-4.29747 -5.644858,0.2368 -11.301805,0.51484 -16.97239,0.77385 m 16.883999,-0.84336 c 0,0 -0.0109,-0.25925 -0.0109,-0.25925 -2.055509,0.0861 -4.112471,0.17769 -6.170952,0.27176 m 3.485079,0.0291 c -0.05285,0.002 -2.212276,0.099 -2.26512,0.10135 m 0.349797,0.0794 c -3.760553,0.16942 -8.938361,0.41768 -12.698914,0.5871 -2.3e-4,-0.006 0.33907,7.46503 0.338819,7.45951 m 9.280111,-8.08922 c -5.88383,0.27258 -3.65478,0.17097 -9.538611,0.44355 -1.79e-4,-0.004 0.27812,6.1035 0.277943,6.09957 m 5.680987,-6.48244 c 2.157859,-0.10077 -8.201667,0.38044 -6.043811,0.27967 -2.3e-4,-0.007 0.361342,7.93519 0.361027,7.92831 0.01746,-6.9e-4 1.089212,-0.0498 1.10666,-0.0506 m -0.642245,-7.62892 c 0.0055,-2.3e-4 -0.59799,0.0273 -0.592459,0.027 -8.8e-5,-0.002 0.186492,4.0844 0.186404,4.0825 m -0.24246,-0.91094 c -9.4e-5,-0.002 0.205422,4.5051 0.205328,4.50301 0.02291,-0.001 1.239029,-0.0564 1.261934,-0.0575 m -0.07763,0.0678 c 4.16157,-0.19062 6.453312,-0.30131 10.614882,-0.49193 m -6.911472,0.22311 c 0.314236,-0.0147 1.410505,-0.066 1.724739,-0.0807 m -1.595265,0.30133 c 4.104645,-0.19166 8.18784,-0.38438 12.250149,-0.55525 2.3e-4,0.006 -0.205339,-4.89378 -0.205097,-4.88802 m 33.383164,-22.13887 c -5.49585,2.00143 -10.81413,4.16561 -16.02272,6.41445 -2.945114,1.26887 -5.858578,2.56425 -8.750882,3.87824 m 25.318552,-0.13017 c -0.44849,0.16829 -0.896,0.33771 -1.34256,0.50821 m -1.87856,11.0592 c 6.39169,2.87012 12.5429,5.95109 18.26331,9.34531"+       id="path10202" />+    <path+       id="path4728"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 111.80954,213.04909 c -0.26629,0.16448 -0.50119,0.30232 -0.6724,0.70346 -0.1712,0.40114 -0.10823,0.66612 -0.0428,0.97219 l 0.12706,-0.0258 c -0.0563,-0.29013 -0.0764,-0.51482 0.0782,-0.87703 0.15531,-0.3639 0.33078,-0.50311 0.57919,-0.66321 z" />+    <path+       id="path4730"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 112.44893,213.61011 c -0.26405,-0.1127 -0.57293,0.002 -0.74125,0.39595 -0.16759,0.39268 -0.0531,0.69166 0.22957,0.8123 0.1574,0.0672 0.29655,0.0506 0.38906,0.012 l -0.0362,-0.13551 c -0.087,0.0209 -0.17996,0.0372 -0.28998,-0.01 -0.18111,-0.0773 -0.26524,-0.26928 -0.12148,-0.6061 0.15025,-0.35206 0.34807,-0.40769 0.5241,-0.33256 0.0812,0.0347 0.14075,0.0921 0.18825,0.18244 l 0.13209,-0.0657 c -0.0613,-0.11423 -0.12691,-0.19023 -0.27416,-0.25307 z" />+    <path+       id="path4732"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 113.09042,213.59577 -0.12706,0.0258 c 0.0563,0.29012 0.0771,0.51313 -0.0782,0.87703 -0.15459,0.36221 -0.33078,0.50311 -0.57918,0.66321 l 0.0693,0.10959 c 0.26629,-0.16448 0.5012,-0.30232 0.67241,-0.70346 0.1712,-0.40114 0.10822,-0.66613 0.0428,-0.97219 z" />+    <path+       id="path4734"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 114.01162,214.30108 -0.24373,-0.10402 -0.49772,1.16618 0.27928,0.11919 c 0.25219,0.10764 0.59679,0.12065 0.79978,-0.35496 0.2066,-0.48407 -0.0397,-0.69924 -0.33761,-0.82639 z m -0.0194,0.14379 c 0.18619,0.0795 0.35432,0.21526 0.18601,0.60962 -0.16398,0.38422 -0.38001,0.38406 -0.5628,0.30604 l -0.13033,-0.0556 0.38864,-0.9106 z" />+    <path+       id="path4736"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 114.96573,216.0869 0.16926,0.0722 0.12536,-1.3251 -0.20311,-0.0867 -0.87179,1.00653 0.16249,0.0693 0.21299,-0.25525 0.44176,0.18854 z m -0.31025,-0.63263 0.44286,-0.53131 -0.079,0.68662 z" />+    <path+       id="path4738"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 116.5494,215.38421 -0.16249,-0.0693 -0.71613,0.86686 0.1305,-1.11681 -0.17264,-0.0737 -0.12197,1.32654 0.17264,0.0737 z" />+    <path+       id="path4740"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 116.89069,215.52987 -0.16079,-0.0686 -0.49773,1.16618 0.1608,0.0686 z" />+    <path+       id="path4742"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 117.4728,215.77831 -0.24373,-0.10402 -0.49772,1.16618 0.27928,0.11919 c 0.25219,0.10764 0.59679,0.12065 0.79978,-0.35496 0.2066,-0.48407 -0.0397,-0.69924 -0.33761,-0.82639 z m -0.0194,0.14379 c 0.18619,0.0795 0.35432,0.21526 0.18601,0.60962 -0.16398,0.38422 -0.38001,0.38406 -0.5628,0.30604 l -0.13033,-0.0556 0.38864,-0.9106 z" />+    <path+       id="path4744"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 118.7188,216.31011 -0.16079,-0.0686 -0.49773,1.16618 0.62118,0.26511 0.0785,-0.13255 -0.479,-0.20443 z" />+    <path+       id="path4746"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 120.03232,216.87072 -0.63133,-0.26946 -0.49773,1.16618 0.64488,0.27523 0.0549,-0.12863 -0.48408,-0.20661 0.17049,-0.39945 0.39267,0.1676 0.0549,-0.12864 -0.39267,-0.16759 0.16253,-0.38082 0.45192,0.19287 z" />+    <path+       id="path4748"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 120.99565,217.28186 -0.83274,-0.35541 -0.0585,0.13709 0.33175,0.14159 -0.43921,1.02909 0.1608,0.0686 0.43921,-1.02908 0.32328,0.13798 z" />+    <path+       id="path4750"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 121.8717,217.65576 -0.83275,-0.35541 -0.0585,0.13709 0.33174,0.14159 -0.43921,1.02908 0.16079,0.0686 0.43922,-1.02908 0.32327,0.13797 z" />+    <path+       id="path4752"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 122.21965,217.80427 -0.1608,-0.0686 -0.49772,1.16618 0.1608,0.0686 z" />+    <path+       id="path4754"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 123.18936,218.21814 -0.63133,-0.26945 -0.49772,1.16617 0.64487,0.27524 0.0549,-0.12864 -0.48407,-0.2066 0.17048,-0.39945 0.39268,0.16759 0.0549,-0.12863 -0.39268,-0.1676 0.16254,-0.38082 0.45192,0.19288 z" />+    <path+       id="path4756"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       d="m 123.58728,219.76657 0.19126,0.0816 -0.0916,-0.65737 c 0.18922,0.0207 0.31576,-0.0413 0.38583,-0.20548 0.0932,-0.21835 -0.0115,-0.39507 -0.30259,-0.51932 l -0.30636,-0.13075 -0.49772,1.16618 0.1608,0.0686 0.21093,-0.49422 0.18111,0.0773 z m -0.19671,-0.81427 0.18059,-0.42314 0.14387,0.0614 c 0.19127,0.0816 0.24892,0.17626 0.18679,0.32182 -0.0672,0.15742 -0.18628,0.17862 -0.34876,0.10927 z" />+  </g>+</svg>
+ src/data/fullscreen-icon.svg view
@@ -0,0 +1,147 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+   width="15"+   height="15"+   viewBox="0 0 3.9687499 3.9687501"+   version="1.1"+   id="svg8"+   inkscape:version="0.92.2 2405546, 2018-03-11"+   sodipodi:docname="fullscreen-icon.svg">+  <defs+     id="defs2">+    <marker+       inkscape:isstock="true"+       style="overflow:visible;"+       id="marker23124"+       refX="0.0"+       refY="0.0"+       orient="auto"+       inkscape:stockid="Arrow2Send">+      <path+         transform="scale(0.3) rotate(180) translate(-2.3,0)"+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "+         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#ffffff;stroke-opacity:0.90196078;fill:#ffffff;fill-opacity:0.90196078"+         id="path23122" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Send"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow1Send"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path876"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#ffffff;stroke-width:1pt;stroke-opacity:0.90196078;fill:#ffffff;fill-opacity:0.90196078"+         transform="scale(0.2) rotate(180) translate(6,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Mend"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow1Mend"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path870"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#ffffff;stroke-width:1pt;stroke-opacity:0.90196078;fill:#ffffff;fill-opacity:0.90196078"+         transform="scale(0.4) rotate(180) translate(10,0)" />+    </marker>+  </defs>+  <sodipodi:namedview+     id="base"+     pagecolor="#ff09e5"+     bordercolor="#666666"+     borderopacity="1.0"+     inkscape:pageopacity="0"+     inkscape:pageshadow="2"+     inkscape:zoom="22.627417"+     inkscape:cx="1.753672"+     inkscape:cy="12.195151"+     inkscape:document-units="px"+     inkscape:current-layer="layer1"+     showgrid="true"+     units="px"+     inkscape:measure-start="30,0"+     inkscape:measure-end="30,15"+     showguides="true"+     inkscape:guide-bbox="true"+     inkscape:window-width="1920"+     inkscape:window-height="1152"+     inkscape:window-x="0"+     inkscape:window-y="320"+     inkscape:window-maximized="1"+     inkscape:snap-global="false"+     inkscape:showpageshadow="false">+    <inkscape:grid+       type="xygrid"+       id="grid815" />+    <sodipodi:guide+       position="8.9958331,3.9687501"+       orientation="0,1"+       id="guide819"+       inkscape:locked="false" />+    <sodipodi:guide+       position="-3.9563476,0.73793947"+       orientation="0.70710678,0.70710678"+       id="guide23230"+       inkscape:locked="false" />+    <sodipodi:guide+       position="3.4106445,3.3072918"+       orientation="0.70710678,0.70710678"+       id="guide23301"+       inkscape:locked="false" />+  </sodipodi:namedview>+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     inkscape:label="Layer 1"+     inkscape:groupmode="layer"+     id="layer1"+     transform="translate(0,-293.03123)">+    <g+       id="g23222"+       transform="matrix(1.0883098,0,0,1.1013122,4.8677154,-29.842988)">+      <path+         style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:0.90196078;fill-rule:evenodd;stroke:none;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1107.35998535;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+         d="m -1.390625,293.46289 c -0.068648,0.002 -0.1651221,-1.7e-4 -0.2129795,0.0491 l -2.4429613,2.66237 c -0.2649166,0.24991 -0.034758,0.47803 0.2137696,0.21181 l 2.6583225,-2.45139 c 0.1715018,-0.16871 0.02432,-0.47898 -0.2161513,-0.4719 z"+         id="path23120"+         inkscape:connector-curvature="0"+         sodipodi:nodetypes="ccccccc" />+      <path+         id="path23228"+         style="fill:#ffffff;fill-opacity:0.90196078;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.09921876;stroke-linejoin:round;stroke-opacity:0.90196078"+         d="m -2.5582351,293.9976 1.67746674,-0.77547 -0.77546234,1.67747 c -0.070334,-0.46221 -0.4357684,-0.82538 -0.9020044,-0.902 z"+         inkscape:connector-curvature="0" />+      <path+         inkscape:connector-curvature="0"+         d="m -3.2578843,296.30294 -1.1648365,0.42381 0.4983491,-1.07802 c 0.0452,0.29704 0.3668619,0.60497 0.6664874,0.65421 z"+         style="fill:#ffffff;fill-opacity:0.90196078;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.09921876;stroke-linejoin:round;stroke-opacity:0.90196078"+         id="path23232"+         sodipodi:nodetypes="cccc" />+    </g>+  </g>+</svg>
src/data/gui.glade view
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?>-<!-- Generated with glade 3.20.0 +<!-- Generated with glade 3.20.4   Copyright (c) 2017 David Lettier All rights reserved.@@ -31,15 +31,16 @@ --> <interface>   <requires lib="gtk+" version="3.10"/>+  <!-- interface-css-provider-path style.css -->   <!-- interface-license-type bsd3c -->   <!-- interface-name Movie Monad -->-  <!-- interface-description A free and simple to use video player built with Haskell. -->+  <!-- interface-description A free and simple to use video player made with Haskell. -->   <!-- interface-copyright 2017 David Lettier -->   <!-- interface-authors David Lettier -->   <object class="GtkImage" id="about-image">     <property name="visible">True</property>     <property name="can_focus">False</property>-    <property name="stock">gtk-dialog-question</property>+    <property name="pixbuf">about-icon.svg</property>   </object>   <object class="GtkButton" id="file-chooser-cancel-button">     <property name="label">gtk-cancel</property>@@ -60,30 +61,38 @@   <object class="GtkImage" id="fullscreen-image">     <property name="visible">True</property>     <property name="can_focus">False</property>-    <property name="stock">gtk-fullscreen</property>+    <property name="pixbuf">fullscreen-icon.svg</property>   </object>   <object class="GtkImage" id="pause-image">+    <property name="name">pause-image</property>     <property name="visible">True</property>     <property name="can_focus">False</property>-    <property name="stock">gtk-media-pause</property>+    <property name="pixbuf">pause-icon.svg</property>   </object>   <object class="GtkImage" id="play-image">+    <property name="name">play-image</property>     <property name="visible">True</property>     <property name="can_focus">False</property>-    <property name="stock">gtk-media-play</property>+    <property name="pixbuf">play-icon.svg</property>   </object>+  <object class="GtkImage" id="repeat-check-button-image">+    <property name="visible">True</property>+    <property name="can_focus">False</property>+    <property name="pixbuf">repeat-icon.svg</property>+  </object>   <object class="GtkAdjustment" id="seek-scale-adjustment">     <property name="upper">100</property>     <property name="step_increment">1</property>     <property name="page_increment">10</property>   </object>   <object class="GtkWindow" id="window">+    <property name="width_request">448</property>     <property name="can_focus">True</property>     <property name="title" translatable="yes">Movie Monad</property>     <property name="window_position">center</property>     <property name="default_width">800</property>     <property name="default_height">600</property>-    <property name="icon">movie-monad-icon.png</property>+    <property name="icon">movie-monad-icon.svg</property>     <property name="gravity">center</property>     <child>       <object class="GtkBox" id="box-1">@@ -91,70 +100,69 @@         <property name="can_focus">False</property>         <property name="orientation">vertical</property>         <child>-          <object class="GtkBox" id="box-2">+          <object class="GtkButton" id="file-chooser-button">             <property name="visible">True</property>-            <property name="can_focus">False</property>+            <property name="app_paintable">True</property>+            <property name="can_focus">True</property>+            <property name="receives_default">True</property>+            <property name="tooltip_text" translatable="yes">Load a Video</property>+            <property name="valign">start</property>             <property name="hexpand">True</property>-            <property name="vexpand">True</property>-            <property name="orientation">vertical</property>+            <property name="relief">half</property>+            <property name="image_position">right</property>+            <property name="always_show_image">True</property>             <child>-              <object class="GtkButton" id="file-chooser-button">+              <object class="GtkBox" id="box-2">                 <property name="visible">True</property>-                <property name="app_paintable">True</property>-                <property name="can_focus">True</property>-                <property name="receives_default">True</property>-                <property name="tooltip_text" translatable="yes">Open a video file</property>-                <property name="valign">start</property>-                <property name="hexpand">True</property>-                <property name="relief">half</property>-                <property name="image_position">right</property>-                <property name="always_show_image">True</property>+                <property name="can_focus">False</property>                 <child>-                  <object class="GtkBox" id="box-3">+                  <object class="GtkLabel" id="file-chooser-button-label">                     <property name="visible">True</property>                     <property name="can_focus">False</property>-                    <child>-                      <object class="GtkLabel" id="file-chooser-button-label">-                        <property name="visible">True</property>-                        <property name="can_focus">False</property>-                        <property name="label" translatable="yes">Open</property>-                        <property name="justify">fill</property>-                        <property name="ellipsize">end</property>-                        <property name="single_line_mode">True</property>-                      </object>-                      <packing>-                        <property name="expand">True</property>-                        <property name="fill">True</property>-                        <property name="position">0</property>-                      </packing>-                    </child>-                    <child>-                      <object class="GtkImage" id="open-image">-                        <property name="visible">True</property>-                        <property name="can_focus">False</property>-                        <property name="stock">gtk-open</property>-                      </object>-                      <packing>-                        <property name="expand">False</property>-                        <property name="fill">False</property>-                        <property name="pack_type">end</property>-                        <property name="position">2</property>-                      </packing>-                    </child>+                    <property name="label" translatable="yes">Open</property>+                    <property name="justify">fill</property>+                    <property name="ellipsize">end</property>+                    <property name="single_line_mode">True</property>                   </object>+                  <packing>+                    <property name="expand">True</property>+                    <property name="fill">True</property>+                    <property name="position">0</property>+                  </packing>                 </child>+                <child>+                  <object class="GtkImage" id="open-image">+                    <property name="visible">True</property>+                    <property name="can_focus">False</property>+                    <property name="stock">gtk-open</property>+                  </object>+                  <packing>+                    <property name="expand">False</property>+                    <property name="fill">False</property>+                    <property name="pack_type">end</property>+                    <property name="position">2</property>+                  </packing>+                </child>               </object>-              <packing>-                <property name="expand">False</property>-                <property name="fill">False</property>-                <property name="position">0</property>-              </packing>             </child>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">False</property>+            <property name="position">1</property>+          </packing>+        </child>+        <child>+          <object class="GtkOverlay" id="video-overlay">+            <property name="visible">True</property>+            <property name="can_focus">False</property>+            <property name="hexpand">True</property>+            <property name="vexpand">True</property>             <child>               <object class="GtkBox" id="video-widget-box">                 <property name="visible">True</property>                 <property name="app_paintable">True</property>-                <property name="can_focus">True</property>+                <property name="can_focus">False</property>                 <property name="hexpand">True</property>                 <property name="vexpand">True</property>                 <property name="orientation">vertical</property>@@ -163,34 +171,32 @@                 </child>               </object>               <packing>-                <property name="expand">True</property>-                <property name="fill">True</property>-                <property name="position">1</property>+                <property name="index">-1</property>               </packing>             </child>-            <child>+            <child type="overlay">               <object class="GtkBox" id="bottom-controls-gtk-box">+                <property name="name">bottom-controls-gtk-box</property>+                <property name="width_request">400</property>                 <property name="visible">True</property>                 <property name="can_focus">False</property>+                <property name="halign">center</property>                 <property name="valign">end</property>+                <property name="margin_bottom">10</property>                 <property name="orientation">vertical</property>                 <property name="baseline_position">bottom</property>                 <child>                   <object class="GtkScale" id="seek-scale">+                    <property name="name">seek-scale</property>                     <property name="visible">True</property>-                    <property name="app_paintable">True</property>-                    <property name="can_focus">False</property>-                    <property name="valign">end</property>+                    <property name="can_focus">True</property>+                    <property name="valign">center</property>                     <property name="margin_left">5</property>                     <property name="margin_right">5</property>-                    <property name="hexpand">True</property>+                    <property name="margin_top">5</property>                     <property name="adjustment">seek-scale-adjustment</property>                     <property name="show_fill_level">True</property>                     <property name="fill_level">100</property>-                    <property name="round_digits">0</property>-                    <property name="digits">-1</property>-                    <property name="draw_value">False</property>-                    <property name="value_pos">left</property>                   </object>                   <packing>                     <property name="expand">False</property>@@ -199,22 +205,25 @@                   </packing>                 </child>                 <child>-                  <object class="GtkBox" id="box-4">+                  <object class="GtkBox" id="box-3">+                    <property name="name">box-3</property>                     <property name="visible">True</property>                     <property name="can_focus">False</property>-                    <property name="valign">end</property>+                    <property name="valign">center</property>+                    <property name="margin_left">5</property>+                    <property name="margin_right">5</property>                     <property name="margin_top">5</property>                     <property name="margin_bottom">5</property>-                    <property name="hexpand">True</property>+                    <property name="spacing">2</property>                     <child>                       <object class="GtkButton" id="play-pause-button">+                        <property name="name">play-pause-button</property>                         <property name="visible">True</property>                         <property name="can_focus">True</property>                         <property name="receives_default">True</property>-                        <property name="tooltip_text" translatable="yes">Click to play</property>-                        <property name="margin_left">5</property>-                        <property name="margin_right">5</property>+                        <property name="tooltip_text" translatable="yes">Click to Play</property>                         <property name="image">play-image</property>+                        <property name="relief">none</property>                         <property name="always_show_image">True</property>                       </object>                       <packing>@@ -224,16 +233,31 @@                       </packing>                     </child>                     <child>+                      <object class="GtkCheckButton" id="repeat-check-button">+                        <property name="name">repeat-check-button</property>+                        <property name="visible">True</property>+                        <property name="can_focus">True</property>+                        <property name="receives_default">False</property>+                        <property name="tooltip_text" translatable="yes">Toggle Repeat On or Off</property>+                        <property name="image">repeat-check-button-image</property>+                        <property name="always_show_image">True</property>+                        <property name="draw_indicator">False</property>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">1</property>+                      </packing>+                    </child>+                    <child>                       <object class="GtkVolumeButton" id="volume-button">+                        <property name="name">volume-button</property>                         <property name="visible">True</property>-                        <property name="app_paintable">True</property>                         <property name="can_focus">True</property>                         <property name="focus_on_click">False</property>                         <property name="receives_default">True</property>                         <property name="double_buffered">False</property>-                        <property name="margin_left">5</property>-                        <property name="margin_right">5</property>-                        <property name="relief">half</property>+                        <property name="relief">none</property>                         <property name="orientation">vertical</property>                         <property name="value">0.5</property>                         <property name="size">button</property>@@ -242,7 +266,8 @@ audio-volume-low-symbolic audio-volume-medium-symbolic</property>                         <child internal-child="plus_button">-                          <object class="GtkButton" id="volume-up-button">+                          <object class="GtkButton" id="volume-plus-button">+                            <property name="name">volume-plus-button</property>                             <property name="can_focus">True</property>                             <property name="receives_default">True</property>                             <property name="halign">center</property>@@ -251,7 +276,8 @@                           </object>                         </child>                         <child internal-child="minus_button">-                          <object class="GtkButton" id="volume-down-button">+                          <object class="GtkButton" id="volume-minus-button">+                            <property name="name">volume-minus-button</property>                             <property name="can_focus">True</property>                             <property name="receives_default">True</property>                             <property name="halign">center</property>@@ -263,22 +289,21 @@                       <packing>                         <property name="expand">False</property>                         <property name="fill">False</property>-                        <property name="position">1</property>+                        <property name="position">2</property>                       </packing>                     </child>                     <child>-                      <object class="GtkComboBoxText" id="video-width-selection-combo-box">+                      <object class="GtkComboBoxText" id="window-width-selection-combo-box-text">+                        <property name="name">window-width-selection-combo-box-text</property>                         <property name="visible">True</property>-                        <property name="app_paintable">True</property>-                        <property name="can_focus">False</property>-                        <property name="tooltip_text" translatable="yes">Set the window width</property>-                        <property name="margin_left">5</property>-                        <property name="margin_right">5</property>+                        <property name="can_focus">True</property>+                        <property name="focus_on_click">False</property>+                        <property name="tooltip_text" translatable="yes">Set the Window Width</property>                         <property name="active">1</property>                         <property name="has_frame">False</property>                         <property name="active_id">800</property>                         <items>-                          <item id="320" translatable="yes">320</item>+                          <item id="448" translatable="yes">448</item>                           <item id="800" translatable="yes">800</item>                           <item id="1024" translatable="yes">1024</item>                           <item id="1152" translatable="yes">1152</item>@@ -298,15 +323,15 @@                       <packing>                         <property name="expand">False</property>                         <property name="fill">False</property>-                        <property name="position">2</property>+                        <property name="position">3</property>                       </packing>                     </child>                     <child>-                      <object class="GtkComboBoxText" id="subtitle-selection-combo-box">-                        <property name="can_focus">False</property>-                        <property name="tooltip_text" translatable="yes">Select the subtitle language</property>-                        <property name="margin_left">5</property>-                        <property name="margin_right">5</property>+                      <object class="GtkComboBoxText" id="subtitle-selection-combo-box-text">+                        <property name="name">subtitle-selection-combo-box-text</property>+                        <property name="can_focus">True</property>+                        <property name="focus_on_click">False</property>+                        <property name="tooltip_text" translatable="yes">Select the Subtitle Language</property>                         <property name="active_id">-1</property>                         <items>                           <item id="-1" translatable="yes">None</item>@@ -315,58 +340,53 @@                       <packing>                         <property name="expand">False</property>                         <property name="fill">True</property>-                        <property name="position">3</property>+                        <property name="position">4</property>                       </packing>                     </child>                     <child>                       <object class="GtkButton" id="fullscreen-button">-                        <property name="app_paintable">True</property>-                        <property name="can_focus">False</property>+                        <property name="name">fullscreen-button</property>+                        <property name="can_focus">True</property>                         <property name="receives_default">False</property>-                        <property name="tooltip_text" translatable="yes">Toggle on or off fullscreen</property>-                        <property name="margin_left">5</property>-                        <property name="margin_right">5</property>+                        <property name="tooltip_text" translatable="yes">Toggle On or Off Fullscreen</property>                         <property name="image">fullscreen-image</property>-                        <property name="relief">half</property>+                        <property name="relief">none</property>                         <property name="always_show_image">True</property>                       </object>                       <packing>                         <property name="expand">False</property>                         <property name="fill">True</property>-                        <property name="position">4</property>+                        <property name="position">5</property>                       </packing>                     </child>                     <child>                       <object class="GtkSpinner" id="buffering-spinner">                         <property name="sensitive">False</property>-                        <property name="app_paintable">True</property>                         <property name="can_focus">False</property>-                        <property name="margin_left">5</property>                       </object>                       <packing>                         <property name="expand">False</property>                         <property name="fill">False</property>-                        <property name="position">5</property>+                        <property name="position">6</property>                       </packing>                     </child>                     <child>                       <object class="GtkButton" id="about-button">+                        <property name="name">about-button</property>                         <property name="visible">True</property>-                        <property name="app_paintable">True</property>-                        <property name="can_focus">False</property>+                        <property name="can_focus">True</property>+                        <property name="focus_on_click">False</property>                         <property name="receives_default">False</property>                         <property name="tooltip_text" translatable="yes">About Movie Monad</property>-                        <property name="margin_left">5</property>-                        <property name="margin_right">5</property>                         <property name="image">about-image</property>-                        <property name="relief">half</property>+                        <property name="relief">none</property>                         <property name="always_show_image">True</property>                       </object>                       <packing>                         <property name="expand">False</property>                         <property name="fill">False</property>                         <property name="pack_type">end</property>-                        <property name="position">6</property>+                        <property name="position">7</property>                       </packing>                     </child>                   </object>@@ -378,17 +398,15 @@                 </child>               </object>               <packing>-                <property name="expand">False</property>-                <property name="fill">False</property>-                <property name="pack_type">end</property>-                <property name="position">3</property>+                <property name="pass_through">True</property>               </packing>             </child>           </object>           <packing>             <property name="expand">True</property>             <property name="fill">True</property>-            <property name="position">0</property>+            <property name="pack_type">end</property>+            <property name="position">2</property>           </packing>         </child>       </object>@@ -408,7 +426,7 @@     <property name="transient_for">window</property>     <property name="attached_to">window</property>     <property name="program_name">Movie Monad</property>-    <property name="version">0.0.4.0</property>+    <property name="version">0.0.5.0</property>     <property name="copyright" translatable="yes">(C) 2017 David Lettier lettier.com</property>     <property name="website">https://github.com/lettier/movie-monad</property>@@ -446,7 +464,7 @@     <property name="logo">movie-monad-logo.svg</property>     <property name="license_type">custom</property>     <child internal-child="vbox">-      <object class="GtkBox" id="box-5">+      <object class="GtkBox" id="box-4">         <property name="can_focus">False</property>         <property name="orientation">vertical</property>         <property name="spacing">2</property>@@ -486,7 +504,7 @@ Thank you.</property>     <property name="secondary_use_markup">True</property>     <child internal-child="vbox">-      <object class="GtkBox" id="box-6">+      <object class="GtkBox" id="box-5">         <property name="can_focus">False</property>         <property name="orientation">vertical</property>         <property name="spacing">2</property>@@ -514,7 +532,7 @@     <property name="type_hint">dialog</property>     <property name="transient_for">window</property>     <child internal-child="vbox">-      <object class="GtkBox" id="box-7">+      <object class="GtkBox" id="box-6">         <property name="can_focus">False</property>         <property name="orientation">vertical</property>         <property name="spacing">2</property>@@ -541,7 +559,7 @@           <object class="GtkEntry" id="file-chooser-entry">             <property name="visible">True</property>             <property name="can_focus">True</property>-            <property name="tooltip_text" translatable="yes">Type in the path to a local file or URL</property>+            <property name="tooltip_text" translatable="yes">Type in a File Path or a URL</property>             <property name="has_frame">False</property>             <property name="truncate_multiline">True</property>             <property name="primary_icon_stock">gtk-edit</property>
− src/data/movie-monad-icon.png

binary file changed (24223 → absent bytes)

+ src/data/movie-monad-icon.svg view
@@ -0,0 +1,267 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<svg+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:xlink="http://www.w3.org/1999/xlink"+   id="svg8"+   version="1.1"+   viewBox="0 0 74.20314 74.20314"+   height="74.20314mm"+   width="74.20314mm">+  <defs+     id="defs2">+    <linearGradient+       id="linearGradient5445">+      <stop+         id="stop5441"+         offset="0"+         style="stop-color:#57ace3;stop-opacity:1;" />+      <stop+         id="stop5443"+         offset="1"+         style="stop-color:#57ace3;stop-opacity:0;" />+    </linearGradient>+    <marker+       style="overflow:visible"+       id="Arrow1Mend"+       refX="0"+       refY="0"+       orient="auto">+      <path+         transform="matrix(-0.4,0,0,-0.4,-4,0)"+         style="fill:#57ace3;fill-opacity:1;fill-rule:evenodd;stroke:#57ace3;stroke-width:1.00000003pt;stroke-opacity:1"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         id="path10335" />+    </marker>+    <marker+       style="overflow:visible"+       id="marker10589"+       refX="0"+       refY="0"+       orient="auto">+      <path+         transform="matrix(0.8,0,0,0.8,10,0)"+         style="fill:#57ace3;fill-opacity:1;fill-rule:evenodd;stroke:#57ace3;stroke-width:1.00000003pt;stroke-opacity:1"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         id="path10326" />+    </marker>+    <linearGradient+       id="linearGradient10200">+      <stop+         style="stop-color:#57ace3;stop-opacity:1"+         offset="0"+         id="stop10196" />+      <stop+         style="stop-color:#e0437f;stop-opacity:0.89019608"+         offset="1"+         id="stop10198" />+    </linearGradient>+    <linearGradient+       osb:paint="solid"+       id="linearGradient8935">+      <stop+         id="stop8933"+         offset="0"+         style="stop-color:#373737;stop-opacity:1;" />+    </linearGradient>+    <linearGradient+       id="linearGradient5282">+      <stop+         id="stop5278"+         offset="0"+         style="stop-color:#814dd2;stop-opacity:1;" />+      <stop+         id="stop5280"+         offset="1"+         style="stop-color:#b46bd3;stop-opacity:0.89019608" />+    </linearGradient>+    <marker+       style="overflow:visible"+       id="Arrow1Lend"+       refX="0"+       refY="0"+       orient="auto">+      <path+         transform="matrix(-0.8,0,0,-0.8,-10,0)"+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         id="path4997" />+    </marker>+    <marker+       style="overflow:visible"+       id="Arrow1Lstart"+       refX="0"+       refY="0"+       orient="auto">+      <path+         transform="matrix(0.8,0,0,0.8,10,0)"+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"+         d="M 0,0 5,-5 -12.5,0 5,5 Z"+         id="path4994" />+    </marker>+    <linearGradient+       gradientUnits="userSpaceOnUse"+       y2="53.285694"+       x2="-64.290207"+       y1="53.642838"+       x1="-119.13808"+       id="linearGradient5284"+       xlink:href="#linearGradient5282" />+    <linearGradient+       y2="55.071407"+       x2="-58.218777"+       y1="53.642838"+       x1="-119.13808"+       gradientUnits="userSpaceOnUse"+       id="linearGradient5300"+       xlink:href="#linearGradient5282" />+    <linearGradient+       y2="55.071407"+       x2="-58.218777"+       y1="53.642838"+       x1="-119.13808"+       gradientUnits="userSpaceOnUse"+       id="linearGradient5352"+       xlink:href="#linearGradient5282" />+    <linearGradient+       y2="53.285694"+       x2="-64.290207"+       y1="53.642838"+       x1="-119.13808"+       gradientUnits="userSpaceOnUse"+       id="linearGradient5354"+       xlink:href="#linearGradient5282" />+    <linearGradient+       gradientTransform="matrix(1.1521699,0,0,1.1943224,-10.9053,-54.269335)"+       gradientUnits="userSpaceOnUse"+       y2="250.69791"+       x2="128.98438"+       y1="250.69791"+       x1="61.251041"+       id="linearGradient5260"+       xlink:href="#linearGradient10200" />+    <clipPath+       id="clipPath5388"+       clipPathUnits="userSpaceOnUse">+      <g+         id="g5394">+        <path+           id="path5390"+           d="m 125.5315,249.78764 c -3.34965,-1.30393 -6.69931,-2.60787 -10.04896,-3.9118 5.21848,-2.15262 10.43696,-4.30525 15.65545,-6.45787 -0.92835,-2.01253 -1.85669,-4.02505 -2.78504,-6.03758 -6.83922,2.90641 -13.67843,5.81282 -20.51763,8.71921 0.0104,2.54721 0.0208,5.09442 0.0312,7.64163 6.86079,2.8724 13.7216,5.74479 20.58242,8.61717 0.90892,-2.11466 1.81783,-4.22931 2.72675,-6.34397 -1.76975,-0.68894 -3.53951,-1.37789 -5.30926,-2.06683 m -2.62477,-4.90221 c 3.04901,-1.25752 6.09801,-2.51505 9.14702,-3.77257 -0.92751,-2.01274 -1.85501,-4.02549 -2.78252,-6.03823 -2.59416,1.10259 -5.18831,2.20519 -7.78247,3.30778 m 5.56493,-1.53082 c -5.40972,2.29966 -10.81943,4.59932 -16.22916,6.89899 0.0117,2.54697 0.0234,5.09394 0.0352,7.64091 6.86463,2.8717 13.72924,5.74341 20.59384,8.61511 0.91009,-2.11486 1.82018,-4.22973 2.73027,-6.3446 -5.23684,-2.04024 -10.47368,-4.08049 -15.71053,-6.12073 0.75831,-0.31271 1.51662,-0.62542 2.27492,-0.93812 m -14.17992,-7.36348 c -0.76309,-1.65493 -1.52619,-3.30987 -2.28928,-4.9648 -6.839321,2.90343 -13.678636,5.80688 -20.517944,8.71032 0.01054,2.5462 0.02107,5.0924 0.03161,7.6386 6.860547,2.86946 13.721102,5.73892 20.581665,8.60838 0.90903,-2.11556 1.81807,-4.23112 2.72711,-6.34668 -5.23993,-2.04195 -10.479854,-4.08389 -15.719772,-6.12583 3.538493,-1.46115 7.076989,-2.9223 10.615482,-4.38345 m -9.578035,6.75815 c -0.379995,-0.14802 -0.759989,-0.29603 -1.139983,-0.44404 5.220982,-2.15291 10.441958,-4.30583 15.662928,-6.45875 -0.54602,-1.18498 -1.09203,-2.36995 -1.63805,-3.55493 m -30.759591,4.52156 c 2.327107,-4.2e-4 4.654213,-8.4e-4 6.981318,-0.001 4.72e-4,-2.42569 9.42e-4,-4.85139 0.0014,-7.27708 -5.608879,-0.001 -11.217765,-0.002 -16.826659,-0.003 4.62e-4,2.42483 9.24e-4,4.84967 0.0014,7.2745 5.611028,-9.8e-4 11.22205,-0.002 16.833063,-0.003 4.54e-4,-2.42568 9.07e-4,-4.85135 0.0014,-7.27703 -1.723988,-3e-4 -3.447976,-5.9e-4 -5.171966,-8.9e-4 m -2.024007,22.444 c 2.816132,-1e-5 5.632262,-2e-5 8.448391,-3e-5 4.56e-4,-2.64572 9.1e-4,-5.29144 0.0014,-7.93716 -5.637754,-2e-5 -11.275514,-5e-5 -16.913281,-7e-5 4.48e-4,2.6457 8.94e-4,5.29139 0.0013,7.93709 5.639668,-2e-5 11.279329,-5e-5 16.918984,-7e-5 4.39e-4,-2.64571 8.77e-4,-5.29143 0.0013,-7.93714 -0.03972,0 -0.07944,0 -0.119166,0 m 27.325498,-18.3087 -17.328914,7.36254 m 21.261664,1.45287 -0.93476,0.39715 m 0.9253,12.30443 14.19828,5.93971"+           style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.23003563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />+        <path+           transform="matrix(0.23003563,0,0,0.23003563,-34.32847,220.35427)"+           style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"+           d="m 650.1385,82.874465 c -10.14856,3.782654 -20.17926,7.700083 -30.11698,11.72366 3e-5,-0.006 -0.20482,33.232065 -0.20478,33.226075 10.46549,4.53108 20.80642,9.17856 30.98016,13.96537 M 633.88611,89.913445 c -4.37599,1.711249 -8.73217,3.445238 -13.07064,5.199586 10e-6,-4.22e-4 -0.0731,11.184859 -0.0731,11.184439 m 0.3725,-3.80674 c 2e-5,-0.002 -0.17666,25.85227 -0.17665,25.8502 14.60689,6.33968 28.96767,12.90811 42.96621,19.76778 m -31.32028,-14.07007 c 25.19819,11.26699 49.55187,23.27873 72.44648,36.3659 1.42471,-2.72961 2.86128,-5.45544 4.31003,-8.17738 m -6.9747,6.68407 c 0.92932,0.52537 1.85629,1.05248 2.78088,1.58133 4.58589,-8.78001 9.29471,-17.52088 14.13698,-26.21901 -6.95333,-3.77163 -14.01978,-7.44184 -21.18454,-11.01929 m 1.28755,-0.18569 c -14.81139,-7.42465 -30.04545,-14.44997 -45.57119,-21.15245 12.62262,-4.62919 25.39834,-9.03993 38.37684,-13.17341 m -18.736,22.83496 c -6.26352,-2.87301 -12.58606,-5.68603 -18.95852,-8.44437 23.14013,-8.47831 46.79246,-16.218619 71.2638,-22.85755 -0.22881,-0.662606 -0.45833,-1.325109 -0.68856,-1.987508 M 654.01463,113.139 c -2.7e-4,-1.2e-4 -0.7157,-0.30906 -0.71597,-0.30917 23.13517,-8.5031 46.78037,-16.274199 71.2423,-22.950019 -2.81543,-8.107892 -5.73743,-16.200324 -8.75838,-24.277065 m -26.0906,33.266668 C 700.9826,95.2376 712.42531,91.81337 724.05294,88.63561 723.6003,87.337599 723.14495,86.039985 722.6869,84.742768 m -0.61698,6.067377 c 0.81695,-0.226028 1.6348,-0.450842 2.45357,-0.674428 -3.17915,-9.162957 -6.49443,-18.306184 -9.93482,-27.429347 -0.62065,0.179639 -1.24074,0.359926 -1.86026,0.540855 m 11.24057,25.511777 c -3e-5,7e-6 0.25989,-0.07102 0.25987,-0.07101 -3.19279,-9.161294 -6.52126,-18.302817 -9.97442,-27.424233 -10.91387,3.159213 -21.65318,6.518244 -32.24401,10.04705 m 11.85645,-2.486221 c -23.89063,7.594747 -46.99669,16.092552 -69.6095,25.158099 m -0.43504,1.234896 c -0.86163,0.346106 -1.72255,0.693034 -2.58277,1.040765 0,-6.34e-4 -0.0817,11.715584 -0.0816,11.714954 m -1.1452,-4.62256 c 2e-5,-0.003 -0.15748,25.97022 -0.15747,25.96764 19.67826,8.52466 38.91018,17.46103 57.41168,26.96201 m -5.18017,-4.09637 c 11.17724,5.62986 22.1038,11.4573 32.71864,17.51516 1.06549,-2.04103 2.13762,-4.07996 3.21651,-6.11673 m -16.16776,-0.69646 c 4.49775,2.43586 8.94607,4.90905 13.34063,7.42189 4.58695,-8.78083 9.2969,-17.5225 14.14034,-26.22142 -13.91794,-7.55008 -28.28862,-14.69392 -42.99342,-21.50079 m 3.21074,0.98686 c -8.79479,-4.11181 -17.71249,-8.10054 -26.7275,-11.98114 9.58226,-3.52312 19.25253,-6.92117 29.03252,-10.1684 m -6.29117,3.40887 c 16.00699,-5.451544 32.29632,-10.509546 48.965,-15.059102 -2.7328,-7.869445 -5.56598,-15.724327 -8.49254,-23.564436 m 9.71391,23.600286 c 0,0 0.0757,-0.02053 0.0757,-0.02053 -3.16863,-9.16775 -6.47406,-18.315717 -9.90529,-27.443567 -14.81942,4.262317 -29.3167,8.895683 -43.55719,13.824889 m 47.96342,-1.486613 c -1.4697,-4.050884 -2.96505,-8.097851 -4.48508,-12.14087 -10.36572,2.9834 -20.57391,6.148352 -30.64696,9.469099 m 34.56573,1.426708 c -1.47522,-4.049947 -2.97598,-8.095973 -4.5013,-12.138051 -19.92422,5.742688 -39.26545,12.153458 -58.18225,19.049877 m 27.30054,-7.799146 c -7.20357,2.383909 -14.33829,4.847277 -21.41236,7.380658 m 13.91885,-6.240903 c -18.55555,6.311359 -36.66528,13.133939 -54.4718,20.303685 M 522.52817,91.33976 c -3.71543,1.71506 -7.42434,3.436 -11.12792,5.16192 -5e-5,-0.0011 0.51202,11.70155 0.51197,11.70043 m -1.1665,-9.974259 c -2e-5,7e-6 -0.1003,0.04677 -0.10032,0.04678 -4.8e-4,-0.01106 1.45486,33.189163 1.45438,33.178103 14.55619,5.39325 29.02314,10.86367 43.33703,16.46536 m -44.30747,-34.95594 c -1.2e-4,-0.003 0.7663,17.43323 0.76618,17.43044 2.49473,0.92408 4.98688,1.85041 7.47614,2.77928 m -7.7994,-15.73106 c -6e-5,-0.001 0.55121,12.57744 0.55114,12.57602 16.53443,6.12668 32.95588,12.35293 49.17089,18.75796 m -49.99946,-25.64531 c -2e-5,-4.2e-4 0.29602,6.72016 0.296,6.71974 21.69281,8.03096 43.19288,16.23183 64.28933,24.78141 m -55.73533,-22.29122 c 16.28128,6.07809 32.43879,12.26569 48.38274,18.6389 m -29.93723,-10.07554 c 13.09037,4.99891 26.07571,10.08848 38.90831,15.30914 4.92668,2.00718 9.8291,4.03142 14.70284,6.07511 m -42.55877,-18.2672 c 9.34563,3.62215 18.63091,7.2968 27.83828,11.03885 8.29429,3.37568 16.52059,6.79982 24.65785,10.28374 2.01069,-4.82106 4.0379,-9.63863 6.08313,-14.45221 m -27.09237,6.5496 c 6.76797,2.77515 13.48798,5.5838 20.1485,8.43215 3.83273,-9.20444 7.72504,-18.39642 11.68744,-27.57238 -2.66279,-1.06701 -5.33349,-2.1269 -8.01145,-3.18005 m -17.67348,24.80831 c -4e-4,-1.7e-4 0.71089,0.29523 0.71049,0.29506 m 0.1423,0.48985 c 4.49734,1.87003 8.97142,3.75596 13.41882,5.65962 m -10.07756,-3.99132 c 3.3045,1.3838 6.59589,2.77646 9.8728,4.17875 3.83071,-9.20427 7.72094,-18.39609 11.68121,-27.57188 -4.68156,-1.87698 -9.38775,-3.73191 -14.11494,-5.56693 m -3.47113,28.46889 c 2.5033,1.05562 4.99884,2.11653 7.48603,3.18308 3.84259,-9.20093 7.74586,-18.38896 11.72032,-27.56052 -12.40258,-4.98562 -24.97809,-9.81439 -37.65896,-14.52577 -3.82029,-1.41856 -7.65021,-2.82596 -11.48865,-4.22321 m 48.53743,21.60948 c -1.7e-4,3.9e-4 0.39562,-0.91482 0.39545,-0.91442 -12.31989,-4.95543 -24.81309,-9.75643 -37.41315,-14.4418 0,0 0,0 0,0 -0.002,-6.7e-4 -1.5944,-0.59165 -1.59619,-0.59232 m 14.92841,5.28033 c -4.43048,-1.68898 -8.87723,-3.36174 -13.33731,-5.02001 -10.81095,-4.01704 -21.70034,-7.94452 -32.64285,-11.80547 3.60406,-1.59938 7.21381,-3.19151 10.83032,-4.77558 m 3.29087,8.88546 c -4.50086,-1.62052 -9.01254,-3.22799 -13.53326,-4.82404 10.49312,-4.65332 21.03521,-9.24496 31.65268,-13.754413 6.66805,-2.833165 13.36682,-5.635506 20.10392,-8.398021 M 554.26188,116.4854 c -2.78093,-0.99529 -5.56581,-1.98581 -8.35423,-2.97194 3.53011,-1.56467 7.06571,-3.12228 10.60782,-4.67206 m -6.28217,1.12112 c 8.75211,-3.85687 17.54116,-7.66857 26.38242,-11.423276 6.20558,-2.636402 12.43772,-5.246109 18.70256,-7.821867 M 565.235,104.41462 c 1.69001,-0.73028 3.38168,-1.45864 5.07513,-2.185 m -3.7095,0.27093 c 3.32978,-1.43549 6.66623,-2.863461 10.01016,-4.283286 12.05562,-5.120857 24.21185,-10.14093 36.5136,-15.007053 -3.81958,-8.195982 -7.69977,-16.37731 -11.6316,-24.543711 m 7.66441,15.992954 c -2.66865,-5.659947 -5.36479,-11.312843 -8.08546,-16.958599 -6.13403,2.520537 -12.22664,5.07595 -18.28339,7.659824 m 21.84963,0.238651 c -1.20001,-2.513838 -2.40514,-5.026273 -3.61513,-7.537296 -5.45027,2.240821 -10.8679,4.509159 -16.25681,6.80051 m 12.33523,-6.475731 c -6.71383,2.781303 -13.37891,5.602978 -20.0026,8.456552 m 5.22342,-1.425141 c -2.06169,0.880321 -4.11923,1.763923 -6.17285,2.650552 -21.36486,9.204436 -42.34641,18.729808 -63.15655,28.416385 m 73.147,-32.390491 c -3.33946,1.415917 -6.66778,2.840803 -9.98587,4.27359 -14.08986,6.07131 -28.0133,12.282249 -41.83112,18.58698 m 34.13476,-15.102029 c -13.55068,5.91156 -26.95662,11.945573 -40.2726,18.06074 m 39.16746,-18.497686 c -10.0099,4.372426 -19.94106,8.811076 -29.81557,13.299296 m 19.59876,-7.374448 c -15.5269,6.890006 -30.88255,13.927354 -46.15087,21.048813 -1e-4,-0.0022 0.70303,16.025174 0.70293,16.022934 m 0.87606,-18.197656 c -1.8e-4,8.6e-5 -0.35811,0.166728 -0.35829,0.166814 m 1.0845,0.822688 c -0.004,0.0019 -1.6924,0.788526 -1.69655,0.790459 -1.3e-4,-0.0029 0.8415,19.229225 0.84138,19.226345 m 0.27161,-20.309876 c -7.4e-4,3.43e-4 -0.7139,0.332478 -0.71464,0.332822 -4.1e-4,-0.0093 1.44551,33.189744 1.44511,33.180454 11.28037,4.18384 22.50704,8.41503 33.65029,12.71877 m -35.32335,-28.4736 c -1.1e-4,-0.002 0.69833,15.95299 0.69823,15.95058 17.67847,6.5524 35.2262,13.2193 52.52889,20.09755 m -13.02772,-5.47913 c 6.6484,2.58631 13.26536,5.19988 19.84453,7.84608 m -14.54076,-5.47895 c 3.37538,1.32474 6.74215,2.65692 10.09948,3.99724 m -5.39576,-1.55957 c 5.19891,2.05665 10.37627,4.13181 15.52899,6.22812 7.99932,3.25904 15.93464,6.56309 23.78707,9.92231 3.57334,-8.58229 7.19846,-17.15376 10.88388,-25.71151 m -48.34699,8.62713 c 4.56751,1.81107 9.1183,3.63669 13.65027,5.47863 8.54576,3.47808 17.01964,7.00763 25.39866,10.60104 1.91828,-4.59494 3.85169,-9.18667 5.80151,-13.77474 m -41.52622,0.53198 c 3.46016,1.38089 6.91028,2.77041 10.34944,4.16935 8.32169,3.38981 16.57422,6.82834 24.73632,10.32703 3.83666,-9.20168 7.7334,-18.39069 11.70074,-27.56344 -5.91972,-2.37789 -11.87907,-4.72026 -17.87072,-7.03142 m 13.95401,4.36254 c -0.002,-8.8e-4 -1.79942,-0.71399 -1.80164,-0.71487 m 0.2527,1.27065 c -10.383,-4.11626 -20.88016,-8.12817 -31.45225,-12.05866 -10.56518,-3.92547 -21.20529,-7.76542 -31.89671,-11.54133 -0.0133,0.006 3.635,-1.60838 3.62171,-1.60249 m 48.06573,20.84643 c -4.71759,-1.82299 -9.45546,-3.6265 -14.21001,-5.41264 m 2.40102,-0.24272 c -2.66027,-1.00343 -5.32589,-2.00128 -7.99623,-2.99393 -10.42273,-3.87217 -20.91774,-7.66119 -31.46237,-11.38766 -0.0155,0.007 3.94408,-1.74398 3.92858,-1.73711 m 20.40457,11.06315 c -7.93034,-2.90965 -15.89953,-5.77414 -23.89767,-8.60246 5.07406,-2.24838 10.15954,-4.48219 15.25944,-6.69909 m -13.61623,6.67486 c -0.009,-0.003 -3.05456,-1.0798 -3.06326,-1.08288 10.62529,-4.71174 21.30067,-9.36051 32.05354,-13.925016 7.17818,-3.048345 14.3921,-6.060956 21.6512,-9.026612 m -8.83851,3.867272 c 7.88156,-3.275909 15.81224,-6.50137 23.80435,-9.661803 -0.90946,-1.951272 -1.82236,-3.901714 -2.73857,-5.851321 m 2.26344,3.123577 c -3.69749,-7.913834 -7.45102,-15.813948 -11.25251,-23.700094 -8.52807,3.498878 -16.97554,7.065434 -25.35735,10.682462 -4.89403,2.107372 -9.76789,4.231576 -14.62411,6.370693 M 445.26039,104.95921 c 8.95388,-0.41892 2.48979,-0.11655 11.44367,-0.53548 m -10.32304,0.17021 c 17.33763,-0.81148 34.68486,-1.62857 52.04397,-2.35972 0,2e-5 -0.46265,-11.003332 -0.46265,-11.003312 m -45.86181,13.509922 c 10.91924,-0.51039 21.84207,-1.01902 32.76909,-1.50304 m -10.72124,-0.82499 c 8.06799,-0.36738 16.13864,-0.72541 24.21221,-1.06487 0.002,0.0443 -1.33278,-31.644013 -1.33091,-31.599662 -6.59015,0.277373 -13.17046,0.56677 -19.74107,0.863273 m 2.25648,0.535649 c -7.33994,0.328149 -36.12847,1.680751 -43.46841,2.0089 m 35.77564,-0.870908 c -10.87947,0.497595 -31.75687,1.489268 -42.63634,1.986863 m 3.35972,-1.504318 c 0.3926,-0.01824 -9.26877,0.428031 -8.87616,0.409785 -0.001,-0.02231 1.44585,31.619878 1.44483,31.597578 0.10319,-0.005 5.20958,-0.23887 5.31278,-0.24357 m -0.204,-30.764537 c 0.20259,-0.0094 -6.92127,0.318259 -6.71869,0.308893 -9.8e-4,-0.02167 1.4404,31.616444 1.43942,31.594774 0.18506,-0.008 6.8961,-0.31721 7.08117,-0.32567 m -6.69282,-6.800653 c 0,-4e-6 0.31803,6.962623 0.31803,6.962613 0.24334,-0.0111 7.70728,-0.35517 7.95063,-0.3663 m -8.35399,-1.37173 c 0,0 0.0827,1.80758 0.0827,1.80758 3.05198,-0.1396 22.3444,-1.0416 25.39639,-1.1812 m 20.54411,-1.2031 c 8.98415,-0.412 17.97129,-0.81375 26.96173,-1.19252 0.002,0.0378 -1.33278,-31.63929 -1.33119,-31.601527 -10.17041,0.427735 -20.31779,0.884055 -30.44258,1.350874 m 30.68618,-0.727576 c -20.40162,0.859073 -40.71202,1.833698 -60.93492,2.777862 m 28.41956,-1.684043 c -4.22241,0.195401 -19.86403,0.929934 -24.08644,1.125334 m 22.1757,-1.068146 c -22.67755,1.053109 -16.70814,0.783245 -39.38568,1.836354 -1.5e-4,-0.0032 0.53526,11.761592 0.53512,11.758434 M 456.1832,71.641038 c -107.36134,5.003653 74.40662,-3.471827 -32.95473,1.531826 -1e-4,-0.0021 0.45249,9.905361 0.45239,9.903239 m 25.13451,-10.51949 c 11.4671,-0.537186 -36.69231,1.710473 -25.2252,1.173287 -0.001,-0.02348 1.44302,31.62008 1.44195,31.5966 6.6279,-0.30246 28.48629,-1.33026 35.11418,-1.63271 m -34.01894,1.55836 c 13.40919,-0.61298 30.78484,-1.43956 44.19403,-2.05254 m -9.57076,1.21557 c 12.84616,-0.59866 25.69743,-1.18654 38.55477,-1.72643 0.003,0.0687 -1.20262,-28.704057 -1.19974,-28.635325 m -20.19182,84.780915 c -0.21095,0.01 8.4496,-0.38049 8.23866,-0.3709 m -8.41928,0.49644 c 7.79043,-0.35497 15.56308,-0.70026 23.31815,-1.02742 0.007,0.17634 -1.454,-34.6511 -1.4466,-34.47476 -7.23283,0.30431 -14.47011,0.62392 -21.71203,0.95211 m 9.43944,34.49334 c 4.35639,-0.19382 8.70719,-0.3835 13.05244,-0.56757 0.003,0.0658 -1.45774,-34.5418 -1.45496,-34.47597 -0.0566,0.002 -5.57856,0.23811 -5.63518,0.2405 m 7.67487,28.58015 c 0,0 -0.41001,-9.7569 -0.41001,-9.7569 m 0.84075,6.75642 c 0.001,0.0345 -1.11266,-26.54189 -1.11121,-26.50737 -17.97928,0.75466 -35.9856,1.60511 -54.02154,2.44839 m 55.02012,23.80444 c 0.006,0.15291 -0.85594,-20.44976 -0.84954,-20.29685 m 0.21926,1.51521 c 3.2e-4,0.007 -0.35057,-8.37981 -0.35026,-8.37231 -10.56586,0.44235 -21.14047,0.91781 -31.72435,1.40548 m 9.07711,1.51928 c -17.08329,0.77653 -35.79512,1.67755 -52.8784,2.45408 -0.001,-0.0288 1.56889,34.50005 1.56758,34.4713 0.0578,-0.003 4.17177,-0.18968 4.22958,-0.1923 m -4.9898,-19.88838 c -3.9e-4,-0.009 0.87703,19.28511 0.87665,19.27657 18.52645,-0.84154 35.36,-1.65485 53.88645,-2.49639 m 11.79881,0.19044 c -0.15813,0.007 8.99192,-0.38652 8.83379,-0.37961 0,-8e-5 -1.43645,-34.11648 -1.43645,-34.11656 m -1.69544,33.35022 c -0.0262,0.001 3.81656,-0.16211 3.79034,-0.16098 0.0154,0.36787 -1.45891,-34.8442 -1.44351,-34.47633 -0.0214,9e-4 -3.51047,0.14833 -3.53187,0.14923 m 4.61961,19.10903 c 0.004,0.0846 -0.7849,-18.76637 -0.78136,-18.68176 -24.53906,1.02942 -49.13067,2.23808 -73.78157,3.36404 m 73.39732,-3.66621 c 0,0 -0.0474,-1.127 -0.0474,-1.127 -8.93561,0.37444 -17.87754,0.77245 -26.82607,1.18138 m 15.15017,0.12669 c -0.22973,0.0101 -9.6171,0.43046 -9.84682,0.44058 m 1.52062,0.345 c -16.3477,0.7365 -38.85642,1.81571 -55.20412,2.55222 -0.001,-0.024 1.47399,32.4516 1.4729,32.4276 m 40.34206,-35.16508 c -25.57791,1.18495 -15.88789,0.74325 -41.4658,1.92819 -7.8e-4,-0.0171 1.20903,26.53287 1.20826,26.51578 m 24.69612,-28.18016 c 9.38054,-0.43806 -35.6539,1.65382 -26.27337,1.21576 -0.001,-0.0299 1.57081,34.49549 1.56944,34.46557 0.0759,-0.003 4.73497,-0.21628 4.81082,-0.21973 m -2.79194,-33.16411 c 0.024,-0.001 -2.59955,0.11863 -2.57551,0.11753 -3.8e-4,-0.008 0.81071,17.75552 0.81033,17.74722 m -1.05401,-3.95996 c -4.1e-4,-0.009 0.893,19.58434 0.89259,19.57526 0.0996,-0.005 5.38625,-0.24533 5.48582,-0.24984 m -0.33746,0.29461 c 18.09098,-0.82865 28.05353,-1.30984 46.14451,-2.13849 m -30.04522,0.96991 c 1.36603,-0.0638 6.13168,-0.28688 7.4977,-0.35072 m -6.93486,1.30994 c 17.84352,-0.83316 35.59379,-1.67094 53.25327,-2.41376 0.001,0.025 -0.89264,-21.27401 -0.89159,-21.24898 M 645.80356,40.256829 c -23.8913,8.70051 -47.01068,18.108537 -69.65321,27.884575 -12.80286,5.515966 -25.46813,11.14719 -38.04142,16.859298 m 110.06361,-0.565846 c -1.94967,0.731567 -3.89505,1.468057 -5.83632,2.209266 m -8.16639,48.076008 c 27.78565,12.47688 54.52593,25.87031 79.39341,40.62548"+           id="path5392" />+      </g>+    </clipPath>+    <linearGradient+       gradientUnits="userSpaceOnUse"+       y2="171.69249"+       x2="208.0477"+       y1="171.69249"+       x1="194.11444"+       id="linearGradient5447"+       xlink:href="#linearGradient5445" />+  </defs>+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     style="display:inline"+     transform="translate(-61.468328,-167.44508)"+     id="layer1">+    <rect+       transform="translate(2.9514358e-6,-40.596579)"+       clip-path="url(#clipPath5388)"+       ry="2.3587098"+       y="206.27705"+       x="59.818722"+       height="77.735466"+       width="77.735458"+       id="rect5250"+       style="display:inline;opacity:1;fill:url(#linearGradient5260);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.31037128;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />+    <path+       id="text10004"+       d="m 125.5315,209.19106 c -3.34965,-1.30393 -6.69931,-2.60787 -10.04896,-3.9118 5.21848,-2.15262 10.43696,-4.30525 15.65545,-6.45787 -0.92835,-2.01253 -1.85669,-4.02505 -2.78504,-6.03758 -6.83922,2.90641 -13.67843,5.81282 -20.51763,8.71921 0.0104,2.54721 0.0208,5.09442 0.0312,7.64163 6.86079,2.8724 13.7216,5.74479 20.58242,8.61717 0.90892,-2.11466 1.81783,-4.22931 2.72675,-6.34397 -1.76975,-0.68894 -3.53951,-1.37789 -5.30926,-2.06683 m -2.62477,-4.90221 c 3.04901,-1.25752 6.09801,-2.51505 9.14702,-3.77257 -0.92751,-2.01274 -1.85501,-4.02549 -2.78252,-6.03823 -2.59416,1.10259 -5.18831,2.20519 -7.78247,3.30778 m 5.56493,-1.53082 c -5.40972,2.29966 -10.81943,4.59932 -16.22916,6.89899 0.0117,2.54697 0.0234,5.09394 0.0352,7.64091 6.86463,2.8717 13.72924,5.74341 20.59384,8.61511 0.91009,-2.11486 1.82018,-4.22973 2.73027,-6.3446 -5.23684,-2.04024 -10.47368,-4.08049 -15.71053,-6.12073 0.75831,-0.31271 1.51662,-0.62542 2.27492,-0.93812 m -14.17992,-7.36348 c -0.76309,-1.65493 -1.52619,-3.30987 -2.28928,-4.9648 -6.839318,2.90343 -13.678633,5.80688 -20.517941,8.71032 0.01054,2.5462 0.02107,5.0924 0.03161,7.6386 6.860547,2.86946 13.721102,5.73892 20.581661,8.60838 0.90903,-2.11556 1.81807,-4.23112 2.72711,-6.34668 -5.23993,-2.04195 -10.47985,-4.08389 -15.719768,-6.12583 3.538493,-1.46115 7.076989,-2.9223 10.615478,-4.38345 m -9.578031,6.75815 c -0.379995,-0.14802 -0.759989,-0.29603 -1.139983,-0.44404 5.220982,-2.15291 10.441954,-4.30583 15.662924,-6.45875 -0.54602,-1.18498 -1.09203,-2.36995 -1.63805,-3.55493 m -30.759587,4.52156 c 2.327107,-4.2e-4 4.654213,-8.4e-4 6.981318,-0.001 4.72e-4,-2.42569 9.42e-4,-4.85139 0.0014,-7.27708 -5.608879,-0.001 -11.217765,-0.002 -16.826659,-0.003 4.62e-4,2.42483 9.24e-4,4.84967 0.0014,7.2745 5.611028,-9.8e-4 11.22205,-0.002 16.833063,-0.003 4.54e-4,-2.42568 9.07e-4,-4.85135 0.0014,-7.27703 -1.723988,-3e-4 -3.447976,-5.9e-4 -5.171966,-8.9e-4 m -2.024007,22.444 c 2.816132,-1e-5 5.632262,-2e-5 8.448391,-3e-5 4.56e-4,-2.64572 9.1e-4,-5.29144 0.0014,-7.93716 -5.637754,-2e-5 -11.275514,-5e-5 -16.913281,-7e-5 4.48e-4,2.6457 8.94e-4,5.29139 0.0013,7.93709 5.639668,-2e-5 11.279329,-5e-5 16.918984,-7e-5 4.39e-4,-2.64571 8.77e-4,-5.29143 0.0013,-7.93714 -0.03972,0 -0.07944,0 -0.119166,0 m 27.32549,-18.3087 -17.328906,7.36254 m 21.261656,1.45287 -0.93476,0.39715 m 0.92531,12.30443 14.19828,5.93971"+       style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2a144d;stroke-width:0.23003563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />+    <path+       id="path10202"+       d="m 115.22655,198.82177 c -2.33453,0.87014 -4.64195,1.77129 -6.92798,2.69686 1e-5,-0.001 -0.0471,7.64456 -0.0471,7.64318 2.40744,1.04231 4.78622,2.11139 7.12654,3.21253 m -3.89008,-11.93336 c -1.00663,0.39365 -2.00871,0.79253 -3.00671,1.19609 0,-9e-5 -0.0168,2.57292 -0.0168,2.57282 m 0.0857,-0.87568 c 10e-6,-4.6e-4 -0.0406,5.94694 -0.0406,5.94646 3.36011,1.45836 6.6636,2.96933 9.88376,4.5473 m -7.20478,-3.23662 c 5.79648,2.59181 11.3987,5.35494 16.66528,8.36545 0.32773,-0.6279 0.65819,-1.25494 0.99146,-1.88109 m -1.60443,1.53758 c 0.21377,0.12085 0.42701,0.24211 0.6397,0.36376 1.05492,-2.01971 2.13811,-4.03043 3.25201,-6.03131 -1.59952,-0.86761 -3.22505,-1.71188 -4.8732,-2.53483 m 0.29618,-0.0427 c -3.40715,-1.70793 -6.91152,-3.32401 -10.483,-4.86582 2.90365,-1.06488 5.84253,-2.0795 8.82804,-3.03035 m -4.30994,5.25285 c -1.44084,-0.66089 -2.89525,-1.30799 -4.36114,-1.9425 5.32305,-1.95032 10.76393,-3.73086 16.39321,-5.25805 -0.0526,-0.15243 -0.10543,-0.30483 -0.15839,-0.4572 m -16.346,5.71656 c -6e-5,-3e-5 -0.16464,-0.0711 -0.1647,-0.0711 5.32191,-1.95602 10.76115,-3.74365 16.38827,-5.27932 -0.64765,-1.86511 -1.31982,-3.72666 -2.01474,-5.58459 m -6.00177,7.65252 c 2.59724,-0.83545 5.22948,-1.62315 7.90424,-2.35414 -0.10412,-0.29859 -0.20887,-0.59709 -0.31423,-0.8955 m -0.14193,1.39572 c 0.18793,-0.052 0.37606,-0.10371 0.56441,-0.15515 -0.73132,-2.1078 -1.49395,-4.21107 -2.28537,-6.30972 -0.14277,0.0413 -0.28541,0.0828 -0.42792,0.12441 m 2.58573,5.86862 c -1e-5,0 0.0598,-0.0163 0.0598,-0.0163 -0.73446,-2.10743 -1.50012,-4.2103 -2.29447,-6.30856 -2.51058,0.72674 -4.98101,1.49943 -7.41727,2.31118 m 2.7274,-0.57192 c -5.49569,1.74707 -10.81091,3.70187 -16.01266,5.78726 m -0.10008,0.28407 c -0.1982,0.0796 -0.39625,0.15943 -0.59413,0.23942 0,-1.5e-4 -0.0188,2.695 -0.0188,2.69485 m -0.26343,-1.06335 c 0,-6.9e-4 -0.0362,5.97408 -0.0362,5.97348 4.5267,1.96098 8.95073,4.01666 13.20673,6.20223 m -1.19162,-0.94232 c 2.57116,1.29507 5.08466,2.63559 7.52645,4.02912 0.2451,-0.46951 0.49173,-0.93854 0.73992,-1.40707 m -3.71917,-0.16021 c 1.03465,0.56033 2.05792,1.12925 3.06882,1.7073 1.05517,-2.01991 2.13862,-4.0308 3.25279,-6.03186 -3.20163,-1.73679 -6.50739,-3.38013 -9.89002,-4.94595 m 0.73858,0.22701 c -2.02311,-0.94586 -4.0745,-1.86341 -6.14827,-2.75609 2.20426,-0.81044 4.42876,-1.59211 6.67851,-2.33909 m -1.44719,0.78416 c 3.68217,-1.25405 7.4293,-2.41757 11.26369,-3.46413 -0.62864,-1.81025 -1.28037,-3.61715 -1.95359,-5.42066 m 2.23455,5.42891 c 0,0 0.0174,-0.005 0.0174,-0.005 -0.72889,-2.1089 -1.48926,-4.21326 -2.27857,-6.31299 -3.40899,0.98048 -6.74388,2.04632 -10.0197,3.18021 m 11.03329,-0.34197 c -0.33808,-0.93185 -0.68206,-1.86279 -1.03172,-2.79283 -2.38449,0.68629 -4.73274,1.41434 -7.0499,2.17823 m 7.95135,0.32819 c -0.33935,-0.93163 -0.68458,-1.86236 -1.03546,-2.79218 -4.58328,1.32102 -9.03245,2.79572 -13.38399,4.38215 m 6.2801,-1.79408 c -1.65708,0.54838 -3.29832,1.11504 -4.92561,1.69781 m 3.20183,-1.43563 c -4.26843,1.45184 -8.43432,3.02127 -12.53045,4.67057 m -22.97746,-0.61053 c -0.854682,0.39452 -1.707863,0.7904 -2.559818,1.18742 -1.2e-5,-2.5e-4 0.117783,2.69178 0.117771,2.69152 m -0.268337,-2.29444 c -4e-6,0 -0.02307,0.0108 -0.02308,0.0108 -1.1e-4,-0.003 0.33467,7.63469 0.33456,7.63215 3.348442,1.24064 6.676356,2.49903 9.969061,3.78762 m -10.192384,-8.04094 c -2.8e-5,-6.9e-4 0.176276,4.01026 0.176248,4.00962 0.573877,0.21257 1.147161,0.42566 1.719779,0.63933 m -1.79414,-3.6187 c -1.4e-5,-2.3e-4 0.126798,2.89326 0.126782,2.89293 3.803508,1.40936 7.581027,2.84161 11.311057,4.315 m -11.501658,-5.89934 c -4e-6,-9e-5 0.06809,1.54588 0.06809,1.54578 4.990119,1.84741 9.935901,3.7339 14.788836,5.70061 m -12.821111,-5.12777 c 3.745274,1.39817 7.462077,2.82154 11.129754,4.28761 m -6.88663,-2.31774 c 3.011252,1.14993 5.998343,2.32071 8.950298,3.52165 1.133312,0.46173 2.261042,0.92737 3.382172,1.39749 m -9.790029,-4.2021 c 2.149828,0.83322 4.285773,1.67852 6.403797,2.53933 1.907982,0.77652 3.800322,1.5642 5.672182,2.36562 0.46253,-1.10901 0.92886,-2.21723 1.39934,-3.32452 m -6.232212,1.50664 c 1.556872,0.63838 3.102712,1.28447 4.634872,1.9397 0.88166,-2.11735 1.77703,-4.23184 2.68853,-6.34263 -0.61254,-0.24545 -1.2269,-0.48927 -1.84292,-0.73153 m -4.06553,5.7068 c -9e-5,-4e-5 0.16353,0.0679 0.16344,0.0679 m 0.0327,0.11268 c 1.03455,0.43018 2.06375,0.86401 3.08681,1.30192 m -2.3182,-0.91815 c 0.76015,0.31833 1.51729,0.63869 2.27109,0.96126 0.8812,-2.11731 1.7761,-4.23175 2.6871,-6.34251 -1.07693,-0.43177 -2.15952,-0.85847 -3.24694,-1.28059 m -0.79848,6.54886 c 0.57584,0.24283 1.14991,0.48687 1.72205,0.73222 0.88393,-2.11654 1.78182,-4.23012 2.69609,-6.3399 -2.85303,-1.14687 -5.74585,-2.25766 -8.6629,-3.34145 -0.878803,-0.32632 -1.759821,-0.65007 -2.642799,-0.97149 m 11.165339,4.97095 c -4e-5,9e-5 0.091,-0.21044 0.091,-0.21035 -2.83402,-1.13992 -5.7079,-2.24432 -8.60636,-3.32213 0,0 0,0 0,0 -4.6e-4,-1.5e-4 -0.366769,-0.1361 -0.367181,-0.13625 m 3.434061,1.21466 c -1.01916,-0.38852 -2.042074,-0.77332 -3.068051,-1.15478 -2.486904,-0.92406 -4.991852,-1.82752 -7.509019,-2.71568 0.829062,-0.36791 1.659434,-0.73416 2.49136,-1.09855 m 0.757017,2.04397 c -1.035358,-0.37277 -2.073205,-0.74255 -3.113132,-1.1097 2.413792,-1.07043 4.838848,-2.12667 7.281244,-3.164 1.533889,-0.65173 3.074841,-1.29637 4.624621,-1.93185 m -9.766347,6.08968 c -0.639713,-0.22895 -1.280335,-0.45681 -1.921771,-0.68365 0.812051,-0.35993 1.625365,-0.71824 2.440177,-1.07474 m -1.445123,0.25789 c 2.013297,-0.88721 4.035092,-1.76404 6.068896,-2.62776 1.427505,-0.60646 2.861118,-1.20679 4.302258,-1.7993 m -6.920229,3.15085 c 0.388763,-0.16799 0.777907,-0.33554 1.167461,-0.50263 m -0.853317,0.0623 c 0.765968,-0.33022 1.53347,-0.6587 2.302693,-0.98531 2.773222,-1.17798 5.569582,-2.33278 8.399432,-3.45216 -0.87864,-1.88537 -1.77123,-3.76736 -2.67569,-5.64593 m 1.76309,3.67895 c -0.61388,-1.30199 -1.23409,-2.60236 -1.85994,-3.90108 -1.41105,0.57981 -2.81257,1.16765 -4.205833,1.76203 m 5.026193,0.0549 c -0.27605,-0.57827 -0.55327,-1.15622 -0.83161,-1.73385 -1.25376,0.51547 -2.5,1.03727 -3.73965,1.56436 m 2.83755,-1.48965 c -1.54442,0.6398 -3.077627,1.28889 -4.601312,1.94531 m 1.201573,-0.32783 c -0.474262,0.2025 -0.94757,0.40576 -1.419976,0.60972 -4.914679,2.11735 -9.741183,4.30852 -14.528256,6.53678 m 16.826411,-7.45096 c -0.76819,0.32571 -1.533822,0.65348 -2.297101,0.98307 -3.24117,1.39662 -6.444057,2.82536 -9.622648,4.27567 m 7.852211,-3.474 c -3.117139,1.35987 -6.200983,2.7479 -9.264133,4.15461 m 9.009911,-4.25513 c -2.302633,1.00582 -4.587154,2.02686 -6.858643,3.05931 m 4.508413,-1.69638 c -3.57174,1.58495 -7.104087,3.20379 -10.616344,4.84198 -2.3e-5,-5.1e-4 0.161722,3.68636 0.161699,3.68584 m 0.201525,-4.18611 c -4.2e-5,2e-5 -0.08238,0.0384 -0.08242,0.0384 m 0.249474,0.18924 c -9.2e-4,4.4e-4 -0.389313,0.18139 -0.390267,0.18184 -3e-5,-6.7e-4 0.193575,4.4234 0.193547,4.42274 m 0.06248,-4.67199 c -1.7e-4,7e-5 -0.164222,0.0765 -0.164393,0.0766 -9.4e-5,-0.002 0.332519,7.63482 0.332427,7.63268 2.594887,0.96244 5.177421,1.93576 7.740766,2.92577 m -8.125629,-6.54994 c -2.5e-5,-4.6e-4 0.160641,3.66976 0.160618,3.6692 4.066678,1.50729 8.103281,3.04091 12.083516,4.62316 m -2.99684,-1.2604 c 1.529369,0.59494 3.051506,1.19616 4.564949,1.80488 m -3.344893,-1.26036 c 0.776458,0.30474 1.550935,0.61119 2.32324,0.91951 m -1.241217,-0.35875 c 1.195935,0.4731 2.386912,0.95046 3.572221,1.43269 1.840131,0.74969 3.665531,1.50974 5.471871,2.28248 0.822,-1.97423 1.6559,-3.94598 2.50368,-5.91456 m -11.121527,1.98454 c 1.05069,0.41661 2.097534,0.83657 3.140048,1.26028 1.965829,0.80009 3.915119,1.61201 5.842599,2.43862 0.44127,-1.057 0.88602,-2.11326 1.33455,-3.16868 m -9.552508,0.12237 c 0.79596,0.31766 1.589611,0.6373 2.38074,0.9591 1.914288,0.77978 3.812658,1.57076 5.690228,2.37559 0.88257,-2.11672 1.77896,-4.23052 2.69159,-6.34058 -1.36174,-0.54699 -2.73261,-1.08582 -4.1109,-1.61747 m 3.20992,1.00354 c -4.6e-4,-2.1e-4 -0.41393,-0.16425 -0.41444,-0.16445 m 0.0581,0.2923 c -2.38846,-0.94689 -4.80318,-1.86977 -7.235138,-2.77392 -2.430368,-0.903 -4.877973,-1.78633 -7.33738,-2.65492 -0.0031,0.001 0.836179,-0.36999 0.833122,-0.36863 m 11.056826,4.79542 c -1.08521,-0.41935 -2.17509,-0.83422 -3.268804,-1.2451 m 0.552314,-0.0558 c -0.611951,-0.23083 -1.225138,-0.46037 -1.839412,-0.68871 -2.397599,-0.89074 -4.811825,-1.76235 -7.237466,-2.61957 -0.0036,0.002 0.907279,-0.40118 0.903714,-0.3996 m 4.693778,2.54492 c -1.824261,-0.66932 -3.657459,-1.32826 -5.497316,-1.97887 1.167215,-0.51721 2.337056,-1.03107 3.510215,-1.54103 m -3.132218,1.53545 c -0.0021,-6.9e-4 -0.702658,-0.24839 -0.704659,-0.2491 2.444195,-1.08387 4.899913,-2.15325 7.373456,-3.20325 1.651238,-0.70123 3.310698,-1.39423 4.980548,-2.07644 m -2.03317,0.88961 c 1.81304,-0.75358 3.63737,-1.49555 5.47584,-2.22256 -0.2092,-0.44886 -0.4192,-0.89753 -0.62996,-1.34601 m 0.52067,0.71853 c -0.85056,-1.82046 -1.714,-3.63777 -2.58848,-5.45186 -1.96176,0.80486 -3.90498,1.6253 -5.833093,2.45734 -1.125801,0.48477 -2.246963,0.97342 -3.364066,1.46549 m -26.743025,7.15179 c 2.059712,-0.0964 0.572741,-0.0268 2.632452,-0.12318 m -2.374667,0.0391 c 3.988273,-0.18667 7.978754,-0.37463 11.971968,-0.54282 0,1e-5 -0.106426,-2.53116 -0.106426,-2.53115 m -10.549851,3.10776 c 2.511814,-0.11741 5.024455,-0.23441 7.538059,-0.34575 m -2.466268,-0.18978 c 1.855925,-0.0845 3.712463,-0.16687 5.569671,-0.24496 4.6e-4,0.0102 -0.306587,-7.27925 -0.306156,-7.26905 -1.51597,0.0638 -3.029675,0.13038 -4.54115,0.19859 m 0.519071,0.12322 c -1.688448,0.0755 -8.310835,0.38663 -9.999283,0.46211 m 8.229672,-0.20034 c -2.502666,0.11447 -7.305212,0.34259 -9.807878,0.45705 m 0.772856,-0.34604 c 0.09031,-0.004 -2.132148,0.0985 -2.041833,0.0943 -2.3e-4,-0.005 0.332597,7.2737 0.332362,7.26857 0.02374,-0.001 1.198389,-0.0549 1.222129,-0.056 m -0.04693,-7.07694 c 0.0466,-0.002 -1.592138,0.0732 -1.545538,0.0711 -2.25e-4,-0.005 0.331344,7.27291 0.331118,7.26792 0.04257,-0.002 1.586349,-0.073 1.628922,-0.0749 m -1.539587,-1.5644 c 0,0 0.07316,1.60165 0.07316,1.60165 0.05598,-0.003 1.772949,-0.0817 1.828928,-0.0843 m -1.921715,-0.31555 c 0,0 0.01902,0.41581 0.01902,0.41581 0.702064,-0.0321 5.140008,-0.2396 5.842074,-0.27172 m 4.725877,-0.27675 c 2.066675,-0.0948 4.134037,-0.18719 6.202159,-0.27432 4.6e-4,0.009 -0.306587,-7.27817 -0.306221,-7.26948 -2.339557,0.0984 -4.673816,0.20336 -7.002878,0.31075 m 7.058915,-0.16737 c -4.6931,0.19762 -9.365216,0.42182 -14.017203,0.63901 m 6.537511,-0.38739 c -0.971305,0.045 -4.569434,0.21391 -5.540739,0.25886 m 5.101201,-0.24571 c -5.216645,0.24225 -3.843468,0.18018 -9.06011,0.42243 -3.4e-5,-7.4e-4 0.123129,2.70558 0.123097,2.70486 m 7.426843,-3.24953 c -24.696934,1.15102 17.116174,-0.79865 -7.580762,0.35237 -2.3e-5,-4.8e-4 0.104089,2.27859 0.104066,2.2781 m 5.781832,-2.41986 c 2.637842,-0.12357 -8.440538,0.39347 -5.802694,0.2699 -2.3e-4,-0.005 0.331946,7.27375 0.331699,7.26835 1.524654,-0.0696 6.552862,-0.30601 8.077513,-0.37559 m -7.825568,0.35848 c 3.084591,-0.14101 7.08161,-0.33115 10.166201,-0.47216 m -2.201616,0.27963 c 2.955075,-0.13771 5.911325,-0.27295 8.868971,-0.39714 6.9e-4,0.0158 -0.276645,-6.60296 -0.275983,-6.58715 m -4.644838,19.50263 c -0.04853,0.002 1.943709,-0.0875 1.895186,-0.0853 m -1.936735,0.1142 c 1.792077,-0.0816 3.580063,-0.16108 5.364006,-0.23634 0.0016,0.0406 -0.334472,-7.97099 -0.33277,-7.93042 -1.663809,0.07 -3.328641,0.14352 -4.99454,0.21902 m 2.171407,7.93469 c 1.002125,-0.0446 2.002964,-0.0882 3.002526,-0.13056 6.9e-4,0.0151 -0.335332,-7.94584 -0.334692,-7.9307 -0.01302,4.6e-4 -1.283268,0.0548 -1.296293,0.0553 m 1.765494,6.57446 c 0,0 -0.09432,-2.24444 -0.09432,-2.24444 m 0.193403,1.55422 c 2.3e-4,0.008 -0.255952,-6.10558 -0.255618,-6.09764 -4.135875,0.1736 -8.27797,0.36923 -12.426879,0.56322 m 12.656588,5.47587 c 0.0014,0.0352 -0.196897,-4.70418 -0.195425,-4.669 m 0.05044,0.34855 c 7.3e-5,0.002 -0.08064,-1.92765 -0.08057,-1.92593 -2.430525,0.10176 -4.863062,0.21113 -7.297731,0.32331 m 2.088058,0.34949 c -3.929765,0.17863 -8.234153,0.3859 -12.163916,0.56453 -2.3e-4,-0.007 0.360901,7.93624 0.3606,7.92962 0.0133,-6.9e-4 0.959655,-0.0436 0.972954,-0.0442 m -1.147832,-4.57504 c -9e-5,-0.002 0.201748,4.43626 0.201661,4.4343 4.261743,-0.19359 8.13406,-0.38068 12.395803,-0.57426 m 2.714147,0.0438 c -0.03638,0.002 2.068462,-0.0889 2.032086,-0.0873 0,-1e-5 -0.330434,-7.848 -0.330434,-7.84802 m -0.390012,7.67174 c -0.006,2.3e-4 0.877945,-0.0373 0.871913,-0.037 0.0035,0.0846 -0.335601,-8.01541 -0.332058,-7.93079 -0.0049,2.1e-4 -0.807534,0.0341 -0.812456,0.0343 m 1.062674,4.39576 c 9.21e-4,0.0195 -0.180555,-4.31693 -0.17974,-4.29747 -5.644858,0.2368 -11.301805,0.51484 -16.97239,0.77385 m 16.883999,-0.84336 c 0,0 -0.0109,-0.25925 -0.0109,-0.25925 -2.055509,0.0861 -4.112471,0.17769 -6.170952,0.27176 m 3.485079,0.0291 c -0.05285,0.002 -2.212276,0.099 -2.26512,0.10135 m 0.349797,0.0794 c -3.760553,0.16942 -8.938361,0.41768 -12.698914,0.5871 -2.3e-4,-0.006 0.33907,7.46503 0.338819,7.45951 m 9.280111,-8.08922 c -5.88383,0.27258 -3.65478,0.17097 -9.538611,0.44355 -1.79e-4,-0.004 0.27812,6.1035 0.277943,6.09957 m 5.680987,-6.48244 c 2.157859,-0.10077 -8.201667,0.38044 -6.043811,0.27967 -2.3e-4,-0.007 0.361342,7.93519 0.361027,7.92831 0.01746,-6.9e-4 1.089212,-0.0498 1.10666,-0.0506 m -0.642245,-7.62892 c 0.0055,-2.3e-4 -0.59799,0.0273 -0.592459,0.027 -8.8e-5,-0.002 0.186492,4.0844 0.186404,4.0825 m -0.24246,-0.91094 c -9.4e-5,-0.002 0.205422,4.5051 0.205328,4.50301 0.02291,-0.001 1.239029,-0.0564 1.261934,-0.0575 m -0.07763,0.0678 c 4.16157,-0.19062 6.453312,-0.30131 10.614882,-0.49193 m -6.911472,0.22311 c 0.314236,-0.0147 1.410505,-0.066 1.724739,-0.0807 m -1.595265,0.30133 c 4.104645,-0.19166 8.18784,-0.38438 12.250149,-0.55525 2.3e-4,0.006 -0.205339,-4.89378 -0.205097,-4.88802 m 33.383164,-22.13887 c -5.49585,2.00143 -10.81413,4.16561 -16.02272,6.41445 -2.945114,1.26887 -5.858578,2.56425 -8.750882,3.87824 m 25.318552,-0.13017 c -0.44849,0.16829 -0.896,0.33771 -1.34256,0.50821 m -1.87856,11.0592 c 6.39169,2.87012 12.5429,5.95109 18.26331,9.34531"+       style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2a144d;stroke-width:0.46007127;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />+    <path+       d="m 111.80954,213.04909 c -0.26629,0.16448 -0.50119,0.30232 -0.6724,0.70346 -0.1712,0.40114 -0.10823,0.66612 -0.0428,0.97219 l 0.12706,-0.0258 c -0.0563,-0.29013 -0.0764,-0.51482 0.0782,-0.87703 0.15531,-0.3639 0.33078,-0.50311 0.57919,-0.66321 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4728" />+    <path+       d="m 112.44893,213.61011 c -0.26405,-0.1127 -0.57293,0.002 -0.74125,0.39595 -0.16759,0.39268 -0.0531,0.69166 0.22957,0.8123 0.1574,0.0672 0.29655,0.0506 0.38906,0.012 l -0.0362,-0.13551 c -0.087,0.0209 -0.17996,0.0372 -0.28998,-0.01 -0.18111,-0.0773 -0.26524,-0.26928 -0.12148,-0.6061 0.15025,-0.35206 0.34807,-0.40769 0.5241,-0.33256 0.0812,0.0347 0.14075,0.0921 0.18825,0.18244 l 0.13209,-0.0657 c -0.0613,-0.11423 -0.12691,-0.19023 -0.27416,-0.25307 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4730" />+    <path+       d="m 113.09042,213.59577 -0.12706,0.0258 c 0.0563,0.29012 0.0771,0.51313 -0.0782,0.87703 -0.15459,0.36221 -0.33078,0.50311 -0.57918,0.66321 l 0.0693,0.10959 c 0.26629,-0.16448 0.5012,-0.30232 0.67241,-0.70346 0.1712,-0.40114 0.10822,-0.66613 0.0428,-0.97219 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4732" />+    <path+       d="m 114.01162,214.30108 -0.24373,-0.10402 -0.49772,1.16618 0.27928,0.11919 c 0.25219,0.10764 0.59679,0.12065 0.79978,-0.35496 0.2066,-0.48407 -0.0397,-0.69924 -0.33761,-0.82639 z m -0.0194,0.14379 c 0.18619,0.0795 0.35432,0.21526 0.18601,0.60962 -0.16398,0.38422 -0.38001,0.38406 -0.5628,0.30604 l -0.13033,-0.0556 0.38864,-0.9106 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4734" />+    <path+       d="m 114.96573,216.0869 0.16926,0.0722 0.12536,-1.3251 -0.20311,-0.0867 -0.87179,1.00653 0.16249,0.0693 0.21299,-0.25525 0.44176,0.18854 z m -0.31025,-0.63263 0.44286,-0.53131 -0.079,0.68662 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4736" />+    <path+       d="m 116.5494,215.38421 -0.16249,-0.0693 -0.71613,0.86686 0.1305,-1.11681 -0.17264,-0.0737 -0.12197,1.32654 0.17264,0.0737 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4738" />+    <path+       d="m 116.89069,215.52987 -0.16079,-0.0686 -0.49773,1.16618 0.1608,0.0686 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4740" />+    <path+       d="m 117.4728,215.77831 -0.24373,-0.10402 -0.49772,1.16618 0.27928,0.11919 c 0.25219,0.10764 0.59679,0.12065 0.79978,-0.35496 0.2066,-0.48407 -0.0397,-0.69924 -0.33761,-0.82639 z m -0.0194,0.14379 c 0.18619,0.0795 0.35432,0.21526 0.18601,0.60962 -0.16398,0.38422 -0.38001,0.38406 -0.5628,0.30604 l -0.13033,-0.0556 0.38864,-0.9106 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4742" />+    <path+       d="m 118.7188,216.31011 -0.16079,-0.0686 -0.49773,1.16618 0.62118,0.26511 0.0785,-0.13255 -0.479,-0.20443 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4744" />+    <path+       d="m 120.03232,216.87072 -0.63133,-0.26946 -0.49773,1.16618 0.64488,0.27523 0.0549,-0.12863 -0.48408,-0.20661 0.17049,-0.39945 0.39267,0.1676 0.0549,-0.12864 -0.39267,-0.16759 0.16253,-0.38082 0.45192,0.19287 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4746" />+    <path+       d="m 120.99565,217.28186 -0.83274,-0.35541 -0.0585,0.13709 0.33175,0.14159 -0.43921,1.02909 0.1608,0.0686 0.43921,-1.02908 0.32328,0.13798 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4748" />+    <path+       d="m 121.8717,217.65576 -0.83275,-0.35541 -0.0585,0.13709 0.33174,0.14159 -0.43921,1.02908 0.16079,0.0686 0.43922,-1.02908 0.32327,0.13797 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4750" />+    <path+       d="m 122.21965,217.80427 -0.1608,-0.0686 -0.49772,1.16618 0.1608,0.0686 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4752" />+    <path+       d="m 123.18936,218.21814 -0.63133,-0.26945 -0.49772,1.16617 0.64487,0.27524 0.0549,-0.12864 -0.48407,-0.2066 0.17048,-0.39945 0.39268,0.16759 0.0549,-0.12863 -0.39268,-0.1676 0.16254,-0.38082 0.45192,0.19288 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4754" />+    <path+       d="m 123.58728,219.76657 0.19126,0.0816 -0.0916,-0.65737 c 0.18922,0.0207 0.31576,-0.0413 0.38583,-0.20548 0.0932,-0.21835 -0.0115,-0.39507 -0.30259,-0.51932 l -0.30636,-0.13075 -0.49772,1.16618 0.1608,0.0686 0.21093,-0.49422 0.18111,0.0773 z m -0.19671,-0.81427 0.18059,-0.42314 0.14387,0.0614 c 0.19127,0.0816 0.24892,0.17626 0.18679,0.32182 -0.0672,0.15742 -0.18628,0.17862 -0.34876,0.10927 z"+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.84028506px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.23003563px;writing-mode:lr-tb;text-anchor:start;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.23003563px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+       id="path4756" />+  </g>+</svg>
+ src/data/pause-icon.svg view
@@ -0,0 +1,83 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+   width="15"+   height="15"+   viewBox="0 0 3.9687499 3.9687501"+   version="1.1"+   id="svg8"+   inkscape:version="0.92.2 2405546, 2018-03-11"+   sodipodi:docname="pause-icon.svg">+  <defs+     id="defs2" />+  <sodipodi:namedview+     id="base"+     pagecolor="#ff09e5"+     bordercolor="#666666"+     borderopacity="1.0"+     inkscape:pageopacity="0"+     inkscape:pageshadow="2"+     inkscape:zoom="32"+     inkscape:cx="-0.82421836"+     inkscape:cy="8.9565174"+     inkscape:document-units="px"+     inkscape:current-layer="layer1"+     showgrid="true"+     units="px"+     inkscape:measure-start="30,0"+     inkscape:measure-end="30,15"+     showguides="true"+     inkscape:guide-bbox="true"+     inkscape:window-width="1920"+     inkscape:window-height="1152"+     inkscape:window-x="0"+     inkscape:window-y="320"+     inkscape:window-maximized="1"+     inkscape:snap-global="false"+     inkscape:showpageshadow="false">+    <inkscape:grid+       type="xygrid"+       id="grid815" />+    <sodipodi:guide+       position="8.9958331,3.9687501"+       orientation="0,1"+       id="guide819"+       inkscape:locked="false" />+  </sodipodi:namedview>+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     inkscape:label="Layer 1"+     inkscape:groupmode="layer"+     id="layer1"+     transform="translate(0,-293.03123)">+    <path+       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.49469224;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1107.35998535;stroke-opacity:0.90196078"+       d="m 1.0583333,296.74984 v -3.46847"+       id="path22947"+       inkscape:connector-curvature="0" />+    <path+       inkscape:connector-curvature="0"+       id="path22972"+       d="m 2.9104167,296.74984 v -3.46847"+       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.49469224;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1107.35998535;stroke-opacity:0.90196078" />+  </g>+</svg>
+ src/data/play-icon.svg view
@@ -0,0 +1,77 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+   width="15"+   height="15"+   viewBox="0 0 3.9687499 3.9687501"+   version="1.1"+   id="svg8"+   inkscape:version="0.92.2 2405546, 2018-03-11"+   sodipodi:docname="play-icon.svg">+  <defs+     id="defs2" />+  <sodipodi:namedview+     id="base"+     pagecolor="#ff09e5"+     bordercolor="#666666"+     borderopacity="1.0"+     inkscape:pageopacity="0"+     inkscape:pageshadow="2"+     inkscape:zoom="16"+     inkscape:cx="1.665001"+     inkscape:cy="15.661218"+     inkscape:document-units="px"+     inkscape:current-layer="layer1"+     showgrid="true"+     units="px"+     inkscape:measure-start="30,0"+     inkscape:measure-end="30,15"+     showguides="true"+     inkscape:guide-bbox="true"+     inkscape:window-width="1920"+     inkscape:window-height="1152"+     inkscape:window-x="0"+     inkscape:window-y="320"+     inkscape:window-maximized="1">+    <inkscape:grid+       type="xygrid"+       id="grid815" />+    <sodipodi:guide+       position="8.9958331,3.9687501"+       orientation="0,1"+       id="guide819"+       inkscape:locked="false" />+  </sodipodi:namedview>+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     inkscape:label="Layer 1"+     inkscape:groupmode="layer"+     id="layer1"+     transform="translate(0,-293.03123)">+    <path+       style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.49019608;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.60342592;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1107.35998535;stroke-opacity:0.90196078;paint-order:fill markers stroke"+       d="m 0.30171295,293.33292 v 3.36536 l 3.36536195,-1.68267 z"+       id="path817"+       inkscape:connector-curvature="0"+       sodipodi:nodetypes="cccc" />+  </g>+</svg>
+ src/data/repeat-icon.svg view
@@ -0,0 +1,193 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+   width="15"+   height="15"+   viewBox="0 0 3.9687499 3.9687501"+   version="1.1"+   id="svg8"+   inkscape:version="0.92.2 2405546, 2018-03-11"+   sodipodi:docname="repeat-icon.svg">+  <defs+     id="defs2">+    <marker+       inkscape:stockid="Arrow2Lend"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow2Lend"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path882"+         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#ffffff;stroke-opacity:0.90196078;fill:#ffffff;fill-opacity:1"+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "+         transform="scale(1.1) rotate(180) translate(1,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Mend"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="marker6275"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path6273"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#ffffff;stroke-width:1pt;stroke-opacity:0.90196078;fill:#ffffff;fill-opacity:0.90196078"+         transform="scale(0.4) rotate(180) translate(10,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow2Mstart"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow2Mstart"+       style="overflow:visible"+       inkscape:isstock="true">+      <path+         id="path885"+         style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "+         transform="scale(0.6) translate(0,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Lstart"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow1Lstart"+       style="overflow:visible"+       inkscape:isstock="true">+      <path+         id="path861"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"+         transform="scale(0.8) translate(12.5,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Mend"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="marker1171"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path1169"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"+         transform="scale(0.4) rotate(180) translate(10,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Mend"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow1Mend"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path870"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"+         transform="scale(0.4) rotate(180) translate(10,0)" />+    </marker>+    <marker+       inkscape:stockid="Arrow1Lend"+       orient="auto"+       refY="0.0"+       refX="0.0"+       id="Arrow1Lend"+       style="overflow:visible;"+       inkscape:isstock="true">+      <path+         id="path864"+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"+         transform="scale(0.8) rotate(180) translate(12.5,0)" />+    </marker>+  </defs>+  <sodipodi:namedview+     id="base"+     pagecolor="#ff09e5"+     bordercolor="#666666"+     borderopacity="1.0"+     inkscape:pageopacity="0"+     inkscape:pageshadow="2"+     inkscape:zoom="45.254834"+     inkscape:cx="5.8605315"+     inkscape:cy="5.9160394"+     inkscape:document-units="px"+     inkscape:current-layer="layer1"+     showgrid="true"+     units="px"+     inkscape:measure-start="30,0"+     inkscape:measure-end="30,15"+     showguides="true"+     inkscape:guide-bbox="true"+     inkscape:window-width="1920"+     inkscape:window-height="1152"+     inkscape:window-x="0"+     inkscape:window-y="320"+     inkscape:window-maximized="1"+     inkscape:snap-global="false">+    <inkscape:grid+       type="xygrid"+       id="grid815" />+    <sodipodi:guide+       position="8.9958331,3.9687501"+       orientation="0,1"+       id="guide819"+       inkscape:locked="false" />+  </sodipodi:namedview>+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     inkscape:label="Layer 1"+     inkscape:groupmode="layer"+     id="layer1"+     transform="translate(0,-293.03123)">+    <g+       id="g22945"+       transform="matrix(1.0076325,0,0,1.0076325,-0.00105415,-2.266855)">+      <path+         sodipodi:nodetypes="cc"+         inkscape:connector-curvature="0"+         id="path6259"+         d="m 3.051295,296.07098 0.6553377,-0.25987"+         style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.14188077;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1107.35998535;stroke-opacity:0.90196078;marker-end:url(#Arrow2Lend)" />+      <path+         d="m 2.5531352,296.27574 a 1.6266046,1.5149276 0 0 1 -2.02684103,-0.85056 1.6266046,1.5149276 0 0 1 0.77738413,-1.93975 1.6266046,1.5149276 0 0 1 2.1295431,0.5943"+         sodipodi:open="true"+         sodipodi:end="5.7558666"+         sodipodi:start="1.2417907"+         sodipodi:ry="1.5149276"+         sodipodi:rx="1.6266046"+         sodipodi:cy="294.84207"+         sodipodi:cx="2.0275757"+         sodipodi:type="arc"+         id="path15490"+         style="opacity:1;fill:none;fill-opacity:0.49019608;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.90196078;paint-order:fill markers stroke" />+    </g>+  </g>+</svg>
+ src/data/style-3-18.css view
@@ -0,0 +1,40 @@+/*+  Movie Monad+  (C) 2018 David Lettier+  lettier.com+*/++#play-pause-button image,+#about-button image,+#volume-button image,+#repeat-check-button image,+#repeat-check-button check,+#fullscreen-button image,+#play-pause-button image:hover,+#about-button image:hover,+#volume-button image:hover,+#repeat-check-button image:hover,+#fullscreen-button image:hover {+  text-decoration-color: transparent;+}++#repeat-check-button:checked {+  background-color: rgba(255, 255, 255, 0.1);+}++combobox button,+GtkComboBox .button {+  text-decoration: none;+}++menuitem,+GtkMenuItem,+menuitem:hover,+GtkMenuItem:hover {+  text-decoration: none;+}++menuitem cellview,+GtkMenuItem GtkCellView {+  text-decoration-color: transparent;+}
+ src/data/style-3-20.css view
@@ -0,0 +1,24 @@+/*+  Movie Monad+  (C) 2018 David Lettier+  lettier.com+*/++slider {+  min-width: 15px;+  min-height: 15px;+}++#play-pause-button image,+#about-button image,+#volume-button image,+#repeat-check-button image,+#repeat-check-button check,+#fullscreen-button image,+#play-pause-button image:hover,+#about-button image:hover,+#volume-button image:hover,+#repeat-check-button image:hover,+#fullscreen-button image:hover {+  -gtk-icon-shadow: none;+}
+ src/data/style.css view
@@ -0,0 +1,299 @@+/*+  Movie Monad+  (C) 2018 David Lettier+  lettier.com+*/++@define-color _movie_monad_black       rgba(10, 10, 10, 0.8);+@define-color _movie_monad_white_nine  rgba(255, 255, 255, 0.9);+@define-color _movie_monad_white_five  rgba(255, 255, 255, 0.5);+@define-color _movie_monad_blue        rgba(87, 172, 227, 1.0);+@define-color _movie_monad_pink        rgba(224, 67, 127, 1.0);++@keyframes movie_monad_fade_in {+  from { opacity: 0; }+  to { opacity: 1; }+}++#bottom-controls-gtk-box {+  background-color: @_movie_monad_black;+  border-color: @_movie_monad_black;+  border-width: 1px;+  border-radius: 5px;+  padding: 5px;+  padding-left: 10px;+  padding-right: 10px;+  margin-bottom: 0px;+}++#play-pause-button,+#about-button,+#volume-button,+#volume-plus-button,+#volume-minus-button,+#repeat-check-button,+#fullscreen-button,+#window-width-selection-combo-box-text button.combo,+#subtitle-selection-combo-box-text button.combo,+#bottom-controls-gtk-box .button {+  background-color: transparent;+  border-color: transparent;+  border-width: 0px;+  border-radius: 5px;+  margin: 5px;+  background-image: none;+  color: white;+  box-shadow: none;+  text-shadow: none;+  border-image-source: none;+}++GtkBox#bottom-controls-gtk-box .button {+  padding-left: 7.5px;+  padding-right: 7.5px;+}++#play-pause-button image,+#about-button image,+#volume-button image,+#repeat-check-button image,+#repeat-check-button check,+#fullscreen-button image,+#play-pause-button image:hover,+#about-button image:hover,+#volume-button image:hover,+#repeat-check-button image:hover,+#fullscreen-button image:hover {+  text-shadow: none;+  border-color: transparent;+  border-top-color: transparent;+  border-bottom-color: transparent;+  border-left-color: transparent;+  border-right-color: transparent;+  background-image: none;+}++#play-pause-button:focus,+#about-button:focus,+#volume-button:focus,+#volume-plus-button:focus,+#volume-minus-button:focus,+#repeat-check-button:focus,+#fullscreen-button:focus,+#window-width-selection-combo-box-text button.combo:focus,+#subtitle-selection-combo-box-text button.combo:focus,+#play-pause-button image:focus,+#about-button image:focus,+#volume-button image:focus,+#repeat-check-button image:focus,+#repeat-check-button check:focus,+#fullscreen-button image:focus,+#play-pause-button image:focus,+#about-button image:focus,+#volume-button image:focus,+#repeat-check-button image:focus,+#fullscreen-button image:focus {+  outline-color: transparent;+  outline-offset: 0px;+  outline-width: 0px;+  outline-style: none;+  outline: none;+}++#play-pause-button:hover,+#about-button:hover,+#volume-button:hover,+#volume-plus-button:hover,+#volume-minus-button:hover,+#repeat-check-button:hover,+#repeat-check-button:active,+#fullscreen-button:hover,+#window-width-selection-combo-box-text button.combo:hover,+#subtitle-selection-combo-box-text button.combo:hover,+#window-width-selection-combo-box-text .button:hover {+  background-color: rgba(255, 255, 255, 0.1);+}++GtkScale {+  background-color: @_movie_monad_black;+  background-image: none;+  border-color: black;+  border: none;+  color: @_movie_monad_white_five;+}++GtkScale.horizontal {+  margin-left: 10px;+  margin-right: 10px;+}++scale slider {+  background-color: @_movie_monad_white_nine;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  background-image: none;+  box-shadow: none;+  border-radius: 100%;+  margin: -5px;+  padding: 0px;+}++#seek-scale .slider,+GtkPopover .slider {+  background-color: @_movie_monad_white_nine;+  margin: -3px;+}++GtkBox#bottom-controls-gtk-box .trough {+  margin-right: 10px;+  margin-left: 10px;+}++scale trough,+GtkScale .trough {+  background-color: rgba(0, 0, 0, 0.1);+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border-image: none;+  border: none;+  background-image: none;+}++scale trough:focus,+GtkScale .trough {+  outline-color: transparent;+  outline-offset: 0px;+  outline-width: 0px;+  outline-style: none;+  outline: none;+}++scale fill {+  background-color: rgba(0, 0, 0, 0.1);+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border: none;+}++scale highlight,+.highlight {+  background-color: @_movie_monad_blue;+  background-image: none;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border: none;+}++scale value {+  color: @_movie_monad_white_five;+  margin-bottom: 5px;+}++scale#seek-scale highlight,+GtkScale#seek-scale .highlight {+  background-image: linear-gradient(to right, @_movie_monad_blue 0%, @_movie_monad_pink 100%);+}++popover highlight,+GtkPopover .highlight {+  background-image: linear-gradient(to top, @_movie_monad_blue 0%, @_movie_monad_pink 100%);+}++combobox button,+GtkComboBox .button {+  color: white;+  text-shadow: none;+}++.scale-popup,+combobox menu,+GtkComboBox .menu {+  background-color: @_movie_monad_black;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border: none;+  box-shadow: none;+}++combobox window,+combobox decoration,+combobox arrow,+GtkComboBox .arrow {+  background-color: transparent;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  box-shadow: none;+}++menuitem,+GtkMenuItem {+  background-color: transparent;+  color: white;+  background-image: none;+  text-shadow: none;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border: none;+  box-shadow: none;+}++menuitem:hover,+GtkMenuItem:hover {+  background-color: @_movie_monad_white_nine;+  color: black;+  background-image: none;+  text-shadow: none;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border: none;+  box-shadow: none;+}++menuitem:focus,+GtkMenuItem:focus {+  outline-color: transparent;+  outline-offset: 0px;+  outline-width: 0px;+  outline-style: none;+  outline: none;+}++menuitem cellview,+GtkMenuItem GtkCellView {+  color: inherit;+}++arrow,+GtkMenu .arrow {+  text-shadow: none;+  color: white;+}++tooltip,+.tooltip {+  color: white;+  background-image: none;+  background-color: @_movie_monad_black;+  border-radius: 0px;+  border-color: @_movie_monad_black;+  border-width: 0px;+  border-style: none;+  border-image-source: none;+  border: none;+  box-shadow: none;+}++.movie-monad-fade-in {+  animation-name: movie_monad_fade_in;+  animation-duration: 1s;+  animation-timing-function: linear;+  animation-iteration-count: 1;+}
src/dev/Paths_movie_monad.hs view
@@ -1,6 +1,6 @@ {-   Movie Monad-  (C) 2017 David lettier+  (C) 2017 David Lettier   lettier.com -} 
stack.yaml view
@@ -1,14 +1,34 @@-flags: {}-extra-package-dbs: []+resolver: lts-9.1+compiler-check: match-exact packages: - '.'+extra-package-dbs: [] explicit-setup-deps:   ! '*': true extra-deps:-- gi-gst-1.0.14-- gi-gtk-3.0.18+- haskell-gi-base-0.21.0+- haskell-gi-overloading-1.0+- haskell-gi-0.21.0+- gi-gobject-2.0.16+- gi-glib-2.0.16+- gi-gdk-3.0.15+- gi-gdkpixbuf-2.0.15+- gi-gst-1.0.15 - gi-gstbase-1.0.15-- gi-gstvideo-1.0.14-- haskell-gi-base-0.20.8-resolver: lts-9.1-compiler-check: match-exact+- gi-gstvideo-1.0.15+- gi-gtk-3.0.21+flags:+  gi-gobject:+    enable-overloading: false+  gi-glib:+    enable-overloading: false+  gi-gdk:+    enable-overloading: false+  gi-gdkpixbuf:+    enable-overloading: false+  gi-gst:+    enable-overloading: false+  gi-gstvideo:+    enable-overloading: false+  gi-gtk:+    enable-overloading: false