[SCM] gnome-mpv/master: New upstream version 0.12

infinity0 at users.alioth.debian.org infinity0 at users.alioth.debian.org
Sun Jun 18 11:54:11 UTC 2017


The following commit has been merged in the master branch:
commit e56be540f19f526705ff6dc3e5be75c0bb557b95
Author: Ximin Luo <infinity0 at debian.org>
Date:   Sun Jun 18 13:02:13 2017 +0200

    New upstream version 0.12

diff --git a/.gitignore b/.gitignore
index e4df03d..24611fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,13 @@ Makefile
 config.*
 po/POTFILES
 po/stamp-it
+/po/Makevars.template
+/po/*~
+/po/*.sed
+/po/*.sin
+/po/*.header
+/po/Rules-quot
+/ABOUT-NLS
 
 # Files generated by `make`
 *.o
diff --git a/Makefile.am b/Makefile.am
index 64e8a03..ceb38c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,16 +2,7 @@ AUTOMAKE_OPTIONS = foreign
 
 SUBDIRS = src data po
 
-DISTCLEANFILES =	intltool-extract \
-			intltool-merge \
-			intltool-update \
-			po/.intltool-merge-cache
-
-INTLTOOL_FILES =	intltool-extract.in \
-			intltool-merge.in \
-			intltool-update.in
-
-EXTRA_DIST = README.md AUTHORS
+EXTRA_DIST = README.md AUTHORS meson.build meson_post_install.py po/meson.build
 
 UPDATE_DESKTOP = update-desktop-database -q || :
 UPDATE_ICON = gtk-update-icon-cache -q $(datadir)/icons/hicolor/ || :
diff --git a/README.md b/README.md
index d41327a..4003c01 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,6 @@ capabilities.
 - autoconf-archive<sup>[[1]](#note1)</sup> (build)
 - automake >= 1.12<sup>[[1]](#note1)</sup> (build)
 - python2<sup>[[1]](#note1)</sup> (build)
-- intltool >= 0.40.6 (build)
 - pkg-config (build)
 - gcc (build)
 - glib >= 2.44
@@ -38,7 +37,7 @@ capabilities.
 - Frugalware: http://www4.frugalware.org/pub/linux/distributions/frugalware/frugalware-current/source/xapps-extra/gnome-mpv/
 - OpenSUSE: https://build.opensuse.org/package/show/home:mermoldy:multimedia/gnome-mpv
 - Gentoo: http://gpo.zugaina.org/media-video/gnome-mpv
-- Solus: https://packages.solus-project.com/v1/g/gnome-mpv/
+- Solus: https://packages.solus-project.com/shannon/g/gnome-mpv/
 - Ubuntu: https://launchpad.net/~xuzhen666/+archive/ubuntu/gnome-mpv
 
 ### Guix
@@ -69,6 +68,12 @@ Run the following command in the source code directory to build and install:
 ./autogen.sh && make && sudo make install
 ```
 
+Alternatively, you can use Meson:
+
+```sh
+meson build && cd build && ninja && sudo ninja install
+```
+
 ## Usage
 
 ### Opening files
@@ -121,7 +126,7 @@ can be found
 
 GNOME MPV defines a set of keybindings in the macro `DEFAULT_KEYBINDS`, which
 can be found in
-[src/def.h](https://github.com/gnome-mpv/gnome-mpv/blob/master/src/def.h). The
+[src/def.h](https://github.com/gnome-mpv/gnome-mpv/blob/master/src/gmpv_def.h). The
 syntax used is exactly the same as mpv's `input.conf`. These keybindings are
 applied on top of default keybindings provided by mpv.
 
@@ -138,6 +143,11 @@ start translating, follow the instructions
 [here](http://docs.zanata.org/en/release/user-guide/translator-guide/). If you'd
 like to add a new language, open an issue on GitHub.
 
+While translating, you will find the string `translator-credits`. You should not
+translate this string. Instead, you should put your name, and optionally your
+email address, in the following format: `FirstName LastName <Email Address>`.
+Your name will then appear in the About dialog when your translation is active.
+
 ## License
 
 GNOME MPV is free software: you can redistribute it and/or modify
diff --git a/autogen.sh b/autogen.sh
index 8d131df..d4ab98a 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -10,8 +10,7 @@ test -z "$srcdir" && srcdir=.
 }
 
 aclocal --install -I m4 || exit 1
-intltoolize --copy --automake || exit 1
-autoreconf --install -Wno-portability || exit 1
+autoreconf --force --install -Wno-portability || exit 1
 
 if [ "$NOCONFIGURE" = "" ]; then
         $srcdir/configure "$@" || exit 1
diff --git a/configure.ac b/configure.ac
index 651a961..52eae12 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 AC_PREREQ([2.69])
 
 AC_INIT(	[gnome-mpv],
-		[0.11],
+		[0.12],
 		[http://github.com/gnome-mpv/gnome-mpv/issues],
 		[gnome-mpv],
 		[http://github.com/gnome-mpv/gnome-mpv] )
@@ -14,11 +14,11 @@ AM_SILENT_RULES([yes])
 AM_MAINTAINER_MODE([enable])
 
 # i18n
-IT_PROG_INTLTOOL([0.40.6])
 GETTEXT_PACKAGE=gnome-mpv
 AC_SUBST(GETTEXT_PACKAGE)
 AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [GETTEXT package name])
-AM_GLIB_GNU_GETTEXT
+AM_GNU_GETTEXT_VERSION([0.19.7])
+AM_GNU_GETTEXT([external])
 
 GLIB_GSETTINGS
 
@@ -101,11 +101,11 @@ AM_COND_IF([NEW_GTK],[
 ])
 
 # Checks for header files.
-AC_CHECK_HEADERS([string.h stdio.h stdlib.h locale.h ctype.h execinfo.h],[],[
+AC_CHECK_HEADERS([string.h stdio.h stdlib.h locale.h],[],[
 	AC_MSG_ERROR([Could not find required headers])
 ])
 
-AC_CHECK_FUNCS([setlocale backtrace backtrace_symbols_fd exit],[],[
+AC_CHECK_FUNCS([setlocale],[],[
 	AC_MSG_ERROR([Could not find required functions])
 ])
 
diff --git a/data/Makefile.am b/data/Makefile.am
index 03d0542..18bd8db 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -5,14 +5,17 @@ gsettings_SCHEMAS = io.github.GnomeMpv.gschema.xml org.gnome-mpv.gschema.xml
 appstream_in_files = io.github.GnomeMpv.appdata.xml.in
 appstream_XML = $(appstream_in_files:.xml.in=.xml)
 
- at INTLTOOL_XML_RULE@
+%.appdata.xml: %.appdata.xml.in
+	$(AM_V_GEN)$(MSGFMT) --xml --template $< -d $(top_srcdir)/po -o $@
+
 @APPSTREAM_XML_RULES@
 
 desktopdir = $(datadir)/applications
 desktop_in_files = io.github.GnomeMpv.desktop.in
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
- at INTLTOOL_DESKTOP_RULE@
+%.desktop: %.desktop.in
+	$(AM_V_GEN)$(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@
 
 icondir = $(datadir)/icons/hicolor/scalable/apps
 icon_DATA = gnome-mpv.svg
@@ -24,6 +27,7 @@ EXTRA_DIST =	$(appstream_in_files) $(desktop_in_files) \
 		gnome-mpv.svg gnome-mpv-symbolic.svg \
 		org.gnome-mpv.gschema.xml \
 		io.github.GnomeMpv.gschema.xml \
-		gmpv_mpris_gdbus.xml gmpv_marshal.lst
+		gmpv_mpris_gdbus.xml gmpv_marshal.lst \
+		meson.build
 
 DISTCLEANFILES = $(appstream_XML) $(desktop_DATA)
diff --git a/data/gmpv_marshal.lst b/data/gmpv_marshal.lst
index 24a84cb..213003d 100644
--- a/data/gmpv_marshal.lst
+++ b/data/gmpv_marshal.lst
@@ -1,2 +1,4 @@
+VOID:POINTER,BOOLEAN
+VOID:STRING,POINTER
 VOID:INT,INT
 VOID:INT64
diff --git a/data/gmpv_mpris_gdbus.xml b/data/gmpv_mpris_gdbus.xml
index e597713..4d994d1 100644
--- a/data/gmpv_mpris_gdbus.xml
+++ b/data/gmpv_mpris_gdbus.xml
@@ -55,4 +55,41 @@
 		<property name='CanSeek' type='b' access='read'/>
 		<property name='CanControl' type='b' access='read'/>
 	</interface>
+
+	<interface name='org.mpris.MediaPlayer2.TrackList'>
+		<method name='GetTracksMetadata'>
+			<arg type='ao' name='TrackIds' direction='in'/>
+			<arg type='aa{sv}' name='Metadata' direction='out'/>
+		</method>
+		<method name='AddTrack'>
+			<arg type='s' name='Uri' direction='in'/>
+			<arg type='o' name='AfterTrack' direction='in'/>
+			<arg type='b' name='SetAsCurrent' direction='in'/>
+		</method>
+		<method name='RemoveTrack'>
+			<arg type='o' name='TrackId' direction='in'/>
+		</method>
+		<method name='GoTo'>
+			<arg type='o' name='TrackId' direction='in'/>
+		</method>
+
+		<signal name='TrackListReplaced'>
+			<arg type='ao' name='Tracks'/>
+			<arg type='o' name='CurrentTrack'/>
+		</signal>
+		<signal name='TrackAdded'>
+			<arg type='a{sv}' name='Metadata'/>
+			<arg type='0' name='AfterTrack'/>
+		</signal>
+		<signal name='TrackRemoved'>
+			<arg type='o' name='TrackId'/>
+		</signal>
+		<signal name='TrackMetadataChanged'>
+			<arg type='o' name='TrackId'/>
+			<arg type='a{sv}' name='Metadata'/>
+		</signal>
+
+		<property name='Tracks' type='ao' access='read'/>
+		<property name='CanEditTracks' type='b' access='read'/>
+	</interface>
 </node>
diff --git a/data/io.github.GnomeMpv.appdata.xml.in b/data/io.github.GnomeMpv.appdata.xml.in
index bc0abc6..3f75b17 100644
--- a/data/io.github.GnomeMpv.appdata.xml.in
+++ b/data/io.github.GnomeMpv.appdata.xml.in
@@ -8,18 +8,18 @@
  <summary>GTK+ frontend for mpv</summary>
  <translation type="gettext">gnome-mpv</translation>
  <description>
-  <_p>
+  <p>
    GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media
    player capable of playing virtually all video and audio formats. The design
    of GNOME MPV is based on GNOME HIG, though it is not dependent on any GNOME
    libraries. GNOME MPV also offers an option to disable client-side decorations
    (CSD) for better compatibility with non-GNOME systems.
-  </_p>
-  <_p>Features:</_p>
+  </p>
+  <p>Features:</p>
   <ul>
-   <_li>Drag and drop playlist</_li>
-   <_li>Loading external mpv configuration files</_li>
-   <_li>MPRIS2 D-Bus interface</_li>
+   <li>Drag and drop playlist</li>
+   <li>Loading external mpv configuration files</li>
+   <li>MPRIS2 D-Bus interface</li>
   </ul>
  </description>
  <screenshots>
@@ -29,11 +29,11 @@
   </screenshot>
   <screenshot>
    <image>http://gnome-mpv.github.io/images/screenshot-1.png</image>
-   <_caption>The main window with CSD disabled</_caption>
+   <caption>The main window with CSD disabled</caption>
   </screenshot>
   <screenshot>
    <image>http://gnome-mpv.github.io/images/screenshot-2.png</image>
-   <_caption>The main window with playlist open</_caption>
+   <caption>The main window with playlist open</caption>
   </screenshot>
  </screenshots>
  <url type="homepage">http://gnome-mpv.github.io</url>
diff --git a/data/io.github.GnomeMpv.desktop.in b/data/io.github.GnomeMpv.desktop.in
index 19e5209..84e09e2 100644
--- a/data/io.github.GnomeMpv.desktop.in
+++ b/data/io.github.GnomeMpv.desktop.in
@@ -1,8 +1,9 @@
 [Desktop Entry]
 Version=1.0
-_Name=GNOME MPV
-_Comment=GTK+ frontend for mpv
+Name=GNOME MPV
+Comment=GTK+ frontend for mpv
 Exec=gnome-mpv %U
+# Translators: This is an icon name, don't translate!
 Icon=gnome-mpv
 Terminal=false
 Type=Application
diff --git a/data/io.github.GnomeMpv.gschema.xml b/data/io.github.GnomeMpv.gschema.xml
index e74dd03..51e4b87 100644
--- a/data/io.github.GnomeMpv.gschema.xml
+++ b/data/io.github.GnomeMpv.gschema.xml
@@ -23,6 +23,12 @@
 			<description>
 			</description>
 		</key>
+		<key name='always-use-floating-controls' type='b'>
+			<default>false</default>
+			<summary>Whether or not to use floating controls in windowed mode</summary>
+			<description>
+			</description>
+		</key>
 		<key name='last-folder-enable' type='b'>
 			<default>false</default>
 			<summary>Whether or not to make file chooser dialog remember last folder accessed</summary>
diff --git a/data/meson.build b/data/meson.build
new file mode 100644
index 0000000..5f27b77
--- /dev/null
+++ b/data/meson.build
@@ -0,0 +1,32 @@
+
+schemadir = join_paths(get_option('datadir'), 'glib-2.0/schemas')
+install_data([
+  'io.github.GnomeMpv.gschema.xml',
+  'org.gnome-mpv.gschema.xml'
+], install_dir: schemadir)
+
+i18n.merge_file(
+  input: 'io.github.GnomeMpv.appdata.xml.in',
+  output: 'io.github.GnomeMpv.appdata.xml',
+  po_dir: '../po',
+  install: true,
+  install_dir: join_paths(get_option('datadir'), 'appdata')
+)
+
+i18n.merge_file(
+  input: 'io.github.GnomeMpv.desktop.in',
+  output: 'io.github.GnomeMpv.desktop',
+  type: 'desktop',
+  po_dir: '../po',
+  install: true,
+  install_dir: join_paths(get_option('datadir'), 'applications')
+)
+
+icondir = join_paths(get_option('datadir'), 'icons/hicolor')
+install_data('gnome-mpv.svg',
+  install_dir: join_paths(icondir, 'scalable/apps')
+)
+
+install_data('gnome-mpv-symbolic.svg',
+  install_dir: join_paths(icondir, 'symbolic/apps')
+)
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..5a4f9c4
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,63 @@
+project('gnome-mpv', 'c',
+  version: '0.11',
+  meson_version: '>= 0.37.0',
+  default_options: [
+    'warning_level=2',
+    'c_std=gnu99',
+  ]
+)
+
+i18n = import('i18n')
+cc = meson.get_compiler('c')
+
+test_cflags = [
+  '-funsigned-char',
+  '-fstack-protector-strong',
+  '-fPIE',
+  '-fPIC',
+  '-Wconversion',
+  '-Winline',
+  '-Wno-padded',
+  '-Wno-unused-parameter',
+  '-Wstrict-prototypes',
+  '-Wmissing-prototypes',
+  '-Werror=implicit-function-declaration',
+  '-Werror=pointer-arith',
+  '-Werror=init-self',
+  ['-Werror=format-security', '-Werror=format=2'], # Must be checked together
+  '-Werror=missing-include-dirs',
+  '-Werror=date-time'
+]
+global_cflags = []
+foreach cflag : test_cflags
+  if cc.has_multi_arguments(cflag)
+    global_cflags += cflag
+  endif
+endforeach
+if cc.has_header('execinfo.h')
+  global_cflags += '-DHAVE_EXECINFO_H'
+endif
+add_project_arguments(global_cflags, language: 'c')
+
+test_ldflags = [
+  '-pie',
+  '-Wl,-z,relro',
+  '-Wl,-z,now'
+]
+global_ldflags = []
+foreach ldflag : test_ldflags
+  if cc.has_argument(ldflag)
+    global_ldflags += ldflag
+  endif
+endforeach
+add_project_link_arguments(global_ldflags, language: 'c')
+
+if not cc.has_function('setlocale')
+  error('Could not find setlocale()')
+endif
+
+subdir('src')
+subdir('data')
+subdir('po')
+
+meson.add_install_script('meson_post_install.py')
diff --git a/meson_post_install.py b/meson_post_install.py
new file mode 100755
index 0000000..351f4d7
--- /dev/null
+++ b/meson_post_install.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+
+prefix = os.environ.get('MESON_INSTALL_PREFIX', '/usr/local')
+datadir = os.path.join(prefix, 'share')
+
+# Packaging tools define DESTDIR and this isn't needed for them
+if not 'DESTDIR' in os.environ:
+	print('Compiling gsettings schemas...')
+	subprocess.call(['glib-compile-schemas', os.path.join(datadir, 'glib-2.0', 'schemas')])
+
+	print('Updating icon cache...')
+	subprocess.call(['gtk-update-icon-cache', '-qtf', os.path.join(datadir, 'icons', 'hicolor')])
+
+	print('Updating desktop database...')
+	subprocess.call(['update-desktop-database', '-q', os.path.join(datadir, 'applications')])
+
diff --git a/po/LINGUAS b/po/LINGUAS
index 5d23fad..828c8d3 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -10,5 +10,7 @@ pl
 pt_PT
 ro
 ru
+sr_RS
+sr_RS at latin
 zh_CN
 zh_TW
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..b2cade0
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,24 @@
+subdir = po
+top_builddir = ..
+
+DOMAIN = $(PACKAGE)
+
+XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 --keyword=g_dngettext:2,3 --add-comments
+
+COPYRIGHT_HOLDER = GNOME MPV
+
+PACKAGE_GNU = no
+
+MSGID_BUGS_ADDRESS = https://github.com/gnome-mpv/gnome-mpv/issues
+
+EXTRA_LOCALE_CATEGORIES =
+
+USE_MSGCTXT = no
+
+MSGMERGE_OPTIONS = --quiet
+
+MSGINIT_OPTIONS =
+
+PO_DEPENDS_ON_POT = no
+
+DIST_DEPENDS_ON_UPDATE_PO = no
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5830f92..9a23cc7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,20 +1,29 @@
-[type: gettext/gsettings]data/org.gnome-mpv.gschema.xml
-[type: gettext/gsettings]data/io.github.GnomeMpv.gschema.xml
-[type: gettext/xml]data/io.github.GnomeMpv.appdata.xml.in
-[type: gettext/ini]data/io.github.GnomeMpv.desktop.in
-src/gmpv_actionctl.c
+data/org.gnome-mpv.gschema.xml
+data/io.github.GnomeMpv.gschema.xml
+data/io.github.GnomeMpv.appdata.xml.in
+data/io.github.GnomeMpv.desktop.in
+src/gmpv_application_action.c
 src/gmpv_application.c
 src/gmpv_common.c
 src/gmpv_control_box.c
+src/gmpv_controller.c
+src/gmpv_file_chooser.c
 src/gmpv_header_bar.c
+src/gmpv_controller_input.c
 src/gmpv_main.c
 src/gmpv_main_window.c
 src/gmpv_menu.c
+src/gmpv_model.c
 src/gmpv_mpv.c
-src/gmpv_open_loc_dialog.c
-src/gmpv_playlist.c
+src/gmpv_mpv_opt.c
+src/gmpv_mpv_wrapper.c
+src/gmpv_open_location_dialog.c
 src/gmpv_playlist_widget.c
 src/gmpv_plugins_manager.c
 src/gmpv_plugins_manager_item.c
 src/gmpv_pref_dialog.c
+src/gmpv_seek_bar.c
 src/gmpv_shortcuts_window.c
+src/gmpv_video_area.c
+src/gmpv_view.c
+
diff --git a/po/ca.po b/po/ca.po
index 3a1ebb3..6c4a784 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -15,93 +15,94 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Habilita o inhabilita el tema fosc"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Habilita o inhabilita les decoracions del client"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 "Si el quadre de diàleg de selecció de fitxers haurà de recordar la darrera "
 "carpeta accedida"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Opcions que passar a l’MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Camí al fitxer de configuració de l’MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "Carrega o no un fitxer de configuració de l’MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Camí al fitxer de configuració d’entrada de l’MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "Carrega o no un fitxer de configuració d’entrada de l’MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Amplada de la finestra"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Alçada de la finestra"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Volum del reproductor"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Amplada de la llista de reproducció"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Mostra o amaga la llista de reproducció"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "URI de la darrera carpeta accedida"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "Si els paràmetres ja s’han migrat des d’una versió anterior"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "Frontal en GTK+ per a l’mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -116,597 +117,617 @@ msgstr ""
 "decoració del client (CSD) i millorar la compatibilitat amb altres sistemes "
 "diferents del GNOME."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Característiques:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr ""
 "La llista de reproducció es pot reorganitzar amb la tècnica d’arrossegar i "
 "deixar anar"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Càrrega de fitxers de configuració externs de l’MPV"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "Interfície per a MPRIS2 del D-Bus"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "La finestra principal en funcionament"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "La finestra principal amb la CSD inhabilitada"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "La finestra principal amb la llista de reproducció oberta"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "Frontal en GTK+ per a l’mpv"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Afegeix un fitxer a una llista de reproducció"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Obre un fitxer"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Obre"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Cancel·la"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
 
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Obre una ubicació"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Desa la llista de reproducció"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Desa"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr ""
-"Cal que reinicieu el %s per tal d’habilitar o inhabilitar les decoracions "
-"del client."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Un frontal en GTK per a l’MPV"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Adolfo Jayme Barrientos <fitojb at ubuntu.com>"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "En reproducció"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr ""
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr ""
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr ""
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Error"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Reprodueix"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Atura"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Avança"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Rebobina"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Capítol següent"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Capítol anterior"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Commuta la pantalla completa"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Posa en pausa"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Error"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Cancel·la"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Obre"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Cap"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Desconegut"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr ""
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Fitxer"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Obre una _ubicació"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "_Desa la llista de reproducció"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Surt"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Edita"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Preferències"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "Pista de _vídeo"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "Pista d’_àudio"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "Pista de s_ubtítols"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Visualitza"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr ""
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Commuta la llista de reproducció"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Pantalla completa"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "Mida _normal"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "Mida _doble"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Meitat de la mida"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Ajuda"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr ""
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_Quant a"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "La reproducció ha terminat de forma anòmala. Motiu: %s"
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "No s’han pogut aplicar alguns paràmetres de l’MPV."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Ubicació:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Afegeix…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Repetició"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Llista de reproducció"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Obre"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Cancel·la"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "«Scripts» en Lua"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "No s’ha pogut copiar el fitxer de «%s» a «%s». Motiu: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "No s’ha trobat cap «script» en Lua"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Suprimeix"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Esteu segur que voleu suprimir aquest «script»? Aquesta acció no es pot "
 "desfer."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "No s’ha pogut suprimir el fitxer «%s». Motiu: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Interfície de l’usuari</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Habilita les decoracions del client"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Habilita el tema fosc"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Recorda la ubicació del darrer fitxer"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Paràmetres de l’MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Carrega un fitxer de configuració de l’MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "Fitxer de configuració de l’MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Assignacions de tecles</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Carrega un fitxer de configuració d’entrada de l’MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Fitxer de configuració d’entrada de l’MPV:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Altres</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Opcions addicionals de l’MPV:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Generals"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "«Scripts» en Lua"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Desa"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Preferències"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Obre un fitxer"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Obre una ubicació"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Mostra el quadre de diàleg Preferències"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Commuta la llista de reproducció"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Commuta el mode de pantalla completa"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Surt del mode de pantalla completa"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Treu l’element seleccionat de la llista"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Desa la llista de reproducció"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Surt"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr ""
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Afegeix un fitxer a una llista de reproducció"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Obre un fitxer"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr ""
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Obre una ubicació"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Desa la llista de reproducció"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Un frontal en GTK per a l’MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Adolfo Jayme Barrientos <fitojb at ubuntu.com>"
diff --git a/po/cs.po b/po/cs.po
index 5275864..e1eb690 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -6,12 +6,13 @@
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2015. #zanata
 # Marek Suchánek <m.suchanek.2 at gmail.com>, 2016. #zanata
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# Marek Suchánek <m.suchanek.2 at gmail.com>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-mpv 0.2\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-11-23 10:58-0500\n"
-"PO-Revision-Date: 2016-10-07 03:06-0400\n"
+"PO-Revision-Date: 2017-02-02 08:22-0500\n"
 "Last-Translator: Marek Suchánek <m.suchanek.2 at gmail.com>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
@@ -21,91 +22,92 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Zapnout nebo vypnout tmavý motiv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Zapnout nebo vypnout dekorace na straně klienta"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "Zda si má dialog pro výběr souborů pamatovat poslední umístění"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Přepínače pro mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Cesta ke konfiguračnímu souboru mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "Načíst nebo nenačíst konfigurační soubor mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Cesta ke konfiguračnímu souboru vstupu mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "Načíst nebo nenačíst konfigurační soubor vstupu mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Šířka okna"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Výška okna"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Hlasitost přehrávání"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Šířka seznamu přehrávání"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Zobrazit nebo nezobrazit seznam přehrávání"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "Cesta k poslední použité složce"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "Zda už byly předvolby konvertovány ze staré na novou verzi"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Povolit více souběžných spuštění"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr "Zobrazit nebo nezobrazit ovládací tlačítka"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "GTK+ rozhraní nad mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -119,595 +121,616 @@ msgstr ""
 "žádných knihovnách GNOME nezávisí. Navíc GNOME MPV umožňuje vypnout okenní "
 "dekorace na straně klienta (CSD), aby lépe zapadal do jiných prostředí."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Nabízí:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "Seznam přehrávání („playlist“) s možností přetáhnout soubory myší"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Načítání externího konfiguračního souboru pro mpv"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "Rozhraní MPRIS2 D-Bus"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Hlavní okno a aplikace v akci"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "Hlavní okno s vypnutými dekoracemi na straně klienta"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "Hlavní okno s otevřeným seznamem přehrávání"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "GTK+ rozhraní nad mpv"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "_Přidat soubory do seznamu přehrávání"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Otevřít soubor"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Otevřít"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Zrušit"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr "Přidat umístění do seznamu přehrávání"
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Otevřít umístění"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "_Uložit seznam přehrávání"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Uložit"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
-"Povolení nebo zakázání dekorací na straně klienta vyžaduje restartování %s."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Načíst externí…"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "GTK frontend pro MPV"
 
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Tomáš Marný"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "Hraje"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr "Zobrazit verzi vydání"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr "Zařadit do fronty"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr "Nepřipojovat k již běžící instanci"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Chyba"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Přehrát"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Zastavit"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Vpřed"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Zpět"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Další kapitola"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Předchozí kapitola"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Zobrazení na celou obrazovku"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Pozastavit"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Chyba"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Zrušit"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Otevřít"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Nic"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 #, fuzzy
 msgid "Unknown"
 msgstr "Neznámý"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Načíst externí…"
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Soubor"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "_Otevřít umístění"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "_Uložit seznam přehrávání"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "U_končit"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "Up_ravit"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Předvolby"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "Stopa _videa"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "Stopa _zvuku"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "_Titulky"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "Zo_brazit"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
-msgstr "T_lačítka ovládání"
+msgstr "Přepnout ovládání"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Přepnout seznam přehrávání"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Celá obrazovka"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Normální velikost"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "_Dvojnásobná velikost"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Poloviční velikost"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Nápověda"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "_Klávesové zkratky"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
-msgstr "_O programu"
+msgstr "_O aplikaci"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "Přehrávání bylo nečekaně ukončeno. Důvod: %s."
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Nebylo možno uplatnit jednu nebo více předvoleb MPV."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Umístění:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Přidat…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 #, fuzzy
 msgid "Add _Location…"
 msgstr "Přidat _umístění…"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Opakovat"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Seznam přehrávání"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Přidat skript Lua"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Otevřít"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Zrušit"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Skripty Lua"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Selhalo kopírování souboru z ‚%s‘ do ‚%s‘. Důvod: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Skript Lua nenalezen"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Odstranit"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr "Určitě si přejete tento skript odstranit? Akci nelze vrátit zpět."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Selhalo smazání souboru ‚%s‘. Důvod: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Uživatelské rozhraní</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Povolit dekorace na straně klienta"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Povolit tmavý motiv"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Pamatovat si umístění posledního souboru"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Nastavení MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Načíst konfigurační soubor MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "Konfigurační soubor MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Klávesové zkratky</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Načíst vstupní konfigurační soubor MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Vstupní konfigurační soubor MPV:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Různé</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Extra možnosti MPV:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Obecné"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Skripty Lua"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Uložit"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Předvolby"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Otevřít soubor"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Otevřít umístění"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Otevřít předvolby"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
-msgstr "Přepnout tlačítka ovládání"
+msgstr "Přepnout ovládání"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Přepnout seznam přehrávání"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Přepnout zobrazení na celou obrazovku"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Opustit celou obrazovku"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr "Přepnout zprávy na obrazovce (normální nebo čas přehrávání)"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr "Ukazovat na obrazovce název souboru"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr "Ukazovat na obrazovce postup, uplynulý čas a celkový čas"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr "Skok zpět o 5 sekund"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr "Přesný skok zpět o 1 sekundu"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr "Skok zpět/vpřed o 1 minutu"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr "Přesný skok zpět/vpřed o 5 sekund"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr "Skok k předchozím/dalším titulkům"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr "Krok zpět/vpřed po jednotlivém snímku"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr "Skok na začátek předchozí/další kapitoly"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr "Zpomalit/zrychlit přehrávání o 10 %"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr "Snížit na polovinu / zdvojnásobit rychlost přehrávání"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr "Obnovit normální rychlost přehrávání"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Jít v seznamu přehrávání zpět/vpřed"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Odstranit vybranou položku v seznamu přehrávání"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Uložit seznam přehrávání"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr "Nastavit/smazat A-B body smyčky"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr "Přepnout opakování"
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Pozastavit nebo hrát dál"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Ukončit"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr "Uložit pozici přehrávání a ukončit"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr "Procházet zvukové stopy"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Snížit/zvýšit hlasitost"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr "Ztlumit nebo obnovit hlasitost"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr "Posunout zvukovou stupu o +/- 0,1 sekundy"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr "Přepnout viditelnost titulků"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr "Procházet načtené titulky"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr "Posunout stupu titulků o +/- 0,1 sekundy"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr "Přepnout styl titulků SSA/ASS"
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Posunout titulky nahoru/dolů"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr "Přepnout mód kompatibility poměru stran VSFilter"
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr "Procházet stopy videa"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr "Snížit/zvýšit rozsah ořezávání videa s jiným poměrem stran"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Pořídit snímek obrazovky"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Pořídit snímek obrazovky, bez titulků"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr "Pořídit snímek obrazovky, tak, jak se okno zobrazuje"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr "Zmenšit na poloviční velikost videa"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr "Obnovit původní velikost videa"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr "Zvětšit na dvojnásobnou velikost videa"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Upravit konstrast"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Upravit jas"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Upravit svítivost (gamma)"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Upravit sytost"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr "Zapnout nebo vypnout odstranění prokládání"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 #, fuzzy
 msgid "Cycle aspect ratio override"
 msgstr "Procházet přepsání poměru stran"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Uživatelské rozhraní"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Video"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Zvuk"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Titulky"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Přehrávání"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr "Posouvání"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "_Přidat soubory do seznamu přehrávání"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Otevřít soubor"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Přidat umístění do seznamu přehrávání"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Otevřít umístění"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "_Uložit seznam přehrávání"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "GTK frontend pro MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Tomáš Marný"
diff --git a/po/de_DE.po b/po/de_DE.po
index 3d9907c..a30badd 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -6,12 +6,13 @@
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2015. #zanata
 # Vincent Bermel <willovince at openmailbox.org>, 2016. #zanata
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# Vincent Bermel <willovince at openmailbox.org>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-mpv 0.6\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-11-23 10:58-0500\n"
-"PO-Revision-Date: 2016-08-23 08:55-0400\n"
+"PO-Revision-Date: 2017-02-20 08:39-0500\n"
 "Last-Translator: Vincent Bermel <willovince at openmailbox.org>\n"
 "Language-Team: German Translations\n"
 "MIME-Version: 1.0\n"
@@ -21,91 +22,93 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Dunkles Thema verwenden"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Kombinierte Titel-/Menüleiste (CSD)"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "Speicherort der zuletzt gespielten Datei merken"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "MPV-Einstellungen"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "MPV-Konfigurationsdatei"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "MPV-Konfiguration aus Datei laden"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Datei mit MPV-Tastenbelegungen"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "MPV-Konfiguration aus Datei laden"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Fensterbreite"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Fensterhöhe"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Lautstärke"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Breite der Wiedergabeliste"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Wiedergabeliste anzeigen"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "Zuletzt geöffnetes Verzeichnis"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "Ob Einstellungen schon von der vorherigen Version übernommen wurden"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+"Ob im Fenstermodus ausblendende Bedienelemente verwendet werden sollen"
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Mehrere Instanzen gleichzeitig zulassen"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr "Wiedergabesteuerung anzeigen"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "Eine GTK-Oberfläche für den Medienspieler mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -120,592 +123,614 @@ msgstr ""
 "Titelleiste für bessere Integration in Nicht-GNOME-Systeme deaktiviert "
 "werden."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Funktionen:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "Wiedergabeliste mit Drag and Drop-Unterstützung"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Laden externer mpv-Konfigurationsdateien"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "MPRIS2 D-Bus Schnittstelle"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Das Hauptfenser von GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "Das Hauptfenster ohne CSD-Titelleiste"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "Das Hauptfenster mit Wiedergabeliste"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "Eine GTK-Oberfläche für den Medienspieler mpv"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Datei zur _Wiedergabeliste hinzufügen"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Datei öffnen"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "Ö_ffnen"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Abbrechen"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr "Verzeichnis oder URL zur Wiedergabeliste hinzufügen"
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Adresse öffnen"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Wiedergabeliste speichern"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Speichern"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr "Die Änderungen erfordern einen Neustart von %s."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Importieren"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Eine GTK-Oberfläche für MPV"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Vincent Bermel"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
+msgstr ""
 
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 #, fuzzy
 msgid "Playing"
 msgstr "Wiedergabe"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr "Release-Version anzeigen"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr "In Warteschlange aufnehmen"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr "Nicht mit einer bereits laufenden Instanz verbinden"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Fehler"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Abspielen"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Stoppen"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Vorspulen"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Zurückspulen"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Weiterspringen"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Zurückspringen"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Vollbild"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Pause"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Fehler"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Abbrechen"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "Ö_ffnen"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr "Alle Dateien"
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Keine"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Originalspur"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Importieren"
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Datei"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "_Adresse öffnen"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "Wiedergabeliste _speichern"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Beenden"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Bearbeiten"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Einstellungen"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "_Videospur"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "_Tonspur"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "_Untertitel"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Ansicht"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr "Wiedergabe_steuerung ein/aus"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Wiedergabeliste ein/aus"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Vollbild"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Ursprüngliche Videogröße"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "_Doppelte Videogröße"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Halbe Videogröße"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Hilfe"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "_Tastenkürzel"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_Info"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "Wiedergabe wurde abgebrochen. Grund: %s."
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "MPV-Optionen konnten nicht angewendet werden."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Adresse (lokal oder Web):"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Hinzufügen"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr "Verzeichnis oder URL hinzufügen"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Wiederholen"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Wiedergabeliste"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Lua-Skript hinzufügen"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Öffnen"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Abbrechen"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua-Skripte"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Datei konnte nicht von '%s' nach '%s' kopiert werden. Grund: %s."
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Es wurde kein Lua-Skript gefunden."
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Entfernen"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr "Wollen Sie dieses Skript unwiderruflich entfernen?"
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Datei '%s' konnte nicht gelöscht werden. Grund: %s."
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Benutzeroberfläche</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Kombinierte Titel-/Menüleiste (CSD)"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Dunkles Thema verwenden"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr "Ausblendende Bedienelemente in Fenstermodus"
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Speicherort der zuletzt gespielten Datei merken"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>MPV-Einstellungen</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "MPV-Konfiguration aus Datei laden"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "MPV-Konfigurationsdatei"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Tastenbelegungen</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "MPV-Tastenbelegung aus Datei laden"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Datei mit MPV-Tastenbelegungen"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Sonstiges</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Weitere Optionen für MPV"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Allgemein"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Lua-Skripte"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Speichern"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Einstellungen"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Öffnen"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Adresse öffnen"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Einstellungen anzeigen"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr "Wiedergabesteuerung ein/aus"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Wiedergabeliste ein/aus"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Vollbild"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Vollbildmodus verlassen"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr "Wiedergabeposition einblenden/ausblenden"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr "Dateiname kurzzeitig einblenden"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr "Wiedergabeposition kurzzeitig einblenden"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr "15 Sekunden zurück/vorwärts springen"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr "Eine Sekunde zurück/vorwärts springen"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr "Eine Minute zurück/vorwärts springen"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr "5 Sekunden zurück/vorwärts springen"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr "Zum vorherigen/nächsten Untertitel springen"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr "Einzelnen Frame zurück/nach vorne springen"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr "Zum vorherigen/nächsten Kapitel springen"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr "Wiedergabegeschwindigkeit um 10% verringern/erhöhen"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr "Wiedergabegeschwindigkeit halbieren/verdoppeln"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr "Wiedergabegeschwindigkeit auf Normalwert zurücksetzen"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Vorheriger/nächster Titel der Wiedergabeliste"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Ausgewählten Titel aus Wiedergabeliste entfernen"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Wiedergabeliste speichern"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr "Loop-Begrenzungen setzen/entfernen"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr "Endloses Loopen aktivieren"
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Pause oder Fortsetzen"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Beenden"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr "Wiedergabeposition merken und beenden"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr "Zwischen verfügbaren Tonspuren springen"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Lautstärke verringern/erhöhen"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr "Stummschalten"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr "Tonspur in Schritten von 0.1 Sekunden vor/zurück verschieben"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr "Untertitel anzeigen/ausblenden"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr "Zwischen verfügbaren Untertiteln springen"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr "Untertitel in Schritten von 0.1 Sekunden verschieben"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr "ASS-Untertitelstil erzwingen"
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Untertitel höher/tiefer anzeigen"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr "Streckungskorrektor für Untertiteldarstellung ein/aus"
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr "Zwischen verfügbaren Videospuren springen"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr "Videoformat schrittweise einpassen (Pan & Scan)"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Bildschirmfoto aufnehmen"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Bildschirmfoto ohne Untertitel aufnehmen"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr "Foto des Fensterinhalts aufnehmen"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr "Halbe Videogröße"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr "Ursprüngliche Videogröße"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr "Doppelte Videogröße"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Kontrast anpassen"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Helligkeit anpassen"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Gammawert anpassen"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Farbsättigung anpassen"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr "Deinterlacing (de)aktivieren"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr "Seitenverhältnis umschalten"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Benutzeroberfläche"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Videowiedergabe"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Audiowiedergabe"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Untertitel"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Wiedergabesteuerung"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr "Wiedergabeposition"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Datei zur _Wiedergabeliste hinzufügen"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Datei öffnen"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Verzeichnis oder URL zur Wiedergabeliste hinzufügen"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Adresse öffnen"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Wiedergabeliste speichern"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Eine GTK-Oberfläche für MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Vincent Bermel"
diff --git a/po/fr.po b/po/fr.po
index 6a62b8e..3693c0b 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -5,13 +5,14 @@
 # Harenome Ranaivorarivony Razanajato <harenome at hareno.me>, 2015.
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2015. #zanata
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# gnome-mpv <gnome-mpv at openmailbox.org>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-mpv 0.5\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-11-23 10:58-0500\n"
-"PO-Revision-Date: 2016-11-03 05:23-0400\n"
-"Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
+"PO-Revision-Date: 2017-02-25 03:55-0500\n"
+"Last-Translator: gnome-mpv <gnome-mpv at openmailbox.org>\n"
 "Language-Team: Français\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -23,91 +24,92 @@ msgstr ""
 "X-Poedit-SearchPath-0: .\n"
 "X-Poedit-SearchPathExcluded-0: mpv.c\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Activer le thème sombre"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Largeur de la fenêtre"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Hauteur de la fenêtre"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Afficher ou cacher la liste de lecture"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Autoriser plusieures instances"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr "Afficher ou cacher les contrôles"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "Interface en GTK+ pour mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -116,597 +118,618 @@ msgid ""
 "decorations (CSD) for better compatibility with non-GNOME systems."
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Fonctionnalités"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr ""
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "Interface en GTK+ pour mpv"
-
-#: ../src/gmpv_actionctl.c:101
-#, fuzzy
-msgid "Add File to Playlist"
-msgstr "_Afficher la liste de lecture"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Ouvrir un fichier"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Ouvrir"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Annuler"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr "Ajouter l'emplacement à la liste de lecture"
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Ouvrir un emplacement"
-
-#: ../src/gmpv_actionctl.c:296
-#, fuzzy
-msgid "Save Playlist"
-msgstr "_Enregistrer la liste de lecture"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Enregistrer"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr ""
-"L'activation ou la désactivation des décorations fenêtre prendra effet après"
-" un redémarrage de %s."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
 
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Une interface GTK pour MPV"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Harenome Ranaivorarivony Razanajato"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "En cours de lecture"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr ""
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr ""
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr ""
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Erreur"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Lecture"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Arret"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Avancer"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Reculer"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Chapitre suivant"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Chapitre précédant"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Plein écran"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Pause"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Erreur"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Annuler"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Ouvrir"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Vide"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Inconnu"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr ""
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Fichier"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Ouvrir un _répertoire"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "_Enregistrer la liste de lecture"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Quitter"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "É_diter"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Préférences"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "Piste _vidéo"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "Piste _audio"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "Sous-titres"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Vue"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr "Afficher les contrôles"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Afficher la liste de lecture"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Plein écran"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "Taille _Normale"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "Taille _Double"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "Taille _Moitié"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Aide"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "_Raccourcis clavier"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "À _propos"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "La lecture a été interrompue pour la raison suivante : %s"
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr ""
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Emplacement:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Ajouter"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr "Ajouter un _Emplacement"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Lire en boucle"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Liste de lecture"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Ajouter un script Lua"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Ouvrir"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Annuler"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Scripts Lua"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr ""
-"Impossible de copier le fichier de '%s' vers '%s' pour la raison suivante :"
+"Impossible de copier le fichier de '%s' vers '%s' pour la raison suivante : "
+"%s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Aucun script Lua trouvé"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Supprimer"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Êtes vous sur de vouloir supprimer ce script ? Cette action est irréversible"
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Impossible de supprimer le fichier '%s' pour la raison suivante : %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Interface utilisateur</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Activer les décorations fenêtre"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Activer le thème sombre"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Se souvenir de l'emplacement du dernier fichier ouvert"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Configuration MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Charger un fichier de configuration MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "Fichier de configuration MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Raccourcis clavier</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Charger un fichier de configuration des raccourcis clavier MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Fichier de configuration des raccourcis clavier MPV:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Divers</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Options supplémentaires pour MPV"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Général"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Scripts Lua"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Enregistrer"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Préférences"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Ouvrir un fichier"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Ouvrir un emplacement"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Afficher les préférences"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr "Afficher les contrôles"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Afficher la liste de lecture"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Plein écran"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Quitter le mode plein écran"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr "Reduire/Augmenter la vitesse de lecture de 10%"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr "Reduire de moitié ou doubler la vitesse de lecture actuelle"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr "Réinitialiser la vitesse de lecture"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Aller en arrière/en avant dans la liste de lecture"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Supprimer l'élément sélectionné de la liste de lecture"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Sauvegarder la liste de lecture"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr "Définir/enlever les repères de boucle A-B"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Pause/reprendre"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Quitter"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Diminuer/augmenter le volume"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr "Muet"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Déplacer les sous titres en haut/bas"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Prendre une capture d'écran"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Prendre une capture d'écran, sans les sous-titres"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr "Réduire de moitié la taille de la vidéo"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr "Redimensionner la vidéo à sa taille d'origine"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr "Doubler la taille de la vidéo"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Ajuster le contraste"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Ajuster la luminosité"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Ajuster la saturation"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Interface de l'utilisateur"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Vidéo"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Audio"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Sous-titre"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Lecture"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr ""
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+#, fuzzy
+msgid "Add File to Playlist"
+msgstr "_Afficher la liste de lecture"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Ouvrir un fichier"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Ajouter l'emplacement à la liste de lecture"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Ouvrir un emplacement"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+#, fuzzy
+msgid "Save Playlist"
+msgstr "_Enregistrer la liste de lecture"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Une interface GTK pour MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Harenome Ranaivorarivony Razanajato"
diff --git a/po/hu.po b/po/hu.po
index b9b69c2..aa2b8ff 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -1,11 +1,12 @@
 # Bendegúz Gyönki <gyonkibendeguz at gmail.com>, 2016. #zanata
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# Bendegúz Gyönki <gyonkibendeguz at gmail.com>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-08-16 23:25+0700\n"
-"PO-Revision-Date: 2016-12-12 07:14-0500\n"
+"PO-Revision-Date: 2017-01-19 05:43-0500\n"
 "Last-Translator: Bendegúz Gyönki <gyonkibendeguz at gmail.com>\n"
 "Language-Team: Hungarian\n"
 "MIME-Version: 1.0\n"
@@ -15,91 +16,92 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Sötét téma engedélyezése/tiltása"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Kliensoldali díszítések engedélyezése/tiltása"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Az mpv-nek átadandó opciók"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Az mpv konfigurációs fájl útvonala"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Az mpv bemeneti konfigurációs fájl útvonala"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Az ablak szélessége"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Az ablak magassága"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "A lejátszó hangereje"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "A lejátszási lista szélessége"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Több példány engedélyezése"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "GTK+ felület az mpv-hez"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -114,593 +116,627 @@ msgstr ""
 "kliensoldali díszítések letiltását a GNOME-tól eltérő rendszerekkel való "
 "jobb kompatibilitás érdekében."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Funkciók:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "Fogd és vidd lejátszási lista"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Külső mpv konfigurációs fájlok betöltése"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "MPRIS2 D-Bus interfész"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Az alkalmazás működés közben"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "A főablak letiltott díszítésekkel"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "A főablak megnyitott lejátszási listával"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "GTK+ felület az mpv-hez"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Fájl hozzáadása a lejátszási listához"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Fájl megnyitása"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Megnyitás"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Mégse"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr "Hely hozzáadása a lejátszási listához"
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Hely megnyitása"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Lejátszási lista mentése"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Mentés"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Külső betöltése..."
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Egy GTK felület az MPV-hez"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
 
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr ""
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
+#, fuzzy
 msgid "Show release version"
-msgstr ""
+msgstr "Kiadási verzió megjelenítése"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
+#, fuzzy
 msgid "Enqueue"
-msgstr ""
+msgstr "Sorba állítás"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr "Ne csatlakozzon egy már futó példányhoz"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Hiba"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Lejátszás"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Megállítás"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Előretekerés"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Visszatekerés"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Következő fejezet"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Előző fejezet"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Átváltás teljes képernyőre"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Szünet"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Hiba"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Mégse"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Megnyitás"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Egyik sem"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Ismeretlen"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Külső betöltése..."
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Fájl"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "_Hely megnyitása"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "Lejátszási lista _mentése"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Kilépés"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Szerkesztés"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Beállítások"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "_Videósáv"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "_Hangsáv"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "F_eliratsáv"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Nézet"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr "_Vezérlők be-/kikapcsolása"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Lejátszási lista be-/kikapcsolása"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Teljes képernyő"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Normál méret"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "_Kétszeres méret"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Fele méret"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Súgó"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "_Billentyűkombinációk"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_Névjegy"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "A lejátszás nem megfelelően lett leállítva. Ok: %s."
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Egy vagy több MPV beállítás alkalmazása nem sikerült"
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Hely:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Hozzáadás..."
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr "_Hely hozzáadása..."
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Ismétlés"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Lejátszási lista"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Lua parancsfájl hozzáadása"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Megnyitás"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Mégse"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua parancsfájlok"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "A fájl másolása innen: „%s\", ide: „%s\" nem sikerült. Ok: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Nem található Lua parancsfájl"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Eltávolítás"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Biztosan el akarja távolítani ezt a parancsfájlt? Ez a művelet nem vonható "
 "vissza."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "„%s\" fájl törlése nem sikerült. Ok: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Felhasználói felület</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Kliensoldali díszítések engedélyezése"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Sötét téma engedélyezése"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Az utolsó fájl pozíciójának megjegyzése"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>MPV konfiguráció</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "MPV konfigurációs fájl betöltése"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "MPV konfigurációs fájl:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Gyorsbillentyűk</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "MPV beviteli konfigurációs fájl betöltése"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "MPV beviteli konfigurációs fájl:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Egyéb</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Extra MPV beállítások:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Általános"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Lua parancsfájlok"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Mentés"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Beállítások"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Fájl megnyitása"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Hely megnyitása"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Beállítások párbeszédablak mutatása"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr "Vezérlők be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Lejátszási lista be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Teljes képernyős mód be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Kilépés a teljes képernyős módból"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr "Váltás a normál és a lejátszási idő/hossz OSD között"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr "Fájlnév megjelenítése az OSD-n"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
+#, fuzzy
 msgid "Seek backward/forward 5 seconds"
-msgstr ""
+msgstr "Visszatekerés/előretekerés 5 másodperccel"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
+#, fuzzy
 msgid "Exact seek backward/forward 1 second"
-msgstr ""
+msgstr "Visszatekerés/előretekerés pontosan 1 másodperccel"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
+#, fuzzy
 msgid "Seek backward/forward 1 minute"
-msgstr ""
+msgstr "Visszatekerés/előretekerés 1 perccel"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
+#, fuzzy
 msgid "Exact seek backward/forward 5 seconds"
-msgstr ""
+msgstr "Visszatekerés/előretekerés pontosan 5 másodperccel"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
+#, fuzzy
 msgid "Seek to previous/next subtitle"
-msgstr ""
+msgstr "Ugrás az előző/következő felirathoz"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
+#, fuzzy
 msgid "Step backward/forward a single frame"
-msgstr ""
+msgstr "Visszalépés/előrelépés egy képkockával"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
+#, fuzzy
 msgid "Seek to the beginning of the previous/next chapter"
-msgstr ""
+msgstr "Ugrás az előző/következő fejezet elejére"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
+#, fuzzy
 msgid "Decrease/increase playback speed by 10%"
-msgstr ""
+msgstr "Lejátszási sebesség csökkentése/növelése 10%-kal"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
+#, fuzzy
 msgid "Halve/double current playback speed"
-msgstr ""
+msgstr "Jelenlegi lejátszási sebesség felezése/duplázása"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
+#, fuzzy
 msgid "Reset playback speed to normal"
-msgstr ""
+msgstr "Normál lejátszási sebesség visszaállítása"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Ugrás előre/hátra a lejátszási listában"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Kiválasztott lejátszási elem eltávolítása"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Lejátszási lista mentése"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr "A-B ismétlési szakasz beállítása/törlése"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr "Végtelen ismétlés be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Szünet vagy folytatás"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Kilépés"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr "Jelenlegi lejátszási pozíció mentése és kilépés"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr "Váltás a hangsávok között"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Hangerő csökkentése/növelése"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr "Némítás be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr "Hangsáv eltolásának beállítása 0,1 mp időközökkel"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr "Felirat láthatóságának be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr "Váltás az elérhető feliratok között"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr "Feliratok eltolásának beállítása 0,1 mp időközökkel"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr "SSA/ASS feliratstílus felülbírálásának be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Feliratok mozgatása fel/le"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr "VSFilter képarány-kompatibilitási mód be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr "Váltás a videósávok között"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr "Pan-and-scan tartomány csökkentése/növelése"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Képernyőkép készítése"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Képernyőkép készítése feliratok nélkül"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr "Képernyőkép készítése az ablak tartalmáról"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr "Videó átméretezése az eredeti méret felére"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr "Videó átméretezése az eredeti méretre"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr "Videó átméretezése az eredeti méret kétszeresére"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Kontraszt beállítása"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Világosság beállítása"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Gamma beállítása"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Telítettség beállítása"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr "Váltottsorosság-mentesítés be-/kikapcsolása"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Felhasználói felület"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Videó"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Hang"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Felirat"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Lejátszás"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr "Tekerés"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Fájl hozzáadása a lejátszási listához"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Fájl megnyitása"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Hely hozzáadása a lejátszási listához"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Hely megnyitása"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Lejátszási lista mentése"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Egy GTK felület az MPV-hez"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr ""
diff --git a/po/it.po b/po/it.po
index 931d3f9..66b08f3 100644
--- a/po/it.po
+++ b/po/it.po
@@ -1,12 +1,13 @@
 # Dino Trevisani <c3v90 at libero.it>, 2016. #zanata
-# gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# Luca <Walach1949 at jourrapide.com>, 2017. #zanata
+# gnome-mpv <gnome-mpv at openmailbox.org>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-08-16 23:25+0700\n"
-"PO-Revision-Date: 2016-11-03 05:23-0400\n"
-"Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
+"PO-Revision-Date: 2017-05-05 01:06-0400\n"
+"Last-Translator: Luca <Walach1949 at jourrapide.com>\n"
 "Language-Team: Italian\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -15,93 +16,94 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Attiva o disattiva il tema scuro"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Attiva o disattiva le decorazioni client-side"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "Ricorda o meno l'ultima cartella visualizzata"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Opzioni da inserire in MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
-msgstr "Posizione del file di configurazione di MPV"
+msgstr "Percorso del file di configurazione di MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "Carica il file di configurazione di MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
-msgstr "Posizione del file di configurazione dell'input di MPV"
+msgstr "Percorso del file di configurazione dell'input di MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "Carica il file di configurazione dell'input di MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Larghezza finestra"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Altezza finestra"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Volume"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Larghezza della playlist"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Mostra o meno la playlist"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "Percorso dell'ultima cartella visualizzata"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 "È stata gia effettuata la migrazione delle preferenze da una versione "
 "precedente"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr "Mostra o meno i controlli fluttuanti in modalità finestra"
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Permetti istanze multiple"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
-msgstr ""
+msgstr "Mostra o meno i controlli"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "Un frontend in GTK+ per MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -116,595 +118,615 @@ msgstr ""
 " le decorazioni client-side (CSD) per una migliore compatibilità con i "
 "sistemi che non usano GNOME."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Caratteristiche:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "Drag and drop della playlist"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Carica un file di configurazione di MPV esterno"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "Interfaccia MPRIS2 D-Bus"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "La finestra principale in funzione"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "La finestra principale con le decorazioni client-side disattivate"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "La finestra principale con la playlist visualizzata"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "Un frontend in GTK+ per MPV"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Aggiungi file alla playlist"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Apri file"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "Apri"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "Annulla"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Apri posizione"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Salva la playlist"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "Salva"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
-"Attivare o disattivare le decorazioni client-side richiede il riavvio di %s "
-"per avere effetto."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Importa..."
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Un frontend in GTK+ per MPV"
 
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Dino Trevisani"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "In riproduzione"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
-msgstr ""
+msgstr "Mostra versione della release"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr "Accoda"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr "Non usare un'istanza già in esecuzione"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Errore"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Riproduci"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Ferma"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Vai avanti"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Torna indietro"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Capitolo successivo"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Capitolo precedente"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Attiva la modalità a schermo intero"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Pausa"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Errore"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "Annulla"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "Apri"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr "Tutti i file"
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Nessuno"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Sconosciuto"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "Importa..."
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "File"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Apri posizione"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "Salva la playlist"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "Esci"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "Modifica"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "Preferenze"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "Traccia video"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "Traccia audio"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "Traccia sottotitoli"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "Visualizza"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
-msgstr ""
+msgstr "Mostra o meno i controlli"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
-msgstr "Mostra la playlist"
+msgstr "Mostra o meno la playlist"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "Modalità a schermo intero"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "Dimensioni normali"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "Dimensioni raddoppiate"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "Dimensioni dimezzate"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "Aiuto"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "Scorciatoie da tastiera"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "Informazioni"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "La riproduzione si è interrota in modo anomalo. Motivo: %s"
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Impossibile applicare una o più opzioni di MPV"
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Posizione:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "Aggiungi"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
-msgstr ""
+msgstr "Aggiungi posizione"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Loop"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Playlist"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Aggiungi script in Lua"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Apri"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Cancella"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Scritps in Lua"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Impossibile copiare file da '%s' a '%s'. Motivo: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Nessuno script in Lua trovato"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Rimuovi"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Sei sicuro di voler cancellare questo script? Questa azione non può essere "
 "annullata."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Impossible cancellare '%s'. Motivo: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Interfaccia utente</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Attiva le decorazioni client-side"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Attiva tema scuro"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr "Mostra i controlli fluttuanti in modalità finestra"
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Ricorda l'ultimo percorso dei file"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Configurazione di MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Carica il file di configurazione di MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "File di configurazione di MPV"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Scorciatoie da tastiera</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Carica il file di configurazione dell'input di MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "File di configurazione dell'input di MPV"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Varie</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Opzioni extra per MPV"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Generale"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Scritps in Lua"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "Salva"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Preferenze"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Apri file"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Apri posizione"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Mostra la finestra della preferenze"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
-msgstr ""
+msgstr "Mostra o meno i controlli"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
-msgstr "Mostra playlist"
+msgstr "Mostra o meno la playlist"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Attiva la modalità a schermo intero"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Disattiva la modalità a schermo intero"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
-msgstr ""
+msgstr "Attiva la visualizzazione in sovraimpressione"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
-msgstr ""
+msgstr "Mostra il nome del file in sovraimpressione"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
-msgstr ""
+msgstr "Mostra tempo trascorso e durata in sovraimpressione"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
-msgstr ""
+msgstr "Vai indietro/avanti di 5 secondi"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
-msgstr ""
+msgstr "Vai indietro/avanti di 1 secondo preciso"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
-msgstr ""
+msgstr "Vai indietro/avanti di un 1 minuto"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
-msgstr ""
+msgstr "Vai indietro/avanti di 5 secondi precisi"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
-msgstr ""
+msgstr "Vai ai sottotitoli precendenti/prossimi"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
-msgstr ""
+msgstr "Vai indietro/avanti di un singolo fotogramma"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
-msgstr ""
+msgstr "Vai all'inizio del capitolo precente/prossimo"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
-msgstr ""
+msgstr "Diminuisci/aumenta la velocità di riproduzione del 10%"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
-msgstr ""
+msgstr "Dimezza/raddoppia la velocità di riproduzione corrente"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
-msgstr ""
+msgstr "Ripristina la velocità di riproduzione normale"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
-msgstr ""
+msgstr "Vai indietro/avanti nella playlist"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Rimuovi dalla playlist"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Salva playlist"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
-msgstr ""
+msgstr "Imposta/rimuovi A-B loop"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
-msgstr ""
+msgstr "Attiva il loop continuo"
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
-msgstr ""
+msgstr "Pausa o meno"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Esci"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
-msgstr ""
+msgstr "Salva la posizione di riproduzione corrente ed esci "
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
-msgstr ""
+msgstr "Scegli fra le tracce audio avviabili"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
-msgstr ""
+msgstr "Diminusci/aumenta il volume"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
-msgstr ""
+msgstr "Muto o meno"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
-msgstr ""
+msgstr "Aggiusta il ritardo dell'audio di +/- 0.1 secondi"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
-msgstr ""
+msgstr "Attiva visualizzazione sottotitoli"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
-msgstr ""
+msgstr "Scegli fra i sottotitoli disponibili"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
-msgstr ""
+msgstr "Aggiusta il ritardo dei sottotitoli di +/- 0.1 secondi"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
-msgstr ""
+msgstr "Attiva la sovrascrittura dello stile dei sottotitoli SSA/ASS"
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Sposta i sottotitoli su/giu"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
-msgstr ""
+msgstr "Attiva la modalità di compatibilità di aspetto per VSFilter"
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
-msgstr ""
+msgstr "Scegli fra le tracce video disponibili"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
-msgstr ""
+msgstr "Diminuisci/aumenta il range pan-and-scan"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
-msgstr ""
+msgstr "Fai uno screenshot"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
-msgstr ""
+msgstr "Fai uno screenshot, senza sottotitoli"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
-msgstr ""
+msgstr "Fai uno screenshot, così come è la finestra"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
-msgstr ""
+msgstr "Dimezza la dimensione originale del video"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
-msgstr ""
+msgstr "Ripristina la dimensione originale del video"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
-msgstr ""
+msgstr "Raddoppia la dimensione originale del video"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Modifica contrasto"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Modifica luminosità"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Modifica gamma"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Modifica saturazione"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
-msgstr ""
+msgstr "Attiva o disattiva il deinterlacciatore"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
-msgstr ""
+msgstr "Scegli fra le proporzioni di aspetto disponibili"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
-msgstr ""
+msgstr "Interfaccia Utente"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Video"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
-msgstr ""
+msgstr "Audio"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Sottotitoli"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
-msgstr ""
+msgstr "Riproduzione"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
+msgstr "Ricerca"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
 msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Aggiungi file alla playlist"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Apri file"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Aggiungi posizione alla playlist"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Apri posizione"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Salva la playlist"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Un frontend in GTK+ per MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Dino Trevisani"
diff --git a/po/ja.po b/po/ja.po
index 9b0a9b7..317363d 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -5,13 +5,14 @@
 # Tista <tista.gma500 at gmail.com>, 2015.
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2015. #zanata
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# gnome-mpv <gnome-mpv at openmailbox.org>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-mpv 0.2\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-11-23 10:58-0500\n"
-"PO-Revision-Date: 2016-11-03 05:24-0400\n"
-"Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
+"PO-Revision-Date: 2017-06-04 08:35-0400\n"
+"Last-Translator: gnome-mpv <gnome-mpv at openmailbox.org>\n"
 "Language-Team: Japanese <>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -20,91 +21,97 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
+#, fuzzy
 msgid "Enable or disable dark theme"
-msgstr ""
+msgstr "暗いテーマを有効または無効にする"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
+#, fuzzy
 msgid "Enable or disable client-side decorations"
-msgstr ""
+msgstr "CSDを有効または無効にする"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
+#, fuzzy
 msgid "Options to pass to mpv"
-msgstr ""
+msgstr "mpvに渡すオプション"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
+#, fuzzy
 msgid "Path to mpv configuration file"
-msgstr ""
+msgstr "MPV設定ファイル"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
+#, fuzzy
 msgid "Path to mpv input configuration file"
-msgstr ""
+msgstr "MPV入力設定ファイル"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr ""
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -113,592 +120,636 @@ msgid ""
 "decorations (CSD) for better compatibility with non-GNOME systems."
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr ""
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "プレイリストの表示・非表示"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "ファイルを開く"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "開く(_O)"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "キャンセル(_C)"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "場所を開く"
-
-#: ../src/gmpv_actionctl.c:296
-#, fuzzy
-msgid "Save Playlist"
-msgstr "_プレイリストの保存"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "保存(_S)"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr "CSDの有効・無効は %s の再起動が必要です。"
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
 
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "MPVのGTKフロントエンド"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Tista"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr ""
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr ""
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr ""
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr ""
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr ""
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
+#, fuzzy
 msgid "Toggle Fullscreen"
-msgstr ""
+msgstr "全面表示を切換える"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr ""
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+#, fuzzy
+msgid "Error"
+msgstr "エラー"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "キャンセル(_C)"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "開く(_O)"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+#, fuzzy
+msgid "All Files"
+msgstr "全てのファイル"
+
+#: src/gmpv_file_chooser.c:143
+#, fuzzy
+msgid "Media Files"
+msgstr "メディア"
+
+#: src/gmpv_file_chooser.c:154
+#, fuzzy
+msgid "Audio Files"
+msgstr "音声"
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr "動画"
+
+#: src/gmpv_file_chooser.c:170
+#, fuzzy
+msgid "Image Files"
+msgstr "画像"
+
+#: src/gmpv_file_chooser.c:180
+#, fuzzy
+msgid "Subtitle Files"
+msgstr "字幕"
+
+#: src/gmpv_menu.c:102
+#, fuzzy
 msgid "None"
-msgstr ""
+msgstr "なし"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
+#, fuzzy
 msgid "Unknown"
-msgstr ""
+msgstr "不明"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr ""
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "ファイル(_F)"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "開く場所(_L)"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "プレイリストの保存(_S)"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "終了(_Q)"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "編集(_E)"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "設定(_P)"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "表示(_V)"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr ""
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "プレイリストの表示・非表示(_T)"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "全画面表示(_F)"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "通常のサイズ(_N)"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "2倍のサイズ(_D)"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "半分のサイズ(_H)"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "ヘルプ(_H)"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
+#, fuzzy
 msgid "_Keyboard Shortcuts"
-msgstr ""
+msgstr "ショートカット"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "このアプリケーションについて(_A)"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr ""
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr ""
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "場所:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "プレイリスト"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr ""
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
+#, fuzzy
 msgid "Remove"
-msgstr ""
+msgstr "削除"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
+#, fuzzy
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
-msgstr ""
+msgstr "このスクリプトを削除してもよろしいですか?このアクションを元に戻すことはできません。"
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "CSDを有効にする"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "暗いテーマを有効にする"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>MPVの設定</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "MPV設定ファイルをロードする"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "MPV設定ファイル:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>キーバインド</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "MPV入力設定ファイルをロードする"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "MPV入力設定ファイル:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>その他</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "その他のMPVオプション:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr ""
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "保存(_S)"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "設定"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
+#, fuzzy
 msgid "Open file"
-msgstr ""
+msgstr "ファイルを開く"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
+#, fuzzy
 msgid "Open location"
+msgstr "場所を開く"
+
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
+#, fuzzy
 msgid "Toggle fullscreen mode"
-msgstr ""
+msgstr "全面表示を切換える"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
+#, fuzzy
 msgid "Leave fullscreen mode"
-msgstr ""
+msgstr "全画面表示を終了"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
+#, fuzzy
 msgid "Save playlist"
-msgstr ""
+msgstr "プレイリストを保存"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
+#, fuzzy
 msgid "Quit"
-msgstr ""
+msgstr "終了"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
+#, fuzzy
 msgid "Take a screenshot"
-msgstr ""
+msgstr "スクリーンショットを撮る"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
+#, fuzzy
 msgid "User Interface"
-msgstr ""
+msgstr "ユーザーインターフェース"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr ""
+
+#: src/gmpv_view.c:742
+#, fuzzy
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr "CSDの有効・無効は再起動が必要です。"
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "プレイリストの表示・非表示"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "ファイルを開く"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr ""
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "場所を開く"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+#, fuzzy
+msgid "Load Subtitle Track…"
+msgstr "字幕をロードする"
+
+#: src/gmpv_view.c:1390
+#, fuzzy
+msgid "Save Playlist"
+msgstr "_プレイリストの保存"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "MPVのGTKフロントエンド"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Tista"
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 0000000..f904cde
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1,3 @@
+i18n.gettext(meson.project_name(),
+  preset: 'glib'
+)
diff --git a/po/nl.po b/po/nl.po
index 7aad344..bcf2381 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -15,100 +15,101 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Schakel donker thema in of uit"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Schakel client-side decoraties in of uit"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 #, fuzzy
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 "Laat de bestandskiezer de laatst geraadpleegde map wel of niet onthouden"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Opties om door te geven aan mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Pad naar mpv configuratiebestand"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 #, fuzzy
 msgid "Load or don't load mpv configuration file"
 msgstr "Laad mpv configuratiebestand wel of niet"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 #, fuzzy
 msgid "Path to mpv input configuration file"
 msgstr "Pad naar mpv input configuratiebestand"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 #, fuzzy
 msgid "Load or don't load mpv input configuration file"
 msgstr "Laad mpv input configuratiebestand wel of niet"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Breedte van het venster"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Hoogte van het venster"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 #, fuzzy
 msgid "Volume of player"
 msgstr "Volume van de speler"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Breedte van de afspeellijst"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Geef de afspeellijst wel of niet weer"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "URI van de map die het laatst is geraadpleegd"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 #, fuzzy
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "Of de instellingen al gemigreerd zijn van een vorige versie"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 #, fuzzy
 msgid "Allow multiple instances"
 msgstr "Sta meerdere instanties to"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 #, fuzzy
 msgid "Show or not show the controls"
 msgstr "Geef de controls wel of niet weer"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "GTK+ frontend voor mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -122,604 +123,624 @@ msgstr ""
 " bibliotheken. GNOME MPV heeft ook een optie om client-side decoraties (CSD)"
 " uit te zetten voor betere compatibiliteit met niet-GNOME systemen"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Functies:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 #, fuzzy
 msgid "Drag and drop playlist"
 msgstr "Drag and drop afspeellijst"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Externe mpv configuratiebestanden laden"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Het hoofdvenster dat de applicatie in actie laat zien"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "Het hoofdvenster met CSD uitgeschakeld"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "Het hoofdvenster met een afspeellijst open"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "GTK+ frontend voor mpv"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Voeg Bestand toe aan Afspeellijst"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Open Bestand"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Open"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Annuleren"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Open Locatie"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Sla Afspeellijst op"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Opslaan"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr ""
-"In- of uitschakelen van client-side decoraties vereist herstarten van %s om "
-"effect te hebben."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Laad Externe…"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Een GTK frontend voor MPV"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
 
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "Afspelen"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr "Toon release versie"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 #, fuzzy
 msgid "Enqueue"
 msgstr "Voeg toe aan wachtrij"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 #, fuzzy
 msgid "Don't connect to an already-running instance"
 msgstr "Verbind niet met instanties die al draaien"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Fout"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Speel af"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Stop"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Voorwaards"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Achterwaards"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Volgend Hoofdstuk"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Vorig Hoofdstuk"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Pauze"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Fout"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Annuleren"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Open"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Geen"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Onbekend"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Laad Externe…"
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Bestand"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Open _Locatie"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "_Sla Afspeellijst op"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Afsluiten"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Bewerken"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Instellingen"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr ""
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr ""
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr ""
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Volledig Scherm"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Normale Grootte"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "_Dubbele Grootte"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Halve Grootte"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Help"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr ""
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_Over"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "Afspelen werd abnormaal beëindigd. Reden: %s."
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Het toepassen van een of meerdere MPV opties is mislukt."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Locatie:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Voeg Toe…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 #, fuzzy
 msgid "Loop"
 msgstr "Lus"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Afspeellijst"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Voeg Lua Script toe"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Openen"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Annuleren"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua Scripts"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Bestand van '%s' naar '%s' kopiëren mislukt. Reden: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Geen Lua script gevonden"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Verwijderen"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Weet je het zeker dat je dit script wil verwijderen? Deze actie kan niet "
 "ongedaan worden gemaakt."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Bestand '%s' verwijderen mislukt. Reden: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Gebruikersomgeving</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Schakel client-side decoratie in"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Schakel donker thema in"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Onthoud de locatie van het laatste bestand"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>MPV Configuratie</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Laad MPV configuratiebestand"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "MPV configuratiebestand:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Sneltoetsen</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 #, fuzzy
 msgid "Load MPV input configuration file"
 msgstr "Laad MPV input configuratiebestand"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 #, fuzzy
 msgid "MPV input configuration file:"
 msgstr "MPV input configuratiebestand:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Diversen</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Extra MPV opties:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Algemeen"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Lua Scripts"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Opslaan"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Instellingen"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Open bestand"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Open locatie"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Toon instellingen dialoog"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Verlaat volledig scherm-modus"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr "Geef bestandsnaam weer op de OSD"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr "Geef vooruitgang, verstreken tijd en duratie weer op de OSD"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr "Zoek 5 seconden achter- of voorwaards"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr "Zoek exact 1 seconde achter- of voorwaards"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr "Zoek 1 minuut achter- of voorwaards"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr "Zoek exact 5 seconden achter- of voorwaards"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr "Ga een frame achter- of voorwaards"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr "Verlaag of verhoog afspeelsnelheid met 10%"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr "Halveer of verdubbel de huidige afspeelsnelheid"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr "Reset afspeelsnelheid naar normaal"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Ga achter- of voorwaards in de afspeellijst"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Verwijder geselecteerde item van de afspeellijst"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Sla afspeellijst op"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Pauzeren of hervatten"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Afsluiten"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr "Sla huidige afspeelpositie op en sluit af"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr "Doorloop audiotracks"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Verlaag of verhoog volume"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr "Verander audiovertraging met ±0.1 seconden"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr "Verander ondertitelingvertraging met ±0.1 seconden"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Verplaats ondertiteling omhoog of omlaag"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 #, fuzzy
 msgid "Cycle through video tracks"
 msgstr "Doorloop videotracks"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Maak een schermafbeelding"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Maak een schermafbeelding zonder ondertiteling"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr "Maak een schermafbeelding zoals het venster het toont"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Verander contrast"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Verander helderheid"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Verander gamma"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Verander verzadiging"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 #, fuzzy
 msgid "Activate or deactivate deinterlacer"
 msgstr "Activeer of deactiveer de deinterlacer"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 #, fuzzy
 msgid "Cycle aspect ratio override"
 msgstr "Doorloop beeldverhouding override"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Gebruikersomgeving"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Video"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Audio"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Ondertiteling"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Afspelen"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr "Zoeken"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Voeg Bestand toe aan Afspeellijst"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Open Bestand"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr ""
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Open Locatie"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Sla Afspeellijst op"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Een GTK frontend voor MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr ""
diff --git a/po/pl.po b/po/pl.po
index 2c174b5..20e6fe2 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -2,9 +2,9 @@
 # Piotr Sokół <psokol.l10n at gmail.com>, 2016. #zanata
 msgid ""
 msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-08-16 23:25+0700\n"
+"Project-Id-Version: gnome-mpv 0.11\n"
+"Report-Msgid-Bugs-To: https://github.com/gnome-mpv/gnome-mpv/issues\n"
+"POT-Creation-Date: 2017-06-04 19:07+0700\n"
 "PO-Revision-Date: 2016-10-09 04:02-0400\n"
 "Last-Translator: Piotr Sokół <psokol.l10n at gmail.com>\n"
 "Language-Team: polski <>\n"
@@ -15,94 +15,95 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Przełącza ciemny styl"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Przełącza wyświetlanie obramowania po stronie klienta"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 "Przełącza przechowywanie ścieżki ostatnio używanego katalogu przez okno "
 "wyboru pliku"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Określa opcje przekazywane do mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Wskazuje ścieżkę pliku konfiguracyjnego mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "Przełącza wczytywanie pliku konfiguracyjnego mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Wskazuje ścieżkę pliku konfiguracyjnego skrótów programu mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "Przełącza wczytywanie pliku konfiguracyjnego skrótów programu mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Określa szerokość okna"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Określa wysokość okna"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Ustala głośność odtwarzania dźwięku"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Określa szerokość listy odtwarzania"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Przełącza wyświetlanie listy odtwarzania"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "Przechowuje adres URI ostatnio używanego katalogu"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 "Określa czy ustawienia zostały zaimportowane z poprzedniej wersji programu"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Wielokrotne wystąpienia programu"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr "Przełącza wyświetlanie przycisków sterujących"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "Wykorzystuje interfejs GTK do obsługi programu MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -117,593 +118,613 @@ msgstr ""
 "stronie klienta (CDS) dla lepszej integracji z systemami bez środowiska "
 "GNOME."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Cechy:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "lista odtwarzania obsługująca przeciąganie plików,"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "wczytywanie zewnętrznych plików konfiguracyjnych programu mpv,"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "obsluga interfejsu D-Bus MPRIS2."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Główne okno przedstawiające działanie programu"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "Głowne okno programu z wyłączonym obramowaniem po stronie klienta"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "Główne okno programu z listą odtwarzania"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "Wykorzystuje interfejs GTK do obsługi programu MPV"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Dodawanie pliku do listy odtwarzania"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Wybór pliku"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Otwórz"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Anuluj"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr "Dodawanie położenia do listy odtwarzania"
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Otwieranie położenia"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Zapisywanie listy odtwarzania"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Zapisz"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
-"Przełączenie wyświetlania obramowań okien po stronie klienta wymaga "
-"ponownego uruchomienia programu %s w celu wprowadzenia zmian."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Wczytaj zewnętrzną..."
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Wykorzystuje interfejs GTK do obsługi programu MPV"
 
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Piotr Sokół <psokol.l10n at gmail.com>, 2016"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "Odtwarzanie"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr "Wypisuje informacje o wersji"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr "Dodaje do kolejki odtwarzania"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr "Nie łączy z uruchomionym wystąpieniem programu"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Błąd"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Rozpoczyna odtwarznie"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Zatrzymuje odtwarzanie"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Przechodzi naprzód"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Przechodzi wstecz"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Następny rozdział"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Poprzedni rozdział"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Przełącza wyświetlanie na pełnym ekranie"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Wstrzymuje odtwarzanie"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Błąd"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Anuluj"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Otwórz"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Brak"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Nieznana"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Wczytaj zewnętrzną..."
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Plik"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Otwórz położe_nie"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "Z_apisz listę odtwarzania"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "Za_kończ"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Edycja"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "P_referencje"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "Ścieżka _wideo"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "Ścieżka _dźwiękowa"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "Ścieżka _napisów"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Widok"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr "P_rzyciski sterujące"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Lista odtwarzania"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Pełny ekran"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Zwykły rozmiar"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "Dwukrotnie _większy rozmiar"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "Dwukrotnie _mniejszy rozmiar"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "Pomo_c"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "_Skróty klawiszowe"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_O programie"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "Zakończono odtwarzanie w nieprawidłowy sposób. Powód: %s"
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Nie udało się wprowadzić jednej lub więcej opcji MPV."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Położenie:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Dodaj..."
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr "Dodaj p_ołożenie…"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Powtarzanie"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Lista odtwarzania"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Dodawanie skryptu Lua"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Otwórz"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Anuluj"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Skrypty Lua"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Nie udało się skopiować pliku z położenia „%s” do „%s”. Powód: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Nie odnaleziono skryptów Lua"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Usuń"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr "Usunąć ten skrypt? Tej czynności nie można cofnąć."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Nie można usunąć pliku „%s”. Powód: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Interfejs użytkownika</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Obramowania okien po stronie klienta"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Ciemny styl"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Przechowywanie położenia ostatnich plików"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Konfiguracja MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Wczytywanie pliku konfiguracji MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "Plik konfiguracji MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Skróty klawiszowe</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Wczytywanie pliku konfiguracji skrótów MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Plik konfiguracji skrótów MPV:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Różne</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Dodatkowe opcje MPV:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Ogólne"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Skrypty Lua"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Zapisz"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Preferencje"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Otwarcie pliku"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Otwarcie położenia"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Wyświetlenie okna preferencji"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr "Przełączenie wyświetlania przycisków sterujących"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Przełączenie wyświetlania listy odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Przełączenie trybu pełnoekranowego"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Opuszczenie trybu pełnoekranowego"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr "Przełączenie wyświetlania czasu odtwarzania/trwania w menu ekranowym"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr "Wyświetlenie nazwy pliku w menu ekranowym"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr "Wyświetlenie postępu, czasu odtwarzania i trwania w menu ekranowym"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr "Przejście 5 sekund wstecz/naprzód"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr "Dokładne przejście 1 sekundę wstecz/naprzód"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr "Przejście 1 minutę wstecz/naprzód"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr "Dokładne przejście 5 sekund wstecz/naprzód"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr "Przejście do poprzedniego/następnego napisu dialogowego"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr "Przejście pojedynczą klatkę wstecz/naprzód"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr "Przejście do początku poprzedniego/następnego rozdziału"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr "Zmniejszenie/zwiększenie prędkości odtwarzania o 10%"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr "Dwukrotne zmniejszenie/zwiększenie aktualnej prędkości odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr "Przywrócenie zwykłej prędkości odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Przejście wstecz/naprzód na liście odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Usunięcie zaznaczonego elementu listy odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Zapisanie listy odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr "Ustalenie/wyczyszczenie punktów zapętlenia A-B"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr "Przełączenia zapętlonego odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Przełączenie wstrzymania odtwarzania"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Zakończenie działania"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr "Zapisanie aktualnego położenia i zakończenie działania"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr "Przełączenie ścieżki dźwiękowej"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Zmniejszenie/zwiększenie głośności"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr "Przełączenie wyciszenia dźwięku"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr "Dostosowanie opóźnienia dźwięku o +/- 0,1 s"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr "Przełączenie widoczności napisów"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr "Przełączenie ścieżki napisów"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr "Dostosowanie opóźnienia napisów o +/- 0,1 s"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr "Przełączenie zastępowania stylów napisów SSA/ASS"
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Przemieszczenie napisów w górę/dół"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr "Przełączenie tryby kompatybilności proporcji VSFilter"
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr "Przełączenie ścieżki wideo"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr "Zmniejszenie/zwiększenie zasięgu pan-and-scan"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Przechwycenie obrazu"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Przechwycenie obrazu bez napisów"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr "Przechwycenie obrazu wyświetlanego w oknie"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr "Ustalenie rozmiaru obrazu dwukrotnie mniejszego niż pierwotny"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr "Przywrócenie pierwotnego rozmiaru obrazu"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr "Ustalenie rozmiaru obrazu dwukrotnie większego niż pierwotny"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Dostosowanie kontrastu"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Dostosowanie jasności"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Dostosowanie gamma"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Dostosowanie nasycenia"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr "Przełączenie usuwania przeplotu"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr "Przełączenie proporcji obrazu"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Interfejs użytkownika"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Wideo"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Dźwięk"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Napisy dialogowe"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Odtwarzanie"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr "Przeszukiwanie"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Dodawanie pliku do listy odtwarzania"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Wybór pliku"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Dodawanie położenia do listy odtwarzania"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Otwieranie położenia"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Zapisywanie listy odtwarzania"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Wykorzystuje interfejs GTK do obsługi programu MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Piotr Sokół <psokol.l10n at gmail.com>, 2016"
diff --git a/po/pt_PT.po b/po/pt_PT.po
index 1feb02c..79ee7aa 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -3,9 +3,9 @@
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
 msgid ""
 msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-08-16 23:25+0700\n"
+"Project-Id-Version: gnome-mpv 0.11\n"
+"Report-Msgid-Bugs-To: https://github.com/gnome-mpv/gnome-mpv/issues\n"
+"POT-Creation-Date: 2017-06-04 19:07+0700\n"
 "PO-Revision-Date: 2016-11-03 05:23-0400\n"
 "Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
 "Language-Team: Portuguese\n"
@@ -16,91 +16,92 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Ativar ou desativar tema escuro"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Ativar ou desativar decorações do lado do cliente"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "Se deve ou não fazer diálogo de seleção lembrar ultima pasta acedida"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Opções de mpv adicionais"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Localização do ficheiro de configuração mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "Carregar ou não o ficheiro de configuração mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Localização do ficheiro input mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "Carregar ou não ficheiro input mpv"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Largura da janela"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Altura da janela"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Volume da aplicação"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Largura da lista de reprodução"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Mostrar ou não lista de reprodução"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "URI da última pasta acedida"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "Se as configurações já foi migrado da versão anterior"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "Interface GTK+ para mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -115,594 +116,614 @@ msgstr ""
 "uma opção para desativar decorações do lado do cliente (CSD) para melhor "
 "compatibilidade com os sistemas não-GNOME."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Características:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "Arrastar e soltar lista de reprodução"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "A carregar ficheiros de configuração mpv externos"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "Interface MPRIS2 D-Bus"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Janela principal mostra a aplicação em ação"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "Janela principal com CSD desativada"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "Janela principal com lista de reprodução aberta"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "Interface GTK+ para mpv"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Adicionar ficheiro a lista de reprodução"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Abrir Ficheiro"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Abrir"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Cancelar"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Abrir Localização"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Guardar Lista de Reprodução"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Gravar"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
-"A ativação ou desativação decorações do lado do cliente requer reiniciar %s "
-"para ter efeito."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "A carregar Externo…"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "Uma interface GTK para MPV"
 
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Bruno Guerreiro"
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "A reproduzir"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr ""
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr ""
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr ""
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Erro"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Reproduzir"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Parar"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Avançar"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Recuar"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Próximo capítulo"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Capítulo anterior"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Alternar ecrã completo"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Pausa"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Erro"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Abrir"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Nenhum"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Desconhecido"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Abrir Externo…"
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Ficheiro"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Abrir _Localização"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "_Guardar Lista de Reprodução"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Sair"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Editar"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Preferências"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "_Faixa de vídeo"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "_Faixa de áudio"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "Faixa de legendas"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Ver"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr ""
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Alternar Lista de Reprodução"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Ecrã completo"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Tamanho Normal"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "_Duplo Tamanho"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Metade do tamanho"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Ajuda"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr ""
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_Sobre"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "A reprodução foi terminada de forma anormal. Motivo: %s."
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Falha ao aplicar uma ou mais opções de MPV."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Localização:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Adicionar…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Ciclo"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Lista de reprodução"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Abrir"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Cancelar"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Scripts Lua"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Falha ao copiar ficheiro de '%s' para '%s'. Motivo: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Nenhum script lua encontrado"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Remover"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Tem certeza que deseja remover este script? Essa ação não pode ser desfeita."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Falha ao excluir ficheiro '%s'. Motivo: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Interface de Utilizador<b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Ativar decorações do lado do cliente"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Ativar tema escuro"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Lembrar localizações dos últimos ficheiros"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Configuração do MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Carregar ficheiro de configuração do MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "Ficheiro de configuração do MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Teclas de atalho</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Carregar ficheiro input do MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Ficheiro input do MPV:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Outras</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Opções extra do MPV:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Geral"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Scripts Lua"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Gravar"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Preferências"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Abrir ficheiro"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Abrir localização"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Mostrar dialogo de preferências"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Alternar lista de reprodução"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Alternar modo ecrã completo"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Deixa modo ecrã completo"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Remover item de lista de reprodução selecionada"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Guardar lista de reprodução"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Sair"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr ""
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Adicionar ficheiro a lista de reprodução"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Abrir Ficheiro"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr ""
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Abrir Localização"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Guardar Lista de Reprodução"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "Uma interface GTK para MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Bruno Guerreiro"
diff --git a/po/ro.po b/po/ro.po
index 3057ef4..cae5aab 100644
--- a/po/ro.po
+++ b/po/ro.po
@@ -7,9 +7,9 @@
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
 msgid ""
 msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-08-16 23:25+0700\n"
+"Project-Id-Version: gnome-mpv 0.11\n"
+"Report-Msgid-Bugs-To: https://github.com/gnome-mpv/gnome-mpv/issues\n"
+"POT-Creation-Date: 2017-02-19 22:47+0700\n"
 "PO-Revision-Date: 2016-11-03 05:24-0400\n"
 "Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
 "Language-Team: Romanian Translations\n"
@@ -20,91 +20,91 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr ""
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:367
 msgid "Allow multiple instances"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:245
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr ""
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -113,593 +113,586 @@ msgid ""
 "decorations (CSD) for better compatibility with non-GNOME systems."
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr ""
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
+msgstr ""
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
+#: src/gmpv_actionctl.c:252
+#, c-format
+msgid ""
+"Enabling or disabling client-side decorations requires restarting %s to take"
+" effect."
 msgstr ""
+"Activarea sau dezactivarea decorațiilor ferestrelor (CSD) necesită "
+"repornirea %s."
 
-#: ../src/gmpv_actionctl.c:101
+#: src/gmpv_actionctl.c:291
 msgid "Add File to Playlist"
 msgstr "Adaugă un fișier Listei de Redare"
 
-#: ../src/gmpv_actionctl.c:102
+#: src/gmpv_actionctl.c:292
 msgid "Open File"
 msgstr "Deschide Fișier"
 
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Deschide"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Anulează"
-
-#: ../src/gmpv_actionctl.c:206
+#: src/gmpv_actionctl.c:325
 msgid "Add Location to Playlist"
 msgstr ""
 
-#: ../src/gmpv_actionctl.c:207
+#: src/gmpv_actionctl.c:326
 msgid "Open Location"
 msgstr "Deschide Adresa"
 
-#: ../src/gmpv_actionctl.c:296
+#: src/gmpv_actionctl.c:405
 msgid "Save Playlist"
 msgstr "Salvează Lista de Redare"
 
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Salvează"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
+#: src/gmpv_actionctl.c:433 src/gmpv_application.c:822
+msgid "Error"
 msgstr ""
-"Activarea sau dezactivarea decorațiilor ferestrelor (CSD) necesită "
-"repornirea %s."
 
-#: ../src/gmpv_actionctl.c:504
+#: src/gmpv_actionctl.c:528
 msgid "Load External…"
 msgstr ""
 
-#: ../src/gmpv_actionctl.c:605
+#: src/gmpv_actionctl.c:620
 msgid "A GTK frontend for MPV"
 msgstr "O interfață GTK pentru MPV"
 
-#: ../src/gmpv_actionctl.c:615
+#: src/gmpv_actionctl.c:630
 msgid "translator-credits"
 msgstr "Robert Datcu"
 
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:963
 msgid "Playing"
 msgstr ""
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:1081
 msgid "Show release version"
 msgstr ""
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:1089
 msgid "Enqueue"
 msgstr ""
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:1097
 msgid "Don't connect to an already-running instance"
 msgstr ""
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr ""
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:192 src/gmpv_control_box.c:365
 msgid "Play"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:193
 msgid "Stop"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:194
 msgid "Forward"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:195
 msgid "Rewind"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:196
 msgid "Next Chapter"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:197
 msgid "Previous Chapter"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:198 src/gmpv_header_bar.c:93
 msgid "Toggle Fullscreen"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:365
 msgid "Pause"
 msgstr ""
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_menu.c:56
 msgid "None"
 msgstr ""
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:71
 msgid "Unknown"
 msgstr ""
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:106
 msgid "_Load External…"
 msgstr ""
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:192
 msgid "_File"
 msgstr "_Fișier"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:193 src/gmpv_menu.c:257 src/gmpv_open_loc_dialog.c:85
+msgid "_Open"
+msgstr "_Deschide"
+
+#: src/gmpv_menu.c:194 src/gmpv_menu.c:258
 msgid "Open _Location"
 msgstr "_Deschide Adresa"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:195 src/gmpv_menu.c:235
 msgid "_Save Playlist"
 msgstr "_Salvează Lista Redare"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:196 src/gmpv_menu.c:272
 msgid "_Quit"
 msgstr "Î_nchide"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:197
 msgid "_Edit"
 msgstr "_Modifică"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:198 src/gmpv_menu.c:268
 msgid "_Preferences"
 msgstr "_Preferințe"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:199 src/gmpv_menu.c:237
 msgid "_Video Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:200 src/gmpv_menu.c:238
 msgid "_Audio Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:201 src/gmpv_menu.c:239
 msgid "S_ubtitle Track"
 msgstr ""
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:202
 msgid "_View"
 msgstr "_Vizualizare"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:203 src/gmpv_menu.c:232
 msgid "_Toggle Controls"
 msgstr ""
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:204 src/gmpv_menu.c:234
 msgid "_Toggle Playlist"
 msgstr "_Afișează Lista Redare"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:205
 msgid "_Fullscreen"
 msgstr "_Tot ecranul"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:206 src/gmpv_menu.c:241
 msgid "_Normal Size"
 msgstr "_Dimensiune Normală"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:207 src/gmpv_menu.c:242
 msgid "_Double Size"
 msgstr "_Dimensiune Dublă"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:208 src/gmpv_menu.c:243
 msgid "_Half Size"
 msgstr "_Dimensiune Înjumătățită"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:209
 msgid "_Help"
 msgstr "_Ajutor"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:210 src/gmpv_menu.c:270
 msgid "_Keyboard Shortcuts"
 msgstr ""
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:211 src/gmpv_menu.c:271
 msgid "_About"
 msgstr "_Despre"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:256
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr ""
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:917
 msgid "Failed to apply one or more MPV options."
 msgstr ""
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_loc_dialog.c:79
 msgid "Location:"
 msgstr "Adresă:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_open_loc_dialog.c:83 src/gmpv_pref_dialog.c:410
+msgid "_Cancel"
+msgstr "_Anulează"
+
+#: src/gmpv_playlist_widget.c:508
 msgid "_Add…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:512
 msgid "Add _Location…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:514
 msgid "Loop"
 msgstr "Buclă"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:612
 msgid "Playlist"
 msgstr "Listă de redare"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
+#: src/gmpv_plugins_manager.c:149 src/gmpv_pref_dialog.c:204
+msgid "All Files"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:407
+msgid "Lua Scripts"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:209
+msgid "Configuration Files"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:331
 msgid "<b>User Interface</b>"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:334
 msgid "Enable client-side decorations"
 msgstr "Activează decorațiile ferestrelor (CSD)"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:337
 msgid "Enable dark theme"
 msgstr "Activează tema întunecată"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:340
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:343
 msgid "Remember last file's location"
 msgstr "Ține minte adresa ultimului fișier"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:346
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Configurare MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:349
 msgid "Load MPV configuration file"
 msgstr "Încarcă fișierul de configurare MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:352
 msgid "MPV configuration file:"
 msgstr "fișier configurare MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:355
 msgid "<b>Keybindings</b>"
 msgstr "<b>Combinații Taste</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:358
 msgid "Load MPV input configuration file"
 msgstr "Încarcă fișierul MPV de combinații taste"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:361
 msgid "MPV input configuration file:"
 msgstr "fișier MPV configurare combinații taste:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:364
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Diverse</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:370
 msgid "Extra MPV options:"
 msgstr "Extraopțiuni MPV:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:403
 msgid "General"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr ""
+#: src/gmpv_pref_dialog.c:412
+msgid "_Save"
+msgstr "_Salvează"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:429
 msgid "Preferences"
 msgstr "Preferințe"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
 msgid "Show preferences dialog"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:59
 msgid "Toggle controls"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:60
 msgid "Toggle playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle fullscreen mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:62
 msgid "Leave fullscreen mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:64
 msgid "Show filename on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:65
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:68
 msgid "Seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:69
 msgid "Exact seek backward/forward 1 second"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 1 minute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:73
 msgid "Step backward/forward a single frame"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:77
 msgid "Decrease/increase playback speed by 10%"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:78
 msgid "Halve/double current playback speed"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:79
 msgid "Reset playback speed to normal"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:80
 msgid "Go backward/forward in the playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:81
 msgid "Remove selected playlist item"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:82
 msgid "Save playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:83
 msgid "Set/clear A-B loop points"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:84
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:85
 msgid "Pause or unpause"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:86
 msgid "Quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:87
 msgid "Save current playback position and quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:90
 msgid "Cycle through audio tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:91 src/gmpv_shortcuts_window.c:92
 msgid "Decrease/increase volume"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:93
 msgid "Mute or unmute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:94
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:97
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:98
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:99
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:100
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:101
 msgid "Move subtitles up/down"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:105
 msgid "Cycle through video tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:106
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:107
 msgid "Take a screenshot"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:108
 msgid "Take a screenshot, without subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot, as the window shows it"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:110
 msgid "Resize video to half its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:111
 msgid "Resize video to its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:113
 msgid "Adjust contrast"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:114
 msgid "Adjust brightness"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust gamma"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust saturation"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:117
 msgid "Activate or deactivate deinterlacer"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:118
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:121
 msgid "User Interface"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:122
 msgid "Video"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:123
 msgid "Audio"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:124
 msgid "Subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:125
 msgid "Playback"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:126
 msgid "Seeking"
 msgstr ""
diff --git a/po/ru.po b/po/ru.po
index cea1c0b..e73d19e 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,12 +1,13 @@
 # Maxim Orlov <murmansksity at gmail.com>, 2016. #zanata
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# Maxim Orlov <murmansksity at gmail.com>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: 0.6\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-01-04 00:00+0700\n"
-"PO-Revision-Date: 2016-11-03 05:23-0400\n"
-"Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
+"PO-Revision-Date: 2017-06-01 12:32-0400\n"
+"Last-Translator: Maxim Orlov <murmansksity at gmail.com>\n"
 "Language-Team: Russian\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -15,91 +16,92 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "Включить или отключить тёмную тему"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "Включить или отключить декорирование на стороне клиента"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "Запомнить или нет последнее расположение в диалоге открытия файла"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "Перейти к опциям MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "Путь к файлу конфигурации MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "Загрузить файл конфигурации MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "Путь к файлу конфигурации ввода MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "Загрузить файл конфигурации ввода MPV"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "Ширина окна"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "Высота окна"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "Громкость плеера"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "Ширина списка воспроизведения"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "Показать или скрыть список воспроизведения"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "Адрес последнего открытого файла"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "Перенос (миграция) пользовательских настроек из предыдущей версии"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr "Разрешить запуск нескольких экземпляров"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr "Показать или не показывать элементы управления"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "GTK+ интерфейс для MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -113,594 +115,615 @@ msgstr ""
 "предлагает опцию, чтобы отключить декорирование на стороне клиента (CSD) для"
 " лучшей совместимости с системами, отличными от GNOME."
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "Возможности:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "Поддержка Drag'n'Drop"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "Загрузка внешних конфигурационных файлов MPV"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "Интерфейс MPRIS2 D-Bus"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "Главное окно, показывающее приложение в действии"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "Главное окно с отключённым CSD"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "Главное окно с открытым списком воспроизведения"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "GTK+ интерфейс для MPV"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
+msgstr "gnome-mpv"
 
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "Добавить файл в список воспроизведения"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "Открыть файл"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "_Открыть"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "_Отмена"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr "Добавить адрес в список воспроизведения"
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "Открыть адрес"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "Сохранить список воспроизведения"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "_Сохранить"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr ""
-"Чтобы изменения вступили в силу, необходимо перезапустить приложение %s."
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "Загрузить внешние…"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "GTK интерфейс для MPV"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
-msgstr "Maxim Orlov <murmansksity at gmail.com>, 2016."
-
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "Воспроизводится"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr "Показать версию релиза"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr "Поставить в очередь"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr "Не подключаться к уже работающему экземпляру"
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "Ошибка"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "Воспроизвести"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "Остановить"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "Перемотать вперёд"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "Перемотать назад"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "Следующая глава"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "Предыдущая глава"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "Переход в полноэкранный режим и обратно"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "Приостановить"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Ошибка"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Отмена"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Открыть"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr "Все файлы"
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr "Медиафайлы"
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr "Аудиофайлы"
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr "Видеофайлы"
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr "Файлы изображений"
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr "Файлы субтитров"
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "Ничего"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "Неизвестный"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "_Загрузить внешние…"
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "_Файл"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "Открыть _адрес"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "_Сохранить список воспроизведения"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "_Выйти"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "_Правка"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "_Настройки"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "_Видео дорожка"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "_Аудио дорожка"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "Дорожка с_убтитров"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "_Вид"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr "_Показать/Скрыть элементы управления"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "_Показать/Скрыть список воспроизведения"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "_Полноэкранный режим"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "_Нормальный размер"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "_Двойной размер"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "_Половинный размер"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "_Справка"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr "Комбинации клавиш"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "_О программе"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "Воспроизведение было прекращено. Причина: %s."
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "Не удалось применить одну или несколько опций MPV."
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "Адрес:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "_Добавить…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr "Добавить _Адрес…"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "Повторить"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "Список воспроизведения"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr "Добавить Lua скрипт"
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr "Открыть"
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr "Отмена"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua скрипты"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr "Не удалось скопировать файл из '%s' в '%s'. Причина: %s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr "Пусто"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr "Удалить"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 "Вы уверены, что хотите удалить этот скрипт? Это действие не может быть "
 "отменено."
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr "Не удалось удалить файл '%s'. Причина: %s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr "<b>Пользовательский интерфейс</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "Включить декорирование на стороне клиента"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "Использовать тёмный вариант темы"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "Запомнить последнее расположение файла(ов)"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>Конфигурация MPV</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "Загрузить файл конфигурации MPV"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "Файл конфигурации MPV:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>Комбинации клавиш</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "Загрузить файл конфигурации ввода MPV"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "Файл конфигурации ввода MPV:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Разное</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "Дополнительные опции MPV:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr "Общие"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr "Lua скрипты"
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Сохранить"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "Настройки"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "Открыть файл"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "Открыть адрес"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr "Добавить файл в список воспроизведения"
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "Показать диалог настройки"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr "Показать/Скрыть элементы управления"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "Показать/Скрыть список воспроизведения"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "Перейти в полноэкранный режим"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "Покинуть полноэкранный режим"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr "Показать время воспроизведения/продолжительность"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr "Показать имя файла"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr "Показать прогресс, пройденное время и продолжительность"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr "Переход назад/вперёд на 5 секунд"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr "Точный переход назад/вперёд на 1 секунду"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr "Переход назад/вперёд на 1 минуту"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr "Точный переход назад/вперёд на 5 секунд"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr "Переход к предыдущему/следующему субтитру"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr "Шаг назад/вперёд на один кадр"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr "Переход к предыдущей/следующей главе"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr "Уменьшить/увеличить скорость воспроизведения на 10%"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr "Сбросить скорость воспроизведения на нормальную"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr "Назад/вперёд по списку воспроизведения"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "Удалить выбранный файл из списка воспроизведения"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "Сохранить список воспроизведения"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr "Установить/очистить A-B точки цикла"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr "Приостановить или возобновить"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "Выйти"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr "Сохранить текущую позицию воспроизведения и выйти"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr "Циклически доступные аудио дорожки"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr "Уменьшить/увеличить громкость"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr "Отключить или включить звук"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr "Изменить задержку аудио на + / - 0,1 секунды"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr "Переключить видимости субтитров"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr "Циклически переключить доступные субтитры"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr "Изменить задержку субтитров на + / - 0,1 секунды"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr "Переместить субтитры вверх/вниз"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr "Циклически доступные видео дорожки"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr "Уменьшает/увеличивает диапазон панорамирования и сканирования"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr "Сделать скриншот"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr "Сделать скриншот, без субтитров"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr "Сделать скриншот, с субтитрами и OSD, масштабированием"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr "Изменить размер видео до половины своего исходного размера"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr "Изменить размер видео до исходного размера"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr "Регулировка контрастности"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr "Регулировка яркости"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr "Регулировка гаммы"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr "Регулировка насыщенности"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr "Включить или отключить деинтерлейсинг"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr "Цикл коррекции соотношения сторон"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr "Пользовательский интерфейс"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr "Видео"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr "Аудио"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr "Субтитры"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr "Воспроизведение"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr "Переход"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Добавить файл в список воспроизведения"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Открыть файл"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Добавить адрес в список воспроизведения"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Открыть адрес"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr "Загрузить звуковую дорожку…"
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr "Загрузить субтитры…"
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Сохранить список воспроизведения"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "GTK интерфейс для MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Maxim Orlov <murmansksity at gmail.com>, 2016."
diff --git a/po/sr_RS.po b/po/sr_RS.po
new file mode 100644
index 0000000..670a63a
--- /dev/null
+++ b/po/sr_RS.po
@@ -0,0 +1,729 @@
+# leipero <lei.pero at gmail.com>, 2017. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: gnome-mpv 0.11\n"
+"Report-Msgid-Bugs-To: https://github.com/gnome-mpv/gnome-mpv/issues\n"
+"POT-Creation-Date: 2017-06-04 19:07+0700\n"
+"PO-Revision-Date: 2017-02-23 05:55-0500\n"
+"Last-Translator: leipero <lei.pero at gmail.com>\n"
+"Language-Team: Serbian (Cyrillic)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sr-Cyrl\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+"X-Generator: Zanata 3.9.6\n"
+
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
+msgid "Enable or disable dark theme"
+msgstr "Омогући или онемогући тамну тему"
+
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
+msgid "Enable or disable client-side decorations"
+msgstr "Омогући или онемогући украсе клијента"
+
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
+msgid ""
+"Whether or not to make file chooser dialog remember last folder accessed"
+msgstr ""
+"Дозвољава дијалогу бирача датотека да упамти последње приступљен "
+"директоријум"
+
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
+msgid "Options to pass to mpv"
+msgstr "Опције које треба пренети на mpv"
+
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
+msgid "Path to mpv configuration file"
+msgstr "Путања до mpv конфигурационе датотеке"
+
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
+msgid "Load or don't load mpv configuration file"
+msgstr "Дозвољава учитавање mpv конфигурационе датотеке"
+
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
+msgid "Path to mpv input configuration file"
+msgstr "Путања до mpv конфигурационе датотеке уноса"
+
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
+msgid "Load or don't load mpv input configuration file"
+msgstr "Дозвољава учитавање mpv конфигурационе датотеке уноса"
+
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
+msgid "Width of the window"
+msgstr "Ширина прозора"
+
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
+msgid "Height of the window"
+msgstr "Висина прозора"
+
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
+msgid "Volume of player"
+msgstr "Јачина звука"
+
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
+msgid "Width of the playlist"
+msgstr "Ширина листе пуштања"
+
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
+msgid "Show or not show the playlist"
+msgstr "Прикажи листу пуштања"
+
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
+msgid "URI of the last folder accessed"
+msgstr "URI последње приступљеног директоријума"
+
+#: data/io.github.GnomeMpv.gschema.xml:10
+msgid ""
+"Whether the settings has already been migrated from the previous version"
+msgstr "Да ли су поставке већ пренете из претходне верзије"
+
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr "Користи пливајуће контроле у режиму прозора"
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
+msgid "Allow multiple instances"
+msgstr "Дозволи вишеструке примерке"
+
+#: data/io.github.GnomeMpv.gschema.xml:105
+msgid "Show or not show the controls"
+msgstr "Дозвољава приказ контрола"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "GTK+ прочеље за mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
+msgid ""
+"GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
+"player capable of playing virtually all video and audio formats. The design "
+"of GNOME MPV is based on GNOME HIG, though it is not dependent on any GNOME "
+"libraries. GNOME MPV also offers an option to disable client-side "
+"decorations (CSD) for better compatibility with non-GNOME systems."
+msgstr ""
+"GNOME MPV је једноставно GTK+ прочеље за mpv, који је веома моћан приказивач"
+" способан да пусти практично све видео и аудио формате. Дизајн GNOME MPV-а "
+"је базиран на GNOME HIG, али је независтан од било које GNOME библиотеке. "
+"GNOME MPV такође нуди опцију онемогућавања декорација клијента (CSD) због "
+"компатибилности с другим окружењима."
+
+#: data/io.github.GnomeMpv.appdata.xml.in:18
+msgid "Features:"
+msgstr "Могућности:"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:20
+msgid "Drag and drop playlist"
+msgstr "Превуци и отпусти листу пуштања"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:21
+msgid "Loading external mpv configuration files"
+msgstr "Учитавам спољне mpv конфигурационе датотеке"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:22
+msgid "MPRIS2 D-Bus interface"
+msgstr "MPRIS2 D-Bus сучеље"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:32
+msgid "The main window with CSD disabled"
+msgstr "Главни прозор са онемогућеним CSD-ом"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:36
+msgid "The main window with playlist open"
+msgstr "Главни прозор са отвореном листом пуштања"
+
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
+msgstr ""
+
+#: src/gmpv_application.c:464
+msgid "Playing"
+msgstr "Репродукција"
+
+#: src/gmpv_application.c:532
+msgid "Show release version"
+msgstr "Прикажи верзију издања"
+
+#: src/gmpv_application.c:540
+msgid "Enqueue"
+msgstr "Нанижи"
+
+#: src/gmpv_application.c:548
+msgid "Don't connect to an already-running instance"
+msgstr "Не повезуј на већ покренут примерак"
+
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
+msgid "Play"
+msgstr "Пусти"
+
+#: src/gmpv_control_box.c:274
+msgid "Stop"
+msgstr "Заустави"
+
+#: src/gmpv_control_box.c:277
+msgid "Forward"
+msgstr "Напред"
+
+#: src/gmpv_control_box.c:280
+msgid "Rewind"
+msgstr "Назад"
+
+#: src/gmpv_control_box.c:283
+msgid "Next Chapter"
+msgstr "Следеће Поглавље"
+
+#: src/gmpv_control_box.c:286
+msgid "Previous Chapter"
+msgstr "Претходно Поглавље"
+
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
+msgid "Toggle Fullscreen"
+msgstr "Цео Екран"
+
+#: src/gmpv_control_box.c:422
+msgid "Pause"
+msgstr "Паузирај"
+
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Грешка"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Откажи"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Отвори"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr "Све Датотеке"
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
+msgid "None"
+msgstr "Ниједан"
+
+#. For simplicity, also dup the default string used when the
+#. * track has no title.
+#: src/gmpv_menu.c:117
+msgid "Unknown"
+msgstr "Непознато"
+
+#: src/gmpv_menu.c:150
+msgid "_Load External…"
+msgstr "_Учитај Спољне..."
+
+#: src/gmpv_menu.c:243
+msgid "_File"
+msgstr "_Датотека"
+
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
+msgid "Open _Location"
+msgstr "Отвори_Локацију"
+
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
+msgid "_Save Playlist"
+msgstr "_Сачувај Листу Пуштања"
+
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
+msgid "_Quit"
+msgstr "_Напусти"
+
+#: src/gmpv_menu.c:248
+msgid "_Edit"
+msgstr "_Уреди"
+
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
+msgid "_Preferences"
+msgstr "_Поставке"
+
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
+msgid "_Video Track"
+msgstr "_Видео Снимак"
+
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
+msgid "_Audio Track"
+msgstr "_Аудио Снимак"
+
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
+msgid "S_ubtitle Track"
+msgstr "_Превод"
+
+#: src/gmpv_menu.c:253
+msgid "_View"
+msgstr "_Преглед"
+
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
+msgid "_Toggle Controls"
+msgstr "_Прикажи Контроле"
+
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
+msgid "_Toggle Playlist"
+msgstr "_Прикажи Листу Пуштања"
+
+#: src/gmpv_menu.c:256
+msgid "_Fullscreen"
+msgstr "_Цео Екран"
+
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
+msgid "_Normal Size"
+msgstr "_Нормална Величина"
+
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
+msgid "_Double Size"
+msgstr "_Двострука Величина"
+
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
+msgid "_Half Size"
+msgstr "_Упола Величине"
+
+#: src/gmpv_menu.c:260
+msgid "_Help"
+msgstr "_Помоћ"
+
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
+msgid "_Keyboard Shortcuts"
+msgstr "_Пречице Тастатуре"
+
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
+msgid "_About"
+msgstr "_О Нама"
+
+#: src/gmpv_mpv.c:408
+#, fuzzy, c-format
+msgid "Playback was terminated abnormally. Reason: %s."
+msgstr "Репродукција је неправилно окончана. Разлог: %s."
+
+#: src/gmpv_mpv.c:1047
+msgid "Failed to apply one or more MPV options."
+msgstr "Неуспешна примена једне или више MPV опција."
+
+#: src/gmpv_open_location_dialog.c:122
+msgid "Location:"
+msgstr "Локација:"
+
+#: src/gmpv_playlist_widget.c:531
+msgid "_Add…"
+msgstr "_Додај..."
+
+#: src/gmpv_playlist_widget.c:535
+msgid "Add _Location…"
+msgstr "Додај_Локацију..."
+
+#: src/gmpv_playlist_widget.c:537
+msgid "Loop"
+msgstr "Понављај"
+
+#: src/gmpv_playlist_widget.c:650
+msgid "Playlist"
+msgstr "Листа Пуштања"
+
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
+msgid "Add Lua Script"
+msgstr "Додај Lua Скрипту"
+
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua Скрипте"
+
+#: src/gmpv_plugins_manager.c:300
+#, fuzzy, c-format
+msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
+msgstr "Неуспешно копирање датотеке из '%s' у '%s'. Разлог: %s"
+
+#: src/gmpv_plugins_manager.c:349
+msgid "No Lua script found"
+msgstr "Lua скрипта није нађена"
+
+#: src/gmpv_plugins_manager_item.c:69
+msgid "Remove"
+msgstr "Уклони"
+
+#: src/gmpv_plugins_manager_item.c:163
+msgid ""
+"Are you sure you want to remove this script? This action cannot be undone."
+msgstr ""
+"Сигурно желите да уклоните ову скрипту? Овај поступак не може бити опозван."
+
+#: src/gmpv_plugins_manager_item.c:184
+#, fuzzy, c-format
+msgid "Failed to delete file '%s'. Reason: %s"
+msgstr "Неуспешно брисање датотеке '%s'. Разлог: %s"
+
+#: src/gmpv_pref_dialog.c:286
+msgid "<b>User Interface</b>"
+msgstr "<b>Корисничко Сучеље</b>"
+
+#: src/gmpv_pref_dialog.c:289
+msgid "Enable client-side decorations"
+msgstr "Омогући украсе клијента"
+
+#: src/gmpv_pref_dialog.c:292
+msgid "Enable dark theme"
+msgstr "Омогући тамну тему"
+
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr "Користи пливајуће контроле у режиму прозора"
+
+#: src/gmpv_pref_dialog.c:298
+msgid "Remember last file's location"
+msgstr "Упамти локацију последње датотеке"
+
+#: src/gmpv_pref_dialog.c:301
+msgid "<b>MPV Configuration</b>"
+msgstr "<b>MPV Конфигурација</b>"
+
+#: src/gmpv_pref_dialog.c:304
+msgid "Load MPV configuration file"
+msgstr "Учитај MPV конфигурациону датотеку"
+
+#: src/gmpv_pref_dialog.c:307
+msgid "MPV configuration file:"
+msgstr "MPV конфигурациона датотека:"
+
+#: src/gmpv_pref_dialog.c:310
+msgid "<b>Keybindings</b>"
+msgstr "<b>Поставке Уноса</b>"
+
+#: src/gmpv_pref_dialog.c:313
+msgid "Load MPV input configuration file"
+msgstr "Учитај MPV конфигурациону датотеку уноса"
+
+#: src/gmpv_pref_dialog.c:316
+msgid "MPV input configuration file:"
+msgstr "MPV конфигурациона датотека уноса:"
+
+#: src/gmpv_pref_dialog.c:319
+msgid "<b>Miscellaneous</b>"
+msgstr "<b>Остало</b>"
+
+#: src/gmpv_pref_dialog.c:325
+msgid "Extra MPV options:"
+msgstr "Додатне MPV опције:"
+
+#: src/gmpv_pref_dialog.c:358
+msgid "General"
+msgstr "Опште"
+
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Сачувај"
+
+#: src/gmpv_pref_dialog.c:384
+msgid "Preferences"
+msgstr "Поставке"
+
+#: src/gmpv_shortcuts_window.c:56
+msgid "Open file"
+msgstr "Отвори датотеку"
+
+#: src/gmpv_shortcuts_window.c:57
+msgid "Open location"
+msgstr "Отвори локацију"
+
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
+msgid "Show preferences dialog"
+msgstr "Прикажи дијалог поставки"
+
+#: src/gmpv_shortcuts_window.c:61
+msgid "Toggle controls"
+msgstr "Прикажи контроле"
+
+#: src/gmpv_shortcuts_window.c:62
+msgid "Toggle playlist"
+msgstr "Прикажи листу пуштања"
+
+#: src/gmpv_shortcuts_window.c:63
+msgid "Toggle fullscreen mode"
+msgstr "Прикажи у режиму целог екрана"
+
+#: src/gmpv_shortcuts_window.c:64
+msgid "Leave fullscreen mode"
+msgstr "Напусти режим целог екрана"
+
+#: src/gmpv_shortcuts_window.c:65
+msgid "Toggle OSD states between normal and playback time/duration"
+msgstr "Промени OSD приказ између нормалног и време пуштања/дужина"
+
+#: src/gmpv_shortcuts_window.c:66
+msgid "Show filename on the OSD"
+msgstr "Прикажи име датотеке у OSD"
+
+#: src/gmpv_shortcuts_window.c:67
+msgid "Show progress, elapsed time, and duration on the OSD"
+msgstr "Прикажи напредак, протекло време и дужину на OSD"
+
+#: src/gmpv_shortcuts_window.c:70
+msgid "Seek backward/forward 5 seconds"
+msgstr "Пребаци 5 секунди уназад/унапред"
+
+#: src/gmpv_shortcuts_window.c:71
+msgid "Exact seek backward/forward 1 second"
+msgstr "Пребаци тачно 1 секунд уназад/унапред"
+
+#: src/gmpv_shortcuts_window.c:72
+msgid "Seek backward/forward 1 minute"
+msgstr "Пребаци 1 минут уназад/унапред"
+
+#: src/gmpv_shortcuts_window.c:73
+msgid "Exact seek backward/forward 5 seconds"
+msgstr "Пребаци тачно 5 секунди уназад/унапред"
+
+#: src/gmpv_shortcuts_window.c:74
+msgid "Seek to previous/next subtitle"
+msgstr "Пребаци на претходни/следећи поднатпис"
+
+#: src/gmpv_shortcuts_window.c:75
+msgid "Step backward/forward a single frame"
+msgstr "Корак за једну слику уназад/унапред"
+
+#: src/gmpv_shortcuts_window.c:76
+msgid "Seek to the beginning of the previous/next chapter"
+msgstr "Пребаци на почетак претходног/следећег поглавља"
+
+#: src/gmpv_shortcuts_window.c:79
+msgid "Decrease/increase playback speed by 10%"
+msgstr "Успори/убрзај репродукцију за 10%"
+
+#: src/gmpv_shortcuts_window.c:80
+msgid "Halve/double current playback speed"
+msgstr "Преполови/удвостручи тренутну брзину репродукције"
+
+#: src/gmpv_shortcuts_window.c:81
+msgid "Reset playback speed to normal"
+msgstr "Поврати нормалну брзину репродукције"
+
+#: src/gmpv_shortcuts_window.c:82
+msgid "Go backward/forward in the playlist"
+msgstr "Иди уназад/унапред у листи пуштања"
+
+#: src/gmpv_shortcuts_window.c:83
+msgid "Remove selected playlist item"
+msgstr "Избаци означену ставку из листе пуштања"
+
+#: src/gmpv_shortcuts_window.c:84
+msgid "Save playlist"
+msgstr "Сачувај листу пуштања"
+
+#: src/gmpv_shortcuts_window.c:85
+msgid "Set/clear A-B loop points"
+msgstr "Постави/очисти A-B тачке понављања"
+
+#: src/gmpv_shortcuts_window.c:86
+msgid "Toggle infinite looping"
+msgstr "Укључи бесконачно понављање"
+
+#: src/gmpv_shortcuts_window.c:87
+msgid "Pause or unpause"
+msgstr "Паузирај или настави"
+
+#: src/gmpv_shortcuts_window.c:88
+msgid "Quit"
+msgstr "Напусти"
+
+#: src/gmpv_shortcuts_window.c:89
+msgid "Save current playback position and quit"
+msgstr "Сачувај тренутну позицију репродукције и напусти"
+
+#: src/gmpv_shortcuts_window.c:92
+msgid "Cycle through audio tracks"
+msgstr "Кружи кроз аудио снимке"
+
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
+msgid "Decrease/increase volume"
+msgstr "Смањи/појачај"
+
+#: src/gmpv_shortcuts_window.c:95
+msgid "Mute or unmute"
+msgstr "Искључи или укључи звук"
+
+#: src/gmpv_shortcuts_window.c:96
+msgid "Adjust audio delay by +/- 0.1 seconds"
+msgstr "Прилагоди кашњење звука за +/- 0.1 секунд"
+
+#: src/gmpv_shortcuts_window.c:99
+msgid "Toggle subtitle visibility"
+msgstr "Промени видљивост поднатписа"
+
+#: src/gmpv_shortcuts_window.c:100
+msgid "Cycle through available subtitles"
+msgstr "Кружи кроз доступне поднатписе"
+
+#: src/gmpv_shortcuts_window.c:101
+msgid "Adjust subtitle delay by +/- 0.1 seconds"
+msgstr "Прилагоди кашњење поднатписа за +/- 0.1 секунд"
+
+#: src/gmpv_shortcuts_window.c:102
+msgid "Toggle SSA/ASS subtitles style override"
+msgstr "Измени SSA/ASS стил поднатписа"
+
+#: src/gmpv_shortcuts_window.c:103
+msgid "Move subtitles up/down"
+msgstr "Помери поднатписе горе/доле"
+
+#: src/gmpv_shortcuts_window.c:104
+msgid "Toggle VSFilter aspect compatibility mode"
+msgstr "Измени VSFilter режим усклађености"
+
+#: src/gmpv_shortcuts_window.c:107
+msgid "Cycle through video tracks"
+msgstr "Кружи кроз видео снимке"
+
+#: src/gmpv_shortcuts_window.c:108
+#, fuzzy
+msgid "Decrease/increase pan-and-scan range"
+msgstr "Повећај/умањи опсег скенирања односа"
+
+#: src/gmpv_shortcuts_window.c:109
+msgid "Take a screenshot"
+msgstr "Направи снимак екрана"
+
+#: src/gmpv_shortcuts_window.c:110
+msgid "Take a screenshot, without subtitles"
+msgstr "Направи снимак екрана без поднатписа"
+
+#: src/gmpv_shortcuts_window.c:111
+msgid "Take a screenshot, as the window shows it"
+msgstr "Направи снимак екрана како га прозор приказује"
+
+#: src/gmpv_shortcuts_window.c:112
+msgid "Resize video to half its original size"
+msgstr "Преполови оригиналну величину видео снимка"
+
+#: src/gmpv_shortcuts_window.c:113
+msgid "Resize video to its original size"
+msgstr "Поврати оригиналну величину видео снимка"
+
+#: src/gmpv_shortcuts_window.c:114
+msgid "Resize video to double its original size"
+msgstr "Удвостручи оригиналну величину видео снимка"
+
+#: src/gmpv_shortcuts_window.c:115
+msgid "Adjust contrast"
+msgstr "Прилагоди контраст"
+
+#: src/gmpv_shortcuts_window.c:116
+msgid "Adjust brightness"
+msgstr "Прилагоди осветљеност"
+
+#: src/gmpv_shortcuts_window.c:117
+msgid "Adjust gamma"
+msgstr "Прилагоди гаму"
+
+#: src/gmpv_shortcuts_window.c:118
+msgid "Adjust saturation"
+msgstr "Прилагоди засићење"
+
+#: src/gmpv_shortcuts_window.c:119
+msgid "Activate or deactivate deinterlacer"
+msgstr "Омогући или онемогући преплитање"
+
+#: src/gmpv_shortcuts_window.c:120
+msgid "Cycle aspect ratio override"
+msgstr "Кружи кроз промену размере"
+
+#: src/gmpv_shortcuts_window.c:123
+msgid "User Interface"
+msgstr "Корисничко Сучеље"
+
+#: src/gmpv_shortcuts_window.c:124
+msgid "Video"
+msgstr "Видео"
+
+#: src/gmpv_shortcuts_window.c:125
+msgid "Audio"
+msgstr "Аудио"
+
+#: src/gmpv_shortcuts_window.c:126
+msgid "Subtitle"
+msgstr "Поднатпис"
+
+#: src/gmpv_shortcuts_window.c:127
+msgid "Playback"
+msgstr "Репродукција"
+
+#: src/gmpv_shortcuts_window.c:128
+msgid "Seeking"
+msgstr "Трагање"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Додај Датотеку у Листу Пуштања"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Отвори Датотеку"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Додај Локацију у Листу Пуштања"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Отвори Локацију"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Сачувај Листу Пуштања"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "GTK прочеље за MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Срђан С."
diff --git a/po/sr_RS at latin.po b/po/sr_RS at latin.po
new file mode 100644
index 0000000..5fa80cd
--- /dev/null
+++ b/po/sr_RS at latin.po
@@ -0,0 +1,729 @@
+# leipero <lei.pero at gmail.com>, 2017. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: gnome-mpv 0.11\n"
+"Report-Msgid-Bugs-To: https://github.com/gnome-mpv/gnome-mpv/issues\n"
+"POT-Creation-Date: 2017-06-04 19:07+0700\n"
+"PO-Revision-Date: 2017-02-23 05:54-0500\n"
+"Last-Translator: leipero <lei.pero at gmail.com>\n"
+"Language-Team: Serbian (Latin)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sr-Latn\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+"X-Generator: Zanata 3.9.6\n"
+
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
+msgid "Enable or disable dark theme"
+msgstr "Omogući ili onemogući tamnu temu"
+
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
+msgid "Enable or disable client-side decorations"
+msgstr "Omogući ili onemogući ukrase klijenta"
+
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
+msgid ""
+"Whether or not to make file chooser dialog remember last folder accessed"
+msgstr ""
+"Dozvoljava dijalogu birača datoteka da upamti poslednje pristupljen "
+"direktorijum"
+
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
+msgid "Options to pass to mpv"
+msgstr "Opcije koje treba preneti na mpv"
+
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
+msgid "Path to mpv configuration file"
+msgstr "Putanja do mpv konfiguracione datoteke"
+
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
+msgid "Load or don't load mpv configuration file"
+msgstr "Dozvoljava učitavanje mpv konfiguracione datoteke"
+
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
+msgid "Path to mpv input configuration file"
+msgstr "Putanja do mpv konfiguracione datoteke unosa"
+
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
+msgid "Load or don't load mpv input configuration file"
+msgstr "Dozvoljava učitavanje mpv konfiguracione datoteke unosa"
+
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
+msgid "Width of the window"
+msgstr "Širina prozora"
+
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
+msgid "Height of the window"
+msgstr "Visina prozora"
+
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
+msgid "Volume of player"
+msgstr "Jačina zvuka"
+
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
+msgid "Width of the playlist"
+msgstr "Širina liste puštanja"
+
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
+msgid "Show or not show the playlist"
+msgstr "Prikaži listu puštanja"
+
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
+msgid "URI of the last folder accessed"
+msgstr "URI poslednje pristupljenog direktorijuma"
+
+#: data/io.github.GnomeMpv.gschema.xml:10
+msgid ""
+"Whether the settings has already been migrated from the previous version"
+msgstr "Da li su postavke već prenete iz prethodne verzije"
+
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr "Koristiti plivajuće kontrole u režimu prozora"
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
+msgid "Allow multiple instances"
+msgstr "Dozvoli višestruke primerke"
+
+#: data/io.github.GnomeMpv.gschema.xml:105
+msgid "Show or not show the controls"
+msgstr "Dozvoljava prikaz kontrola"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "GTK+ pročelje za mpv"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
+msgid ""
+"GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
+"player capable of playing virtually all video and audio formats. The design "
+"of GNOME MPV is based on GNOME HIG, though it is not dependent on any GNOME "
+"libraries. GNOME MPV also offers an option to disable client-side "
+"decorations (CSD) for better compatibility with non-GNOME systems."
+msgstr ""
+"GNOME MPV je jednostavno GTK+ pročelje za mpv, koji je veoma moćan "
+"prikazivač sposoban da pusti praktično sve video i audio formate. Dizajn "
+"GNOME MPV-a je baziran na GNOME HIG, ali je nezavistan od bilo koje GNOME "
+"biblioteke. GNOME MPV takođe nudi opciju onemogućavanja dekoracija klijenta "
+"(CSD) zbog kompatibilnosti s drugim okruženjima."
+
+#: data/io.github.GnomeMpv.appdata.xml.in:18
+msgid "Features:"
+msgstr "Mogućnosti:"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:20
+msgid "Drag and drop playlist"
+msgstr "Prevuci i otpusti listu puštanja"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:21
+msgid "Loading external mpv configuration files"
+msgstr "Učitavam spoljne mpv konfiguracione datoteke"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:22
+msgid "MPRIS2 D-Bus interface"
+msgstr "MPRIS2 D-Bus sučelje"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:32
+msgid "The main window with CSD disabled"
+msgstr "Glavni prozor sa onemogućenim CSD-om"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:36
+msgid "The main window with playlist open"
+msgstr "Glavni prozor sa otvorenom listom puštanja"
+
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
+msgstr ""
+
+#: src/gmpv_application.c:464
+msgid "Playing"
+msgstr "Reprodukcija"
+
+#: src/gmpv_application.c:532
+msgid "Show release version"
+msgstr "Prikaži verziju izdanja"
+
+#: src/gmpv_application.c:540
+msgid "Enqueue"
+msgstr "Naniži"
+
+#: src/gmpv_application.c:548
+msgid "Don't connect to an already-running instance"
+msgstr "Ne povezuj na već pokrenut primerak"
+
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
+msgid "Play"
+msgstr "Pusti"
+
+#: src/gmpv_control_box.c:274
+msgid "Stop"
+msgstr "Zaustavi"
+
+#: src/gmpv_control_box.c:277
+msgid "Forward"
+msgstr "Napred"
+
+#: src/gmpv_control_box.c:280
+msgid "Rewind"
+msgstr "Nazad"
+
+#: src/gmpv_control_box.c:283
+msgid "Next Chapter"
+msgstr "Sledeće Poglavlje"
+
+#: src/gmpv_control_box.c:286
+msgid "Previous Chapter"
+msgstr "Prethodno Poglavlje"
+
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
+msgid "Toggle Fullscreen"
+msgstr "Ceo Ekran"
+
+#: src/gmpv_control_box.c:422
+msgid "Pause"
+msgstr "Pauziraj"
+
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "Greška"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "_Otkaži"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "_Otvori"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr "Sve Datoteke"
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
+msgid "None"
+msgstr "Nijedan"
+
+#. For simplicity, also dup the default string used when the
+#. * track has no title.
+#: src/gmpv_menu.c:117
+msgid "Unknown"
+msgstr "Nepoznato"
+
+#: src/gmpv_menu.c:150
+msgid "_Load External…"
+msgstr "_Učitaj Spoljne..."
+
+#: src/gmpv_menu.c:243
+msgid "_File"
+msgstr "_Datoteka"
+
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
+msgid "Open _Location"
+msgstr "Otvori_Lokaciju"
+
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
+msgid "_Save Playlist"
+msgstr "_Sačuvaj Listu Puštanja"
+
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
+msgid "_Quit"
+msgstr "_Napusti"
+
+#: src/gmpv_menu.c:248
+msgid "_Edit"
+msgstr "_Uredi"
+
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
+msgid "_Preferences"
+msgstr "_Postavke"
+
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
+msgid "_Video Track"
+msgstr "_Video Snimak"
+
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
+msgid "_Audio Track"
+msgstr "_Audio Snimak"
+
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
+msgid "S_ubtitle Track"
+msgstr "_Prevod"
+
+#: src/gmpv_menu.c:253
+msgid "_View"
+msgstr "_Pregled"
+
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
+msgid "_Toggle Controls"
+msgstr "_Prikaži Kontrole"
+
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
+msgid "_Toggle Playlist"
+msgstr "_Prikaži Listu Puštanja"
+
+#: src/gmpv_menu.c:256
+msgid "_Fullscreen"
+msgstr "_Ceo Ekran"
+
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
+msgid "_Normal Size"
+msgstr "_Normalna Veličina"
+
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
+msgid "_Double Size"
+msgstr "_Dvostruka Veličina"
+
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
+msgid "_Half Size"
+msgstr "_Upola Veličine"
+
+#: src/gmpv_menu.c:260
+msgid "_Help"
+msgstr "_Pomoć"
+
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
+msgid "_Keyboard Shortcuts"
+msgstr "_Prečice Tastature"
+
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
+msgid "_About"
+msgstr "_O Nama"
+
+#: src/gmpv_mpv.c:408
+#, fuzzy, c-format
+msgid "Playback was terminated abnormally. Reason: %s."
+msgstr "Reprodukcija je nepravilno okončana. Razlog: %s."
+
+#: src/gmpv_mpv.c:1047
+msgid "Failed to apply one or more MPV options."
+msgstr "Neuspešna primena jedne ili više MPV opcija."
+
+#: src/gmpv_open_location_dialog.c:122
+msgid "Location:"
+msgstr "Lokacija:"
+
+#: src/gmpv_playlist_widget.c:531
+msgid "_Add…"
+msgstr "_Dodaj..."
+
+#: src/gmpv_playlist_widget.c:535
+msgid "Add _Location…"
+msgstr "Dodaj_Lokaciju..."
+
+#: src/gmpv_playlist_widget.c:537
+msgid "Loop"
+msgstr "Ponavljaj"
+
+#: src/gmpv_playlist_widget.c:650
+msgid "Playlist"
+msgstr "Lista Puštanja"
+
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
+msgid "Add Lua Script"
+msgstr "Dodaj Lua Skriptu"
+
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua Skripte"
+
+#: src/gmpv_plugins_manager.c:300
+#, fuzzy, c-format
+msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
+msgstr "Neuspešno kopiranje datoteke iz '%s' u '%s'. Razlog: %s"
+
+#: src/gmpv_plugins_manager.c:349
+msgid "No Lua script found"
+msgstr "Lua skripta nije nađena"
+
+#: src/gmpv_plugins_manager_item.c:69
+msgid "Remove"
+msgstr "Ukloni"
+
+#: src/gmpv_plugins_manager_item.c:163
+msgid ""
+"Are you sure you want to remove this script? This action cannot be undone."
+msgstr ""
+"Sigurno želite da uklonite ovu skriptu? Ovaj postupak ne može biti opozvan."
+
+#: src/gmpv_plugins_manager_item.c:184
+#, fuzzy, c-format
+msgid "Failed to delete file '%s'. Reason: %s"
+msgstr "Neuspešno brisanje datoteke '%s'. Razlog: %s"
+
+#: src/gmpv_pref_dialog.c:286
+msgid "<b>User Interface</b>"
+msgstr "<b>Korisničko Sučelje</b>"
+
+#: src/gmpv_pref_dialog.c:289
+msgid "Enable client-side decorations"
+msgstr "Omogući ukrase klijenta"
+
+#: src/gmpv_pref_dialog.c:292
+msgid "Enable dark theme"
+msgstr "Omogući tamnu temu"
+
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr "Koristi plivajuće kontrole u režimu prozora"
+
+#: src/gmpv_pref_dialog.c:298
+msgid "Remember last file's location"
+msgstr "Upamti lokaciju poslednje datoteke"
+
+#: src/gmpv_pref_dialog.c:301
+msgid "<b>MPV Configuration</b>"
+msgstr "<b>MPV Konfiguracija</b>"
+
+#: src/gmpv_pref_dialog.c:304
+msgid "Load MPV configuration file"
+msgstr "Učitaj MPV konfiguracionu datoteku"
+
+#: src/gmpv_pref_dialog.c:307
+msgid "MPV configuration file:"
+msgstr "MPV konfiguraciona datoteka:"
+
+#: src/gmpv_pref_dialog.c:310
+msgid "<b>Keybindings</b>"
+msgstr "<b>Postavke Unosa</b>"
+
+#: src/gmpv_pref_dialog.c:313
+msgid "Load MPV input configuration file"
+msgstr "Učitaj MPV konfiguracionu datoteku"
+
+#: src/gmpv_pref_dialog.c:316
+msgid "MPV input configuration file:"
+msgstr "MPV konfiguraciona datoteka unosa:"
+
+#: src/gmpv_pref_dialog.c:319
+msgid "<b>Miscellaneous</b>"
+msgstr "<b>Ostalo</b>"
+
+#: src/gmpv_pref_dialog.c:325
+msgid "Extra MPV options:"
+msgstr "Dodatne MPV opcije:"
+
+#: src/gmpv_pref_dialog.c:358
+msgid "General"
+msgstr "Opšte"
+
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "_Sačuvaj"
+
+#: src/gmpv_pref_dialog.c:384
+msgid "Preferences"
+msgstr "Postavke"
+
+#: src/gmpv_shortcuts_window.c:56
+msgid "Open file"
+msgstr "Otvori datoteku"
+
+#: src/gmpv_shortcuts_window.c:57
+msgid "Open location"
+msgstr "Otvori lokaciju"
+
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
+msgid "Show preferences dialog"
+msgstr "Prikaži dijalog postavki"
+
+#: src/gmpv_shortcuts_window.c:61
+msgid "Toggle controls"
+msgstr "Prikaži kontrole"
+
+#: src/gmpv_shortcuts_window.c:62
+msgid "Toggle playlist"
+msgstr "Prikaži listu puštanja"
+
+#: src/gmpv_shortcuts_window.c:63
+msgid "Toggle fullscreen mode"
+msgstr "Prikaži u režimu celog ekrana"
+
+#: src/gmpv_shortcuts_window.c:64
+msgid "Leave fullscreen mode"
+msgstr "Napusti režim celog ekrana"
+
+#: src/gmpv_shortcuts_window.c:65
+msgid "Toggle OSD states between normal and playback time/duration"
+msgstr "Promeni OSD prikaz između normalnog i vreme puštanja/dužina"
+
+#: src/gmpv_shortcuts_window.c:66
+msgid "Show filename on the OSD"
+msgstr "Prikaži ime datoteke u OSD"
+
+#: src/gmpv_shortcuts_window.c:67
+msgid "Show progress, elapsed time, and duration on the OSD"
+msgstr "Prikaži napredak, proteklo vreme i dužinu na OSD"
+
+#: src/gmpv_shortcuts_window.c:70
+msgid "Seek backward/forward 5 seconds"
+msgstr "Prebaci 5 sekundi unazad/unapred"
+
+#: src/gmpv_shortcuts_window.c:71
+msgid "Exact seek backward/forward 1 second"
+msgstr "Prebaci tačno 1 sekund unazad/unapred"
+
+#: src/gmpv_shortcuts_window.c:72
+msgid "Seek backward/forward 1 minute"
+msgstr "Prebaci 1 minut unazad/unapred"
+
+#: src/gmpv_shortcuts_window.c:73
+msgid "Exact seek backward/forward 5 seconds"
+msgstr "Prebaci tačno 5 sekundi unazad/unapred"
+
+#: src/gmpv_shortcuts_window.c:74
+msgid "Seek to previous/next subtitle"
+msgstr "Prebaci na prethodni/sledeći podnatpis"
+
+#: src/gmpv_shortcuts_window.c:75
+msgid "Step backward/forward a single frame"
+msgstr "Korak za jednu sliku unazad/unapred"
+
+#: src/gmpv_shortcuts_window.c:76
+msgid "Seek to the beginning of the previous/next chapter"
+msgstr "Prebaci na početak prethodnog/sledećeg poglavlja"
+
+#: src/gmpv_shortcuts_window.c:79
+msgid "Decrease/increase playback speed by 10%"
+msgstr "Uspori/ubrzaj reprodukciju za 10%"
+
+#: src/gmpv_shortcuts_window.c:80
+msgid "Halve/double current playback speed"
+msgstr "Prepolovi/udvostruči trenutnu brzinu reprodukcije"
+
+#: src/gmpv_shortcuts_window.c:81
+msgid "Reset playback speed to normal"
+msgstr "Povrati normalnu brzinu reprodukcije"
+
+#: src/gmpv_shortcuts_window.c:82
+msgid "Go backward/forward in the playlist"
+msgstr "Idi unazad/unapred u listi puštanja"
+
+#: src/gmpv_shortcuts_window.c:83
+msgid "Remove selected playlist item"
+msgstr "Izbaci označenu stavku iz liste puštanja"
+
+#: src/gmpv_shortcuts_window.c:84
+msgid "Save playlist"
+msgstr "Sačuvaj listu puštanja"
+
+#: src/gmpv_shortcuts_window.c:85
+msgid "Set/clear A-B loop points"
+msgstr "Postavi/očisti A-B tačke ponavljanja"
+
+#: src/gmpv_shortcuts_window.c:86
+msgid "Toggle infinite looping"
+msgstr "Uključi beskonačno ponavljanje"
+
+#: src/gmpv_shortcuts_window.c:87
+msgid "Pause or unpause"
+msgstr "Pauziraj ili nastavi"
+
+#: src/gmpv_shortcuts_window.c:88
+msgid "Quit"
+msgstr "Napusti"
+
+#: src/gmpv_shortcuts_window.c:89
+msgid "Save current playback position and quit"
+msgstr "Sačuvaj trenutnu poziciju reprodukcije i napusti"
+
+#: src/gmpv_shortcuts_window.c:92
+msgid "Cycle through audio tracks"
+msgstr "Kruži kroz audio snimke"
+
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
+msgid "Decrease/increase volume"
+msgstr "Smanji/pojačaj"
+
+#: src/gmpv_shortcuts_window.c:95
+msgid "Mute or unmute"
+msgstr "Isključi ili uključi zvuk"
+
+#: src/gmpv_shortcuts_window.c:96
+msgid "Adjust audio delay by +/- 0.1 seconds"
+msgstr "Prilagodi kašnjenje zvuka za +/- 0.1 sekund"
+
+#: src/gmpv_shortcuts_window.c:99
+msgid "Toggle subtitle visibility"
+msgstr "Promeni vidljivost podnatpisa"
+
+#: src/gmpv_shortcuts_window.c:100
+msgid "Cycle through available subtitles"
+msgstr "Kruži kroz dostupne podnatpise"
+
+#: src/gmpv_shortcuts_window.c:101
+msgid "Adjust subtitle delay by +/- 0.1 seconds"
+msgstr "Prilagodi kašnjenje podnatpisa za +/- 0.1 sekund"
+
+#: src/gmpv_shortcuts_window.c:102
+msgid "Toggle SSA/ASS subtitles style override"
+msgstr "Izmeni SSA/ASS stil podnatpisa"
+
+#: src/gmpv_shortcuts_window.c:103
+msgid "Move subtitles up/down"
+msgstr "Pomeri podnatpis gore/dole"
+
+#: src/gmpv_shortcuts_window.c:104
+msgid "Toggle VSFilter aspect compatibility mode"
+msgstr "Izmeni VSFilter režim usklađenosti"
+
+#: src/gmpv_shortcuts_window.c:107
+msgid "Cycle through video tracks"
+msgstr "Kruži kroz video snimke"
+
+#: src/gmpv_shortcuts_window.c:108
+#, fuzzy
+msgid "Decrease/increase pan-and-scan range"
+msgstr "Povećaj/umanji opseg skeniranja odnosa"
+
+#: src/gmpv_shortcuts_window.c:109
+msgid "Take a screenshot"
+msgstr "Napravi snimak ekrana"
+
+#: src/gmpv_shortcuts_window.c:110
+msgid "Take a screenshot, without subtitles"
+msgstr "Napravi snimak ekrana bez podnatpisa"
+
+#: src/gmpv_shortcuts_window.c:111
+msgid "Take a screenshot, as the window shows it"
+msgstr "Napravi snimak ekrana kako ga prozor prikazuje"
+
+#: src/gmpv_shortcuts_window.c:112
+msgid "Resize video to half its original size"
+msgstr "Prepolovi originalnu veličinu video snimka"
+
+#: src/gmpv_shortcuts_window.c:113
+msgid "Resize video to its original size"
+msgstr "Povrati originalnu veličinu video snimka"
+
+#: src/gmpv_shortcuts_window.c:114
+msgid "Resize video to double its original size"
+msgstr "Udvostruči originalnu veličinu video snimka"
+
+#: src/gmpv_shortcuts_window.c:115
+msgid "Adjust contrast"
+msgstr "Prilagodi kontrast"
+
+#: src/gmpv_shortcuts_window.c:116
+msgid "Adjust brightness"
+msgstr "Prilagodi osvetljenost"
+
+#: src/gmpv_shortcuts_window.c:117
+msgid "Adjust gamma"
+msgstr "Prilagodi gamu"
+
+#: src/gmpv_shortcuts_window.c:118
+msgid "Adjust saturation"
+msgstr "Prilagodi zasićenje"
+
+#: src/gmpv_shortcuts_window.c:119
+msgid "Activate or deactivate deinterlacer"
+msgstr "Omogući ili onemogući preplitanje"
+
+#: src/gmpv_shortcuts_window.c:120
+msgid "Cycle aspect ratio override"
+msgstr "Kruži kroz promenu razmere"
+
+#: src/gmpv_shortcuts_window.c:123
+msgid "User Interface"
+msgstr "Korisničko Sučelje"
+
+#: src/gmpv_shortcuts_window.c:124
+msgid "Video"
+msgstr "Video"
+
+#: src/gmpv_shortcuts_window.c:125
+msgid "Audio"
+msgstr "Audio"
+
+#: src/gmpv_shortcuts_window.c:126
+msgid "Subtitle"
+msgstr "Podnatpis"
+
+#: src/gmpv_shortcuts_window.c:127
+msgid "Playback"
+msgstr "Reprodukcija"
+
+#: src/gmpv_shortcuts_window.c:128
+msgid "Seeking"
+msgstr "Traganje"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "Dodaj Datoteku u Listu Puštanja"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "Otvori Datoteku"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "Dodaj Lokaciju u Listu Puštnja"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "Otvori Lokaciju"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "Sačuvaj Listu Puštanja"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "GTK pročelje za MPV"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr "Srđan S."
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 48ff514..ab76e89 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -6,14 +6,14 @@
 # Mingye Wang <arthur2e5 at aosc.xyz>, 2015.
 # gnome-mpv <gnome-mpv at openmailbox.org>, 2015. #zanata
 # Mingye Wang <arthur2e5 at aosc.xyz>, 2016. #zanata
-# gnome-mpv <gnome-mpv at openmailbox.org>, 2016. #zanata
+# Huang Jiayao <huangjiayao_1992 at 163.com>, 2017. #zanata
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-mpv 0.6\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-11-16 21:24+0800\n"
-"PO-Revision-Date: 2016-11-03 05:23-0400\n"
-"Last-Translator: Copied by Zanata <copied-by-zanata at zanata.org>\n"
+"PO-Revision-Date: 2017-03-27 03:58-0400\n"
+"Last-Translator: Huang Jiayao <huangjiayao_1992 at 163.com>\n"
 "Language-Team: AOSC zh_CN <aosc at member.fsf.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -22,91 +22,92 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "启用或禁用暗色主题"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "启用或禁用客户端装饰"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "是否让文件选择对话框记住最近访问的文件夹"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "要传递给 mpv 的选项"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "mpv 配置文件的路径"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "是否载入 mpv 配置文件"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "mpv 输入配置文件的路径"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "是否载入 mpv 输入配置文件"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "窗口宽度"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "窗口高度"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "播放器音量"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "播放列表宽度"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "是否显示播放列表"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "最近访问的文件夹 URI"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr "是否已从上一个版本迁移设置"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr "是否在窗口模式下启用浮动控制"
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
-msgstr ""
+msgstr "允许多实例"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
-msgstr ""
+msgstr "是否显示控制栏"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "MPV 的 GTK 前端程序"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -118,594 +119,617 @@ msgstr ""
 " GNOME 库,GNOME MPV 是一个基于 GNOME HIG(人机界面准则)设计的程序。GNOME MPV "
 "还提供禁用客户端装饰(CSD)的选项以为不运行 GNOME 的系统提供更好的兼容性。"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "特性:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "拖放播放列表"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "正在载入外部 mpv 配置文件"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "MPRIS2 D-Bus 界面"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "显示运行中应用的主窗口"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "关闭了 CSD 的主窗口"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "打开了播放列表的主窗口"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "MPV 的 GTK 前端程序"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "添加文件到播放列表"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "打开文件"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "打开(_O)"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "取消(_C)"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "打开位置"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "保存播放列表"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "保存(_S)"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr "启用或禁用客户端装饰需要重启 %s 生效。"
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "载入外部配置文件…"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "MPV 的 GTK 前端程序"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
-"Mingye Wang <arthur2e5 at aosc.xyz>, 2015, 2016.\n"
-"Jeff Bai <jeffbai at aosc.xyz>, 2015, 2016.\n"
-"Sun <warmsun0220 at gmail.com>, 2015, 2016."
 
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "正在播放"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
-msgstr ""
+msgstr "显示发布版本号"
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
-msgstr ""
+msgstr "加入队列"
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
-msgstr ""
-
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "错误"
+msgstr "不要连接到已经运行中的实例"
 
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr "播放"
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr "停止"
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr "快进"
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr "快退"
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr "下一章节"
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr "上一章节"
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr "切换全屏"
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr "暂停"
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "错误"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "取消(_C)"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "打开(_O)"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr "所有文件"
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "无"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "未知"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr "载入外部(_L)…"
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "文件(_F)"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "打开位置(_L)"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "保存播放列表(_S)"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "退出(_Q)"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "编辑(_E)"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "首选项(_P)"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "视频轨道(_V)"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "音轨(_A)"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "字幕轨道(_U)"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "视图(_V)"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
-msgstr ""
+msgstr "切换控制栏(_T)"
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "切换播放列表(_T)"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "全屏(_F)"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "正常尺寸(_N)"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "两倍尺寸(_D)"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "一半尺寸(_H)"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "帮助(_F)"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
-msgstr ""
+msgstr "快捷键(_K)"
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "关于(_A)"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "回放被异常终止。原因:%s。"
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "应用一个或多个 MPV 选项失败。"
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "位置:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "添加(_A)…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
-msgstr ""
+msgstr "添加位置(_L)"
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "循环"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "播放列表"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
-msgstr ""
-
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr ""
+msgstr "添加 Lua 脚本"
 
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
-msgstr ""
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
+msgstr "Lua 脚本"
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
-msgstr ""
+msgstr "从 '%s' 拷贝文件到 '%s' 失败。原因:%s"
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
-msgstr ""
+msgstr "未找到 Lua 脚本"
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
-msgstr ""
+msgstr "移除"
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
-msgstr ""
+msgstr "您确定移除此脚本吗?该操作无法被撤销。"
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
-msgstr ""
+msgstr "删除文件 '%s' 失败。原因:%s"
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
-msgstr ""
+msgstr "<b>用户界面</b>"
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "启用客户端装饰"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "启用暗色主题"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr "在窗口模式下启用浮动控制"
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "记住最后一次打开位置"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>MPV 配置</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "加载 MPV 配置文件"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "MPV 配置文件:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>键绑定</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "加载 MPV 输入配置文件"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "MPV 输入配置文件:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>杂项</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "额外的 MPV 选项:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
-msgstr ""
+msgstr "通用"
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr ""
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "保存(_S)"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "首选项"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr "打开文件"
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr "打开位置"
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr "显示首选项对话框"
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
-msgstr ""
+msgstr "切换控制栏"
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr "切换播放列表"
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr "切换全屏模式"
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr "离开全屏模式"
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
-msgstr ""
+msgstr "切换 OSD 状态为“普通”或者“播放时间/总时长”"
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
-msgstr ""
+msgstr "在 OSD 上显示文件名"
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
-msgstr ""
+msgstr "在 OSD 上显示进度、已播放时间、总时长"
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
-msgstr ""
+msgstr "向后/向前跳转 5 秒"
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
-msgstr ""
+msgstr "向后/向前精确跳转 1 秒"
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
-msgstr ""
+msgstr "向后/向前跳转 1 分钟"
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
-msgstr ""
+msgstr "向后/向前精确跳转 5 秒"
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
-msgstr ""
+msgstr "查找上一个/下一个字幕"
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
-msgstr ""
+msgstr "跳转到上一帧/下一帧"
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
-msgstr ""
+msgstr "跳转到上一章/下一章的开头"
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
-msgstr ""
+msgstr "减少/增加 10% 播放速度"
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
-msgstr ""
+msgstr "减半/加倍当前的播放速度"
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
-msgstr ""
+msgstr "重置播放速度为正常速度"
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
-msgstr ""
+msgstr "跳转到当前播放列表中的前一项/后一项"
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr "移除选定的播放列表项"
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr "保存播放列表"
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
-msgstr ""
+msgstr "设置/清除 A-B 循环点"
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
-msgstr ""
+msgstr "开启或关闭无限循环"
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
-msgstr ""
+msgstr "暂停/播放"
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr "退出"
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
-msgstr ""
+msgstr "保存当前播放进度并退出"
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
-msgstr ""
+msgstr "循环播放音轨"
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
-msgstr ""
+msgstr "减少/增大音量"
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
-msgstr ""
+msgstr "静音/取消静音"
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
-msgstr ""
+msgstr "将音频延迟调整为 +/- 0.1 秒"
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
-msgstr ""
+msgstr "切换字幕可见性"
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
-msgstr ""
+msgstr "循环播放当前字幕范围"
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
-msgstr ""
+msgstr "将字幕延迟调整为 +/- 0.1 秒"
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
-msgstr ""
+msgstr "切换 SSA/ASS 字幕样式覆盖"
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
-msgstr ""
+msgstr "移动到上一行/下一行字幕"
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
-msgstr ""
+msgstr "切换 VSFilter aspect 兼容模式"
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
-msgstr ""
+msgstr "循环播放视频轨道"
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
-msgstr ""
+msgstr "减小/增加 pan-and-scan 范围"
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
-msgstr ""
+msgstr "截取屏幕截图"
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
-msgstr ""
+msgstr "截取屏幕截图,不包含字幕"
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
-msgstr ""
+msgstr "截取屏幕截图,并在窗口中显示截图"
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
-msgstr ""
+msgstr "调整视频大小为其原始大小的一半"
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
-msgstr ""
+msgstr "调整视频大小为其原始大小"
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
-msgstr ""
+msgstr "调整视频大小为其原始大小的两倍"
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
-msgstr ""
+msgstr "调整对比度"
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
-msgstr ""
+msgstr "调整亮度"
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
-msgstr ""
+msgstr "调整伽玛值"
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
-msgstr ""
+msgstr "调整饱和度"
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
-msgstr ""
+msgstr "激活/取消激活去隔行扫描器"
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
-msgstr ""
+msgstr "循环切换宽高比重写"
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
-msgstr ""
+msgstr "用户界面"
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
-msgstr ""
+msgstr "视频"
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
-msgstr ""
+msgstr "音频"
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
-msgstr ""
+msgstr "字幕"
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
-msgstr ""
+msgstr "音频"
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
+msgstr "跳转"
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
 msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "添加文件到播放列表"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "打开文件"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr "添加位置到播放列表"
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "打开位置"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "保存播放列表"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "MPV 的 GTK 前端程序"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr ""
+"Mingye Wang <arthur2e5 at aosc.xyz>, 2015, 2016.\n"
+"Jeff Bai <jeffbai at aosc.xyz>, 2015, 2016.\n"
+"Sun <warmsun0220 at gmail.com>, 2015, 2016.\n"
+"Huang Jiayao <huangjiayao_1992 at 163.com>, 2017."
diff --git a/po/zh_TW.po b/po/zh_TW.po
index c516336..eebd32d 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -22,91 +22,92 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: Zanata 3.9.6\n"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:1
-#: ../data/io.github.GnomeMpv.gschema.xml.h:2
+#: data/org.gnome-mpv.gschema.xml:9 data/io.github.GnomeMpv.gschema.xml:16
 msgid "Enable or disable dark theme"
 msgstr "啟用或禁用暗色主題"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:2
-#: ../data/io.github.GnomeMpv.gschema.xml.h:3
+#: data/org.gnome-mpv.gschema.xml:15 data/io.github.GnomeMpv.gschema.xml:22
 msgid "Enable or disable client-side decorations"
 msgstr "啟用或禁用客戶端裝飾"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:3
-#: ../data/io.github.GnomeMpv.gschema.xml.h:4
+#: data/org.gnome-mpv.gschema.xml:21 data/io.github.GnomeMpv.gschema.xml:34
 msgid ""
 "Whether or not to make file chooser dialog remember last folder accessed"
 msgstr "是否讓檔案選擇對話窗記住最近訪問的資料夾"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:4
-#: ../data/io.github.GnomeMpv.gschema.xml.h:6
+#: data/org.gnome-mpv.gschema.xml:27 data/io.github.GnomeMpv.gschema.xml:46
 msgid "Options to pass to mpv"
 msgstr "要傳遞給 mpv 的選項"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:5
-#: ../data/io.github.GnomeMpv.gschema.xml.h:7
+#: data/org.gnome-mpv.gschema.xml:33 data/io.github.GnomeMpv.gschema.xml:52
 msgid "Path to mpv configuration file"
 msgstr "mpv 配置檔的路徑"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:6
-#: ../data/io.github.GnomeMpv.gschema.xml.h:8
+#: data/org.gnome-mpv.gschema.xml:39 data/io.github.GnomeMpv.gschema.xml:58
 msgid "Load or don't load mpv configuration file"
 msgstr "是否載入 mpv 配置檔"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:7
-#: ../data/io.github.GnomeMpv.gschema.xml.h:9
+#: data/org.gnome-mpv.gschema.xml:45 data/io.github.GnomeMpv.gschema.xml:64
 msgid "Path to mpv input configuration file"
 msgstr "mpv 輸入配置檔的路徑"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:8
-#: ../data/io.github.GnomeMpv.gschema.xml.h:10
+#: data/org.gnome-mpv.gschema.xml:51 data/io.github.GnomeMpv.gschema.xml:70
 msgid "Load or don't load mpv input configuration file"
 msgstr "是否載入 mpv 輸入配置檔"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:9
-#: ../data/io.github.GnomeMpv.gschema.xml.h:11
+#: data/org.gnome-mpv.gschema.xml:61 data/io.github.GnomeMpv.gschema.xml:80
 msgid "Width of the window"
 msgstr "視窗寬度"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:10
-#: ../data/io.github.GnomeMpv.gschema.xml.h:12
+#: data/org.gnome-mpv.gschema.xml:67 data/io.github.GnomeMpv.gschema.xml:86
 msgid "Height of the window"
 msgstr "視窗高度"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:11
-#: ../data/io.github.GnomeMpv.gschema.xml.h:13
+#: data/org.gnome-mpv.gschema.xml:73 data/io.github.GnomeMpv.gschema.xml:93
 msgid "Volume of player"
 msgstr "播放器音量"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:12
-#: ../data/io.github.GnomeMpv.gschema.xml.h:14
+#: data/org.gnome-mpv.gschema.xml:79 data/io.github.GnomeMpv.gschema.xml:99
 msgid "Width of the playlist"
 msgstr "播放列表寬度"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:13
-#: ../data/io.github.GnomeMpv.gschema.xml.h:16
+#: data/org.gnome-mpv.gschema.xml:85 data/io.github.GnomeMpv.gschema.xml:111
 msgid "Show or not show the playlist"
 msgstr "是否顯示播放列表"
 
-#: ../data/org.gnome-mpv.gschema.xml.h:14
-#: ../data/io.github.GnomeMpv.gschema.xml.h:17
+#: data/org.gnome-mpv.gschema.xml:91 data/io.github.GnomeMpv.gschema.xml:117
 msgid "URI of the last folder accessed"
 msgstr "最近訪問的資料夾 URI"
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:1
+#: data/io.github.GnomeMpv.gschema.xml:10
 msgid ""
 "Whether the settings has already been migrated from the previous version"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:5 ../src/gmpv_pref_dialog.c:315
+#: data/io.github.GnomeMpv.gschema.xml:28
+msgid "Whether or not to use floating controls in windowed mode"
+msgstr ""
+
+#: data/io.github.GnomeMpv.gschema.xml:40 src/gmpv_pref_dialog.c:322
 msgid "Allow multiple instances"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.gschema.xml.h:15
+#: data/io.github.GnomeMpv.gschema.xml:105
 msgid "Show or not show the controls"
 msgstr ""
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:1
+#: data/io.github.GnomeMpv.appdata.xml.in:7
+#: data/io.github.GnomeMpv.desktop.in:4 src/gmpv_application.c:410
+#: src/gmpv_view.c:994
+msgid "GNOME MPV"
+msgstr "GNOME MPV"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:8
+#: data/io.github.GnomeMpv.desktop.in:5
+msgid "GTK+ frontend for mpv"
+msgstr "MPV 之 GTK 前端程式"
+
+#: data/io.github.GnomeMpv.appdata.xml.in:11
 msgid ""
 "GNOME MPV is a simple GTK+ frontend for mpv, which is a very powerful media "
 "player capable of playing virtually all video and audio formats. The design "
@@ -118,593 +119,615 @@ msgstr ""
 " GNOME 庫,GNOME MPV 是一個基於 GNOME HIG(人機介面準則)設計的程式。GNOME MPV "
 "還提供禁用客戶端裝飾(CSD)的選項以為不執行 GNOME 的系統提供更好的相容性。"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:2
+#: data/io.github.GnomeMpv.appdata.xml.in:18
 msgid "Features:"
 msgstr "特性:"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:3
+#: data/io.github.GnomeMpv.appdata.xml.in:20
 msgid "Drag and drop playlist"
 msgstr "拖放播放列表"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:4
+#: data/io.github.GnomeMpv.appdata.xml.in:21
 msgid "Loading external mpv configuration files"
 msgstr "正在載入外部 mpv 配置檔"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:5
+#: data/io.github.GnomeMpv.appdata.xml.in:22
 msgid "MPRIS2 D-Bus interface"
 msgstr "MPRIS2 D-Bus 介面"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:6
-msgid "The main window showing the application in action"
-msgstr "顯示執行中套用的主視窗"
-
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:7
+#: data/io.github.GnomeMpv.appdata.xml.in:32
 msgid "The main window with CSD disabled"
 msgstr "關閉了 CSD 的主視窗"
 
-#: ../data/io.github.GnomeMpv.appdata.xml.in.h:8
+#: data/io.github.GnomeMpv.appdata.xml.in:36
 msgid "The main window with playlist open"
 msgstr "打開了播放列表的主視窗"
 
-#: ../data/io.github.GnomeMpv.desktop.in.h:1 ../src/gmpv_application.c:260
-msgid "GNOME MPV"
-msgstr "GNOME MPV"
-
-#: ../data/io.github.GnomeMpv.desktop.in.h:2
-msgid "GTK+ frontend for mpv"
-msgstr "MPV 之 GTK 前端程式"
-
-#: ../src/gmpv_actionctl.c:101
-msgid "Add File to Playlist"
-msgstr "新增檔案到播放列表"
-
-#: ../src/gmpv_actionctl.c:102
-msgid "Open File"
-msgstr "開啟檔案"
-
-#: ../src/gmpv_actionctl.c:105 ../src/gmpv_actionctl.c:508
-#: ../src/gmpv_menu.c:190 ../src/gmpv_menu.c:254
-#: ../src/gmpv_open_loc_dialog.c:84
-msgid "_Open"
-msgstr "開啟(_O)"
-
-#: ../src/gmpv_actionctl.c:106 ../src/gmpv_actionctl.c:300
-#: ../src/gmpv_actionctl.c:507 ../src/gmpv_open_loc_dialog.c:82
-#: ../src/gmpv_pref_dialog.c:358
-msgid "_Cancel"
-msgstr "取消(_C)"
-
-#: ../src/gmpv_actionctl.c:206
-msgid "Add Location to Playlist"
-msgstr ""
-
-#: ../src/gmpv_actionctl.c:207
-msgid "Open Location"
-msgstr "開啟位置"
-
-#: ../src/gmpv_actionctl.c:296
-msgid "Save Playlist"
-msgstr "儲存播放列表"
-
-#: ../src/gmpv_actionctl.c:299 ../src/gmpv_pref_dialog.c:360
-msgid "_Save"
-msgstr "儲存(_S)"
-
-#: ../src/gmpv_actionctl.c:417
-#, c-format
-msgid ""
-"Enabling or disabling client-side decorations requires restarting %s to take"
-" effect."
-msgstr "啟用或禁用客戶端裝飾需要重啟 %s 生效。"
-
-#: ../src/gmpv_actionctl.c:504
-msgid "Load External…"
-msgstr "載入外部配置檔…"
-
-#: ../src/gmpv_actionctl.c:605
-msgid "A GTK frontend for MPV"
-msgstr "MPV 的 GTK 前端程式"
-
-#: ../src/gmpv_actionctl.c:615
-msgid "translator-credits"
+#. Translators: This is an icon name, don't translate!
+#: data/io.github.GnomeMpv.desktop.in:8
+msgid "gnome-mpv"
 msgstr ""
-"Mingye Wang\n"
-"Sun"
 
-#: ../src/gmpv_application.c:1225
+#: src/gmpv_application.c:464
 msgid "Playing"
 msgstr "正在播放"
 
-#: ../src/gmpv_application.c:1356
+#: src/gmpv_application.c:532
 msgid "Show release version"
 msgstr ""
 
-#: ../src/gmpv_application.c:1364
+#: src/gmpv_application.c:540
 msgid "Enqueue"
 msgstr ""
 
-#: ../src/gmpv_application.c:1372
+#: src/gmpv_application.c:548
 msgid "Don't connect to an already-running instance"
 msgstr ""
 
-#: ../src/gmpv_common.c:250
-msgid "Error"
-msgstr "錯誤"
-
-#: ../src/gmpv_control_box.c:190 ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:271 src/gmpv_control_box.c:422
 msgid "Play"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:191
+#: src/gmpv_control_box.c:274
 msgid "Stop"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:192
+#: src/gmpv_control_box.c:277
 msgid "Forward"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:193
+#: src/gmpv_control_box.c:280
 msgid "Rewind"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:194
+#: src/gmpv_control_box.c:283
 msgid "Next Chapter"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:195
+#: src/gmpv_control_box.c:286
 msgid "Previous Chapter"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:196 ../src/gmpv_main_window.c:576
+#: src/gmpv_control_box.c:289 src/gmpv_header_bar.c:89
 msgid "Toggle Fullscreen"
 msgstr ""
 
-#: ../src/gmpv_control_box.c:363
+#: src/gmpv_control_box.c:422
 msgid "Pause"
 msgstr ""
 
-#: ../src/gmpv_menu.c:53
+#: src/gmpv_controller.c:675 src/gmpv_view.c:1416
+msgid "Error"
+msgstr "錯誤"
+
+#: src/gmpv_file_chooser.c:90 src/gmpv_open_location_dialog.c:126
+#: src/gmpv_pref_dialog.c:365
+msgid "_Cancel"
+msgstr "取消(_C)"
+
+#: src/gmpv_file_chooser.c:92 src/gmpv_menu.c:244 src/gmpv_menu.c:321
+#: src/gmpv_open_location_dialog.c:128
+msgid "_Open"
+msgstr "開啟(_O)"
+
+#: src/gmpv_file_chooser.c:135 src/gmpv_plugins_manager.c:149
+msgid "All Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:143
+msgid "Media Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:154
+msgid "Audio Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:162
+msgid "Video Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:170
+msgid "Image Files"
+msgstr ""
+
+#: src/gmpv_file_chooser.c:180
+msgid "Subtitle Files"
+msgstr ""
+
+#: src/gmpv_menu.c:102
 msgid "None"
 msgstr "無"
 
 #. For simplicity, also dup the default string used when the
 #. * track has no title.
-#: ../src/gmpv_menu.c:68
+#: src/gmpv_menu.c:117
 msgid "Unknown"
 msgstr "未知"
 
-#: ../src/gmpv_menu.c:103
+#: src/gmpv_menu.c:150
 msgid "_Load External…"
 msgstr ""
 
-#: ../src/gmpv_menu.c:189
+#: src/gmpv_menu.c:243
 msgid "_File"
 msgstr "檔案(_F)"
 
-#: ../src/gmpv_menu.c:191 ../src/gmpv_menu.c:255
+#: src/gmpv_menu.c:245 src/gmpv_menu.c:322
 msgid "Open _Location"
 msgstr "開啟位置(_L)"
 
-#: ../src/gmpv_menu.c:192 ../src/gmpv_menu.c:232
+#: src/gmpv_menu.c:246 src/gmpv_menu.c:296
 msgid "_Save Playlist"
 msgstr "儲存播放列表(_S)"
 
-#: ../src/gmpv_menu.c:193 ../src/gmpv_menu.c:269
+#: src/gmpv_menu.c:247 src/gmpv_menu.c:336
 msgid "_Quit"
 msgstr "退出(_Q)"
 
-#: ../src/gmpv_menu.c:194
+#: src/gmpv_menu.c:248
 msgid "_Edit"
 msgstr "編輯(_E)"
 
-#: ../src/gmpv_menu.c:195 ../src/gmpv_menu.c:265
+#: src/gmpv_menu.c:249 src/gmpv_menu.c:332
 msgid "_Preferences"
 msgstr "偏好設定(_P)"
 
-#: ../src/gmpv_menu.c:196 ../src/gmpv_menu.c:234
+#: src/gmpv_menu.c:250 src/gmpv_menu.c:298
 msgid "_Video Track"
 msgstr "視訊軌道(_V)"
 
-#: ../src/gmpv_menu.c:197 ../src/gmpv_menu.c:235
+#: src/gmpv_menu.c:251 src/gmpv_menu.c:299
 msgid "_Audio Track"
 msgstr "音軌(_A)"
 
-#: ../src/gmpv_menu.c:198 ../src/gmpv_menu.c:236
+#: src/gmpv_menu.c:252 src/gmpv_menu.c:300
 msgid "S_ubtitle Track"
 msgstr "字幕軌道(_U)"
 
-#: ../src/gmpv_menu.c:199
+#: src/gmpv_menu.c:253
 msgid "_View"
 msgstr "檢視(_V)"
 
-#: ../src/gmpv_menu.c:200 ../src/gmpv_menu.c:229
+#: src/gmpv_menu.c:254 src/gmpv_menu.c:293
 msgid "_Toggle Controls"
 msgstr ""
 
-#: ../src/gmpv_menu.c:201 ../src/gmpv_menu.c:231
+#: src/gmpv_menu.c:255 src/gmpv_menu.c:295
 msgid "_Toggle Playlist"
 msgstr "切換播放列表(_T)"
 
-#: ../src/gmpv_menu.c:202
+#: src/gmpv_menu.c:256
 msgid "_Fullscreen"
 msgstr "全屏(_F)"
 
-#: ../src/gmpv_menu.c:203 ../src/gmpv_menu.c:238
+#: src/gmpv_menu.c:257 src/gmpv_menu.c:302
 msgid "_Normal Size"
 msgstr "正常尺寸(_N)"
 
-#: ../src/gmpv_menu.c:204 ../src/gmpv_menu.c:239
+#: src/gmpv_menu.c:258 src/gmpv_menu.c:303
 msgid "_Double Size"
 msgstr "兩倍尺寸(_D)"
 
-#: ../src/gmpv_menu.c:205 ../src/gmpv_menu.c:240
+#: src/gmpv_menu.c:259 src/gmpv_menu.c:304
 msgid "_Half Size"
 msgstr "一半尺寸(_H)"
 
-#: ../src/gmpv_menu.c:206
+#: src/gmpv_menu.c:260
 msgid "_Help"
 msgstr "幫助(_F)"
 
-#: ../src/gmpv_menu.c:207 ../src/gmpv_menu.c:267
+#: src/gmpv_menu.c:261 src/gmpv_menu.c:334
 msgid "_Keyboard Shortcuts"
 msgstr ""
 
-#: ../src/gmpv_menu.c:208 ../src/gmpv_menu.c:268
+#: src/gmpv_menu.c:262 src/gmpv_menu.c:335
 msgid "_About"
 msgstr "關於(_A)"
 
-#: ../src/gmpv_mpv_obj.c:240
+#: src/gmpv_mpv.c:408
 #, fuzzy, c-format
 msgid "Playback was terminated abnormally. Reason: %s."
 msgstr "回放被異常終止。原因:%s。"
 
-#: ../src/gmpv_mpv_obj.c:1040
+#: src/gmpv_mpv.c:1047
 msgid "Failed to apply one or more MPV options."
 msgstr "套用一個或多個 MPV 選項失敗。"
 
-#: ../src/gmpv_open_loc_dialog.c:78
+#: src/gmpv_open_location_dialog.c:122
 msgid "Location:"
 msgstr "位置:"
 
-#: ../src/gmpv_playlist_widget.c:503
+#: src/gmpv_playlist_widget.c:531
 msgid "_Add…"
 msgstr "新增(_A)…"
 
-#: ../src/gmpv_playlist_widget.c:507
+#: src/gmpv_playlist_widget.c:535
 msgid "Add _Location…"
 msgstr ""
 
-#: ../src/gmpv_playlist_widget.c:509
+#: src/gmpv_playlist_widget.c:537
 msgid "Loop"
 msgstr "迴圈"
 
-#: ../src/gmpv_playlist_widget.c:607
+#: src/gmpv_playlist_widget.c:650
 msgid "Playlist"
 msgstr "播放列表"
 
-#: ../src/gmpv_plugins_manager.c:141 ../src/gmpv_plugins_manager.c:366
+#: src/gmpv_plugins_manager.c:142 src/gmpv_plugins_manager.c:373
 msgid "Add Lua Script"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:144
-msgid "Open"
-msgstr ""
-
-#: ../src/gmpv_plugins_manager.c:145
-msgid "Cancel"
+#: src/gmpv_plugins_manager.c:154 src/gmpv_pref_dialog.c:362
+msgid "Lua Scripts"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:293
+#: src/gmpv_plugins_manager.c:300
 #, fuzzy, c-format
 msgid "Failed to copy file from '%s' to '%s'. Reason: %s"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager.c:342
+#: src/gmpv_plugins_manager.c:349
 msgid "No Lua script found"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:65
+#: src/gmpv_plugins_manager_item.c:69
 msgid "Remove"
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:159
+#: src/gmpv_plugins_manager_item.c:163
 msgid ""
 "Are you sure you want to remove this script? This action cannot be undone."
 msgstr ""
 
-#: ../src/gmpv_plugins_manager_item.c:180
+#: src/gmpv_plugins_manager_item.c:184
 #, fuzzy, c-format
 msgid "Failed to delete file '%s'. Reason: %s"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:282
+#: src/gmpv_pref_dialog.c:286
 msgid "<b>User Interface</b>"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:285
+#: src/gmpv_pref_dialog.c:289
 msgid "Enable client-side decorations"
 msgstr "啟用客戶端裝飾"
 
-#: ../src/gmpv_pref_dialog.c:288
+#: src/gmpv_pref_dialog.c:292
 msgid "Enable dark theme"
 msgstr "啟用暗色主題"
 
-#: ../src/gmpv_pref_dialog.c:291
+#: src/gmpv_pref_dialog.c:295
+msgid "Use floating controls in windowed mode"
+msgstr ""
+
+#: src/gmpv_pref_dialog.c:298
 msgid "Remember last file's location"
 msgstr "記住最後一次開啟位置"
 
-#: ../src/gmpv_pref_dialog.c:294
+#: src/gmpv_pref_dialog.c:301
 msgid "<b>MPV Configuration</b>"
 msgstr "<b>MPV 配置</b>"
 
-#: ../src/gmpv_pref_dialog.c:297
+#: src/gmpv_pref_dialog.c:304
 msgid "Load MPV configuration file"
 msgstr "載入 MPV 配置檔"
 
-#: ../src/gmpv_pref_dialog.c:300
+#: src/gmpv_pref_dialog.c:307
 msgid "MPV configuration file:"
 msgstr "MPV 配置檔:"
 
-#: ../src/gmpv_pref_dialog.c:303
+#: src/gmpv_pref_dialog.c:310
 msgid "<b>Keybindings</b>"
 msgstr "<b>鍵繫結</b>"
 
-#: ../src/gmpv_pref_dialog.c:306
+#: src/gmpv_pref_dialog.c:313
 msgid "Load MPV input configuration file"
 msgstr "載入 MPV 輸入配置檔"
 
-#: ../src/gmpv_pref_dialog.c:309
+#: src/gmpv_pref_dialog.c:316
 msgid "MPV input configuration file:"
 msgstr "MPV 輸入配置檔:"
 
-#: ../src/gmpv_pref_dialog.c:312
+#: src/gmpv_pref_dialog.c:319
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>雜項</b>"
 
-#: ../src/gmpv_pref_dialog.c:318
+#: src/gmpv_pref_dialog.c:325
 msgid "Extra MPV options:"
 msgstr "額外的 MPV 選項:"
 
-#: ../src/gmpv_pref_dialog.c:351
+#: src/gmpv_pref_dialog.c:358
 msgid "General"
 msgstr ""
 
-#: ../src/gmpv_pref_dialog.c:355
-msgid "Lua Scripts"
-msgstr ""
+#: src/gmpv_pref_dialog.c:367
+msgid "_Save"
+msgstr "儲存(_S)"
 
-#: ../src/gmpv_pref_dialog.c:377
+#: src/gmpv_pref_dialog.c:384
 msgid "Preferences"
 msgstr "偏好設定"
 
-#: ../src/gmpv_shortcuts_window.c:54
+#: src/gmpv_shortcuts_window.c:56
 msgid "Open file"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:55
+#: src/gmpv_shortcuts_window.c:57
 msgid "Open location"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:56
+#: src/gmpv_shortcuts_window.c:58
+msgid "Add file to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:59
+msgid "Add location to playlist"
+msgstr ""
+
+#: src/gmpv_shortcuts_window.c:60
 msgid "Show preferences dialog"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:57
+#: src/gmpv_shortcuts_window.c:61
 msgid "Toggle controls"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:58
+#: src/gmpv_shortcuts_window.c:62
 msgid "Toggle playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:59
+#: src/gmpv_shortcuts_window.c:63
 msgid "Toggle fullscreen mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:60
+#: src/gmpv_shortcuts_window.c:64
 msgid "Leave fullscreen mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:61
+#: src/gmpv_shortcuts_window.c:65
 msgid "Toggle OSD states between normal and playback time/duration"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:62
+#: src/gmpv_shortcuts_window.c:66
 msgid "Show filename on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:63
+#: src/gmpv_shortcuts_window.c:67
 msgid "Show progress, elapsed time, and duration on the OSD"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:66
+#: src/gmpv_shortcuts_window.c:70
 msgid "Seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:67
+#: src/gmpv_shortcuts_window.c:71
 msgid "Exact seek backward/forward 1 second"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:68
+#: src/gmpv_shortcuts_window.c:72
 msgid "Seek backward/forward 1 minute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:69
+#: src/gmpv_shortcuts_window.c:73
 msgid "Exact seek backward/forward 5 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:70
+#: src/gmpv_shortcuts_window.c:74
 msgid "Seek to previous/next subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:71
+#: src/gmpv_shortcuts_window.c:75
 msgid "Step backward/forward a single frame"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:72
+#: src/gmpv_shortcuts_window.c:76
 msgid "Seek to the beginning of the previous/next chapter"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:75
+#: src/gmpv_shortcuts_window.c:79
 msgid "Decrease/increase playback speed by 10%"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:76
+#: src/gmpv_shortcuts_window.c:80
 msgid "Halve/double current playback speed"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:77
+#: src/gmpv_shortcuts_window.c:81
 msgid "Reset playback speed to normal"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:78
+#: src/gmpv_shortcuts_window.c:82
 msgid "Go backward/forward in the playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:79
+#: src/gmpv_shortcuts_window.c:83
 msgid "Remove selected playlist item"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:80
+#: src/gmpv_shortcuts_window.c:84
 msgid "Save playlist"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:81
+#: src/gmpv_shortcuts_window.c:85
 msgid "Set/clear A-B loop points"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:82
+#: src/gmpv_shortcuts_window.c:86
 msgid "Toggle infinite looping"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:83
+#: src/gmpv_shortcuts_window.c:87
 msgid "Pause or unpause"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:84
+#: src/gmpv_shortcuts_window.c:88
 msgid "Quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:85
+#: src/gmpv_shortcuts_window.c:89
 msgid "Save current playback position and quit"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:88
+#: src/gmpv_shortcuts_window.c:92
 msgid "Cycle through audio tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:89 ../src/gmpv_shortcuts_window.c:90
+#: src/gmpv_shortcuts_window.c:93 src/gmpv_shortcuts_window.c:94
 msgid "Decrease/increase volume"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:91
+#: src/gmpv_shortcuts_window.c:95
 msgid "Mute or unmute"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:92
+#: src/gmpv_shortcuts_window.c:96
 msgid "Adjust audio delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:95
+#: src/gmpv_shortcuts_window.c:99
 msgid "Toggle subtitle visibility"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:96
+#: src/gmpv_shortcuts_window.c:100
 msgid "Cycle through available subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:97
+#: src/gmpv_shortcuts_window.c:101
 msgid "Adjust subtitle delay by +/- 0.1 seconds"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:98
+#: src/gmpv_shortcuts_window.c:102
 msgid "Toggle SSA/ASS subtitles style override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:99
+#: src/gmpv_shortcuts_window.c:103
 msgid "Move subtitles up/down"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:100
+#: src/gmpv_shortcuts_window.c:104
 msgid "Toggle VSFilter aspect compatibility mode"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:103
+#: src/gmpv_shortcuts_window.c:107
 msgid "Cycle through video tracks"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:104
+#: src/gmpv_shortcuts_window.c:108
 msgid "Decrease/increase pan-and-scan range"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:105
+#: src/gmpv_shortcuts_window.c:109
 msgid "Take a screenshot"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:106
+#: src/gmpv_shortcuts_window.c:110
 msgid "Take a screenshot, without subtitles"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:107
+#: src/gmpv_shortcuts_window.c:111
 msgid "Take a screenshot, as the window shows it"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:108
+#: src/gmpv_shortcuts_window.c:112
 msgid "Resize video to half its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:109
+#: src/gmpv_shortcuts_window.c:113
 msgid "Resize video to its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:110
+#: src/gmpv_shortcuts_window.c:114
 msgid "Resize video to double its original size"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:111
+#: src/gmpv_shortcuts_window.c:115
 msgid "Adjust contrast"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:112
+#: src/gmpv_shortcuts_window.c:116
 msgid "Adjust brightness"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:113
+#: src/gmpv_shortcuts_window.c:117
 msgid "Adjust gamma"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:114
+#: src/gmpv_shortcuts_window.c:118
 msgid "Adjust saturation"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:115
+#: src/gmpv_shortcuts_window.c:119
 msgid "Activate or deactivate deinterlacer"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:116
+#: src/gmpv_shortcuts_window.c:120
 msgid "Cycle aspect ratio override"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:119
+#: src/gmpv_shortcuts_window.c:123
 msgid "User Interface"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:120
+#: src/gmpv_shortcuts_window.c:124
 msgid "Video"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:121
+#: src/gmpv_shortcuts_window.c:125
 msgid "Audio"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:122
+#: src/gmpv_shortcuts_window.c:126
 msgid "Subtitle"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:123
+#: src/gmpv_shortcuts_window.c:127
 msgid "Playback"
 msgstr ""
 
-#: ../src/gmpv_shortcuts_window.c:124
+#: src/gmpv_shortcuts_window.c:128
 msgid "Seeking"
 msgstr ""
+
+#: src/gmpv_view.c:742
+msgid ""
+"Enabling or disabling client-side decorations requires restarting to take "
+"effect."
+msgstr ""
+
+#: src/gmpv_view.c:1296
+msgid "Add File to Playlist"
+msgstr "新增檔案到播放列表"
+
+#: src/gmpv_view.c:1297
+msgid "Open File"
+msgstr "開啟檔案"
+
+#: src/gmpv_view.c:1324
+msgid "Add Location to Playlist"
+msgstr ""
+
+#: src/gmpv_view.c:1325
+msgid "Open Location"
+msgstr "開啟位置"
+
+#: src/gmpv_view.c:1346
+msgid "Load Audio Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1365
+msgid "Load Subtitle Track…"
+msgstr ""
+
+#: src/gmpv_view.c:1390
+msgid "Save Playlist"
+msgstr "儲存播放列表"
+
+#: src/gmpv_view.c:1455
+msgid "A GTK frontend for MPV"
+msgstr "MPV 的 GTK 前端程式"
+
+#: src/gmpv_view.c:1465
+msgid "translator-credits"
+msgstr ""
+"Mingye Wang\n"
+"Sun"
diff --git a/src/Makefile.am b/src/Makefile.am
index 2fd188c..2ee2028 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,8 +4,10 @@ bin_PROGRAMS = gnome-mpv
 
 mpris_generated = mpris/gmpv_mpris_gdbus.c mpris/gmpv_mpris_gdbus.h
 mpris_files =	mpris/gmpv_mpris.c mpris/gmpv_mpris.h \
+		mpris/gmpv_mpris_module.c mpris/gmpv_mpris_module.h \
 		mpris/gmpv_mpris_base.c mpris/gmpv_mpris_base.h \
 		mpris/gmpv_mpris_player.c mpris/gmpv_mpris_player.h \
+		mpris/gmpv_mpris_track_list.c mpris/gmpv_mpris_track_list.h \
 		$(mpris_generated)
 $(mpris_generated): $(top_srcdir)/data/gmpv_mpris_gdbus.xml
 	$(AM_V_GEN) \
@@ -37,28 +39,31 @@ media_key_files = media_keys/gmpv_media_keys.c media_keys/gmpv_media_keys.h
 BUILT_SOURCES = $(mpris_generated) $(marshal_generated) $(authors_generated)
 
 gnome_mpv_SOURCES =	gmpv_main.c gmpv_def.h \
-			gmpv_actionctl.c gmpv_actionctl.h \
 			gmpv_application.c gmpv_application.h \
+			gmpv_application_private.h \
+			gmpv_application_action.c gmpv_application_action.h \
 			gmpv_common.c gmpv_common.h \
+			gmpv_controller.c gmpv_controller.h \
+			gmpv_controller_private.h \
+			gmpv_controller_input.c gmpv_controller_input.h \
 			gmpv_control_box.c gmpv_control_box.h \
+			gmpv_file_chooser.c gmpv_file_chooser.h \
 			gmpv_geometry.h \
 			gmpv_header_bar.c gmpv_header_bar.h \
-			gmpv_inputctl.c gmpv_inputctl.h \
 			gmpv_main_window.c gmpv_main_window.h \
 			gmpv_menu.c gmpv_menu.h \
+			gmpv_model.c gmpv_model.h \
 			gmpv_mpv.c gmpv_mpv.h \
 			gmpv_mpv_private.h \
 			gmpv_mpv_opt.c gmpv_mpv_opt.h \
-			gmpv_open_loc_dialog.c gmpv_open_loc_dialog.h \
-			gmpv_playbackctl.c gmpv_playbackctl.h \
-			gmpv_playlist.c gmpv_playlist.h \
+			gmpv_open_location_dialog.c gmpv_open_location_dialog.h \
 			gmpv_playlist_widget.c gmpv_playlist_widget.h \
 			gmpv_plugins_manager.c gmpv_plugins_manager.h \
 			gmpv_plugins_manager_item.c gmpv_plugins_manager_item.h \
 			gmpv_pref_dialog.c gmpv_pref_dialog.h \
 			gmpv_seek_bar.c gmpv_seek_bar.h \
-			gmpv_track.c gmpv_track.h \
 			gmpv_video_area.c gmpv_video_area.h \
+			gmpv_view.c gmpv_view.h \
 			gmpv_mpv_wrapper.c gmpv_mpv_wrapper.h \
 			$(mpris_files) $(marshal_files) $(media_key_files) \
 			$(authors_files)
@@ -69,8 +74,10 @@ endif
 
 gnome_mpv_CFLAGS =	$(DEPS_CFLAGS) \
 			-DG_SETTINGS_ENABLE_BACKEND \
-			-DPACKAGE_LOCALEDIR=\""$(localedir)"\"
+			-DPACKAGE_LOCALEDIR=\""$(localedir)"\" \
+			-Impris
 
 gnome_mpv_LDADD = $(DEPS_LIBS)
 
 CLEANFILES = $(mpris_generated) $(marshal_generated) $(authors_generated)
+EXTRA_DIST = meson.build generate_authors.py
diff --git a/src/generate_authors.py b/src/generate_authors.py
new file mode 100755
index 0000000..fb3f1f6
--- /dev/null
+++ b/src/generate_authors.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+
+import sys
+
+in_file = sys.argv[1]
+out_file = sys.argv[2]
+
+with open(in_file) as i, open(out_file, 'w') as o:
+    o.write('#pragma once\n\n')
+    o.write('#define AUTHORS {\\\n')
+
+    for author in i:
+        if not author.startswith('#'):
+            o.write('"{}",\\\n'.format(author.rstrip()))
+
+    o.write('NULL}\n')
+
diff --git a/src/gmpv_actionctl.c b/src/gmpv_actionctl.c
deleted file mode 100644
index 9c994fb..0000000
--- a/src/gmpv_actionctl.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/*
- * Copyright (c) 2015-2016 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <gio/gio.h>
-#include <glib-object.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <mpv/client.h>
-#include <string.h>
-
-#include "gmpv_actionctl.h"
-#include "gmpv_playlist_widget.h"
-#include "gmpv_def.h"
-#include "gmpv_mpv.h"
-#include "gmpv_mpv_wrapper.h"
-#include "gmpv_main_window.h"
-#include "gmpv_playlist.h"
-#include "gmpv_open_loc_dialog.h"
-#include "gmpv_pref_dialog.h"
-#include "gmpv_common.h"
-#include "gmpv_control_box.h"
-#include "gmpv_authors.h"
-
-#if GTK_CHECK_VERSION(3, 20, 0)
-#include "gmpv_shortcuts_window.h"
-#endif
-
-static void open_dialog_response_handler(	GtkDialog *dialog,
-						gint response_id,
-						gpointer data );
-static void open_location_dialog_response_handler(	GtkDialog *dialog,
-							gint response_id,
-							gpointer data );
-static void preferences_dialog_response_handler(	GtkDialog *dialog,
-							gint response_id,
-							gpointer data );
-static void show_open_dialog_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data );
-static void show_open_location_dialog_handler(	GSimpleAction *action,
-						GVariant *param,
-						gpointer data );
-static void toggle_loop_handler(	GSimpleAction *action,
-					GVariant *value,
-					gpointer data );
-static void show_shortcuts_dialog_handler(	GSimpleAction *action,
-						GVariant *param,
-						gpointer data );
-static void toggle_controls_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data );
-static void toggle_playlist_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data );
-static void save_playlist_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data );
-static void remove_selected_playlist_item_handler(	GSimpleAction *action,
-							GVariant *param,
-							gpointer data );
-static void show_preferences_dialog_handler(	GSimpleAction *action,
-						GVariant *param,
-						gpointer data );
-static void quit_handler(	GSimpleAction *action,
-				GVariant *param,
-				gpointer data );
-static void set_track_handler(	GSimpleAction *action,
-					GVariant *value,
-					gpointer data );
-static void load_track_handler(	GSimpleAction *action,
-				GVariant *param,
-				gpointer data );
-static void fullscreen_handler(	GSimpleAction *action,
-				GVariant *param,
-				gpointer data );
-static void set_video_size_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data );
-static void show_about_dialog_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data );
-
-static void open_dialog_response_handler(	GtkDialog *dialog,
-						gint response_id,
-						gpointer data )
-{
-	GPtrArray *args = data;
-	GmpvApplication *app = g_ptr_array_index(args, 0);
-	gboolean *append = g_ptr_array_index(args, 1);
-
-	if(response_id == GTK_RESPONSE_ACCEPT)
-	{
-		GtkFileChooser *file_chooser;
-		GSList *uri_slist;
-		GSList *uri;
-		GSettings *main_config;
-		GSettings *win_config;
-		gboolean last_folder_enable;
-		gsize uri_list_size;
-		const gchar **uri_list;
-		gint i;
-
-		file_chooser = GTK_FILE_CHOOSER(dialog);
-		uri_slist = gtk_file_chooser_get_filenames(file_chooser);
-		uri = uri_slist;
-		main_config = g_settings_new(CONFIG_ROOT);
-		win_config = g_settings_new(CONFIG_WIN_STATE);
-		last_folder_enable =	g_settings_get_boolean
-					(main_config, "last-folder-enable");
-		uri_list_size =	sizeof(gchar **)*(g_slist_length(uri_slist)+1);
-		uri_list = g_malloc(uri_list_size);
-
-		for(i = 0; uri; i++)
-		{
-			uri_list[i] = uri->data;
-			uri = g_slist_next(uri);
-		}
-
-		uri_list[i] = NULL;
-
-		if(uri_slist)
-		{
-			GmpvMpv *mpv = gmpv_application_get_mpv(app);
-
-			gmpv_mpv_load_list(mpv, uri_list, *append, TRUE);
-		}
-
-		if(last_folder_enable)
-		{
-			gchar *last_folder_uri
-				= gtk_file_chooser_get_current_folder_uri
-					(file_chooser);
-
-			g_settings_set_string(	win_config,
-						"last-folder-uri",
-						last_folder_uri?:"" );
-
-			g_free(last_folder_uri);
-		}
-
-		g_free(uri_list);
-		g_slist_free_full(uri_slist, g_free);
-		g_object_unref(main_config);
-		g_object_unref(win_config);
-	}
-
-	g_free(append);
-	g_ptr_array_free(args, TRUE);
-	gmpv_file_chooser_destroy(dialog);
-}
-
-static void open_location_dialog_response_handler(	GtkDialog *dialog,
-							gint response_id,
-							gpointer data )
-{
-	GPtrArray *args = data;
-	gboolean *append = g_ptr_array_index(args, 1);
-
-	if(response_id == GTK_RESPONSE_ACCEPT)
-	{
-		GmpvApplication *app;
-		GmpvMpv *mpv;
-		const gchar *loc_str;
-
-		app = g_ptr_array_index(args, 0);
-		mpv = gmpv_application_get_mpv(app);
-		loc_str =	gmpv_open_loc_dialog_get_string
-				(GMPV_OPEN_LOC_DIALOG(dialog));
-
-		gmpv_mpv_set_property_flag(mpv, "pause", FALSE);
-		gmpv_mpv_load(mpv, loc_str, *append, TRUE);
-	}
-
-	g_free(append);
-	g_ptr_array_free(args, TRUE);
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-static void preferences_dialog_response_handler(	GtkDialog *dialog,
-							gint response_id,
-							gpointer data )
-{
-	if(response_id == GTK_RESPONSE_ACCEPT)
-	{
-		GmpvApplication *app;
-		GmpvMainWindow *wnd;
-		GmpvMpv *mpv;
-		GSettings *settings;
-		gboolean csd_enable;
-		gboolean dark_theme_enable;
-
-		app = data;
-		wnd = gmpv_application_get_main_window(app);
-		mpv = gmpv_application_get_mpv(app);
-		settings = g_settings_new(CONFIG_ROOT);
-		csd_enable = g_settings_get_boolean(settings, "csd-enable");
-		dark_theme_enable =	g_settings_get_boolean
-					(settings, "dark-theme-enable");
-
-		if(gmpv_main_window_get_csd_enabled(wnd) != csd_enable)
-		{
-			GtkWidget *dialog;
-
-			dialog =	gtk_message_dialog_new
-					(	GTK_WINDOW(wnd),
-						GTK_DIALOG_DESTROY_WITH_PARENT,
-						GTK_MESSAGE_INFO,
-						GTK_BUTTONS_OK,
-						_("Enabling or disabling "
-						"client-side decorations "
-						"requires restarting %s to "
-						"take effect." ),
-						g_get_application_name() );
-
-			g_signal_connect(	dialog,
-						"response",
-						G_CALLBACK(gtk_widget_destroy),
-						NULL );
-
-			gtk_widget_show_all(dialog);
-		}
-
-		g_object_set(	gtk_settings_get_default(),
-				"gtk-application-prefer-dark-theme",
-				dark_theme_enable,
-				NULL );
-
-		gmpv_mpv_reset(mpv);
-		gtk_widget_queue_draw(GTK_WIDGET(wnd));
-		g_object_unref(settings);
-	}
-
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-static void show_open_dialog_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data )
-{
-	const gchar *pl_exts[] = PLAYLIST_EXTS;
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd = NULL;
-	GSettings *main_config = NULL;
-	GSettings *win_config = NULL;
-	GtkFileChooser *file_chooser = NULL;
-	GtkFileFilter *filter = NULL;
-	GmpvFileChooser *open_dialog = NULL;
-	gboolean last_folder_enable = FALSE;
-	gboolean *append = g_malloc(sizeof(gboolean));
-	GPtrArray *args = g_ptr_array_sized_new(2);
-
-	g_variant_get(param, "b", append);
-
-	wnd = gmpv_application_get_main_window(app);
-	open_dialog = gmpv_file_chooser_new(	(*append)?
-						_("Add File to Playlist"):
-						_("Open File"),
-						GTK_WINDOW(wnd),
-						GTK_FILE_CHOOSER_ACTION_OPEN,
-						_("_Open"),
-						_("_Cancel"));
-	main_config = g_settings_new(CONFIG_ROOT);
-	file_chooser = GTK_FILE_CHOOSER(open_dialog);
-	last_folder_enable =	g_settings_get_boolean
-				(main_config, "last-folder-enable");
-	filter = gtk_file_filter_new();
-
-	g_ptr_array_add(args, app);
-	g_ptr_array_add(args, append);
-
-	g_signal_connect(	open_dialog,
-				"response",
-				G_CALLBACK(open_dialog_response_handler),
-				args );
-
-	gtk_file_filter_add_mime_type(filter, "video/*");
-	gtk_file_filter_add_mime_type(filter, "audio/*");
-	gtk_file_filter_add_mime_type(filter, "image/*");
-
-	for(gint i = 0; pl_exts[i]; i++)
-	{
-		gchar *pattern = g_strdup_printf("*.%s", pl_exts[i]);
-
-		gtk_file_filter_add_pattern(filter, pattern);
-		g_free(pattern);
-	}
-
-	gtk_file_chooser_set_filter(file_chooser, filter);
-
-	if(last_folder_enable)
-	{
-		gchar *last_folder_uri;
-
-		win_config = g_settings_new(CONFIG_WIN_STATE);
-		last_folder_uri =	g_settings_get_string
-					(win_config, "last-folder-uri");
-
-		if(last_folder_uri && strlen(last_folder_uri) > 0)
-		{
-			gtk_file_chooser_set_current_folder_uri
-				(file_chooser, last_folder_uri);
-		}
-
-		g_free(last_folder_uri);
-	}
-
-	gtk_file_chooser_set_select_multiple(file_chooser, TRUE);
-	gmpv_file_chooser_set_modal(open_dialog, TRUE);
-	gmpv_file_chooser_show(open_dialog);
-
-	g_object_unref(main_config);
-	g_object_unref(win_config);
-}
-
-static void show_open_location_dialog_handler(	GSimpleAction *action,
-						GVariant *param,
-						gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	GtkWidget *dlg = NULL;
-	gboolean *append = g_malloc(sizeof(gboolean));
-	GPtrArray *args = g_ptr_array_sized_new(2);
-
-	g_variant_get(param, "b", append);
-
-	dlg = gmpv_open_loc_dialog_new(	GTK_WINDOW(wnd),
-					(*append)?
-					_("Add Location to Playlist"):
-					_("Open Location") );
-	g_ptr_array_add(args, app);
-	g_ptr_array_add(args, append);
-
-	g_signal_connect
-		(	dlg,
-			"response",
-			G_CALLBACK(open_location_dialog_response_handler),
-			args );
-
-	gtk_widget_show_all(dlg);
-}
-
-static void toggle_loop_handler(	GSimpleAction *action,
-					GVariant *value,
-					gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
-	gboolean loop = g_variant_get_boolean(value);
-
-	g_simple_action_set_state(action, value);
-	gmpv_mpv_set_property_string(mpv, "loop", loop?"inf":"no");
-}
-
-static void show_shortcuts_dialog_handler(	GSimpleAction *action,
-						GVariant *param,
-						gpointer data )
-{
-#if GTK_CHECK_VERSION(3, 20, 0)
-	GmpvApplication *app = data;
-	GmpvMainWindow *mwnd = gmpv_application_get_main_window(app);
-	GtkWidget *wnd = gmpv_shortcuts_window_new(GTK_WINDOW(mwnd));
-
-	gtk_widget_show_all(wnd);
-#endif
-}
-
-static void toggle_controls_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	GmpvControlBox *ctrl = gmpv_main_window_get_control_box(wnd);
-	gboolean visible = gtk_widget_get_visible(GTK_WIDGET(ctrl));
-
-	gtk_widget_set_visible(GTK_WIDGET(ctrl), !visible);
-}
-
-static void toggle_playlist_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	gboolean visible = gmpv_main_window_get_playlist_visible(wnd);
-
-	gmpv_main_window_set_playlist_visible(wnd, !visible);
-}
-
-static void save_playlist_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMpv *mpv;
-	GmpvMainWindow *wnd;
-	GmpvPlaylist *playlist;
-	GtkTreeModel *model;
-	GFile *dest_file;
-	GOutputStream *dest_stream;
-	GtkFileChooser *file_chooser;
-	GmpvFileChooser *save_dialog;
-	GError *error;
-	GtkTreeIter iter;
-	gboolean rc;
-
-	mpv = gmpv_application_get_mpv(app);
-	wnd = gmpv_application_get_main_window(app);
-	playlist = gmpv_mpv_get_playlist(mpv);
-	model = GTK_TREE_MODEL(gmpv_playlist_get_store(playlist));
-	dest_file = NULL;
-	dest_stream = NULL;
-	save_dialog =	gmpv_file_chooser_new
-			(	_("Save Playlist"),
-				GTK_WINDOW(wnd),
-				GTK_FILE_CHOOSER_ACTION_SAVE,
-				_("_Save"),
-				_("_Cancel") );
-	file_chooser = GTK_FILE_CHOOSER(save_dialog);
-	error = NULL;
-	rc = FALSE;
-
-	gtk_file_chooser_set_do_overwrite_confirmation(file_chooser, TRUE);
-	gtk_file_chooser_set_current_name(file_chooser, "playlist.m3u");
-
-	if(gmpv_file_chooser_run(save_dialog) == GTK_RESPONSE_ACCEPT)
-	{
-		/* There should be only one file selected. */
-		dest_file = gtk_file_chooser_get_file(file_chooser);
-	}
-
-	gmpv_file_chooser_destroy(save_dialog);
-
-	if(dest_file)
-	{
-		GFileOutputStream *dest_file_stream;
-
-		dest_file_stream = g_file_replace(	dest_file,
-							NULL,
-							FALSE,
-							G_FILE_CREATE_NONE,
-							NULL,
-							&error );
-
-		dest_stream = G_OUTPUT_STREAM(dest_file_stream);
-		rc = gtk_tree_model_get_iter_first(model, &iter);
-		rc &= !!dest_stream;
-	}
-
-	while(rc)
-	{
-		gchar *uri;
-		gsize written;
-
-		gtk_tree_model_get
-			(model, &iter, PLAYLIST_URI_COLUMN, &uri, -1);
-
-		rc &= g_output_stream_printf(	dest_stream,
-						&written,
-						NULL,
-						&error,
-						"%s\n",
-						uri );
-		rc &= gtk_tree_model_iter_next(model, &iter);
-	}
-
-	if(dest_stream)
-	{
-		g_output_stream_close(dest_stream, NULL, &error);
-	}
-
-	if(dest_file)
-	{
-		g_object_unref(dest_file);
-	}
-
-	if(error)
-	{
-		show_error_dialog(app, NULL, error->message);
-
-		g_error_free(error);
-	}
-}
-
-static void remove_selected_playlist_item_handler(	GSimpleAction *action,
-							GVariant *param,
-							gpointer data )
-{
-	GmpvMainWindow *wnd =	gmpv_application_get_main_window
-				(GMPV_APPLICATION(data));
-
-	if(gmpv_main_window_get_playlist_visible(wnd))
-	{
-		GmpvPlaylistWidget *playlist;
-
-		playlist = gmpv_main_window_get_playlist(wnd);
-
-		gmpv_playlist_widget_remove_selected(playlist);
-	}
-}
-
-static void show_preferences_dialog_handler(	GSimpleAction *action,
-						GVariant *param,
-						gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	GtkWidget *pref_dialog = gmpv_pref_dialog_new(GTK_WINDOW(wnd));
-
-	g_signal_connect_after(	pref_dialog,
-				"response",
-				G_CALLBACK(preferences_dialog_response_handler),
-				app );
-
-	gtk_widget_show_all(pref_dialog);
-}
-
-static void quit_handler(	GSimpleAction *action,
-				GVariant *param,
-				gpointer data )
-{
-	gmpv_application_quit(data);
-}
-
-static void set_track_handler(	GSimpleAction *action,
-				GVariant *value,
-				gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMpv *mpv;
-	gint64 id;
-	gchar *name;
-	const gchar *mpv_prop;
-
-	g_object_get(action, "name", &name, NULL);
-	g_variant_get(value, "x", &id);
-	g_simple_action_set_state(action, value);
-
-	if(g_strcmp0(name, "set-audio-track") == 0)
-	{
-		mpv_prop = "aid";
-	}
-	else if(g_strcmp0(name, "set-video-track") == 0)
-	{
-		mpv_prop = "vid";
-	}
-	else if(g_strcmp0(name, "set-subtitle-track") == 0)
-	{
-		mpv_prop = "sid";
-	}
-	else
-	{
-		g_assert_not_reached();
-	}
-
-	mpv = gmpv_application_get_mpv(app);
-
-	if(id > 0)
-	{
-		gmpv_mpv_set_property(mpv, mpv_prop, MPV_FORMAT_INT64, &id);
-	}
-	else
-	{
-		gmpv_mpv_set_property_string(mpv, mpv_prop, "no");
-	}
-}
-
-static void load_track_handler(	GSimpleAction *action,
-				GVariant *param,
-				gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd;
-	GtkFileChooser *file_chooser;
-	GtkFileFilter *filter;
-	GtkWidget *open_dialog;
-	const gchar *cmd_name;
-
-	g_variant_get(param, "s", &cmd_name);
-
-	wnd = gmpv_application_get_main_window(app);
-	open_dialog =	gtk_file_chooser_dialog_new
-			(	_("Load External…"),
-				GTK_WINDOW(wnd),
-				GTK_FILE_CHOOSER_ACTION_OPEN,
-				_("_Cancel"), GTK_RESPONSE_CANCEL,
-				_("_Open"), GTK_RESPONSE_ACCEPT,
-				NULL );
-	file_chooser = GTK_FILE_CHOOSER(open_dialog);
-	filter = gtk_file_filter_new();
-
-	gtk_file_chooser_set_filter(file_chooser, filter);
-
-	if (g_strcmp0(cmd_name, "audio-add") == 0)
-	{
-		gtk_file_filter_add_mime_type(filter, "audio/*");
-	}
-	else if (g_strcmp0(cmd_name, "sub-add") == 0)
-	{
-		static const char *const sub_exts[] = SUBTITLE_EXTS;
-
-		for(gint i = 0; sub_exts[i]; i++)
-		{
-			gchar *pattern = g_strdup_printf("*.%s", sub_exts[i]);
-
-			gtk_file_filter_add_pattern(filter, pattern);
-			g_free(pattern);
-		}
-	}
-
-	gtk_file_chooser_set_select_multiple(file_chooser, TRUE);
-
-	if(gtk_dialog_run(GTK_DIALOG(open_dialog)) == GTK_RESPONSE_ACCEPT)
-	{
-		const gchar *cmd[] = {cmd_name, NULL, NULL};
-		GmpvMpv *mpv = gmpv_application_get_mpv(app);
-		GSList *uri_list = gtk_file_chooser_get_filenames(file_chooser);
-		GSList *uri = uri_list;
-
-		while(uri)
-		{
-			cmd[1] = uri->data;
-
-			gmpv_mpv_command(mpv, cmd);
-
-			uri = g_slist_next(uri);
-		}
-
-		g_slist_free_full(uri_list, g_free);
-	}
-
-	gtk_widget_destroy(open_dialog);
-}
-
-static void fullscreen_handler(	GSimpleAction *action,
-				GVariant *param,
-				gpointer data )
-{
-	GmpvMainWindow *wnd =	gmpv_application_get_main_window
-				(GMPV_APPLICATION(data));
-	gchar *name;
-
-	g_object_get(action, "name", &name, NULL);
-
-	if(g_strcmp0(name, "toggle-fullscreen") == 0)
-	{
-		gmpv_main_window_toggle_fullscreen(wnd);
-	}
-	else if(g_strcmp0(name, "enter-fullscreen") == 0)
-	{
-		gmpv_main_window_set_fullscreen(wnd, TRUE);
-	}
-	else if(g_strcmp0(name, "leave-fullscreen") == 0)
-	{
-		gmpv_main_window_set_fullscreen(wnd, FALSE);
-	}
-
-	g_free(name);
-}
-
-static void set_video_size_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data )
-{
-	gdouble value = g_variant_get_double (param);
-
-	resize_window_to_fit((GmpvApplication *)data, value);
-}
-
-static void show_about_dialog_handler(	GSimpleAction *action,
-					GVariant *param,
-					gpointer data )
-{
-	GmpvApplication *app = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	const gchar *authors[] = AUTHORS;
-
-	gtk_show_about_dialog(	GTK_WINDOW(wnd),
-				"logo-icon-name",
-				ICON_NAME,
-				"version",
-				VERSION,
-				"comments",
-				_("A GTK frontend for MPV"),
-				"website",
-				"https://github.com/gnome-mpv/gnome-mpv",
-				"license-type",
-				GTK_LICENSE_GPL_3_0,
-				"copyright",
-				"\u00A9 2014-2016 The GNOME MPV authors",
-				"authors",
-				authors,
-				"translator-credits",
-				_("translator-credits"),
-				NULL );
-}
-
-void gmpv_actionctl_map_actions(GmpvApplication *app)
-{
-	const GActionEntry entries[]
-		= {	{.name = "show-open-dialog",
-			.activate = show_open_dialog_handler,
-			.parameter_type = "b"},
-			{.name = "quit",
-			.activate = quit_handler},
-			{.name = "show-about-dialog",
-			.activate = show_about_dialog_handler},
-			{.name = "show-preferences-dialog",
-			.activate = show_preferences_dialog_handler},
-			{.name = "show-open-location-dialog",
-			.activate = show_open_location_dialog_handler,
-			.parameter_type = "b"},
-			{.name = "toggle-loop",
-			.state = "false",
-			.change_state = toggle_loop_handler},
-			{.name = "show-shortcuts-dialog",
-			.activate = show_shortcuts_dialog_handler},
-			{.name = "toggle-controls",
-			.activate = toggle_controls_handler},
-			{.name = "toggle-playlist",
-			.activate = toggle_playlist_handler},
-			{.name = "save-playlist",
-			.activate = save_playlist_handler},
-			{.name = "remove-selected-playlist-item",
-			.activate = remove_selected_playlist_item_handler},
-			{.name = "set-audio-track",
-			.change_state = set_track_handler,
-			.state = "@x 0",
-			.parameter_type = "x"},
-			{.name = "set-video-track",
-			.change_state = set_track_handler,
-			.state = "@x 0",
-			.parameter_type = "x"},
-			{.name = "set-subtitle-track",
-			.change_state = set_track_handler,
-			.state = "@x 0",
-			.parameter_type = "x"},
-			{.name = "load-track",
-			.activate = load_track_handler,
-			.parameter_type = "s"},
-			{.name = "toggle-fullscreen",
-			.activate = fullscreen_handler},
-			{.name = "enter-fullscreen",
-			.activate = fullscreen_handler},
-			{.name = "leave-fullscreen",
-			.activate = fullscreen_handler},
-			{.name = "set-video-size",
-			.activate = set_video_size_handler,
-			.parameter_type = "d"} };
-
-	g_action_map_add_action_entries(	G_ACTION_MAP(app),
-						entries,
-						G_N_ELEMENTS(entries),
-						app );
-}
diff --git a/src/gmpv_application.c b/src/gmpv_application.c
index 9e90a1b..06344a5 100644
--- a/src/gmpv_application.c
+++ b/src/gmpv_application.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -20,273 +20,175 @@
 #include <glib/gi18n.h>
 #include <glib/gprintf.h>
 #include <glib-unix.h>
-#include <gdk/gdk.h>
+#include <gio/gio.h>
 #include <locale.h>
-#include <epoxy/gl.h>
 
 #include "gmpv_application.h"
-#include "gmpv_control_box.h"
-#include "gmpv_actionctl.h"
-#include "gmpv_inputctl.h"
-#include "gmpv_playbackctl.h"
-#include "gmpv_playlist_widget.h"
-#include "gmpv_track.h"
+#include "gmpv_application_private.h"
+#include "gmpv_application_action.h"
+#include "gmpv_mpv_wrapper.h"
 #include "gmpv_common.h"
 #include "gmpv_menu.h"
-#include "gmpv_mpv.h"
-#include "gmpv_mpv_wrapper.h"
-#include "gmpv_video_area.h"
 #include "gmpv_def.h"
 #include "mpris/gmpv_mpris.h"
 #include "media_keys/gmpv_media_keys.h"
 
-struct _GmpvApplication
-{
-	GtkApplication parent;
-	gboolean no_existing_session;
-	GmpvMpv *mpv;
-	GQueue *action_queue;
-	gchar **files;
-	guint inhibit_cookie;
-	gint64 target_playlist_pos;
-	GSettings *config;
-	GmpvMainWindow *gui;
-	GtkWidget *fs_control;
-	GmpvPlaylist *playlist_store;
-};
-
-struct _GmpvApplicationClass
-{
-	GtkApplicationClass parent_class;
-};
-
-static gboolean vid_area_render_handler(	GtkGLArea *area,
-						GdkGLContext *context,
-						gpointer data );
+static void migrate_config(void);
+static void activate_action_string(GmpvApplication *app, const gchar *str);
+static void update_track_id(	GmpvApplication *app,
+				const gchar *action_name,
+				const gchar *prop );
+static void initialize_gui(GmpvApplication *app);
+static gboolean shutdown_signal_handler(gpointer data);
+static void activate_handler(GApplication *gapp, gpointer data);
+static void open_handler(	GApplication *gapp,
+				GFile **files,
+				gint n_files,
+				gchar *hint,
+				gpointer data );
 static gint options_handler(	GApplication *gapp,
 				GVariantDict *options,
 				gpointer data );
-static gint command_line_handler(	GApplication *app,
+static gint command_line_handler(	GApplication *gapp,
 					GApplicationCommandLine *cli,
 					gpointer data );
 static void startup_handler(GApplication *gapp, gpointer data);
-static void activate_handler(GApplication *gapp, gpointer data);
-static void open_handler(	GApplication *gapp,
-				gpointer files,
-				gint n_files,
-				gchar *hint,
+static void aid_handler(	GObject *object,
+				GParamSpec *pspec,
 				gpointer data );
-static gboolean draw_handler(GtkWidget *widget, cairo_t *cr, gpointer data);
-static gboolean delete_handler(	GtkWidget *widget,
-				GdkEvent *event,
+static void vid_handler(	GObject *object,
+				GParamSpec *pspec,
 				gpointer data );
-static void grab_handler(GtkWidget *widget, gboolean was_grabbed, gpointer data);
-static void playlist_row_activated_handler(	GmpvPlaylistWidget *playlist,
-						gint64 pos,
-						gpointer data );
-static void playlist_row_deleted_handler(	GmpvPlaylistWidget *playlist,
-						gint pos,
-						gpointer data );
-static void playlist_row_reodered_handler(	GmpvPlaylistWidget *playlist,
-						gint src,
-						gint dest,
-						gpointer data );
-static GmpvTrack *parse_track_list(mpv_node_list *node);
-static void update_track_list(GmpvApplication *app, mpv_node* track_list);
-static gchar *strnjoinv(	const gchar *separator,
-				const gchar **str_array,
-				gsize count );
-static gboolean process_action(gpointer data);
-static void mpv_prop_change_handler(mpv_event_property *prop, gpointer data);
-static void mpv_event_handler(mpv_event *event, gpointer data);
-static void mpv_error_handler(GmpvMpv *mpv, const gchar *err, gpointer data);
-static gboolean shutdown_signal_handler(gpointer data);
-static void drag_data_handler(	GtkWidget *widget,
-				GdkDragContext *context,
-				gint x,
-				gint y,
-				GtkSelectionData *sel_data,
-				guint info,
-				guint time,
-				gpointer data);
-static gboolean window_state_handler(	GtkWidget *widget,
-					GdkEvent *event,
-					gpointer data );
-static gboolean queue_render(GtkGLArea *area);
-static void opengl_cb_update_callback(void *cb_ctx);
-static void set_playlist_pos(GmpvApplication *app, gint64 pos);
-static void set_inhibit_idle(GmpvApplication *app, gboolean inhibit);
-static gboolean load_files(	GmpvApplication* app,
-				const gchar **files,
-				gboolean append );
-static void connect_signals(GmpvApplication *app);
+static void sid_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static void idle_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static void ready_handler(GObject *object, GParamSpec *pspec, gpointer data);
+static void message_handler(	GmpvController *controller,
+				const gchar *message,
+				gpointer data );
+static void shutdown_handler(GmpvController *controller, gpointer data);
 static void gmpv_application_class_init(GmpvApplicationClass *klass);
 static void gmpv_application_init(GmpvApplication *app);
 
 G_DEFINE_TYPE(GmpvApplication, gmpv_application, GTK_TYPE_APPLICATION)
 
-static gboolean vid_area_render_handler(	GtkGLArea *area,
-						GdkGLContext *context,
-						gpointer data )
+static void migrate_config()
 {
-	GmpvApplication *app = data;
-	mpv_opengl_cb_context *opengl_ctx;
+	const gchar *keys[] = {	"dark-theme-enable",
+				"csd-enable",
+				"last-folder-enable",
+				"mpv-options",
+				"mpv-config-file",
+				"mpv-config-enable",
+				"mpv-input-config-file",
+				"mpv-input-config-enable",
+				NULL };
 
-	opengl_ctx = gmpv_mpv_get_opengl_cb_context(app->mpv);
+	GSettings *old_settings = g_settings_new("org.gnome-mpv");
+	GSettings *new_settings = g_settings_new(CONFIG_ROOT);
 
-	if(opengl_ctx)
+	if(!g_settings_get_boolean(new_settings, "settings-migrated"))
 	{
-		int width;
-		int height;
-		int fbo;
+		g_settings_set_boolean(new_settings, "settings-migrated", TRUE);
 
-		width = gtk_widget_get_allocated_width(GTK_WIDGET(area));
-		height = (-1)*gtk_widget_get_allocated_height(GTK_WIDGET(area));
-		fbo = -1;
+		for(gint i = 0; keys[i]; i++)
+		{
+			GVariant *buf = g_settings_get_user_value
+						(old_settings, keys[i]);
 
-		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
-		mpv_opengl_cb_draw(opengl_ctx, fbo, width, height);
-	}
+			if(buf)
+			{
+				g_settings_set_value
+					(new_settings, keys[i], buf);
 
-	while(gtk_events_pending())
-	{
-		gtk_main_iteration();
+				g_variant_unref(buf);
+			}
+		}
 	}
 
-	return TRUE;
+	g_object_unref(old_settings);
+	g_object_unref(new_settings);
 }
 
-static gint options_handler(	GApplication *gapp,
-				GVariantDict *options,
-				gpointer data )
+static void activate_action_string(GmpvApplication *app, const gchar *str)
 {
-	gboolean version = FALSE;
+	GActionMap *map = G_ACTION_MAP(app);
+	GAction *action = NULL;
+	gchar *name = NULL;
+	GVariant *param = NULL;
+	gboolean param_match = FALSE;
 
-	g_variant_dict_lookup(options, "version", "b", &version);
+	g_action_parse_detailed_name(str, &name, &param, NULL);
 
-	if(version)
-	{
-		g_printf("GNOME MPV " VERSION "\n");
-	}
-	else
+	if(name)
 	{
-		GmpvApplication *app = data;
-		GSettings *settings = g_settings_new(CONFIG_ROOT);
+		const GVariantType *action_ptype;
+		const GVariantType *given_ptype;
 
-		g_variant_dict_lookup(	options,
-					"no-existing-session",
-					"b",
-					&app->no_existing_session );
-
-		app->no_existing_session
-			|=	g_settings_get_boolean
-				(	settings,
-					"multiple-instances-enable" );
-
-		if(app->no_existing_session)
-		{
-			GApplicationFlags flags = g_application_get_flags(gapp);
-
-			g_info("Single instance negotiation is disabled");
-			g_application_set_flags
-				(gapp, flags|G_APPLICATION_NON_UNIQUE);
-		}
+		action = g_action_map_lookup_action(map, name);
+		action_ptype = g_action_get_parameter_type(action);
+		given_ptype = param?g_variant_get_type(param):NULL;
 
-		g_clear_object(&settings);
+		param_match =	(action_ptype == given_ptype) ||
+				(	given_ptype &&
+					g_variant_type_is_subtype_of
+					(action_ptype, given_ptype) );
 	}
 
-	return -1;
+	if(action && param_match)
+	{
+		g_debug("Activating action %s", str);
+		g_action_activate(action, param);
+	}
+	else
+	{
+		g_warning("Failed to activate action \"%s\"", str);
+	}
 }
 
-static gint command_line_handler(	GApplication *app,
-					GApplicationCommandLine *cli,
-					gpointer data )
+static void update_track_id(	GmpvApplication *app,
+				const gchar *action_name,
+				const gchar *prop )
 {
-	gint argc = 1;
-	gchar **argv = g_application_command_line_get_arguments(cli, &argc);
-	GVariantDict *options = g_application_command_line_get_options_dict(cli);
-	gboolean enqueue = FALSE;
-	const gint n_files = argc-1;
-	GFile *files[n_files];
+	GActionMap *action_map = G_ACTION_MAP(app);
+	GAction *action = g_action_map_lookup_action(action_map, action_name);
+	gint64 id = 0;
 
-	g_variant_dict_lookup(options, "enqueue", "b", &enqueue);
+	g_object_get(app->controller, prop, &id, NULL);
 
-	for(gint i = 0; i < n_files; i++)
+	if(id >= 0 && action)
 	{
-		files[i] =	g_application_command_line_create_file_for_arg
-				(cli, argv[i+1]);
-	}
+		GVariant *value = g_variant_new_int64(id);
 
-	if(n_files > 0)
-	{
-		g_application_open(app, files, n_files, enqueue?"enqueue":"");
+		g_action_change_state(action, value);
 	}
-
-	for(gint i = 0; i < n_files; i++)
+	else if(!action)
 	{
-		g_object_unref(files[i]);
+		g_warning("Cannot find action: %s", action_name);
 	}
-
-	g_strfreev(argv);
-
-	return 0;
 }
 
-static void startup_handler(GApplication *gapp, gpointer data)
+static void initialize_gui(GmpvApplication *app)
 {
-	GmpvApplication *app = data;
-	GmpvControlBox *control_box;
-	const gchar *style = ".gmpv-vid-area{background-color: black}";
-	GtkCssProvider *style_provider;
-	gboolean css_loaded;
+	GSettings *settings = g_settings_new(CONFIG_ROOT);
 	gboolean csd_enable;
-	gboolean dark_theme_enable;
+	gboolean always_floating;
 	gint64 wid;
 	gchar *mpvinput;
 
-	setlocale(LC_NUMERIC, "C");
-	g_set_application_name(_("GNOME MPV"));
-	gtk_window_set_default_icon_name(ICON_NAME);
-
-	bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALEDIR);
-	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
-	textdomain(GETTEXT_PACKAGE);
+	csd_enable =		g_settings_get_boolean
+				(settings, "csd-enable");
+	always_floating =	g_settings_get_boolean
+				(settings, "always-use-floating-controls");
+	mpvinput =		g_settings_get_string
+				(settings, "mpv-input-config-file");
 
-	g_info("Starting GNOME MPV " VERSION);
-
-	app->files = NULL;
-	app->inhibit_cookie = 0;
-	app->target_playlist_pos = -1;
-	app->config = g_settings_new(CONFIG_ROOT);
-	app->playlist_store = gmpv_playlist_new();
-	app->gui = GMPV_MAIN_WINDOW(gmpv_main_window_new(app, app->playlist_store));
-	app->fs_control = NULL;
+	app->gui = GMPV_MAIN_WINDOW(gmpv_main_window_new(app, always_floating));
 
-	migrate_config(app);
-
-	control_box = gmpv_main_window_get_control_box(app->gui);
-	style_provider = gtk_css_provider_new();
-	css_loaded =	gtk_css_provider_load_from_data
-			(style_provider, style, -1, NULL);
-
-	if(!css_loaded)
-	{
-		g_warning ("Failed to apply background color css");
-	}
-
-	gtk_style_context_add_provider_for_screen
-		(	gtk_window_get_screen(GTK_WINDOW(app->gui)),
-			GTK_STYLE_PROVIDER(style_provider),
-			GTK_STYLE_PROVIDER_PRIORITY_APPLICATION );
-
-	g_object_unref(style_provider);
-
-	csd_enable = g_settings_get_boolean
-				(app->config, "csd-enable");
-	dark_theme_enable = g_settings_get_boolean
-				(app->config, "dark-theme-enable");
-	mpvinput = g_settings_get_string
-				(app->config, "mpv-input-config-file");
+	migrate_config();
 
 	if(csd_enable)
 	{
@@ -302,663 +204,257 @@ static void startup_handler(GApplication *gapp, gpointer data)
 	{
 		GMenu *full_menu = g_menu_new();
 
-		gmpv_menu_build_full(full_menu, NULL, NULL, NULL);
+		gmpv_menu_build_full(full_menu, NULL);
 		gtk_application_set_app_menu(GTK_APPLICATION(app), NULL);
 
 		gtk_application_set_menubar
 			(GTK_APPLICATION(app), G_MENU_MODEL(full_menu));
 	}
 
-	gmpv_actionctl_map_actions(app);
-	gmpv_main_window_load_state(app->gui);
-	gtk_widget_show_all(GTK_WIDGET(app->gui));
-
-	if(csd_enable)
-	{
-		gmpv_control_box_set_fullscreen_btn_visible(control_box, FALSE);
-	}
+	app->view = gmpv_view_new(app->gui);
+	wid = gmpv_video_area_get_xid(gmpv_main_window_get_video_area(app->gui));
+	app->mpv = gmpv_mpv_new(wid);
+	app->model = gmpv_model_new(app->mpv);
+	app->controller = gmpv_controller_new(app->model, app->view);
 
-	gmpv_control_box_set_chapter_enabled(control_box, FALSE);
+	g_unix_signal_add(SIGHUP, shutdown_signal_handler, app);
+	g_unix_signal_add(SIGINT, shutdown_signal_handler, app);
+	g_unix_signal_add(SIGTERM, shutdown_signal_handler, app);
 
-	wid = gmpv_video_area_get_xid(gmpv_main_window_get_video_area(app->gui));
-	app->mpv = gmpv_mpv_new(app->playlist_store, wid);
+	g_signal_connect(	app->controller,
+				"notify::aid",
+				G_CALLBACK(aid_handler),
+				app );
+	g_signal_connect(	app->controller,
+				"notify::vid",
+				G_CALLBACK(vid_handler),
+				app );
+	g_signal_connect(	app->controller,
+				"notify::sid",
+				G_CALLBACK(sid_handler),
+				app );
+	g_signal_connect(	app->controller,
+				"notify::idle",
+				G_CALLBACK(idle_handler),
+				app );
+	g_signal_connect(	app->controller,
+				"notify::ready",
+				G_CALLBACK(ready_handler),
+				app );
+	g_signal_connect(	app->controller,
+				"message",
+				G_CALLBACK(message_handler),
+				app );
+	g_signal_connect(	app->controller,
+				"shutdown",
+				G_CALLBACK(shutdown_handler),
+				app );
 
-	connect_signals(app);
+	gmpv_application_action_add_actions(app);
 	gmpv_mpris_init(app);
 	gmpv_media_keys_init(app);
 
-	g_object_set(	gtk_settings_get_default(),
-			"gtk-application-prefer-dark-theme",
-			dark_theme_enable,
-			NULL );
-
-	g_timeout_add(	SEEK_BAR_UPDATE_INTERVAL,
-			(GSourceFunc)update_seek_bar,
-			app );
-
 	g_free(mpvinput);
 }
 
-static void activate_handler(GApplication *gapp, gpointer data)
+static gboolean shutdown_signal_handler(gpointer data)
 {
-	gtk_window_present(GTK_WINDOW(GMPV_APPLICATION(data)->gui));
+	g_info("Shutdown signal received. Shutting down...");
+	gmpv_application_quit(data);
+
+	return FALSE;
 }
 
-static void mpv_init_handler(GmpvMpv *mpv, gpointer data)
+static void activate_handler(GApplication *gapp, gpointer data)
 {
 	GmpvApplication *app = data;
-	gchar *current_vo = gmpv_mpv_get_property_string(mpv, "current-vo");
-	GmpvVideoArea *vid_area = gmpv_main_window_get_video_area(app->gui);
-
-	gmpv_video_area_set_use_opengl(vid_area, !current_vo);
 
-	/* current_vo should be NULL if the selected vo is opengl-cb */
-	if(!current_vo)
+	if(!app->gui)
 	{
-		GtkGLArea *gl_area = gmpv_video_area_get_gl_area(vid_area);
-
-		g_signal_connect(	gl_area,
-					"render",
-					G_CALLBACK(vid_area_render_handler),
-					app );
-
-		gtk_gl_area_make_current(gl_area);
-		gmpv_mpv_init_gl(app->mpv);
+		initialize_gui(app);
 	}
 
-	mpv_free(current_vo);
-	load_files(app, (const gchar **)app->files, FALSE);
+	gmpv_controller_present(GMPV_APPLICATION(data)->controller);
 }
 
 static void open_handler(	GApplication *gapp,
-				gpointer files,
+				GFile **files,
 				gint n_files,
 				gchar *hint,
 				gpointer data )
 {
 	GmpvApplication *app = data;
-	gboolean append = (g_strcmp0(hint, "enqueue") == 0);
-	gint i;
+	gboolean ready = FALSE;
 
-	if(n_files > 0)
+	if(app->controller)
 	{
-		app->files = g_malloc(sizeof(GFile *)*(gsize)(n_files+1));
-
-		for(i = 0; i < n_files; i++)
-		{
-			app->files[i] = g_file_get_uri(((GFile **)files)[i]);
-		}
-
-		app->files[i] = NULL;
-
-		if(gmpv_mpv_get_state(app->mpv)->ready)
-		{
-			load_files(app, (const gchar **)app->files, append);
-		}
-	}
-
-	gdk_notify_startup_complete();
-}
-
-static gboolean draw_handler(GtkWidget *widget, cairo_t *cr, gpointer data)
-{
-	GmpvApplication *app = data;
-	guint signal_id = g_signal_lookup("draw", GMPV_TYPE_MAIN_WINDOW);
-
-	g_signal_handlers_disconnect_matched(	widget,
-						G_SIGNAL_MATCH_ID
-						|G_SIGNAL_MATCH_DATA,
-						signal_id,
-						0,
-						0,
-						NULL,
-						app );
-
-	gmpv_mpv_initialize(app->mpv);
-	gmpv_main_window_set_geometry
-		(app->gui, gmpv_mpv_get_geometry(app->mpv));
-	gmpv_mpv_set_opengl_cb_callback
-		(app->mpv, opengl_cb_update_callback, app);
-	gmpv_mpv_set_event_callback
-		(app->mpv, mpv_event_handler, app);
-
-	if(!app->files)
-	{
-		GmpvControlBox *control_box;
-
-		control_box = gmpv_main_window_get_control_box(app->gui);
-
-		gmpv_control_box_set_enabled(control_box, FALSE);
+		g_object_get(app->controller, "ready", &ready, NULL);
 	}
 
-	return FALSE;
-}
+	app->enqueue = (g_strcmp0(hint, "enqueue") == 0);
 
-static gboolean delete_handler(	GtkWidget *widget,
-				GdkEvent *event,
-				gpointer data )
-{
-	gmpv_application_quit(data);
-
-	return TRUE;
-}
-
-static void grab_handler(GtkWidget *widget, gboolean was_grabbed, gpointer data)
-{
-	GmpvApplication *app = data;
-
-	if(!was_grabbed)
-	{
-		g_debug(	"Main window has been shadowed; "
-				"sending global keyup to mpv" );
-
-		gmpv_mpv_command_string(app->mpv, "keyup");
-	}
-}
-
-static void playlist_row_activated_handler(	GmpvPlaylistWidget *playlist,
-						gint64 pos,
-						gpointer data )
-{
-	set_playlist_pos(data, pos);
-}
-
-static void playlist_row_deleted_handler(	GmpvPlaylistWidget *playlist,
-						gint pos,
-						gpointer data )
-{
-	GmpvApplication *app = data;
-
-	if(gmpv_mpv_get_state(app->mpv)->loaded)
-	{
-		const gchar *cmd[] = {"playlist_remove", NULL, NULL};
-		gchar *index_str = g_strdup_printf("%d", pos);
-
-		cmd[1] = index_str;
-
-		gmpv_mpv_command(app->mpv, cmd);
-
-		g_free(index_str);
-	}
-
-	if(gmpv_playlist_empty(app->playlist_store))
+	if(n_files > 0)
 	{
-		GmpvControlBox *control_box;
-
-		control_box = gmpv_main_window_get_control_box(app->gui);
-
-		gmpv_control_box_set_enabled(control_box, FALSE);
-	}
-}
-
-static void playlist_row_reodered_handler(	GmpvPlaylistWidget *playlist,
-						gint src,
-						gint dest,
-						gpointer data )
-{
-	GmpvApplication *app = data;
-	const gchar *cmd[] = {"playlist_move", NULL, NULL, NULL};
-	gchar *src_str = g_strdup_printf("%d", (src > dest)?--src:src);
-	gchar *dest_str = g_strdup_printf("%d", dest);
-
-	cmd[1] = src_str;
-	cmd[2] = dest_str;
-
-	gmpv_mpv_command(app->mpv, cmd);
-
-	g_free(src_str);
-	g_free(dest_str);
-}
+		if(ready)
+		{
+			for(gint i = 0; i < n_files; i++)
+			{
+				gchar *uri = g_file_get_uri(((GFile **)files)[i]);
 
-static GmpvTrack *parse_track_list(mpv_node_list *node)
-{
-	GmpvTrack *entry = gmpv_track_new();
+				gmpv_controller_open
+					(app->controller, uri, i != 0 || app->enqueue);
 
-	for(gint i = 0; i < node->num; i++)
-	{
-		if(g_strcmp0(node->keys[i], "type") == 0)
+				g_free(uri);
+			}
+		}
+		else
 		{
-			const gchar *type = node->values[i].u.string;
+			app->files = g_malloc(sizeof(GFile *)*(gsize)(n_files+1));
 
-			if(g_strcmp0(type, "audio") == 0)
-			{
-				entry->type = TRACK_TYPE_AUDIO;
-			}
-			else if(g_strcmp0(type, "video") == 0)
+			for(gint i = 0; i < n_files; i++)
 			{
-				entry->type = TRACK_TYPE_VIDEO;
+				app->files[i] = g_file_get_uri(((GFile **)files)[i]);
 			}
-			else if(g_strcmp0(type, "sub") == 0)
-			{
-				entry->type = TRACK_TYPE_SUBTITLE;
-			}
-		}
-		else if(g_strcmp0(node->keys[i], "title") == 0)
-		{
-			entry->title = g_strdup(node->values[i].u.string);
-		}
-		else if(g_strcmp0(node->keys[i], "lang") == 0)
-		{
-			entry->lang = g_strdup(node->values[i].u.string);
-		}
-		else if(g_strcmp0(node->keys[i], "id") == 0)
-		{
-			entry->id = node->values[i].u.int64;
+
+			app->files[n_files] = NULL;
 		}
 	}
-
-	return entry;
 }
 
-static void update_track_list(GmpvApplication *app, mpv_node* track_list)
+static gint options_handler(	GApplication *gapp,
+				GVariantDict *options,
+				gpointer data )
 {
-	const struct
+	gboolean version = FALSE;
+
+	g_variant_dict_lookup(options, "version", "b", &version);
+
+	if(version)
 	{
-		const gchar *prop_name;
-		const gchar *action_name;
+		g_printf("GNOME MPV " VERSION "\n");
 	}
-	track_map[] = {	{"aid", "set-audio-track"},
-			{"vid", "set-video-track"},
-			{"sid", "set-subtitle-track"},
-			{NULL, NULL} };
-
-	GmpvMpv *mpv = app->mpv;
-	mpv_node_list *org_list = track_list->u.list;
-	GSList *audio_list = NULL;
-	GSList *video_list = NULL;
-	GSList *sub_list = NULL;
-
-	for(gint i = 0; track_map[i].prop_name; i++)
+	else
 	{
-		GAction *action;
-		gchar *buf;
-		gint64 val;
-
-		action =	g_action_map_lookup_action
-				(G_ACTION_MAP(app), track_map[i].action_name);
-		buf =	gmpv_mpv_get_property_string
-			(mpv, track_map[i].prop_name);
-		val = g_ascii_strtoll(buf, NULL, 10);
-
-		g_simple_action_set_state
-			(G_SIMPLE_ACTION(action), g_variant_new_int64(val));
+		GmpvApplication *app = GMPV_APPLICATION(gapp);
+		GSettings *settings = g_settings_new(CONFIG_ROOT);
 
-		gmpv_mpv_free(buf);
-	}
+		g_variant_dict_lookup(	options,
+					"no-existing-session",
+					"b",
+					&app->no_existing_session );
 
-	for(gint i = 0; i < org_list->num; i++)
-	{
-		GmpvTrack *entry = parse_track_list(org_list->values[i].u.list);
-		GSList **list;
+		app->no_existing_session
+			|=	g_settings_get_boolean
+				(	settings,
+					"multiple-instances-enable" );
 
-		if(entry->type == TRACK_TYPE_AUDIO)
-		{
-			list = &audio_list;
-		}
-		else if(entry->type == TRACK_TYPE_VIDEO)
-		{
-			list = &video_list;
-		}
-		else if(entry->type == TRACK_TYPE_SUBTITLE)
-		{
-			list = &sub_list;
-		}
-		else
+		if(app->no_existing_session)
 		{
-			g_assert_not_reached();
+			GApplicationFlags flags = g_application_get_flags(gapp);
+
+			g_info("Single instance negotiation is disabled");
+			g_application_set_flags
+				(gapp, flags|G_APPLICATION_NON_UNIQUE);
 		}
 
-		*list = g_slist_prepend(*list, entry);
+		g_clear_object(&settings);
 	}
 
-	audio_list = g_slist_reverse(audio_list);
-	video_list = g_slist_reverse(video_list);
-	sub_list = g_slist_reverse(sub_list);
-
-	gmpv_main_window_update_track_list
-		(app->gui, audio_list, video_list, sub_list);
-
-	g_slist_free_full(audio_list, (GDestroyNotify)gmpv_track_free);
-	g_slist_free_full(video_list, (GDestroyNotify)gmpv_track_free);
-	g_slist_free_full(sub_list, (GDestroyNotify)gmpv_track_free);
-}
-
-static gchar *strnjoinv(	const gchar *separator,
-				const gchar **str_array,
-				gsize count )
-{
-	gsize args_size = ((gsize)count+1)*sizeof(gchar *);
-	gchar **args = g_malloc(args_size);
-	gchar *result;
-
-	memcpy(args, str_array, args_size-sizeof(gchar *));
-	args[count] = NULL;
-	result = g_strjoinv(separator, args);
-
-	g_free(args);
-
-	return result;
+	return version?0:-1;
 }
 
-static gboolean process_action(gpointer data)
-{
-	GmpvApplication *app = data;
-	gchar *action_str = g_queue_pop_tail(app->action_queue);
-
-	activate_action_string(app, action_str);
-
-	g_free(action_str);
-
-	return FALSE;
-}
-
-static void mpv_prop_change_handler(mpv_event_property *prop, gpointer data)
+static gint command_line_handler(	GApplication *gapp,
+					GApplicationCommandLine *cli,
+					gpointer data )
 {
-	GmpvApplication *app = data;
-	GmpvMpv *mpv = app->mpv;
-	GmpvControlBox *control_box = gmpv_main_window_get_control_box(app->gui);
-	const GmpvMpvState *state = gmpv_mpv_get_state(mpv);
-
-	if(g_strcmp0(prop->name, "pause") == 0)
-	{
-		gboolean paused = prop->data?*((gboolean *)prop->data):TRUE;
-
-		gmpv_control_box_set_playing_state(control_box, !paused);
-	}
-	else if(g_strcmp0(prop->name, "core-idle") == 0)
-	{
-		gboolean idle = prop->data?*((gboolean *)prop->data):TRUE;
+	gint argc = 1;
+	gchar **argv = g_application_command_line_get_arguments(cli, &argc);
+	GVariantDict *options = g_application_command_line_get_options_dict(cli);
+	gboolean enqueue = FALSE;
+	const gint n_files = argc-1;
+	GFile *files[n_files];
 
-		set_inhibit_idle(app, !idle);
-	}
-	else if(g_strcmp0(prop->name, "track-list") == 0 && prop->data)
-	{
-		update_track_list(app, prop->data);
-	}
-	else if(g_strcmp0(prop->name, "volume") == 0
-	&& (state->init_load || state->loaded))
-	{
-		gdouble volume = prop->data?*((double *)prop->data)/100.0:0;
+	g_variant_dict_lookup(options, "enqueue", "b", &enqueue);
 
-		gmpv_control_box_set_volume(control_box, volume);
-	}
-	else if(g_strcmp0(prop->name, "duration") == 0 && prop->data)
+	for(gint i = 0; i < n_files; i++)
 	{
-		gdouble duration = *((gdouble *) prop->data);
-
-		gmpv_control_box_set_seek_bar_duration
-			(control_box, (gint)duration);
+		files[i] =	g_application_command_line_create_file_for_arg
+				(cli, argv[i+1]);
 	}
-	else if(g_strcmp0(prop->name, "media-title") == 0 && prop->data)
-	{
-		const gchar *title = *((const gchar **)prop->data);
 
-		gtk_window_set_title(GTK_WINDOW(app->gui), title);
-	}
-	else if(g_strcmp0(prop->name, "playlist-pos") == 0 && prop->data)
+	if(n_files > 0)
 	{
-		GmpvPlaylist *playlist = gmpv_mpv_get_playlist(mpv);
-		gint64 pos = *((gint64 *)prop->data);
-
-		gmpv_playlist_set_indicator_pos(playlist, (gint)pos);
+		g_application_open(gapp, files, n_files, enqueue?"enqueue":"");
 	}
-	else if(g_strcmp0(prop->name, "chapters") == 0 && prop->data)
-	{
-		gint64 count = *((gint64 *) prop->data);
 
-		gmpv_control_box_set_chapter_enabled(control_box, (count > 1));
-	}
-	else if(g_strcmp0(prop->name, "fullscreen") == 0 && prop->data)
+	if(n_files == 0 || !GMPV_APPLICATION(gapp)->gui)
 	{
-		gboolean fullscreen = *((gboolean *)prop->data);
-
-		gmpv_main_window_set_fullscreen(app->gui, fullscreen);
+		g_application_activate(gapp);
 	}
-}
 
-static void mpv_event_handler(mpv_event *event, gpointer data)
-{
-	GmpvApplication *app = data;
-	GmpvMpv *mpv = app->mpv;
-	const GmpvMpvState *state = gmpv_mpv_get_state(mpv);
-
-	if(event->event_id == MPV_EVENT_VIDEO_RECONFIG)
-	{
-		gdouble autofit_ratio = gmpv_mpv_get_autofit_ratio(app->mpv);
-
-		if(state->new_file && autofit_ratio > 0)
-		{
-			resize_window_to_fit(app, autofit_ratio);
-		}
-	}
-	else if(event->event_id == MPV_EVENT_PROPERTY_CHANGE)
-	{
-		if(state->loaded)
-		{
-			mpv_prop_change_handler(event->data, data);
-		}
-	}
-	else if(event->event_id == MPV_EVENT_FILE_LOADED)
+	for(gint i = 0; i < n_files; i++)
 	{
-		GmpvControlBox *control_box;
-		GmpvPlaylist *playlist;
-		gchar *title;
-		gint64 pos = -1;
-		gdouble duration = 0;
-
-		control_box = gmpv_main_window_get_control_box(app->gui);
-		playlist = gmpv_mpv_get_playlist(mpv);
-
-		if(app->target_playlist_pos != -1)
-		{
-			gmpv_mpv_set_property
-				(	mpv,
-					"playlist-pos",
-					MPV_FORMAT_INT64,
-					&app->target_playlist_pos );
-
-			app->target_playlist_pos = -1;
-		}
-
-		gmpv_mpv_get_property
-			(mpv, "playlist-pos", MPV_FORMAT_INT64, &pos);
-		gmpv_mpv_get_property
-			(mpv, "duration", MPV_FORMAT_DOUBLE, &duration);
-
-		title = gmpv_mpv_get_property_string(mpv, "media-title");
-
-		gmpv_control_box_set_enabled(control_box, TRUE);
-		gmpv_control_box_set_playing_state(control_box, !state->paused);
-		gmpv_playlist_set_indicator_pos(playlist, (gint)pos);
-		gmpv_control_box_set_seek_bar_duration(control_box, (gint)duration);
-		gtk_window_set_title(GTK_WINDOW(app->gui), title);
-
-		gmpv_mpv_free(title);
+		g_object_unref(files[i]);
 	}
-	else if(event->event_id == MPV_EVENT_CLIENT_MESSAGE)
-	{
-		mpv_event_client_message *event_cmsg = event->data;
 
-		if(event_cmsg->num_args >= 2
-		&& g_strcmp0(event_cmsg->args[0], "gmpv-action") == 0)
-		{
-			gchar *action_str;
-
-			action_str = strnjoinv(	" ",
-						event_cmsg->args+1,
-						(gsize)event_cmsg->num_args-1 );
-
-			g_queue_push_head(app->action_queue, action_str);
-			g_idle_add(process_action, app);
-		}
-		else
-		{
-			gchar *full_str;
-
-			full_str = strnjoinv(	" ",
-						event_cmsg->args,
-						(gsize)event_cmsg->num_args);
+	gdk_notify_startup_complete();
 
-			g_warning(	"Invalid client message received: %s",
-					full_str );
+	g_strfreev(argv);
 
-			g_free(full_str);
-		}
-	}
-	else if(event->event_id == MPV_EVENT_IDLE)
-	{
-		if(!state->init_load && !state->loaded)
-		{
-			gmpv_main_window_reset(app->gui);
-			set_inhibit_idle(app, FALSE);
-		}
-	}
-	else if(event->event_id == MPV_EVENT_SHUTDOWN)
-	{
-		gmpv_application_quit(app);
-	}
+	return 0;
 }
 
-static void mpv_error_handler(GmpvMpv *mpv, const gchar *err, gpointer data)
+static void startup_handler(GApplication *gapp, gpointer data)
 {
-	GmpvApplication *app = data;
-
-	gmpv_main_window_reset(app->gui);
-	show_error_dialog(app, NULL, err);
-}
+	setlocale(LC_NUMERIC, "C");
+	g_set_application_name(_("GNOME MPV"));
+	gtk_window_set_default_icon_name(ICON_NAME);
 
-static gboolean shutdown_signal_handler(gpointer data)
-{
-	g_info("Shutdown signal received. Terminating...");
-	gmpv_application_quit(data);
+	bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALEDIR);
+	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+	textdomain(GETTEXT_PACKAGE);
 
-	return FALSE;
+	g_info("Starting GNOME MPV " VERSION);
 }
 
-static void drag_data_handler(	GtkWidget *widget,
-				GdkDragContext *context,
-				gint x,
-				gint y,
-				GtkSelectionData *sel_data,
-				guint info,
-				guint time,
-				gpointer data)
+static void aid_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	GmpvApplication *app = data;
-	gchar *type = gdk_atom_name(gtk_selection_data_get_target(sel_data));
-	const guchar *raw_data = gtk_selection_data_get_data(sel_data);
-	gchar **uri_list = gtk_selection_data_get_uris(sel_data);
-	gboolean append = GMPV_IS_PLAYLIST_WIDGET(widget);
-
-	if(g_strcmp0(type, "PLAYLIST_PATH") == 0)
-	{
-		GtkTreePath *path =	gtk_tree_path_new_from_string
-					((const gchar *)raw_data);
-
-		g_assert(path);
-		set_playlist_pos(app, gtk_tree_path_get_indices(path)[0]);
-
-		gtk_tree_path_free(path);
-	}
-	else
-	{
-		if(uri_list)
-		{
-			gmpv_mpv_load_list(	app->mpv,
-						(const gchar **)uri_list,
-						append,
-						TRUE );
-		}
-		else
-		{
-			gmpv_mpv_load(	app->mpv,
-					(const gchar *)raw_data,
-					append,
-					TRUE );
-		}
-	}
-
-	g_strfreev(uri_list);
-	g_free(type);
+	update_track_id(data,  "set-audio-track", "aid");
 }
 
-static gboolean window_state_handler(	GtkWidget *widget,
-					GdkEvent *event,
-					gpointer data )
+static void vid_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	GtkApplication *app = data;
-	GdkEventWindowState *state = (GdkEventWindowState *)event;
+	GmpvController *controller = GMPV_APPLICATION(data)->controller;
+	GAction *action = g_action_map_lookup_action(data, "set-video-size");
+	gint vid = 0;
 
-	if(state->changed_mask&GDK_WINDOW_STATE_FULLSCREEN)
-	{
-		gboolean fullscreen;
-		GAction *action;
+	g_object_get(controller, "vid", &vid, NULL);
+	g_simple_action_set_enabled(G_SIMPLE_ACTION(action), vid > 0);
 
-		fullscreen =	state->new_window_state&
-				GDK_WINDOW_STATE_FULLSCREEN;
-
-		action = g_action_map_lookup_action(	G_ACTION_MAP(app),
-							"toggle-playlist" );
-		g_object_set(action, "enabled", !fullscreen, NULL);
-
-		action = g_action_map_lookup_action(	G_ACTION_MAP(app),
-							"set-video-size" );
-		g_object_set(action, "enabled", !fullscreen, NULL);
-	}
-
-	return FALSE;
+	update_track_id(data,  "set-video-track", "vid");
 }
 
-static gboolean queue_render(GtkGLArea *area)
-{
-	gtk_gl_area_queue_render(area);
-
-	return FALSE;
-}
-
-static void opengl_cb_update_callback(void *cb_ctx)
+static void sid_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	GmpvApplication *app = cb_ctx;
-	GtkGLArea *area =	gmpv_video_area_get_gl_area
-				(gmpv_main_window_get_video_area(app->gui));
-
-	g_idle_add_full(	G_PRIORITY_HIGH,
-				(GSourceFunc)queue_render,
-				area,
-				NULL );
+	update_track_id(data,  "set-subtitle-track", "sid");
 }
 
-static void set_playlist_pos(GmpvApplication *app, gint64 pos)
+static void idle_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	gint64 mpv_pos;
-	gint rc;
-
-	rc = gmpv_mpv_get_property(	app->mpv,
-					"playlist-pos",
-					MPV_FORMAT_INT64,
-					&mpv_pos );
-
-	gmpv_mpv_set_property_flag(app->mpv, "pause", FALSE);
+	GmpvApplication *app = data;
+	gboolean idle = TRUE;
 
-	if(pos != mpv_pos)
-	{
-		if(rc >= 0)
-		{
-			gmpv_mpv_set_property(	app->mpv,
-						"playlist-pos",
-						MPV_FORMAT_INT64,
-						&pos );
-		}
-		else
-		{
-			app->target_playlist_pos = pos;
-		}
-	}
-}
+	g_object_get(object, "idle", &idle, NULL);
 
-static void set_inhibit_idle(GmpvApplication *app, gboolean inhibit)
-{
-	if(inhibit && app->inhibit_cookie == 0)
+	if(!idle && app->inhibit_cookie == 0)
 	{
 		app->inhibit_cookie
 			= gtk_application_inhibit
@@ -967,7 +463,7 @@ static void set_inhibit_idle(GmpvApplication *app, gboolean inhibit)
 					GTK_APPLICATION_INHIBIT_IDLE,
 					_("Playing") );
 	}
-	else if(!inhibit && app->inhibit_cookie != 0)
+	else if(idle && app->inhibit_cookie != 0)
 	{
 		gtk_application_uninhibit
 			(GTK_APPLICATION(app), app->inhibit_cookie);
@@ -976,81 +472,42 @@ static void set_inhibit_idle(GmpvApplication *app, gboolean inhibit)
 	}
 }
 
-static gboolean load_files(	GmpvApplication *app,
-				const gchar **files,
-				gboolean append )
+static void ready_handler(GObject *object, GParamSpec *pspec, gpointer data)
 {
-	if(files)
+	GmpvApplication *app = data;
+	gboolean ready = FALSE;
+
+	g_object_get(object, "ready", &ready, NULL);
+
+	if(ready && app->files)
 	{
-		gmpv_mpv_load_list(app->mpv, files, append, TRUE);
+		for(gint i = 0; app->files[i]; i++)
+		{
+			gmpv_controller_open
+				(app->controller, app->files[i], i != 0);
+		}
 
 		g_strfreev(app->files);
-
 		app->files = NULL;
 	}
-
-	return FALSE;
 }
 
-static void connect_signals(GmpvApplication *app)
+static void message_handler(	GmpvController *controller,
+				const gchar *message,
+				gpointer data )
 {
-	GmpvPlaylistWidget *playlist;
-	GmpvVideoArea *video_area;
-
-	playlist = gmpv_main_window_get_playlist(app->gui);
-	video_area = gmpv_main_window_get_video_area(app->gui);
+	const gsize prefix_length = sizeof(ACTION_PREFIX)-1;
 
-	gmpv_inputctl_connect_signals(app);
-	gmpv_playbackctl_connect_signals(app);
-
-	g_unix_signal_add(SIGHUP, shutdown_signal_handler, app);
-	g_unix_signal_add(SIGINT, shutdown_signal_handler, app);
-	g_unix_signal_add(SIGTERM, shutdown_signal_handler, app);
+	if(message && strncmp(message, ACTION_PREFIX, prefix_length) == 0)
+	{
+		/* Strip prefix and activate */
+		activate_action_string(data, message+prefix_length+1);
+	}
+}
 
-	g_signal_connect_after(	app->gui,
-				"draw",
-				G_CALLBACK(draw_handler),
-				app );
-	g_signal_connect(	app->mpv,
-				"mpv-init",
-				G_CALLBACK(mpv_init_handler),
-				app );
-	g_signal_connect(	video_area,
-				"drag-data-received",
-				G_CALLBACK(drag_data_handler),
-				app );
-	g_signal_connect(	playlist,
-				"drag-data-received",
-				G_CALLBACK(drag_data_handler),
-				app );
-	g_signal_connect(	app->gui,
-				"window-state-event",
-				G_CALLBACK(window_state_handler),
-				app );
-	g_signal_connect(	app->gui,
-				"grab-notify",
-				G_CALLBACK(grab_handler),
-				app );
-	g_signal_connect(	app->gui,
-				"delete-event",
-				G_CALLBACK(delete_handler),
-				app );
-	g_signal_connect(	playlist,
-				"row-activated",
-				G_CALLBACK(playlist_row_activated_handler),
-				app );
-	g_signal_connect(	playlist,
-				"row-deleted",
-				G_CALLBACK(playlist_row_deleted_handler),
-				app );
-	g_signal_connect(	playlist,
-				"row-reordered",
-				G_CALLBACK(playlist_row_reodered_handler),
-				app );
-	g_signal_connect(	app->mpv,
-				"mpv-error",
-				G_CALLBACK(mpv_error_handler),
-				app );
+static void shutdown_handler(GmpvController *controller, gpointer data)
+{
+	gmpv_application_quit(data);
 }
 
 static void gmpv_application_class_init(GmpvApplicationClass *klass)
@@ -1059,8 +516,12 @@ static void gmpv_application_class_init(GmpvApplicationClass *klass)
 
 static void gmpv_application_init(GmpvApplication *app)
 {
+	app->enqueue = FALSE;
 	app->no_existing_session = FALSE;
 	app->action_queue = g_queue_new();
+	app->files = NULL;
+	app->inhibit_cookie = 0;
+	app->gui = NULL;
 
 	g_application_add_main_option
 		(	G_APPLICATION(app),
@@ -1119,32 +580,6 @@ GmpvMpv *gmpv_application_get_mpv(GmpvApplication *app)
 
 void gmpv_application_quit(GmpvApplication *app)
 {
-	const gchar *cmd[] = {"quit", NULL};
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-
-	if(gmpv_mpv_get_mpv_handle(mpv))
-	{
-		GmpvVideoArea *vid_area = gmpv_main_window_get_video_area(wnd);
-		GtkGLArea *gl_area = gmpv_video_area_get_gl_area(vid_area);
-
-		if(gtk_widget_get_realized(GTK_WIDGET(gl_area)))
-		{
-			/* Needed by gmpv_mpv_quit() to uninitialize
-			 * opengl-cb
-			 */
-			gtk_gl_area_make_current(GTK_GL_AREA(gl_area));
-		}
-
-		gmpv_mpv_command(mpv, cmd);
-		gmpv_mpv_quit(mpv);
-	}
-
-	if(!gmpv_main_window_get_fullscreen(wnd))
-	{
-		gmpv_main_window_save_state(wnd);
-	}
-
 	g_application_quit(G_APPLICATION(app));
 }
 
diff --git a/src/gmpv_application.h b/src/gmpv_application.h
index ceda7a7..5ffdae8 100644
--- a/src/gmpv_application.h
+++ b/src/gmpv_application.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,7 +23,6 @@
 #include <gtk/gtk.h>
 
 #include "gmpv_main_window.h"
-#include "gmpv_playlist.h"
 #include "gmpv_mpv.h"
 
 G_BEGIN_DECLS
diff --git a/src/gmpv_application_action.c b/src/gmpv_application_action.c
new file mode 100644
index 0000000..8b0495c
--- /dev/null
+++ b/src/gmpv_application_action.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2015-2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "gmpv_application_action.h"
+#include "gmpv_file_chooser.h"
+#include "gmpv_application_private.h"
+#include "gmpv_common.h"
+
+static gboolean track_id_to_state(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data );
+static gboolean state_to_track_id(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data );
+static gboolean boolean_to_state(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data );
+static gboolean state_to_boolean(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data );
+static void bind_properties(GmpvApplication *app);
+static void show_open_dialog_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void show_open_location_dialog_handler(	GSimpleAction *action,
+						GVariant *param,
+						gpointer data );
+static void toggle_loop_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data );
+static void show_shortcuts_dialog_handler(	GSimpleAction *action,
+						GVariant *param,
+						gpointer data );
+static void toggle_controls_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void toggle_playlist_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void save_playlist_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void remove_selected_playlist_item_handler(	GSimpleAction *action,
+							GVariant *param,
+							gpointer data );
+static void show_preferences_dialog_handler(	GSimpleAction *action,
+						GVariant *param,
+						gpointer data );
+static void quit_handler(	GSimpleAction *action,
+				GVariant *param,
+				gpointer data );
+static void set_audio_track_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data );
+static void set_video_track_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data );
+static void set_subtitle_track_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data );
+static void load_track_handler(	GSimpleAction *action,
+				GVariant *param,
+				gpointer data );
+static void toggle_fullscreen_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void enter_fullscreen_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void leave_fullscreen_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void set_video_size_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+static void show_about_dialog_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data );
+
+static gboolean track_id_to_state(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data )
+{
+	gint64 id = g_value_get_int(from_value);
+	GVariant *to = g_variant_new("x", id);
+
+	g_value_set_variant(to_value, to);
+
+	return TRUE;
+}
+
+static gboolean state_to_track_id(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data )
+{
+	GVariant *from = g_value_get_variant(from_value);
+	gint64 id = g_variant_get_int64(from);
+
+	g_value_set_int(to_value, (gint)id);
+
+	return TRUE;
+}
+
+static gboolean boolean_to_state(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data )
+{
+	gboolean from = g_value_get_boolean(from_value);
+	GVariant *to = g_variant_new("b", from);
+
+	g_value_set_variant(to_value, to);
+
+	return TRUE;
+}
+
+static gboolean state_to_boolean(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer user_data )
+{
+	GVariant *from = g_value_get_variant(from_value);
+	gboolean to = g_variant_get_boolean(from);
+
+	g_value_set_boolean(to_value, to);
+
+	return TRUE;
+}
+
+static void bind_properties(GmpvApplication *app)
+{
+	GAction *action = NULL;
+
+	action =	g_action_map_lookup_action
+			(G_ACTION_MAP(app), "set-audio-track");
+	g_object_bind_property_full(	app->controller, "aid",
+					action, "state",
+					G_BINDING_BIDIRECTIONAL,
+					track_id_to_state,
+					state_to_track_id,
+					NULL,
+					NULL );
+
+	action =	g_action_map_lookup_action
+			(G_ACTION_MAP(app), "set-video-track");
+	g_object_bind_property_full(	app->controller, "vid",
+					action, "state",
+					G_BINDING_BIDIRECTIONAL,
+					track_id_to_state,
+					state_to_track_id,
+					NULL,
+					NULL );
+
+	action =	g_action_map_lookup_action
+			(G_ACTION_MAP(app), "set-subtitle-track");
+	g_object_bind_property_full(	app->controller, "sid",
+					action, "state",
+					G_BINDING_BIDIRECTIONAL,
+					track_id_to_state,
+					state_to_track_id,
+					NULL,
+					NULL );
+
+	action =	g_action_map_lookup_action
+			(G_ACTION_MAP(app), "toggle-loop");
+	g_object_bind_property_full(	app->controller, "loop",
+					action, "state",
+					G_BINDING_BIDIRECTIONAL,
+					boolean_to_state,
+					state_to_boolean,
+					NULL,
+					NULL );
+}
+
+static void show_open_dialog_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	gboolean append = g_variant_get_boolean(param);
+
+	gmpv_view_show_open_dialog
+		(GMPV_APPLICATION(data)->view, append);
+}
+
+static void show_open_location_dialog_handler(	GSimpleAction *action,
+						GVariant *param,
+						gpointer data )
+{
+	gboolean append = g_variant_get_boolean(param);
+
+	gmpv_view_show_open_location_dialog
+		(GMPV_APPLICATION(data)->view, append);
+}
+
+static void toggle_loop_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data )
+{
+	g_simple_action_set_state(action, value);
+}
+
+static void show_shortcuts_dialog_handler(	GSimpleAction *action,
+						GVariant *param,
+						gpointer data )
+{
+	gmpv_view_show_shortcuts_dialog(GMPV_APPLICATION(data)->view);
+}
+
+static void toggle_controls_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	GmpvApplication *app = data;
+	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
+	GmpvControlBox *ctrl = gmpv_main_window_get_control_box(wnd);
+	gboolean visible = gtk_widget_get_visible(GTK_WIDGET(ctrl));
+
+	gtk_widget_set_visible(GTK_WIDGET(ctrl), !visible);
+}
+
+static void toggle_playlist_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	GmpvApplication *app = data;
+	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
+	gboolean visible = gmpv_main_window_get_playlist_visible(wnd);
+
+	gmpv_main_window_set_playlist_visible(wnd, !visible);
+}
+
+static void save_playlist_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	gmpv_view_show_save_playlist_dialog(GMPV_APPLICATION(data)->view);
+}
+
+static void remove_selected_playlist_item_handler(	GSimpleAction *action,
+							GVariant *param,
+							gpointer data )
+{
+	GmpvMainWindow *wnd =	gmpv_application_get_main_window
+				(GMPV_APPLICATION(data));
+
+	if(gmpv_main_window_get_playlist_visible(wnd))
+	{
+		GmpvPlaylistWidget *playlist;
+
+		playlist = gmpv_main_window_get_playlist(wnd);
+
+		gmpv_playlist_widget_remove_selected(playlist);
+	}
+}
+
+static void show_preferences_dialog_handler(	GSimpleAction *action,
+						GVariant *param,
+						gpointer data )
+{
+	gmpv_view_show_preferences_dialog(GMPV_APPLICATION(data)->view);
+}
+
+static void quit_handler(	GSimpleAction *action,
+				GVariant *param,
+				gpointer data )
+{
+	gmpv_application_quit(data);
+}
+
+static void set_audio_track_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data )
+{
+	g_simple_action_set_state(action, value);
+}
+
+static void set_video_track_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data )
+{
+	g_simple_action_set_state(action, value);
+}
+
+static void set_subtitle_track_handler(	GSimpleAction *action,
+					GVariant *value,
+					gpointer data )
+{
+	g_simple_action_set_state(action, value);
+}
+
+static void load_track_handler(	GSimpleAction *action,
+				GVariant *param,
+				gpointer data )
+{
+	GmpvApplication *app = data;
+	gchar *cmd_name = NULL;
+
+	g_variant_get(param, "s", &cmd_name);
+
+	if(g_strcmp0(cmd_name, "audio-add") == 0)
+	{
+		gmpv_view_show_open_audio_track_dialog(app->view);
+	}
+	else if(g_strcmp0(cmd_name, "sub-add") == 0)
+	{
+		gmpv_view_show_open_subtitle_track_dialog(app->view);
+	}
+	else
+	{
+		g_assert_not_reached();
+	}
+
+	g_free(cmd_name);
+}
+
+static void toggle_fullscreen_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	GmpvView *view = GMPV_APPLICATION(data)->view;
+	gboolean fullscreen = FALSE;
+
+	g_object_get(view, "fullscreen", &fullscreen, NULL);
+	gmpv_view_set_fullscreen(view, !fullscreen);
+}
+
+static void enter_fullscreen_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	gmpv_view_set_fullscreen(GMPV_APPLICATION(data)->view, TRUE);
+}
+
+static void leave_fullscreen_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	gmpv_view_set_fullscreen(GMPV_APPLICATION(data)->view, FALSE);
+}
+
+static void set_video_size_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	gdouble value = g_variant_get_double(param);
+
+	gmpv_controller_autofit(GMPV_APPLICATION(data)->controller, value);
+}
+
+static void show_about_dialog_handler(	GSimpleAction *action,
+					GVariant *param,
+					gpointer data )
+{
+	gmpv_view_show_about_dialog(GMPV_APPLICATION(data)->view);
+}
+
+void gmpv_application_action_add_actions(GmpvApplication *app)
+{
+	const GActionEntry entries[]
+		= {	{.name = "show-open-dialog",
+			.activate = show_open_dialog_handler,
+			.parameter_type = "b"},
+			{.name = "quit",
+			.activate = quit_handler},
+			{.name = "show-about-dialog",
+			.activate = show_about_dialog_handler},
+			{.name = "show-preferences-dialog",
+			.activate = show_preferences_dialog_handler},
+			{.name = "show-open-location-dialog",
+			.activate = show_open_location_dialog_handler,
+			.parameter_type = "b"},
+			{.name = "toggle-loop",
+			.state = "false",
+			.change_state = toggle_loop_handler},
+			{.name = "show-shortcuts-dialog",
+			.activate = show_shortcuts_dialog_handler},
+			{.name = "toggle-controls",
+			.activate = toggle_controls_handler},
+			{.name = "toggle-playlist",
+			.activate = toggle_playlist_handler},
+			{.name = "save-playlist",
+			.activate = save_playlist_handler},
+			{.name = "remove-selected-playlist-item",
+			.activate = remove_selected_playlist_item_handler},
+			{.name = "set-audio-track",
+			.change_state = set_audio_track_handler,
+			.state = "@x 0",
+			.parameter_type = "x"},
+			{.name = "set-video-track",
+			.change_state = set_video_track_handler,
+			.state = "@x 0",
+			.parameter_type = "x"},
+			{.name = "set-subtitle-track",
+			.change_state = set_subtitle_track_handler,
+			.state = "@x 0",
+			.parameter_type = "x"},
+			{.name = "load-track",
+			.activate = load_track_handler,
+			.parameter_type = "s"},
+			{.name = "toggle-fullscreen",
+			.activate = toggle_fullscreen_handler},
+			{.name = "enter-fullscreen",
+			.activate = enter_fullscreen_handler},
+			{.name = "leave-fullscreen",
+			.activate = leave_fullscreen_handler},
+			{.name = "set-video-size",
+			.activate = set_video_size_handler,
+			.parameter_type = "d"} };
+
+	g_action_map_add_action_entries(	G_ACTION_MAP(app),
+						entries,
+						G_N_ELEMENTS(entries),
+						app );
+
+	bind_properties(app);
+}
diff --git a/src/gmpv_actionctl.h b/src/gmpv_application_action.h
similarity index 82%
rename from src/gmpv_actionctl.h
rename to src/gmpv_application_action.h
index 786fbdd..abf2580 100644
--- a/src/gmpv_actionctl.h
+++ b/src/gmpv_application_action.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,8 +17,8 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef ACTIONCTL_H
-#define ACTIONCTL_H
+#ifndef APPLICATION_ACTION_H
+#define APPLICATION_ACTION_H
 
 #include <glib.h>
 
@@ -26,7 +26,7 @@
 
 G_BEGIN_DECLS
 
-void gmpv_actionctl_map_actions(GmpvApplication *app);
+void gmpv_application_action_add_actions(GmpvApplication *app);
 
 G_END_DECLS
 
diff --git a/src/gmpv_mpv_opt.h b/src/gmpv_application_private.h
similarity index 59%
copy from src/gmpv_mpv_opt.h
copy to src/gmpv_application_private.h
index 268757f..b68ddcb 100644
--- a/src/gmpv_mpv_opt.h
+++ b/src/gmpv_application_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,28 +17,34 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef MPV_OPT_H
-#define MPV_OPT_H
+#ifndef APPLICATION_PRIVATE_H
+#define APPLICATION_PRIVATE_H
 
-#include <glib.h>
-#include <mpv/client.h>
-
-#include "gmpv_mpv.h"
+#include "gmpv_controller.h"
+#include "gmpv_model.h"
+#include "gmpv_view.h"
 
 G_BEGIN_DECLS
 
-typedef struct module_log_level module_log_level;
-
-struct module_log_level
+struct _GmpvApplication
 {
-	gchar *prefix;
-	mpv_log_level level;
+	GtkApplication parent;
+	GmpvController *controller;
+	GmpvModel *model;
+	GmpvView *view;
+	gboolean enqueue;
+	gboolean no_existing_session;
+	GmpvMpv *mpv;
+	GQueue *action_queue;
+	gchar **files;
+	guint inhibit_cookie;
+	GmpvMainWindow *gui;
 };
 
-void gmpv_mpv_opt_handle_geometry(GmpvMpv *mpv);
-void gmpv_mpv_opt_handle_autofit(GmpvMpv *mpv);
-void gmpv_mpv_opt_handle_fs(GmpvMpv *mpv);
-void gmpv_mpv_opt_handle_msg_level(GmpvMpv *mpv);
+struct _GmpvApplicationClass
+{
+	GtkApplicationClass parent_class;
+};
 
 G_END_DECLS
 
diff --git a/src/gmpv_common.c b/src/gmpv_common.c
index 4c8717c..44eca6a 100644
--- a/src/gmpv_common.c
+++ b/src/gmpv_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -31,6 +31,63 @@
 #include "gmpv_main_window.h"
 #include "gmpv_control_box.h"
 
+GmpvPlaylistEntry *gmpv_playlist_entry_new(	const gchar *filename,
+						const gchar *title )
+{
+	GmpvPlaylistEntry *entry = g_malloc(sizeof(GmpvPlaylistEntry));
+
+	entry->filename = g_strdup(filename);
+	entry->title = g_strdup(title);
+
+	return entry;
+}
+
+void gmpv_playlist_entry_free(GmpvPlaylistEntry *entry)
+{
+	g_free(entry->filename);
+	g_free(entry->title);
+	g_free(entry);
+}
+
+GmpvMetadataEntry *gmpv_metadata_entry_new(const gchar *key, const gchar *value)
+{
+	GmpvMetadataEntry *entry = g_malloc(sizeof(GmpvMetadataEntry));
+
+	entry->key = g_strdup(key);
+	entry->value = g_strdup(value);
+
+	return entry;
+}
+
+void gmpv_metadata_entry_free(GmpvMetadataEntry *entry)
+{
+	g_free(entry->key);
+	g_free(entry->value);
+	g_free(entry);
+}
+
+GmpvTrack *gmpv_track_new(void)
+{
+	GmpvTrack *entry = g_malloc(sizeof(GmpvTrack));
+
+	entry->type = TRACK_TYPE_INVALID;
+	entry->title = NULL;
+	entry->lang = NULL;
+	entry->id = 0;
+
+	return entry;
+}
+
+void gmpv_track_free(GmpvTrack *entry)
+{
+	if(entry)
+	{
+		g_free(entry->title);
+		g_free(entry->lang);
+		g_free(entry);
+	}
+}
+
 gchar *get_config_dir_path(void)
 {
 	return g_build_filename(	g_get_user_config_dir(),
@@ -73,224 +130,56 @@ gchar *get_name_from_path(const gchar *path)
 	return basename?basename:g_strdup(path);
 }
 
-void activate_action_string(GmpvApplication *app, const gchar *str)
-{
-	GActionMap *map = G_ACTION_MAP(app);
-	GAction *action = NULL;
-	gchar *name = NULL;
-	GVariant *param = NULL;
-	gboolean param_match = FALSE;
-
-	g_action_parse_detailed_name(str, &name, &param, NULL);
-
-	if(name)
-	{
-		const GVariantType *action_ptype;
-		const GVariantType *given_ptype;
-
-		action = g_action_map_lookup_action(map, name);
-		action_ptype = g_action_get_parameter_type(action);
-		given_ptype = param?g_variant_get_type(param):NULL;
-
-		param_match =	(action_ptype == given_ptype) ||
-				g_variant_type_is_subtype_of
-				(action_ptype, given_ptype);
-	}
-
-	if(action && param_match)
-	{
-		g_debug("Activating action %s", str);
-		g_action_activate(action, param);
-	}
-	else
-	{
-		g_warning("Failed to activate action \"%s\"", str);
-	}
-}
-
-void migrate_config(GmpvApplication *app)
+gboolean extension_matches(const gchar *filename, const gchar **extensions)
 {
-	const gchar *keys[] = {	"dark-theme-enable",
-				"csd-enable",
-				"last-folder-enable",
-				"mpv-options",
-				"mpv-config-file",
-				"mpv-config-enable",
-				"mpv-input-config-file",
-				"mpv-input-config-enable",
-				NULL };
-
-	GSettings *old_settings = g_settings_new("org.gnome-mpv");
-	GSettings *new_settings = g_settings_new(CONFIG_ROOT);
-
-	if(!g_settings_get_boolean(new_settings, "settings-migrated"))
-	{
-		g_settings_set_boolean(new_settings, "settings-migrated", TRUE);
-
-		for(gint i = 0; keys[i]; i++)
-		{
-			GVariant *buf = g_settings_get_user_value
-						(old_settings, keys[i]);
-
-			if(buf)
-			{
-				g_settings_set_value
-					(new_settings, keys[i], buf);
-
-				g_variant_unref(buf);
-			}
-		}
-	}
-
-	g_object_unref(old_settings);
-	g_object_unref(new_settings);
-}
+	const gchar *ext = strrchr(filename, '.');
+	gboolean result = FALSE;
 
-gboolean update_seek_bar(gpointer data)
-{
-	GmpvApplication *app = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
-	mpv_handle *mpv_ctx = gmpv_mpv_get_mpv_handle(mpv);
-	gdouble time_pos = -1;
-	gint rc = -1;
-
-	if(gmpv_mpv_get_state(mpv)->loaded)
-	{
-		rc = gmpv_mpv_get_property(	mpv,
-						"time-pos",
-						MPV_FORMAT_DOUBLE,
-						&time_pos );
-	}
-
-	if(rc >= 0)
+	/* Only start checking the extension if there is at
+	 * least one character after the dot.
+	 */
+	if(ext && ++ext)
 	{
-		GmpvMainWindow *wnd;
-		GmpvControlBox *control_box;
+		const gchar **iter = extensions;
 
-		wnd = gmpv_application_get_main_window(app);
-		control_box = gmpv_main_window_get_control_box(wnd);
+		/* Check if the file extension matches one of the
+		 * supported subtitle formats.
+		 */
+		while(*iter && g_strcmp0(ext, *(iter++)) != 0);
 
-		gmpv_control_box_set_seek_bar_pos(control_box, time_pos);
+		result = !!(*iter);
 	}
 
-	return !!mpv_ctx;
+	return result;
 }
 
-void seek(GmpvApplication *app, gdouble time)
+void *gslist_to_array(GSList *slist)
 {
-	const gchar *cmd[] = {"seek", NULL, "absolute", NULL};
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
+	void **result = g_malloc(sizeof(void **)*(g_slist_length(slist)+1));
+	gint i = 0;
 
-	if(!gmpv_mpv_get_state(mpv)->loaded)
+	for(GSList *iter = slist; iter; iter = g_slist_next(iter))
 	{
-		gmpv_mpv_load(mpv, NULL, FALSE, TRUE);
+		result[i++] = iter->data;
 	}
-	else
-	{
-		gchar *value_str = g_strdup_printf("%.2f", time);
-
-		cmd[1] = value_str;
 
-		gmpv_mpv_command(mpv, cmd);
-		update_seek_bar(app);
-
-		g_free(value_str);
-	}
+	result[i] = NULL;
 
+	return result;
 }
 
-void show_error_dialog(GmpvApplication *app, const gchar *prefix, const gchar *msg)
+gchar *strnjoinv(const gchar *separator, const gchar **str_array, gsize count)
 {
-	GmpvMainWindow *wnd;
-	GtkWidget *dialog;
-	GtkWidget *msg_area;
-	GList *iter;
-
-	wnd = gmpv_application_get_main_window(app);
-	dialog =	gtk_message_dialog_new
-			(	GTK_WINDOW(wnd),
-				GTK_DIALOG_DESTROY_WITH_PARENT,
-				GTK_MESSAGE_ERROR,
-				GTK_BUTTONS_OK,
-				_("Error") );
-	msg_area =	gtk_message_dialog_get_message_area
-			(GTK_MESSAGE_DIALOG(dialog));
-	iter = gtk_container_get_children(GTK_CONTAINER(msg_area));
-
-	while(iter)
-	{
-		if(GTK_IS_LABEL(iter->data))
-		{
-			GtkLabel *label = iter->data;
-
-			gtk_label_set_line_wrap_mode
-				(label, PANGO_WRAP_WORD_CHAR);
-		}
+	gsize args_size = ((gsize)count+1)*sizeof(gchar *);
+	gchar **args = g_malloc(args_size);
+	gchar *result;
 
-		iter = g_list_next(iter);
-	}
+	memcpy(args, str_array, args_size-sizeof(gchar *));
+	args[count] = NULL;
+	result = g_strjoinv(separator, args);
 
-	g_list_free(iter);
-
-	if(prefix)
-	{
-		gchar *prefix_escaped = g_markup_printf_escaped("%s", prefix);
-		gchar *msg_escaped = g_markup_printf_escaped("%s", msg);
-
-		gtk_message_dialog_format_secondary_markup
-			(	GTK_MESSAGE_DIALOG(dialog),
-				"<b>[%s]</b> %s",
-				prefix_escaped,
-				msg_escaped );
-
-		g_free(prefix_escaped);
-		g_free(msg_escaped);
-	}
-	else
-	{
-		gtk_message_dialog_format_secondary_text
-			(GTK_MESSAGE_DIALOG(dialog), "%s", msg);
-	}
+	g_free(args);
 
-	gtk_dialog_run(GTK_DIALOG(dialog));
-	gtk_widget_destroy(dialog);
+	return result;
 }
 
-void resize_window_to_fit(GmpvApplication *app, gdouble multiplier)
-{
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
-	gchar *video = gmpv_mpv_get_property_string(mpv, "video");
-	gint64 width;
-	gint64 height;
-	gint mpv_width_rc;
-	gint mpv_height_rc;
-
-	mpv_width_rc = gmpv_mpv_get_property(	mpv,
-						"dwidth",
-						MPV_FORMAT_INT64,
-						&width );
-	mpv_height_rc = gmpv_mpv_get_property(	mpv,
-						"dheight",
-						MPV_FORMAT_INT64,
-						&height );
-
-	if(video
-	&& strncmp(video, "no", 3) != 0
-	&& mpv_width_rc >= 0
-	&& mpv_height_rc >= 0)
-	{
-		GmpvMainWindow *wnd;
-		gint new_width;
-		gint new_height;
-
-		wnd = gmpv_application_get_main_window(app);
-		new_width = (gint)(multiplier*(gdouble)width);
-		new_height = (gint)(multiplier*(gdouble)height);
-
-		g_debug("Resizing window to %dx%d", new_width, new_height);
-
-		gmpv_main_window_resize_video_area(wnd, new_width, new_height);
-	}
-
-	gmpv_mpv_free(video);
-}
diff --git a/src/gmpv_common.h b/src/gmpv_common.h
index 51ea156..52c4362 100644
--- a/src/gmpv_common.h
+++ b/src/gmpv_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,44 +23,61 @@
 #include <glib.h>
 #include <gtk/gtk.h>
 
-#include "gmpv_application.h"
-
 G_BEGIN_DECLS
 
+typedef struct _GmpvPlaylistEntry GmpvPlaylistEntry;
+typedef struct _GmpvMetadataEntry GmpvMetadataEntry;
+
+typedef enum TrackType TrackType;
+typedef struct GmpvTrack GmpvTrack;
+
+enum TrackType
+{
+	TRACK_TYPE_INVALID,
+	TRACK_TYPE_AUDIO,
+	TRACK_TYPE_VIDEO,
+	TRACK_TYPE_SUBTITLE,
+	TRACK_TYPE_N
+};
+
+struct _GmpvPlaylistEntry
+{
+	gchar *filename;
+	gchar *title;
+};
+
+struct _GmpvMetadataEntry
+{
+	gchar *key;
+	gchar *value;
+};
+
+struct GmpvTrack
+{
+	TrackType type;
+	gint64 id;
+	gchar *title;
+	gchar *lang;
+};
+
+GmpvPlaylistEntry *gmpv_playlist_entry_new(	const gchar *filename,
+						const gchar *title );
+void gmpv_playlist_entry_free(GmpvPlaylistEntry *entry);
+
+GmpvMetadataEntry *gmpv_metadata_entry_new(	const gchar *key,
+						const gchar *value );
+void gmpv_metadata_entry_free(GmpvMetadataEntry *entry);
+
+GmpvTrack *gmpv_track_new(void);
+void gmpv_track_free(GmpvTrack *entry);
+
 gchar *get_config_dir_path(void);
 gchar *get_scripts_dir_path(void);
 gchar *get_path_from_uri(const gchar *uri);
 gchar *get_name_from_path(const gchar *path);
-gboolean update_seek_bar(gpointer data);
-void activate_action_string(GmpvApplication *app, const gchar *str);
-void migrate_config(GmpvApplication *app);
-void seek(GmpvApplication *app, gdouble time);
-void show_error_dialog(GmpvApplication *app, const gchar *prefix, const gchar *msg);
-void resize_window_to_fit(GmpvApplication *app, gdouble multiplier);
-void load_keybind(	GmpvApplication *app,
-			const gchar *config_path,
-			gboolean notify_ignore );
-
-#if GTK_CHECK_VERSION(3, 19, 7)
-#define GmpvFileChooser GtkFileChooserNative
-#define gmpv_file_chooser_destroy(x) gtk_native_dialog_destroy(GTK_NATIVE_DIALOG(x))
-#define gmpv_file_chooser_show(x) gtk_native_dialog_show(GTK_NATIVE_DIALOG(x))
-#define gmpv_file_chooser_set_modal(x, y) gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(x), y)
-#define gmpv_file_chooser_run(x) gtk_native_dialog_run(GTK_NATIVE_DIALOG(x))
-#define gmpv_file_chooser_new(title,parent,action,accept,cancel) \
-	gtk_file_chooser_native_new(title,parent,action,accept,cancel)
-#else
-#define GmpvFileChooser GtkWidget
-#define gmpv_file_chooser_destroy(x) gtk_widget_destroy(GTK_WIDGET(x))
-#define gmpv_file_chooser_show(x) gtk_widget_show_all(GTK_DIALOG(x))
-#define gmpv_file_chooser_set_modal(x, y) gtk_window_set_modal(GTK_WINDOW(x), y)
-#define gmpv_file_chooser_run(x) gtk_dialog_run(GTK_DIALOG(x))
-#define gmpv_file_chooser_new(title,parent,action,accept,cancel) \
-	gtk_file_chooser_dialog_new(	title,parent,action,\
-					cancel,GTK_RESPONSE_CANCEL,\
-					accept,GTK_RESPONSE_ACCEPT,\
-					NULL )
-#endif
+gboolean extension_matches(const gchar *filename, const gchar **extensions);
+void *gslist_to_array(GSList *slist);
+gchar *strnjoinv(const gchar *separator, const gchar **str_array, gsize count);
 
 G_END_DECLS
 
diff --git a/src/gmpv_control_box.c b/src/gmpv_control_box.c
index 61192fa..37301ce 100644
--- a/src/gmpv_control_box.c
+++ b/src/gmpv_control_box.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -24,6 +24,13 @@
 #include "gmpv_control_box.h"
 #include "gmpv_seek_bar.h"
 
+enum
+{
+	PROP_0,
+	PROP_VOLUME,
+	N_PROPERTIES
+};
+
 struct _GmpvControlBox
 {
 	GtkBox parent_instance;
@@ -36,6 +43,7 @@ struct _GmpvControlBox
 	GtkWidget *volume_button;
 	GtkWidget *fullscreen_button;
 	GtkWidget *seek_bar;
+	gdouble volume;
 };
 
 struct _GmpvControlBoxClass
@@ -43,6 +51,22 @@ struct _GmpvControlBoxClass
 	GtkBoxClass parent_class;
 };
 
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static gboolean gtk_to_mpv_volume(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
+static gboolean mpv_to_gtk_volume(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
 static void seek_handler(	GmpvSeekBar *seek_bar,
 				gdouble value,
 				gpointer data );
@@ -50,9 +74,68 @@ static void volume_changed_handler(	GtkVolumeButton *button,
 					gdouble value,
 					gpointer data );
 static void simple_signal_handler(GtkWidget *widget, gpointer data);
+static void init_button(	GtkWidget *button,
+				const gchar *icon_name,
+				const gchar *tooltip_text );
 
 G_DEFINE_TYPE(GmpvControlBox, gmpv_control_box, GTK_TYPE_BOX)
 
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvControlBox *self = GMPV_CONTROL_BOX(object);
+
+	if(property_id == PROP_VOLUME)
+	{
+		self->volume = g_value_get_double(value);
+	}
+	else
+	{
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvControlBox *self = GMPV_CONTROL_BOX(object);
+
+	if(property_id == PROP_VOLUME)
+	{
+		g_value_set_double(value, self->volume);
+	}
+	else
+	{
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+	}
+}
+
+static gboolean gtk_to_mpv_volume(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	gdouble from = g_value_get_double(from_value);
+	g_value_set_double(to_value, from*100);
+
+	return TRUE;
+}
+
+static gboolean mpv_to_gtk_volume(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	gdouble from = g_value_get_double(from_value);
+	g_value_set_double(to_value, from/100.0);
+
+	return TRUE;
+}
+
 static void seek_handler(	GmpvSeekBar *seek_bar,
 				gdouble value,
 				gpointer data )
@@ -64,7 +147,7 @@ static void volume_changed_handler(	GtkVolumeButton *button,
 					gdouble value,
 					gpointer data )
 {
-	g_signal_emit_by_name(data, "volume-changed", value);
+	g_signal_emit_by_name(data, "volume-changed", value*100.0);
 }
 
 static void simple_signal_handler(GtkWidget *widget, gpointer data)
@@ -95,6 +178,19 @@ static void simple_signal_handler(GtkWidget *widget, gpointer data)
 	}
 }
 
+static void init_button(	GtkWidget *button,
+				const gchar *icon_name,
+				const gchar *tooltip_text )
+{
+	GtkWidget *icon =	gtk_image_new_from_icon_name
+				(icon_name, GTK_ICON_SIZE_BUTTON);
+
+	gtk_widget_set_tooltip_text(button, tooltip_text);
+	g_object_set(button, "relief", GTK_RELIEF_NONE, NULL);
+	gtk_widget_set_can_focus(button, FALSE);
+	gtk_button_set_image(GTK_BUTTON(button), icon);
+}
+
 static void gmpv_control_box_class_init(GmpvControlBoxClass *klass)
 {
 	/* Names of signals that have no parameter and return nothing */
@@ -106,6 +202,21 @@ static void gmpv_control_box_class_init(GmpvControlBoxClass *klass)
 						"next-button-clicked",
 						"fullscreen-button-clicked",
 						NULL };
+	GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+
+	pspec = g_param_spec_double
+		(	"volume",
+			"Volume",
+			"The value of the volume button",
+			0.0,
+			G_MAXDOUBLE,
+			0.0,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_VOLUME, pspec);
 
 	for(gint i = 0; simple_signals[i]; i++)
 	{
@@ -145,109 +256,62 @@ static void gmpv_control_box_class_init(GmpvControlBoxClass *klass)
 
 static void gmpv_control_box_init(GmpvControlBox *box)
 {
-	GtkWidget *play_icon;
-	GtkWidget *stop_icon;
-	GtkWidget *forward_icon;
-	GtkWidget *rewind_icon;
-	GtkWidget *previous_icon;
-	GtkWidget *next_icon;
-	GtkWidget *fullscreen_icon;
-
-	box->play_button = gtk_button_new_with_label(NULL);
-	box->stop_button = gtk_button_new_with_label(NULL);
-	box->forward_button = gtk_button_new_with_label(NULL);
-	box->rewind_button = gtk_button_new_with_label(NULL);
-	box->next_button = gtk_button_new_with_label(NULL);
-	box->previous_button = gtk_button_new_with_label(NULL);
-	box->fullscreen_button = gtk_button_new_with_label(NULL);
+	box->play_button = gtk_button_new();
+	box->stop_button = gtk_button_new();
+	box->forward_button = gtk_button_new();
+	box->rewind_button = gtk_button_new();
+	box->next_button = gtk_button_new();
+	box->previous_button = gtk_button_new();
+	box->fullscreen_button = gtk_button_new();
 	box->volume_button = gtk_volume_button_new();
 	box->seek_bar = gmpv_seek_bar_new();
 
-	play_icon
-		= gtk_image_new_from_icon_name
-			("media-playback-start-symbolic", GTK_ICON_SIZE_BUTTON);
-	stop_icon
-		= gtk_image_new_from_icon_name
-			("media-playback-stop-symbolic", GTK_ICON_SIZE_BUTTON);
-	forward_icon
-		= gtk_image_new_from_icon_name
-			("media-seek-forward-symbolic", GTK_ICON_SIZE_BUTTON);
-	rewind_icon
-		= gtk_image_new_from_icon_name
-			("media-seek-backward-symbolic", GTK_ICON_SIZE_BUTTON);
-	next_icon
-		= gtk_image_new_from_icon_name
-			("media-skip-forward-symbolic", GTK_ICON_SIZE_BUTTON);
-	previous_icon
-		= gtk_image_new_from_icon_name
-			("media-skip-backward-symbolic", GTK_ICON_SIZE_BUTTON);
-	fullscreen_icon
-		= gtk_image_new_from_icon_name
-			("view-fullscreen-symbolic", GTK_ICON_SIZE_BUTTON);
+	init_button(	box->play_button,
+			"media-playback-start-symbolic",
+			_("Play") );
+	init_button(	box->stop_button,
+			"media-playback-stop-symbolic",
+			_("Stop") );
+	init_button(	box->forward_button,
+			"media-seek-forward-symbolic",
+			_("Forward") );
+	init_button(	box->rewind_button,
+			"media-seek-backward-symbolic",
+			_("Rewind") );
+	init_button(	box->next_button,
+			"media-skip-forward-symbolic",
+			_("Next Chapter") );
+	init_button(	box->previous_button,
+			"media-skip-backward-symbolic",
+			_("Previous Chapter") );
+	init_button(	box->fullscreen_button,
+			"view-fullscreen-symbolic",
+			_("Toggle Fullscreen") );
 
 	gtk_style_context_add_class
 		(	gtk_widget_get_style_context(GTK_WIDGET(box)),
 			GTK_STYLE_CLASS_BACKGROUND );
 
-	gtk_widget_set_tooltip_text(box->play_button, _("Play"));
-	gtk_widget_set_tooltip_text(box->stop_button, _("Stop"));
-	gtk_widget_set_tooltip_text(box->forward_button, _("Forward"));
-	gtk_widget_set_tooltip_text(box->rewind_button, _("Rewind"));
-	gtk_widget_set_tooltip_text(box->next_button, _("Next Chapter"));
-	gtk_widget_set_tooltip_text(box->previous_button, _("Previous Chapter"));
-	gtk_widget_set_tooltip_text(box->fullscreen_button, _("Toggle Fullscreen"));
-
-	g_object_set(box->play_button, "relief", GTK_RELIEF_NONE, NULL);
-	g_object_set(box->stop_button, "relief", GTK_RELIEF_NONE, NULL);
-	g_object_set(box->forward_button, "relief", GTK_RELIEF_NONE, NULL);
-	g_object_set(box->rewind_button, "relief", GTK_RELIEF_NONE, NULL);
-	g_object_set(box->next_button, "relief", GTK_RELIEF_NONE, NULL);
-	g_object_set(box->previous_button, "relief", GTK_RELIEF_NONE, NULL);
-	g_object_set(box->fullscreen_button, "relief", GTK_RELIEF_NONE, NULL);
-
-	gtk_widget_set_can_focus(box->previous_button, FALSE);
-	gtk_widget_set_can_focus(box->rewind_button, FALSE);
-	gtk_widget_set_can_focus(box->play_button, FALSE);
-	gtk_widget_set_can_focus(box->stop_button, FALSE);
-	gtk_widget_set_can_focus(box->forward_button, FALSE);
-	gtk_widget_set_can_focus(box->next_button, FALSE);
-	gtk_widget_set_can_focus(box->seek_bar, FALSE);
 	gtk_widget_set_can_focus(box->volume_button, FALSE);
-	gtk_widget_set_can_focus(box->fullscreen_button, FALSE);
-
-	gtk_button_set_image
-		(GTK_BUTTON(box->play_button), play_icon);
-	gtk_button_set_image
-		(GTK_BUTTON(box->stop_button), stop_icon);
-	gtk_button_set_image
-		(GTK_BUTTON(box->forward_button), forward_icon);
-	gtk_button_set_image
-		(GTK_BUTTON(box->rewind_button), rewind_icon);
-	gtk_button_set_image
-		(GTK_BUTTON(box->next_button), next_icon);
-	gtk_button_set_image
-		(GTK_BUTTON(box->previous_button), previous_icon);
-	gtk_button_set_image
-		(GTK_BUTTON(box->fullscreen_button), fullscreen_icon);
-
-	gtk_container_add
-		(GTK_CONTAINER(box), box->previous_button);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->rewind_button);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->play_button);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->stop_button);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->forward_button);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->next_button);
-	gtk_box_pack_start
-		(GTK_BOX(box), box->seek_bar, TRUE, TRUE, 0);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->volume_button);
-	gtk_container_add
-		(GTK_CONTAINER(box), box->fullscreen_button);
+	gtk_widget_set_can_focus(box->seek_bar, FALSE);
+
+	gtk_container_add(GTK_CONTAINER(box), box->previous_button);
+	gtk_container_add(GTK_CONTAINER(box), box->rewind_button);
+	gtk_container_add(GTK_CONTAINER(box), box->play_button);
+	gtk_container_add(GTK_CONTAINER(box), box->stop_button);
+	gtk_container_add(GTK_CONTAINER(box), box->forward_button);
+	gtk_container_add(GTK_CONTAINER(box), box->next_button);
+	gtk_box_pack_start(GTK_BOX(box), box->seek_bar, TRUE, TRUE, 0);
+	gtk_container_add(GTK_CONTAINER(box), box->volume_button);
+	gtk_container_add(GTK_CONTAINER(box), box->fullscreen_button);
+
+	g_object_bind_property_full(	box->volume_button, "value",
+					box, "volume",
+					G_BINDING_BIDIRECTIONAL,
+					gtk_to_mpv_volume,
+					mpv_to_gtk_volume,
+					NULL,
+					NULL );
 
 	g_signal_connect(	box,
 				"button-press-event",
@@ -335,7 +399,7 @@ void gmpv_control_box_set_volume(GmpvControlBox *box, gdouble volume)
 	g_signal_handlers_block_by_func(box, volume_changed_handler, box);
 
 	gtk_scale_button_set_value
-		(GTK_SCALE_BUTTON(box->volume_button), volume);
+		(GTK_SCALE_BUTTON(box->volume_button), volume/100.0);
 
 	g_signal_handlers_unblock_by_func(box, volume_changed_handler, box);
 }
@@ -354,36 +418,31 @@ gboolean gmpv_control_box_get_volume_popup_visible(GmpvControlBox *box)
 
 void gmpv_control_box_set_playing_state(GmpvControlBox *box, gboolean playing)
 {
-	GtkWidget *play_icon;
-	const gchar *tooltip;
+	GtkWidget *image = gtk_button_get_image(GTK_BUTTON(box->play_button));
+	const gchar *tooltip = playing?_("Pause"):_("Play");
 
-	play_icon = gtk_image_new_from_icon_name
-			( 	playing
-				?"media-playback-pause-symbolic"
-				:"media-playback-start-symbolic",
-				GTK_ICON_SIZE_BUTTON );
-	tooltip = playing?_("Pause"):_("Play");
+	gtk_image_set_from_icon_name( 	GTK_IMAGE(image),
+					playing?
+					"media-playback-pause-symbolic":
+					"media-playback-start-symbolic",
+					GTK_ICON_SIZE_BUTTON );
 
-	gtk_button_set_image(GTK_BUTTON(box->play_button), play_icon);
 	gtk_widget_set_tooltip_text(box->play_button, tooltip);
 }
 
 void gmpv_control_box_set_fullscreen_state(	GmpvControlBox *box,
 						gboolean fullscreen )
 {
-	GtkWidget *fullscreen_icon;
+	GtkWidget *image = gtk_button_get_image(GTK_BUTTON(box->fullscreen_button));
 
-	fullscreen_icon = gtk_image_new_from_icon_name
-				(	fullscreen
-					?"view-restore-symbolic"
-					:"view-fullscreen-symbolic",
+	gtk_image_set_from_icon_name(	GTK_IMAGE(image),
+					fullscreen?
+					"view-restore-symbolic":
+					"view-fullscreen-symbolic",
 					GTK_ICON_SIZE_BUTTON );
-
-	gtk_button_set_image(	GTK_BUTTON(box->fullscreen_button),
-				fullscreen_icon );
 }
 
-void gmpv_control_box_set_fullscreen_btn_visible(	GmpvControlBox *box,
+void gmpv_control_box_set_fullscreen_button_visible(	GmpvControlBox *box,
 							gboolean value )
 {
 	gtk_widget_set_visible(box->fullscreen_button, value);
diff --git a/src/gmpv_control_box.h b/src/gmpv_control_box.h
index 54b94eb..e5ca0bf 100644
--- a/src/gmpv_control_box.h
+++ b/src/gmpv_control_box.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -41,7 +41,7 @@ gboolean gmpv_control_box_get_volume_popup_visible(GmpvControlBox *box);
 void gmpv_control_box_set_playing_state(GmpvControlBox *box, gboolean playing);
 void gmpv_control_box_set_fullscreen_state(	GmpvControlBox *box,
 						gboolean fullscreen );
-void gmpv_control_box_set_fullscreen_btn_visible(	GmpvControlBox *box,
+void gmpv_control_box_set_fullscreen_button_visible(	GmpvControlBox *box,
 							gboolean value );
 void gmpv_control_box_reset(GmpvControlBox *box);
 
diff --git a/src/gmpv_controller.c b/src/gmpv_controller.c
new file mode 100644
index 0000000..c09b1c8
--- /dev/null
+++ b/src/gmpv_controller.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <gtk/gtk.h>
+#include <glib-unix.h>
+#include <locale.h>
+
+#include "gmpv_controller_private.h"
+#include "gmpv_controller.h"
+#include "gmpv_controller_input.h"
+#include "gmpv_def.h"
+
+static void constructed(GObject *object);
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static void view_ready_handler(GmpvView *view, gpointer data);
+static void render_handler(GmpvView *view, gpointer data);
+static void preferences_updated_handler(GmpvView *view, gpointer data);
+static void audio_track_load_handler(	GmpvView *view,
+					const gchar *uri,
+					gpointer data );
+static void subtitle_track_load_handler(	GmpvView *view,
+						const gchar *uri,
+						gpointer data );
+static void file_open_handler(	GmpvView *view,
+				const gchar **uri_list,
+				gboolean append,
+				gpointer data );
+static void grab_handler(GmpvView *view, gboolean was_grabbed, gpointer data);
+static void delete_handler(GmpvView *view, gpointer data);
+static void playlist_item_activated_handler(	GmpvView *view,
+						gint pos,
+						gpointer data );
+static void playlist_item_deleted_handler(	GmpvView *view,
+						gint pos,
+						gpointer data );
+static void playlist_reordered_handler(	GmpvView *view,
+					gint src,
+					gint dst,
+					gpointer data );
+static void connect_signals(GmpvController *controller);
+static gboolean update_seek_bar(gpointer data);
+static gboolean track_str_to_int(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
+static gboolean int_to_track_str(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
+static gboolean loop_str_to_boolean(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
+static gboolean boolean_to_loop_str(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
+static gboolean is_more_than_one(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data );
+static void idle_active_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data);
+static void playlist_handler(		GObject *object,
+					GParamSpec *pspec,
+					gpointer data);
+static void model_ready_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data );
+static void frame_ready_handler(GmpvModel *model, gpointer data);
+static void autofit_handler(GmpvModel *model, gdouble multiplier, gpointer data);
+static void message_handler(GmpvMpv *mpv, const gchar *message, gpointer data);
+static void error_handler(GmpvMpv *mpv, const gchar *message, gpointer data);
+static void shutdown_handler(GmpvMpv *mpv, gpointer data);
+static void post_shutdown_handler(GmpvMpv *mpv, gpointer data);
+static void play_button_handler(GtkButton *button, gpointer data);
+static void stop_button_handler(GtkButton *button, gpointer data);
+static void forward_button_handler(GtkButton *button, gpointer data);
+static void rewind_button_handler(GtkButton *button, gpointer data);
+static void next_button_handler(GtkButton *button, gpointer data);
+static void previous_button_handler(GtkButton *button, gpointer data);
+static void seek_handler(GtkButton *button, gdouble value, gpointer data);
+static void gmpv_controller_class_init(GmpvControllerClass *klass);
+static void gmpv_controller_init(GmpvController *controller);
+
+G_DEFINE_TYPE(GmpvController, gmpv_controller, G_TYPE_OBJECT)
+
+static void constructed(GObject *object)
+{
+	GmpvController *controller = GMPV_CONTROLLER(object);
+
+	connect_signals(controller);
+	gmpv_controller_input_connect_signals(controller);
+}
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvController *self = GMPV_CONTROLLER(object);
+
+	switch(property_id)
+	{
+		case PROP_MODEL:
+		self->model = g_value_get_pointer(value);
+		break;
+
+		case PROP_VIEW:
+		self->view = g_value_get_pointer(value);
+		break;
+
+		case PROP_READY:
+		self->ready = g_value_get_boolean(value);
+		break;
+
+		case PROP_AID:
+		self->aid = g_value_get_int(value);
+		break;
+
+		case PROP_VID:
+		self->vid = g_value_get_int(value);
+		break;
+
+		case PROP_SID:
+		self->sid = g_value_get_int(value);
+		break;
+
+		case PROP_LOOP:
+		self->loop = g_value_get_boolean(value);
+		break;
+
+		case PROP_IDLE:
+		self->idle = g_value_get_boolean(value);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvController *self = GMPV_CONTROLLER(object);
+
+	switch(property_id)
+	{
+		case PROP_MODEL:
+		g_value_set_pointer(value, self->model);
+		break;
+
+		case PROP_VIEW:
+		g_value_set_pointer(value, self->view);
+		break;
+
+		case PROP_READY:
+		g_value_set_boolean(value, self->ready);
+		break;
+
+		case PROP_AID:
+		g_value_set_int(value, self->aid);
+		break;
+
+		case PROP_VID:
+		g_value_set_int(value, self->vid);
+		break;
+
+		case PROP_SID:
+		g_value_set_int(value, self->sid);
+		break;
+
+		case PROP_LOOP:
+		g_value_set_boolean(value, self->loop);
+		break;
+
+		case PROP_IDLE:
+		g_value_set_boolean(value, self->idle);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void view_ready_handler(GmpvView *view, gpointer data)
+{
+	gmpv_model_initialize(GMPV_CONTROLLER(data)->model);
+}
+
+static void render_handler(GmpvView *view, gpointer data)
+{
+	GmpvController *controller = data;
+	gint scale = 1;
+	gint width = -1;
+	gint height = -1;
+
+	scale = gmpv_view_get_scale_factor(controller->view);
+	gmpv_view_get_video_area_geometry(controller->view, &width, &height);
+	gmpv_model_render_frame(controller->model, scale*width, scale*height);
+
+	while(gtk_events_pending())
+	{
+		gtk_main_iteration();
+	}
+}
+
+static void preferences_updated_handler(GmpvView *view, gpointer data)
+{
+	gmpv_model_reset(GMPV_CONTROLLER(data)->model);
+}
+
+static void audio_track_load_handler(	GmpvView *view,
+					const gchar *uri,
+					gpointer data )
+{
+	gmpv_model_load_audio_track(GMPV_CONTROLLER(data)->model, uri);
+}
+
+static void subtitle_track_load_handler(	GmpvView *view,
+						const gchar *uri,
+						gpointer data )
+{
+	gmpv_model_load_subtitle_track(GMPV_CONTROLLER(data)->model, uri);
+}
+
+static void file_open_handler(	GmpvView *view,
+				const gchar **uri_list,
+				gboolean append,
+				gpointer data )
+{
+	for(const gchar **iter = uri_list; iter && *iter; iter++)
+	{
+		gmpv_model_load_file(	GMPV_CONTROLLER(data)->model,
+					*iter,
+					append || iter != uri_list );
+	}
+}
+
+static void grab_handler(GmpvView *view, gboolean was_grabbed, gpointer data)
+{
+	if(!was_grabbed)
+	{
+		gmpv_model_reset_keys(GMPV_CONTROLLER(data)->model);
+	}
+}
+
+static void delete_handler(GmpvView *view, gpointer data)
+{
+	gmpv_model_quit(GMPV_CONTROLLER(data)->model);
+	g_signal_emit_by_name(data, "shutdown");
+}
+
+static void playlist_item_activated_handler(	GmpvView *view,
+						gint pos,
+						gpointer data )
+{
+	GmpvController *controller = GMPV_CONTROLLER(data);
+	gboolean idle_active = FALSE;
+
+	g_object_get(controller->model, "idle-active", &idle_active, NULL);
+	gmpv_model_play(controller->model);
+
+	if(idle_active)
+	{
+		controller->target_playlist_pos = pos;
+	}
+	else
+	{
+		gmpv_model_set_playlist_position(controller->model, pos);
+	}
+}
+
+static void playlist_item_deleted_handler(	GmpvView *view,
+						gint pos,
+						gpointer data )
+{
+	gmpv_model_remove_playlist_entry(GMPV_CONTROLLER(data)->model, pos);
+}
+
+static void playlist_reordered_handler(	GmpvView *view,
+					gint src,
+					gint dst,
+					gpointer data )
+{
+	gmpv_model_move_playlist_entry(GMPV_CONTROLLER(data)->model, src, dst);
+}
+
+static void connect_signals(GmpvController *controller)
+{
+	g_object_bind_property_full(	controller->model, "aid",
+					controller, "aid",
+					G_BINDING_BIDIRECTIONAL,
+					track_str_to_int,
+					int_to_track_str,
+					NULL,
+					NULL );
+	g_object_bind_property_full(	controller->model, "vid",
+					controller, "vid",
+					G_BINDING_BIDIRECTIONAL,
+					track_str_to_int,
+					int_to_track_str,
+					NULL,
+					NULL );
+	g_object_bind_property_full(	controller->model, "sid",
+					controller, "sid",
+					G_BINDING_BIDIRECTIONAL,
+					track_str_to_int,
+					int_to_track_str,
+					NULL,
+					NULL );
+	g_object_bind_property_full(	controller->model, "loop",
+					controller, "loop",
+					G_BINDING_BIDIRECTIONAL,
+					loop_str_to_boolean,
+					boolean_to_loop_str,
+					NULL,
+					NULL );
+	g_object_bind_property(	controller->model, "core-idle",
+				controller, "idle",
+				G_BINDING_DEFAULT );
+
+	g_object_bind_property(	controller->model, "pause",
+				controller->view, "pause",
+				G_BINDING_DEFAULT );
+	g_object_bind_property(	controller->model, "media-title",
+				controller->view, "title",
+				G_BINDING_DEFAULT );
+	g_object_bind_property(	controller->model, "volume",
+				controller->view, "volume",
+				G_BINDING_BIDIRECTIONAL );
+	g_object_bind_property(	controller->model, "duration",
+				controller->view, "duration",
+				G_BINDING_DEFAULT );
+	g_object_bind_property(	controller->model, "playlist-pos",
+				controller->view, "playlist-pos",
+				G_BINDING_DEFAULT );
+	g_object_bind_property(	controller->model, "track-list",
+				controller->view, "track-list",
+				G_BINDING_DEFAULT );
+	g_object_bind_property_full(	controller->model, "chapters",
+					controller->view, "chapters-enabled",
+					G_BINDING_DEFAULT,
+					is_more_than_one,
+					NULL,
+					NULL,
+					NULL );
+
+	g_signal_connect(	controller->model,
+				"notify::ready",
+				G_CALLBACK(model_ready_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"notify::idle-active",
+				G_CALLBACK(idle_active_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"notify::playlist",
+				G_CALLBACK(playlist_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"frame-ready",
+				G_CALLBACK(frame_ready_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"autofit",
+				G_CALLBACK(autofit_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"message",
+				G_CALLBACK(message_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"error",
+				G_CALLBACK(error_handler),
+				controller );
+	g_signal_connect(	controller->model,
+				"shutdown",
+				G_CALLBACK(shutdown_handler),
+				controller );
+	g_signal_connect_after(	controller->model,
+				"shutdown",
+				G_CALLBACK(post_shutdown_handler),
+				controller );
+
+	g_signal_connect(	controller->view,
+				"button-clicked::play",
+				G_CALLBACK(play_button_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"button-clicked::stop",
+				G_CALLBACK(stop_button_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"button-clicked::forward",
+				G_CALLBACK(forward_button_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"button-clicked::rewind",
+				G_CALLBACK(rewind_button_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"button-clicked::next",
+				G_CALLBACK(next_button_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"button-clicked::previous",
+				G_CALLBACK(previous_button_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"seek",
+				G_CALLBACK(seek_handler),
+				controller );
+
+	g_signal_connect(	controller->view,
+				"ready",
+				G_CALLBACK(view_ready_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"render",
+				G_CALLBACK(render_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"preferences-updated",
+				G_CALLBACK(preferences_updated_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"audio-track-load",
+				G_CALLBACK(audio_track_load_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"subtitle-track-load",
+				G_CALLBACK(subtitle_track_load_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"file-open",
+				G_CALLBACK(file_open_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"grab-notify",
+				G_CALLBACK(grab_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"delete-notify",
+				G_CALLBACK(delete_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"playlist-item-activated",
+				G_CALLBACK(playlist_item_activated_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"playlist-item-deleted",
+				G_CALLBACK(playlist_item_deleted_handler),
+				controller );
+	g_signal_connect(	controller->view,
+				"playlist-reordered",
+				G_CALLBACK(playlist_reordered_handler),
+				controller );
+
+	controller->update_seekbar_id
+		= g_timeout_add(	SEEK_BAR_UPDATE_INTERVAL,
+					(GSourceFunc)update_seek_bar,
+					controller );
+}
+
+gboolean update_seek_bar(gpointer data)
+{
+	GmpvController *controller = data;
+	gdouble time_pos = gmpv_model_get_time_position(controller->model);
+
+	gmpv_view_set_time_position(controller->view, time_pos);
+
+	return TRUE;
+}
+
+static gboolean track_str_to_int(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	gchar *endptr = NULL;
+	const gchar *from = g_value_get_string(from_value);
+	gint to = (gint)g_ascii_strtoll(from, &endptr, 10);
+
+	if(to == 0 && g_strcmp0(from, "no") != 0)
+	{
+		to = -1;
+	}
+
+	g_value_set_int(to_value, to);
+
+	return TRUE;
+}
+
+static gboolean int_to_track_str(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	gint from = g_value_get_int(from_value);
+	gchar buf[16] = "no";
+
+	g_snprintf(buf, 16, "%d", from);
+	g_value_set_string(to_value, buf);
+
+	return TRUE;
+}
+
+static gboolean loop_str_to_boolean(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	const gchar *from = g_value_get_string(from_value);
+
+	g_value_set_boolean(to_value, g_strcmp0(from, "no") != 0);
+
+	return TRUE;
+}
+
+static gboolean boolean_to_loop_str(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	gboolean from = g_value_get_boolean(from_value);
+
+	g_value_set_string(to_value, from?"inf":"no");
+
+	return TRUE;
+}
+
+static gboolean is_more_than_one(	GBinding *binding,
+					const GValue *from_value,
+					GValue *to_value,
+					gpointer data )
+{
+	gint64 from = g_value_get_int64(from_value);
+
+	g_value_set_boolean(to_value, from > 1);
+
+	return TRUE;
+}
+
+static void idle_active_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data )
+{
+	GmpvController *controller = data;
+	gboolean idle_active = TRUE;
+
+	g_object_get(object, "idle-active", &idle_active, NULL);
+
+	if(idle_active)
+	{
+		gmpv_view_reset(GMPV_CONTROLLER(data)->view);
+	}
+	else if(controller->target_playlist_pos >= 0)
+	{
+		gmpv_model_set_playlist_position
+			(controller->model, controller->target_playlist_pos);
+	}
+}
+
+static void playlist_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
+{
+	GmpvView *view = GMPV_CONTROLLER(data)->view;
+	GPtrArray *playlist = NULL;
+	gint64 pos = 0;
+
+	g_object_get(object, "playlist", &playlist, "playlist-pos", &pos, NULL);
+	gmpv_view_update_playlist(view, playlist);
+	gmpv_view_set_playlist_pos(view, pos);
+}
+
+static void model_ready_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data )
+{
+	GmpvController *controller = data;
+	gboolean ready = FALSE;
+
+	g_object_get(object, "ready", &ready, NULL);
+
+	if(ready)
+	{
+		gboolean use_opengl_cb;
+
+		use_opengl_cb = gmpv_model_get_use_opengl_cb(controller->model);
+
+		gmpv_view_set_use_opengl_cb(controller->view, use_opengl_cb);
+
+		if(use_opengl_cb)
+		{
+			gmpv_view_make_gl_context_current(controller->view);
+			gmpv_model_initialize_gl(controller->model);
+		}
+	}
+
+	controller->ready = ready;
+	g_object_notify(data, "ready");
+}
+
+static void frame_ready_handler(GmpvModel *model, gpointer data)
+{
+	gmpv_view_queue_render(GMPV_CONTROLLER(data)->view);
+}
+
+static void autofit_handler(GmpvModel *model, gdouble multiplier, gpointer data)
+{
+	GmpvController *controller = data;
+	gint64 width = -1;
+	gint64 height = -1;
+
+	gmpv_model_get_video_geometry(model, &width, &height);
+
+	if(width > 0 && height > 0)
+	{
+		gint new_width;
+		gint new_height;
+
+		new_width = (gint)(multiplier*(gdouble)width);
+		new_height = (gint)(multiplier*(gdouble)height);
+
+		g_debug("Resizing window to %dx%d", new_width, new_height);
+
+		gmpv_view_resize_video_area
+			(controller->view, new_width, new_height);
+	}
+
+}
+
+static void message_handler(GmpvMpv *mpv, const gchar *message, gpointer data)
+{
+	g_signal_emit_by_name(data, "message", message);
+}
+
+static void error_handler(GmpvMpv *mpv, const gchar *message, gpointer data)
+{
+	gmpv_view_show_message_dialog(	GMPV_CONTROLLER(data)->view,
+					GTK_MESSAGE_ERROR,
+					_("Error"),
+					NULL,
+					message );
+}
+
+static void shutdown_handler(GmpvMpv *mpv, gpointer data)
+{
+	GmpvController *controller = data;
+
+	g_source_remove(controller->update_seekbar_id);
+	gmpv_view_make_gl_context_current(controller->view);
+}
+
+static void post_shutdown_handler(GmpvMpv *mpv, gpointer data)
+{
+	gmpv_view_quit(GMPV_CONTROLLER(data)->view);
+}
+
+static void play_button_handler(GtkButton *button, gpointer data)
+{
+	GmpvModel *model = GMPV_CONTROLLER(data)->model;
+	gboolean pause = TRUE;
+
+	g_object_get(model, "pause", &pause, NULL);
+
+	if(pause)
+	{
+		gmpv_model_play(model);
+	}
+	else
+	{
+		gmpv_model_pause(model);
+	}
+}
+
+static void stop_button_handler(GtkButton *button, gpointer data)
+{
+	gmpv_model_stop(GMPV_CONTROLLER(data)->model);
+}
+
+static void forward_button_handler(GtkButton *button, gpointer data)
+{
+	gmpv_model_forward(GMPV_CONTROLLER(data)->model);
+}
+
+static void rewind_button_handler(GtkButton *button, gpointer data)
+{
+	gmpv_model_rewind(GMPV_CONTROLLER(data)->model);
+}
+
+static void next_button_handler(GtkButton *button, gpointer data)
+{
+	gmpv_model_next_chapter(GMPV_CONTROLLER(data)->model);
+}
+
+static void previous_button_handler(GtkButton *button, gpointer data)
+{
+	gmpv_model_previous_chapter(GMPV_CONTROLLER(data)->model);
+}
+
+static void seek_handler(GtkButton *button, gdouble value, gpointer data)
+{
+	gmpv_model_seek(GMPV_CONTROLLER(data)->model, value);
+}
+
+static void gmpv_controller_class_init(GmpvControllerClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec;
+
+	obj_class->constructed = constructed;
+	obj_class->set_property = set_property;
+	obj_class->get_property = get_property;
+
+	pspec = g_param_spec_pointer
+		(	"model",
+			"Model",
+			"The GmpvModel to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_MODEL, pspec);
+
+	pspec = g_param_spec_pointer
+		(	"view",
+			"View",
+			"The GmpvView to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_VIEW, pspec);
+
+	pspec = g_param_spec_int
+		(	"aid",
+			"Audio track ID",
+			"The ID of the current audio track",
+			-1,
+			G_MAXINT,
+			-1,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_AID, pspec);
+
+	pspec = g_param_spec_int
+		(	"vid",
+			"Video track ID",
+			"The ID of the current video track",
+			-1,
+			G_MAXINT,
+			-1,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_VID, pspec);
+
+	pspec = g_param_spec_int
+		(	"sid",
+			"Subtitle track ID",
+			"The ID of the current subtitle track",
+			-1,
+			G_MAXINT,
+			-1,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_SID, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"ready",
+			"Ready",
+			"Whether mpv is ready to receive commands",
+			FALSE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_READY, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"loop",
+			"Loop",
+			"Whether or not to loop when the playlist ends",
+			FALSE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_LOOP, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"idle",
+			"Idle",
+			"Whether or not the player is idle",
+			TRUE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_IDLE, pspec);
+
+	g_signal_new(	"message",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__STRING,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_STRING );
+	g_signal_new(	"shutdown",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+}
+
+static void gmpv_controller_init(GmpvController *controller)
+{
+	controller->model = NULL;
+	controller->view = NULL;
+	controller->aid = 0;
+	controller->vid = 0;
+	controller->sid = 0;
+	controller->ready = FALSE;
+	controller->loop = FALSE;
+	controller->idle = TRUE;
+	controller->action_queue = g_queue_new();
+	controller->files = NULL;
+	controller->inhibit_cookie = 0;
+	controller->target_playlist_pos = -1;
+	controller->update_seekbar_id = 0;
+}
+
+GmpvController *gmpv_controller_new(GmpvModel *model, GmpvView *view)
+{
+	return GMPV_CONTROLLER(g_object_new(	gmpv_controller_get_type(),
+						"model", model,
+						"view", view,
+						NULL ));
+}
+
+void gmpv_controller_quit(GmpvController *controller)
+{
+	gmpv_view_quit(controller->view);
+}
+
+void gmpv_controller_autofit(GmpvController *controller, gdouble multiplier)
+{
+	gchar *vid = NULL;
+	gint64 width = -1;
+	gint64 height = -1;
+
+	g_object_get(G_OBJECT(controller->model), "vid", &vid, NULL);
+	gmpv_model_get_video_geometry(controller->model, &width, &height);
+
+	if(vid && strncmp(vid, "no", 3) != 0 && width >= 0 && width >= 0)
+	{
+		gint new_width = (gint)(multiplier*(gdouble)width);
+		gint new_height = (gint)(multiplier*(gdouble)height);
+
+		g_debug("Resizing window to %dx%d", new_width, new_height);
+		gmpv_view_resize_video_area(	controller->view,
+						new_width,
+						new_height );
+	}
+
+	g_free(vid);
+}
+
+void gmpv_controller_present(GmpvController *controller)
+{
+	gmpv_view_present(controller->view);
+}
+
+void gmpv_controller_open(	GmpvController *controller,
+				const gchar *uri,
+				gboolean append )
+{
+	gmpv_model_load_file(controller->model, uri, append);
+}
diff --git a/src/gmpv_playlist_widget.h b/src/gmpv_controller.h
similarity index 54%
copy from src/gmpv_playlist_widget.h
copy to src/gmpv_controller.h
index 6e8a5dc..34e09f8 100644
--- a/src/gmpv_playlist_widget.h
+++ b/src/gmpv_controller.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,25 +17,27 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef PLAYLIST_WIDGET_H
-#define PLAYLIST_WIDGET_H
+#ifndef CONTROLLER_H
+#define CONTROLLER_H
 
 #include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
 
-#include "gmpv_playlist.h"
+#include "gmpv_model.h"
+#include "gmpv_view.h"
 
 G_BEGIN_DECLS
 
-#define GMPV_TYPE_PLAYLIST_WIDGET (gmpv_playlist_widget_get_type ())
+#define GMPV_TYPE_CONTROLLER (gmpv_controller_get_type())
 
-G_DECLARE_FINAL_TYPE(GmpvPlaylistWidget, gmpv_playlist_widget, GMPV, PLAYLIST_WIDGET, GtkScrolledWindow)
+G_DECLARE_FINAL_TYPE(GmpvController, gmpv_controller, GMPV, CONTROLLER, GObject)
 
-GtkWidget *gmpv_playlist_widget_new(GmpvPlaylist *store);
-void gmpv_playlist_widget_remove_selected(GmpvPlaylistWidget *wgt);
-void gmpv_playlist_widget_queue_draw(GmpvPlaylistWidget *wgt);
-GmpvPlaylist *gmpv_playlist_widget_get_store(GmpvPlaylistWidget *wgt);
+GmpvController *gmpv_controller_new(GmpvModel *model, GmpvView *view);
+void gmpv_controller_quit(GmpvController *controller);
+void gmpv_controller_autofit(GmpvController *controller, gdouble multiplier);
+void gmpv_controller_present(GmpvController *controller);
+void gmpv_controller_open(	GmpvController *controller,
+				const gchar *urii,
+				gboolean append );
 
 G_END_DECLS
 
diff --git a/src/gmpv_inputctl.c b/src/gmpv_controller_input.c
similarity index 74%
rename from src/gmpv_inputctl.c
rename to src/gmpv_controller_input.c
index 5e6354d..5fd2cd8 100644
--- a/src/gmpv_inputctl.c
+++ b/src/gmpv_controller_input.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,7 +23,9 @@
 #include <gtk/gtk.h>
 #include <string.h>
 
-#include "gmpv_inputctl.h"
+#include "gmpv_controller_private.h"
+#include "gmpv_controller.h"
+#include "gmpv_controller_input.h"
 #include "gmpv_mpv.h"
 #include "gmpv_mpv_wrapper.h"
 #include "gmpv_main_window.h"
@@ -72,7 +74,8 @@ static gchar *get_full_keystr(guint keyval, guint state)
 		g_strlcat(modstr, "Alt+", max_modstr_len);
 	}
 
-	if((state&GDK_META_MASK) != 0 || (state&GDK_SUPER_MASK) != 0)
+	/* Super is Meta in mpv */
+	if((state&GDK_SUPER_MASK) != 0)
 	{
 		g_strlcat(modstr, "Meta+", max_modstr_len);
 	}
@@ -98,21 +101,14 @@ static gboolean key_press_handler(	GtkWidget *widget,
 					GdkEvent *event,
 					gpointer data )
 {
-	const gchar *cmd[] = {"keydown", NULL, NULL};
-	GmpvApplication *app = data;
+	GmpvController *controller = data;
 	guint keyval = ((GdkEventKey*)event)->keyval;
 	guint state = ((GdkEventKey*)event)->state;
-	gchar *keystr = NULL;
-
-	cmd[1] = keystr = get_full_keystr(keyval, state);
+	gchar *keystr = get_full_keystr(keyval, state);
 
 	if(keystr)
 	{
-		GmpvMpv *mpv = gmpv_application_get_mpv(app);
-
-		g_debug("Sent '%s' key down to mpv", keystr);
-		gmpv_mpv_command(mpv, cmd);
-
+		gmpv_model_key_down(controller->model, keystr);
 		g_free(keystr);
 	}
 
@@ -123,21 +119,14 @@ static gboolean key_release_handler(	GtkWidget *widget,
 					GdkEvent *event,
 					gpointer data )
 {
-	GmpvApplication *app = data;
+	GmpvController *controller = data;
 	guint keyval = ((GdkEventKey*)event)->keyval;
 	guint state = ((GdkEventKey*)event)->state;
-	gchar *keystr = NULL;
-	const gchar *cmd[] = {"keyup", NULL, NULL};
-
-	cmd[1] = keystr = get_full_keystr(keyval, state);
+	gchar *keystr = get_full_keystr(keyval, state);
 
 	if(keystr)
 	{
-		GmpvMpv *mpv = gmpv_application_get_mpv(app);
-
-		g_debug("Sent '%s' key up to mpv", keystr);
-		gmpv_mpv_command(mpv, cmd);
-
+		gmpv_model_key_up(controller->model, keystr);
 		g_free(keystr);
 	}
 
@@ -154,20 +143,16 @@ static gboolean mouse_button_handler(	GtkWidget *widget,
 	|| btn_event->type == GDK_BUTTON_RELEASE
 	|| btn_event->type == GDK_SCROLL)
 	{
-		GmpvApplication *app = data;
-		GmpvMpv *mpv = gmpv_application_get_mpv(app);
+		GmpvController *controller = data;
 		gchar *btn_str =	g_strdup_printf
 					("MOUSE_BTN%u", btn_event->button-1);
-		const gchar *type_str =	(btn_event->type == GDK_SCROLL)?
-					"keypress":
-					(btn_event->type == GDK_BUTTON_PRESS)?
-					"keydown":"keyup";
-		const gchar *key_cmd[] = {type_str, btn_str, NULL};
-
-		g_debug(	"Sent %s event for button %s to mpv",
-				type_str, btn_str );
+		void (*func)(GmpvModel *, const gchar *)
+			=	(btn_event->type == GDK_SCROLL)?
+				gmpv_model_key_press:
+				(btn_event->type == GDK_BUTTON_PRESS)?
+				gmpv_model_key_down:gmpv_model_key_up;
 
-		gmpv_mpv_command(mpv, key_cmd);
+		func(controller->model, btn_str);
 
 		g_free(btn_str);
 	}
@@ -179,17 +164,12 @@ static gboolean mouse_move_handler(	GtkWidget *widget,
 					GdkEvent *event,
 					gpointer data )
 {
-	GmpvApplication *app = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
+	GmpvController *controller = data;
 	GdkEventMotion *motion_event = (GdkEventMotion *)event;
-	gchar *x_str = g_strdup_printf("%d", (gint)motion_event->x);
-	gchar *y_str = g_strdup_printf("%d", (gint)motion_event->y);
-	const gchar *cmd[] = {"mouse", x_str, y_str, NULL};
 
-	gmpv_mpv_command(mpv, cmd);
-
-	g_free(x_str);
-	g_free(y_str);
+	gmpv_model_mouse(	controller->model,
+				(gint)motion_event->x,
+				(gint)motion_event->y );
 
 	return FALSE;
 }
@@ -262,33 +242,30 @@ static gboolean scroll_handler(	GtkWidget *widget,
 	return TRUE;
 }
 
-void gmpv_inputctl_connect_signals(GmpvApplication *app)
+void gmpv_controller_input_connect_signals(GmpvController *controller)
 {
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	GmpvVideoArea *video_area = gmpv_main_window_get_video_area(wnd);
-
-	g_signal_connect(	wnd,
+	g_signal_connect(	controller->view,
 				"key-press-event",
 				G_CALLBACK(key_press_handler),
-				app );
-	g_signal_connect(	wnd,
+				controller );
+	g_signal_connect(	controller->view,
 				"key-release-event",
 				G_CALLBACK(key_release_handler),
-				app );
-	g_signal_connect(	video_area,
+				controller );
+	g_signal_connect(	controller->view,
 				"button-press-event",
 				G_CALLBACK(mouse_button_handler),
-				app );
-	g_signal_connect(	video_area,
+				controller );
+	g_signal_connect(	controller->view,
 				"button-release-event",
 				G_CALLBACK(mouse_button_handler),
-				app );
-	g_signal_connect(	video_area,
+				controller );
+	g_signal_connect(	controller->view,
 				"motion-notify-event",
 				G_CALLBACK(mouse_move_handler),
-				app );
-	g_signal_connect(	video_area,
+				controller );
+	g_signal_connect(	controller->view,
 				"scroll-event",
 				G_CALLBACK(scroll_handler),
-				app );
+				controller );
 }
diff --git a/src/gmpv_inputctl.h b/src/gmpv_controller_input.h
similarity index 78%
rename from src/gmpv_inputctl.h
rename to src/gmpv_controller_input.h
index 10d3966..61f25ee 100644
--- a/src/gmpv_inputctl.h
+++ b/src/gmpv_controller_input.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,16 +17,16 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef INPUTCTL_H
-#define INPUTCTL_H
+#ifndef CONTROLLER_INPUT_H
+#define CONTROLLER_INPUT_H
 
 #include <glib.h>
 
-#include "gmpv_application.h"
+#include "gmpv_controller_input.h"
 
 G_BEGIN_DECLS
 
-void gmpv_inputctl_connect_signals(GmpvApplication *app);
+void gmpv_controller_input_connect_signals(GmpvController *controller);
 
 G_END_DECLS
 
diff --git a/src/gmpv_mpv_private.h b/src/gmpv_controller_private.h
similarity index 56%
copy from src/gmpv_mpv_private.h
copy to src/gmpv_controller_private.h
index 0136736..86b07f1 100644
--- a/src/gmpv_mpv_private.h
+++ b/src/gmpv_controller_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,48 +17,51 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef MPV_OBJ_PRIVATE_H
-#define MPV_OBJ_PRIVATE_H
+#ifndef CONTROLLER_PRIVATE_H
+#define CONTROLLER_PRIVATE_H
 
-#include "gmpv_mpv_opt.h"
+#include "gmpv_model.h"
+#include "gmpv_view.h"
 
 G_BEGIN_DECLS
 
 enum
 {
 	PROP_0,
-	PROP_WID,
-	PROP_PLAYLIST,
+	PROP_MODEL,
+	PROP_VIEW,
+	PROP_AID,
+	PROP_VID,
+	PROP_SID,
+	PROP_READY,
+	PROP_LOOP,
+	PROP_IDLE,
 	N_PROPERTIES
 };
 
-struct _GmpvMpv
+struct _GmpvController
 {
 	GObject parent;
-	GmpvMpvState state;
-	mpv_handle *mpv_ctx;
-	mpv_opengl_cb_context *opengl_ctx;
-	GmpvPlaylist *playlist;
-	GtkGLArea *glarea;
-	gchar *tmp_input_file;
-	GSList *log_level_list;
-	gdouble autofit_ratio;
-	GmpvGeometry *geometry;
-	gboolean force_opengl;
-	gint64 wid;
-	void *event_callback_data;
-	void *opengl_cb_callback_data;
-	void (*event_callback)(mpv_event *, void *data);
-	void (*opengl_cb_callback)(void *data);
+	GmpvModel *model;
+	GmpvView *view;
+	gint aid;
+	gint vid;
+	gint sid;
+	gboolean ready;
+	gboolean loop;
+	gboolean idle;
+	GQueue *action_queue;
+	gchar **files;
+	guint inhibit_cookie;
+	gint64 target_playlist_pos;
+	guint update_seekbar_id;
 };
 
-struct _GmpvMpvClass
+struct _GmpvControllerClass
 {
 	GObjectClass parent_class;
 };
 
-void mpv_check_error(int status);
-
 G_END_DECLS
 
 #endif
diff --git a/src/gmpv_def.h b/src/gmpv_def.h
index 383097c..3e1e04c 100644
--- a/src/gmpv_def.h
+++ b/src/gmpv_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -25,9 +25,11 @@
 #define CONFIG_DIR "gnome-mpv"
 #define CONFIG_ROOT APP_ID
 #define CONFIG_WIN_STATE APP_ID".window-state"
+#define ACTION_PREFIX "gmpv-action"
 #define DEFAULT_LOG_LEVEL MPV_LOG_LEVEL_ERROR
-#define MPRIS_TRACK_ID_PREFIX "/org/gnome_mpv/GmpvTrack/"
-#define MPRIS_BUS_NAME "org.mpris.MediaPlayer2.gnome-mpv"
+#define MPRIS_TRACK_ID_NO_TRACK "/org/mpris/MediaPlayer2/TrackList/NoTrack"
+#define MPRIS_TRACK_ID_PREFIX "/io/github/GnomeMpv/Track/"
+#define MPRIS_BUS_NAME "org.mpris.MediaPlayer2.GnomeMpv"
 #define MPRIS_OBJ_ROOT_PATH "/org/mpris/MediaPlayer2"
 #define PLAYLIST_DEFAULT_WIDTH 200
 #define PLAYLIST_MIN_WIDTH 20
@@ -82,6 +84,8 @@
 #define DEFAULT_KEYBINDS \
 	{	"Ctrl+o script-message gmpv-action show-open-dialog(false)",\
 		"Ctrl+l script-message gmpv-action show-open-location-dialog(false)",\
+		"Ctrl+Shift+o script-message gmpv-action show-open-dialog(true)",\
+		"Ctrl+Shift+l script-message gmpv-action show-open-location-dialog(true)",\
 		"Ctrl+Shift+s script-message gmpv-action save-playlist",\
 		"Ctrl+q script-message gmpv-action quit",\
 		"Ctrl+? script-message gmpv-action show-shortcuts-dialog",\
@@ -108,6 +112,10 @@
 		"Alt+1 script-message gmpv-action set-video-size(1.0)",\
 		"Alt+2 script-message gmpv-action set-video-size(2.0)",\
 		"MOUSE_BTN0_DBL script-message gmpv-action toggle-fullscreen",\
+		"MOUSE_BTN3 add volume 2",\
+		"MOUSE_BTN4 add volume -2",\
+		"MOUSE_BTN5 no-osd seek -10",\
+		"MOUSE_BTN6 no-osd seek 10",\
 		NULL }
 
 #define KEYSTRING_MAP	{	"<", "less",\
@@ -211,15 +219,15 @@
 					"rar",\
 					NULL }
 
-#define SUPPORTED_MIME_TYPES	{	"gmpv_application/ogg",\
-					"gmpv_application/x-ogg",\
-					"gmpv_application/sdp",\
-					"gmpv_application/smil",\
-					"gmpv_application/x-smil",\
-					"gmpv_application/streamingmedia",\
-					"gmpv_application/x-streamingmedia",\
-					"gmpv_application/vnd.rn-realmedia",\
-					"gmpv_application/vnd.rn-realmedia-vbr",\
+#define SUPPORTED_MIME_TYPES	{	"application/ogg",\
+					"application/x-ogg",\
+					"application/sdp",\
+					"application/smil",\
+					"application/x-smil",\
+					"application/streamingmedia",\
+					"application/x-streamingmedia",\
+					"application/vnd.rn-realmedia",\
+					"application/vnd.rn-realmedia-vbr",\
 					"audio/aac",\
 					"audio/x-aac",\
 					"audio/m4a",\
diff --git a/src/gmpv_file_chooser.c b/src/gmpv_file_chooser.c
new file mode 100644
index 0000000..5feac0a
--- /dev/null
+++ b/src/gmpv_file_chooser.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gmpv_file_chooser.h"
+#include "gmpv_def.h"
+
+static void load_last_folder(GtkFileChooser *chooser);
+static void save_last_folder(GtkFileChooser *chooser);
+static void response_handler(GtkDialog *dialog, gint response_id, gpointer data);
+
+static void load_last_folder(GtkFileChooser *chooser)
+{
+	GSettings *win_config = g_settings_new(CONFIG_WIN_STATE);
+	gchar *uri = g_settings_get_string(win_config, "last-folder-uri");
+
+	if(uri && *uri)
+	{
+		gtk_file_chooser_set_current_folder_uri(chooser, uri);
+	}
+
+	g_free(uri);
+	g_object_unref(win_config);
+}
+
+static void save_last_folder(GtkFileChooser *chooser)
+{
+	gchar *uri = gtk_file_chooser_get_current_folder_uri(chooser);
+	GSettings *win_config = g_settings_new(CONFIG_WIN_STATE);
+
+	g_settings_set_string(win_config, "last-folder-uri", uri?:"");
+
+	g_free(uri);
+	g_object_unref(win_config);
+}
+
+static void response_handler(GtkDialog *dialog, gint response_id, gpointer data)
+{
+	if(response_id == GTK_RESPONSE_ACCEPT)
+	{
+		GSettings *main_config;
+		gboolean last_folder_enable;
+
+		main_config = g_settings_new(CONFIG_ROOT);
+		last_folder_enable =	g_settings_get_boolean
+					(main_config, "last-folder-enable");
+
+		if(last_folder_enable)
+		{
+			save_last_folder(GTK_FILE_CHOOSER(dialog));
+		}
+
+		g_object_unref(main_config);
+	}
+}
+
+GmpvFileChooser *gmpv_file_chooser_new(	const gchar *title,
+					GtkWindow *parent,
+					GtkFileChooserAction action )
+{
+	GmpvFileChooser *chooser;
+	GtkFileChooser *gtk_chooser;
+	GSettings *main_config;
+	gboolean last_folder_enable;
+
+#if GTK_CHECK_VERSION(3, 19, 7)
+	chooser = gtk_file_chooser_native_new(title, parent, action, NULL, NULL);
+#else
+	chooser = gtk_file_chooser_dialog_new(	title,
+						parent,
+						action,
+						_("_Cancel"),
+						GTK_RESPONSE_CANCEL,
+						_("_Open"),
+						GTK_RESPONSE_ACCEPT,
+						NULL );
+#endif
+
+	gtk_chooser = GTK_FILE_CHOOSER(chooser);
+	main_config = g_settings_new(CONFIG_ROOT);
+	last_folder_enable =	g_settings_get_boolean
+				(main_config, "last-folder-enable");
+
+	if(last_folder_enable)
+	{
+		load_last_folder(GTK_FILE_CHOOSER(chooser));
+	}
+
+	gmpv_file_chooser_set_modal(chooser, TRUE);
+	gtk_file_chooser_set_select_multiple(gtk_chooser, TRUE);
+	gtk_file_chooser_set_do_overwrite_confirmation(gtk_chooser, TRUE);
+
+	g_signal_connect(chooser, "response", G_CALLBACK(response_handler), NULL);
+
+	g_object_unref(main_config);
+
+	return chooser;
+}
+
+void gmpv_file_chooser_set_default_filters(	GmpvFileChooser *chooser,
+						gboolean audio,
+						gboolean video,
+						gboolean image,
+						gboolean subtitle )
+{
+	GtkFileChooser *gtk_chooser = GTK_FILE_CHOOSER(chooser);
+	GSList *filters = gtk_file_chooser_list_filters(gtk_chooser);
+
+	for(GSList *iter = filters; iter; iter = g_slist_next(iter))
+	{
+		gtk_file_chooser_remove_filter(gtk_chooser, iter->data);
+	}
+
+	if(audio || video || image || subtitle)
+	{
+		GtkFileFilter *filter = gtk_file_filter_new();
+		gtk_file_filter_set_name(filter, _("All Files"));
+		gtk_file_filter_add_pattern(filter, "*");
+		gtk_file_chooser_add_filter(gtk_chooser, filter);
+	}
+
+	if(audio || video || image)
+	{
+		GtkFileFilter *filter = gtk_file_filter_new();
+		gtk_file_filter_set_name(filter, _("Media Files"));
+		gtk_file_filter_add_mime_type(filter, "audio/*");
+		gtk_file_filter_add_mime_type(filter, "video/*");
+		gtk_file_filter_add_mime_type(filter, "images/*");
+		gtk_file_chooser_add_filter(gtk_chooser, filter);
+		gtk_file_chooser_set_filter(gtk_chooser, filter);
+	}
+
+	if(audio)
+	{
+		GtkFileFilter *filter = gtk_file_filter_new();
+		gtk_file_filter_set_name(filter, _("Audio Files"));
+		gtk_file_filter_add_mime_type(filter, "audio/*");
+		gtk_file_chooser_add_filter(gtk_chooser, filter);
+	}
+
+	if(video)
+	{
+		GtkFileFilter *filter = gtk_file_filter_new();
+		gtk_file_filter_set_name(filter, _("Video Files"));
+		gtk_file_filter_add_mime_type(filter, "video/*");
+		gtk_file_chooser_add_filter(gtk_chooser, filter);
+	}
+
+	if(image)
+	{
+		GtkFileFilter *filter = gtk_file_filter_new();
+		gtk_file_filter_set_name(filter, _("Image Files"));
+		gtk_file_filter_add_mime_type(filter, "images/*");
+		gtk_file_chooser_add_filter(gtk_chooser, filter);
+	}
+
+	if(subtitle)
+	{
+		GtkFileFilter *filter = gtk_file_filter_new();
+		const gchar *exts[] = SUBTITLE_EXTS;
+
+		gtk_file_filter_set_name(filter, _("Subtitle Files"));
+
+		for(gint i = 0; exts[i]; i++)
+		{
+			gchar *pattern = g_strdup_printf("*.%s", exts[i]);
+
+			gtk_file_filter_add_pattern(filter, pattern);
+			g_free(pattern);
+		}
+
+		gtk_file_chooser_add_filter(gtk_chooser, filter);
+
+		if(!(audio || video || image))
+		{
+			gtk_file_chooser_set_filter(gtk_chooser, filter);
+		}
+	}
+}
+
diff --git a/src/gmpv_common.h b/src/gmpv_file_chooser.h
similarity index 55%
copy from src/gmpv_common.h
copy to src/gmpv_file_chooser.h
index 51ea156..43af297 100644
--- a/src/gmpv_common.h
+++ b/src/gmpv_file_chooser.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,51 +17,38 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef COMMON_H
-#define COMMON_H
+#ifndef FILE_CHOOSER_H
+#define FILE_CHOOSER_H
 
-#include <glib.h>
 #include <gtk/gtk.h>
 
-#include "gmpv_application.h"
-
 G_BEGIN_DECLS
 
-gchar *get_config_dir_path(void);
-gchar *get_scripts_dir_path(void);
-gchar *get_path_from_uri(const gchar *uri);
-gchar *get_name_from_path(const gchar *path);
-gboolean update_seek_bar(gpointer data);
-void activate_action_string(GmpvApplication *app, const gchar *str);
-void migrate_config(GmpvApplication *app);
-void seek(GmpvApplication *app, gdouble time);
-void show_error_dialog(GmpvApplication *app, const gchar *prefix, const gchar *msg);
-void resize_window_to_fit(GmpvApplication *app, gdouble multiplier);
-void load_keybind(	GmpvApplication *app,
-			const gchar *config_path,
-			gboolean notify_ignore );
-
 #if GTK_CHECK_VERSION(3, 19, 7)
+#define GMPV_FILE_CHOOSER GTK_FILE_CHOOSER_NATIVE
 #define GmpvFileChooser GtkFileChooserNative
 #define gmpv_file_chooser_destroy(x) gtk_native_dialog_destroy(GTK_NATIVE_DIALOG(x))
 #define gmpv_file_chooser_show(x) gtk_native_dialog_show(GTK_NATIVE_DIALOG(x))
 #define gmpv_file_chooser_set_modal(x, y) gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(x), y)
 #define gmpv_file_chooser_run(x) gtk_native_dialog_run(GTK_NATIVE_DIALOG(x))
-#define gmpv_file_chooser_new(title,parent,action,accept,cancel) \
-	gtk_file_chooser_native_new(title,parent,action,accept,cancel)
 #else
+#define GMPV_FILE_CHOOSER GTK_WIDGET
 #define GmpvFileChooser GtkWidget
 #define gmpv_file_chooser_destroy(x) gtk_widget_destroy(GTK_WIDGET(x))
-#define gmpv_file_chooser_show(x) gtk_widget_show_all(GTK_DIALOG(x))
+#define gmpv_file_chooser_show(x) gtk_widget_show_all(GTK_WIDGET(x))
 #define gmpv_file_chooser_set_modal(x, y) gtk_window_set_modal(GTK_WINDOW(x), y)
 #define gmpv_file_chooser_run(x) gtk_dialog_run(GTK_DIALOG(x))
-#define gmpv_file_chooser_new(title,parent,action,accept,cancel) \
-	gtk_file_chooser_dialog_new(	title,parent,action,\
-					cancel,GTK_RESPONSE_CANCEL,\
-					accept,GTK_RESPONSE_ACCEPT,\
-					NULL )
 #endif
 
+GmpvFileChooser *gmpv_file_chooser_new(	const gchar *title,
+					GtkWindow *parent,
+					GtkFileChooserAction action );
+void gmpv_file_chooser_set_default_filters(	GmpvFileChooser *chooser,
+						gboolean audio,
+						gboolean video,
+						gboolean image,
+						gboolean subtitle );
+
 G_END_DECLS
 
 #endif
diff --git a/src/gmpv_header_bar.c b/src/gmpv_header_bar.c
index fa259b2..a2653f1 100644
--- a/src/gmpv_header_bar.c
+++ b/src/gmpv_header_bar.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -48,39 +48,35 @@ static void gmpv_header_bar_init(GmpvHeaderBar *hdr)
 	GtkHeaderBar *ghdr;
 	GMenu *open_btn_menu;
 	GMenu *menu_btn_menu;
-	GIcon *open_icon;
-	GIcon *fullscreen_icon;
-	GIcon *menu_icon;
+	GtkWidget *open_icon;
+	GtkWidget *fullscreen_icon;
+	GtkWidget *menu_icon;
 
 	ghdr = GTK_HEADER_BAR(hdr);
 	open_btn_menu = g_menu_new();
 	menu_btn_menu = g_menu_new();
-	open_icon =	g_themed_icon_new_with_default_fallbacks
-			("list-add-symbolic");
-	fullscreen_icon =	g_themed_icon_new_with_default_fallbacks
-				("view-fullscreen-symbolic");
-	menu_icon =	g_themed_icon_new_with_default_fallbacks
-			("open-menu-symbolic");
+
+	open_icon =		gtk_image_new_from_icon_name
+				("list-add-symbolic", GTK_ICON_SIZE_MENU);
+	fullscreen_icon =	gtk_image_new_from_icon_name
+				("view-fullscreen-symbolic", GTK_ICON_SIZE_MENU);
+	menu_icon =		gtk_image_new_from_icon_name
+				("open-menu-symbolic", GTK_ICON_SIZE_MENU);
 
 	hdr->open_btn = gtk_menu_button_new();
 	hdr->fullscreen_btn = gtk_button_new();
 	hdr->menu_btn = gtk_menu_button_new();
 
 	gmpv_menu_build_open_btn(open_btn_menu);
-	gmpv_menu_build_menu_btn(menu_btn_menu, NULL, NULL, NULL);
-
-	gtk_button_set_image
-		(	GTK_BUTTON(hdr->open_btn),
-			gtk_image_new_from_gicon
-			(open_icon, GTK_ICON_SIZE_MENU) );
-	gtk_button_set_image
-		(	GTK_BUTTON(hdr->fullscreen_btn),
-			gtk_image_new_from_gicon
-			(fullscreen_icon, GTK_ICON_SIZE_MENU) );
-	gtk_button_set_image
-		(	GTK_BUTTON(hdr->menu_btn),
-			gtk_image_new_from_gicon
-			(menu_icon, GTK_ICON_SIZE_MENU) );
+	gmpv_menu_build_menu_btn(menu_btn_menu, NULL);
+
+	g_object_set(open_icon, "use-fallback", TRUE, NULL);
+	g_object_set(fullscreen_icon, "use-fallback", TRUE, NULL);
+	g_object_set(menu_icon, "use-fallback", TRUE, NULL);
+
+	gtk_button_set_image(GTK_BUTTON(hdr->open_btn), open_icon);
+	gtk_button_set_image(GTK_BUTTON(hdr->fullscreen_btn), fullscreen_icon);
+	gtk_button_set_image(GTK_BUTTON(hdr->menu_btn), menu_icon);
 
 	gtk_menu_button_set_menu_model
 		(	GTK_MENU_BUTTON(hdr->open_btn),
@@ -128,18 +124,23 @@ gboolean gmpv_header_bar_get_menu_button_popup_visible(GmpvHeaderBar *hdr)
 void gmpv_header_bar_set_fullscreen_state(	GmpvHeaderBar *hdr,
 						gboolean fullscreen )
 {
+	GtkWidget *image = gtk_button_get_image(GTK_BUTTON(hdr->fullscreen_btn));
+
+	gtk_image_set_from_icon_name(	GTK_IMAGE(image),
+					fullscreen?
+					"view-restore-symbolic":
+					"view-fullscreen-symbolic",
+					GTK_ICON_SIZE_MENU );
+
 	gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(hdr), !fullscreen);
 }
 
 void gmpv_header_bar_update_track_list(	GmpvHeaderBar *hdr,
-					const GSList *audio_list,
-					const GSList *video_list,
-					const GSList *sub_list )
+					const GPtrArray *track_list )
 {
 	GMenu *menu = g_menu_new();
 
-	gmpv_menu_build_menu_btn
-		(menu, audio_list, video_list, sub_list);
+	gmpv_menu_build_menu_btn(menu, track_list);
 	gtk_menu_button_set_menu_model
 		(GTK_MENU_BUTTON(hdr->menu_btn), G_MENU_MODEL(menu));
 }
diff --git a/src/gmpv_header_bar.h b/src/gmpv_header_bar.h
index 1c5b15d..ce78ffb 100644
--- a/src/gmpv_header_bar.h
+++ b/src/gmpv_header_bar.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -34,8 +34,6 @@ gboolean gmpv_header_bar_get_menu_button_popup_visible(GmpvHeaderBar *hdr);
 void gmpv_header_bar_set_fullscreen_state(	GmpvHeaderBar *hdr,
 						gboolean fullscreen );
 void gmpv_header_bar_update_track_list(	GmpvHeaderBar *hdr,
-					const GSList *audio_list,
-					const GSList *video_list,
-					const GSList *sub_list );
+					const GPtrArray *track_list );
 
 #endif
diff --git a/src/gmpv_main_window.c b/src/gmpv_main_window.c
index 79e8dae..a5fc361 100644
--- a/src/gmpv_main_window.c
+++ b/src/gmpv_main_window.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,6 +23,7 @@
 #include <gdk/gdk.h>
 
 #include "gmpv_def.h"
+#include "gmpv_marshal.h"
 #include "gmpv_menu.h"
 #include "gmpv_application.h"
 #include "gmpv_playlist_widget.h"
@@ -34,18 +35,19 @@
 enum
 {
 	PROP_0,
-	PROP_PLAYLIST,
+	PROP_ALWAYS_FLOATING,
 	N_PROPERTIES
 };
 
 struct _GmpvMainWindow
 {
 	GtkApplicationWindow parent_instance;
-	GmpvPlaylist *playlist_store;
 	gint width_offset;
 	gint height_offset;
 	gint resize_target[2];
 	gboolean csd;
+	gboolean always_floating;
+	gboolean use_floating_controls;
 	gboolean fullscreen;
 	gboolean playlist_visible;
 	gboolean playlist_first_toggle;
@@ -74,6 +76,7 @@ static void gmpv_main_window_get_property(	GObject *object,
 						guint property_id,
 						GValue *value,
 						GParamSpec *pspec );
+static void gmpv_main_window_notify(GObject *object, GParamSpec *pspec);
 static void resize_video_area_finalize(	GtkWidget *widget,
 					GdkRectangle *allocation,
 					gpointer data );
@@ -86,7 +89,7 @@ static void gmpv_main_window_constructed(GObject *object)
 {
 	GmpvMainWindow *self = GMPV_MAIN_WINDOW(object);
 
-	self->playlist = gmpv_playlist_widget_new(self->playlist_store);
+	self->playlist = gmpv_playlist_widget_new();
 
 	gtk_widget_show_all(self->playlist);
 	gtk_widget_hide(self->playlist);
@@ -115,10 +118,9 @@ static void gmpv_main_window_set_property(	GObject *object,
 {
 	GmpvMainWindow *self = GMPV_MAIN_WINDOW(object);
 
-	if(property_id == PROP_PLAYLIST)
+	if(property_id == PROP_ALWAYS_FLOATING)
 	{
-		self->playlist_store = g_value_get_pointer(value);
-
+		self->always_floating = g_value_get_boolean(value);
 	}
 	else
 	{
@@ -133,9 +135,9 @@ static void gmpv_main_window_get_property(	GObject *object,
 {
 	GmpvMainWindow *self = GMPV_MAIN_WINDOW(object);
 
-	if(property_id == PROP_PLAYLIST)
+	if(property_id == PROP_ALWAYS_FLOATING)
 	{
-		g_value_set_pointer(value, self->playlist_store);
+		g_value_set_boolean(value, self->always_floating);
 	}
 	else
 	{
@@ -143,6 +145,17 @@ static void gmpv_main_window_get_property(	GObject *object,
 	}
 }
 
+static void gmpv_main_window_notify(GObject *object, GParamSpec *pspec)
+{
+	if(g_strcmp0(pspec->name, "always-use-floating-controls") == 0)
+	{
+		GmpvMainWindow *wnd = GMPV_MAIN_WINDOW(object);
+		gboolean floating = wnd->always_floating || wnd->fullscreen;
+
+		gmpv_main_window_set_use_floating_controls(wnd, floating);
+	}
+}
+
 static void resize_video_area_finalize(	GtkWidget *widget,
 					GdkRectangle *allocation,
 					gpointer data )
@@ -262,19 +275,22 @@ static void gmpv_main_window_class_init(GmpvMainWindowClass *klass)
 	obj_class->constructed = gmpv_main_window_constructed;
 	obj_class->set_property = gmpv_main_window_set_property;
 	obj_class->get_property = gmpv_main_window_get_property;
-
-	pspec = g_param_spec_pointer
-		(	"playlist",
-			"Playlist",
-			"Playlist object used to store playlist items",
-			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
-
-	g_object_class_install_property(obj_class, PROP_PLAYLIST, pspec);
+	obj_class->notify = gmpv_main_window_notify;
+
+	pspec = g_param_spec_boolean
+		(	"always-use-floating-controls",
+			"Always use floating controls",
+			"Whether or not to use floating controls in windowed mode",
+			FALSE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_ALWAYS_FLOATING, pspec);
 }
 
 static void gmpv_main_window_init(GmpvMainWindow *wnd)
 {
 	wnd->csd = FALSE;
+	wnd->always_floating = FALSE;
+	wnd->use_floating_controls = FALSE;
 	wnd->fullscreen = FALSE;
 	wnd->playlist_visible = FALSE;
 	wnd->pre_fs_playlist_visible = FALSE;
@@ -290,6 +306,10 @@ static void gmpv_main_window_init(GmpvMainWindow *wnd)
 	wnd->width_offset = 0;
 	wnd->height_offset = 0;
 
+	g_object_bind_property(	wnd, "title",
+				wnd->vid_area, "title",
+				G_BINDING_DEFAULT );
+
 	gtk_widget_add_events(	wnd->vid_area,
 				GDK_ENTER_NOTIFY_MASK
 				|GDK_LEAVE_NOTIFY_MASK );
@@ -310,11 +330,14 @@ static void gmpv_main_window_init(GmpvMainWindow *wnd)
 	gtk_container_add(GTK_CONTAINER(wnd), wnd->main_box);
 }
 
-GtkWidget *gmpv_main_window_new(GmpvApplication *app, GmpvPlaylist *playlist)
+GtkWidget *gmpv_main_window_new(	GmpvApplication *app,
+					gboolean always_floating )
 {
 	return GTK_WIDGET(g_object_new(	gmpv_main_window_get_type(),
-					"application", app,
-					"playlist", playlist,
+					"application",
+					app,
+					"always-use-floating-controls",
+					always_floating,
 					NULL ));
 }
 
@@ -333,14 +356,15 @@ GmpvVideoArea *gmpv_main_window_get_video_area(GmpvMainWindow *wnd)
 	return GMPV_VIDEO_AREA(wnd->vid_area);
 }
 
-void gmpv_main_window_set_fullscreen(GmpvMainWindow *wnd, gboolean fullscreen)
+void gmpv_main_window_set_use_floating_controls(	GmpvMainWindow *wnd,
+							gboolean floating )
 {
-	if(fullscreen != wnd->fullscreen)
+	if(floating != wnd->use_floating_controls)
 	{
 		GmpvVideoArea *vid_area = GMPV_VIDEO_AREA(wnd->vid_area);
 		GtkContainer *main_box = GTK_CONTAINER(wnd->main_box);
 
-		if(fullscreen)
+		if(floating)
 		{
 			g_object_ref(wnd->control_box);
 			gtk_container_remove(main_box, wnd->control_box);
@@ -348,10 +372,6 @@ void gmpv_main_window_set_fullscreen(GmpvMainWindow *wnd, gboolean fullscreen)
 				(vid_area, wnd->control_box);
 			g_object_unref(wnd->control_box);
 
-			gtk_window_fullscreen(GTK_WINDOW(wnd));
-			gtk_window_present(GTK_WINDOW(wnd));
-
-			wnd->pre_fs_playlist_visible = wnd->playlist_visible;
 		}
 		else
 		{
@@ -359,7 +379,35 @@ void gmpv_main_window_set_fullscreen(GmpvMainWindow *wnd, gboolean fullscreen)
 			gmpv_video_area_set_control_box(vid_area, NULL);
 			gtk_container_add(main_box, wnd->control_box);
 			g_object_unref(wnd->control_box);
+		}
+
+		wnd->use_floating_controls = floating;
+	}
+}
+
+gboolean gmpv_main_window_get_use_floating_controls(GmpvMainWindow *wnd)
+{
+	return wnd->use_floating_controls;
+}
+
+void gmpv_main_window_set_fullscreen(GmpvMainWindow *wnd, gboolean fullscreen)
+{
+	if(fullscreen != wnd->fullscreen)
+	{
+		GmpvVideoArea *vid_area = GMPV_VIDEO_AREA(wnd->vid_area);
+		gboolean floating = wnd->always_floating || fullscreen;
+		gboolean playlist_visible =	!fullscreen &&
+						wnd->pre_fs_playlist_visible;
 
+		if(fullscreen)
+		{
+			gtk_window_fullscreen(GTK_WINDOW(wnd));
+			gtk_window_present(GTK_WINDOW(wnd));
+
+			wnd->pre_fs_playlist_visible = wnd->playlist_visible;
+		}
+		else
+		{
 			gtk_window_unfullscreen(GTK_WINDOW(wnd));
 
 			wnd->playlist_visible = wnd->pre_fs_playlist_visible;
@@ -372,9 +420,8 @@ void gmpv_main_window_set_fullscreen(GmpvMainWindow *wnd, gboolean fullscreen)
 		}
 
 		gmpv_video_area_set_fullscreen_state(vid_area, fullscreen);
-		gtk_widget_set_visible(	wnd->playlist,
-					!fullscreen &&
-					wnd->pre_fs_playlist_visible );
+		gmpv_main_window_set_use_floating_controls(wnd, floating);
+		gtk_widget_set_visible(wnd->playlist, playlist_visible);
 
 		wnd->fullscreen = fullscreen;
 	}
@@ -392,12 +439,8 @@ void gmpv_main_window_toggle_fullscreen(GmpvMainWindow *wnd)
 
 void gmpv_main_window_reset(GmpvMainWindow *wnd)
 {
-	GmpvPlaylist *store =	gmpv_playlist_widget_get_store
-				(GMPV_PLAYLIST_WIDGET(wnd->playlist));
-
 	gtk_window_set_title(GTK_WINDOW(wnd), g_get_application_name());
 	gmpv_control_box_reset(GMPV_CONTROL_BOX(wnd->control_box));
-	gmpv_playlist_set_indicator_pos(store, -1);
 }
 
 void gmpv_main_window_save_state(GmpvMainWindow *wnd)
@@ -494,22 +537,14 @@ void gmpv_main_window_set_geometry(	GmpvMainWindow *wnd,
 }
 
 void gmpv_main_window_update_track_list(	GmpvMainWindow *wnd,
-						const GSList *audio_list,
-						const GSList *video_list,
-						const GSList *sub_list )
+						const GPtrArray *track_list )
 {
 	if(gmpv_main_window_get_csd_enabled(wnd))
 	{
 		gmpv_header_bar_update_track_list
-			(	GMPV_HEADER_BAR(wnd->header_bar),
-				audio_list,
-				video_list,
-				sub_list );
+			(GMPV_HEADER_BAR(wnd->header_bar), track_list);
 		gmpv_video_area_update_track_list
-			(	GMPV_VIDEO_AREA(wnd->vid_area),
-				audio_list,
-				video_list,
-				sub_list );
+			(GMPV_VIDEO_AREA(wnd->vid_area), track_list);
 	}
 	else
 	{
@@ -522,8 +557,7 @@ void gmpv_main_window_update_track_list(	GmpvMainWindow *wnd,
 		if(menu)
 		{
 			g_menu_remove_all(menu);
-			gmpv_menu_build_full
-				(menu, audio_list, video_list, sub_list);
+			gmpv_menu_build_full(menu, track_list);
 		}
 	}
 }
diff --git a/src/gmpv_main_window.h b/src/gmpv_main_window.h
index 0572384..fb031fd 100644
--- a/src/gmpv_main_window.h
+++ b/src/gmpv_main_window.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -24,7 +24,6 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include "gmpv_playlist.h"
 #include "gmpv_playlist_widget.h"
 #include "gmpv_control_box.h"
 #include "gmpv_video_area.h"
@@ -38,10 +37,14 @@ G_DECLARE_FINAL_TYPE(GmpvMainWindow, gmpv_main_window, GMPV, MAIN_WINDOW, GtkApp
 
 typedef struct _GmpvApplication GmpvApplication;
 
-GtkWidget *gmpv_main_window_new(GmpvApplication *app, GmpvPlaylist *playlist);
+GtkWidget *gmpv_main_window_new(	GmpvApplication *app,
+					gboolean always_floating );
 GmpvPlaylistWidget *gmpv_main_window_get_playlist(GmpvMainWindow *wnd);
 GmpvControlBox *gmpv_main_window_get_control_box(GmpvMainWindow *wnd);
 GmpvVideoArea *gmpv_main_window_get_video_area(GmpvMainWindow *wnd);
+void gmpv_main_window_set_use_floating_controls(	GmpvMainWindow *wnd,
+							gboolean floating );
+gboolean gmpv_main_window_get_use_floating_controls(GmpvMainWindow *wnd);
 void gmpv_main_window_set_fullscreen(GmpvMainWindow *wnd, gboolean fullscreen);
 gboolean gmpv_main_window_get_fullscreen(GmpvMainWindow *wnd);
 void gmpv_main_window_toggle_fullscreen(GmpvMainWindow *wnd);
@@ -51,9 +54,7 @@ void gmpv_main_window_load_state(GmpvMainWindow *wnd);
 void gmpv_main_window_set_geometry(	GmpvMainWindow *wnd,
 					const GmpvGeometry *geom );
 void gmpv_main_window_update_track_list(	GmpvMainWindow *wnd,
-						const GSList *audio_list,
-						const GSList *video_list,
-						const GSList *sub_list );
+						const GPtrArray *track_list );
 void gmpv_main_window_resize_video_area(	GmpvMainWindow *wnd,
 						gint width,
 						gint height );
diff --git a/src/gmpv_menu.c b/src/gmpv_menu.c
index eab1f93..6ba7a53 100644
--- a/src/gmpv_menu.c
+++ b/src/gmpv_menu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,7 +23,7 @@
 #include <glib/gi18n.h>
 
 #include "gmpv_menu.h"
-#include "gmpv_track.h"
+#include "gmpv_common.h"
 
 typedef struct GmpvMenuEntry GmpvMenuEntry;
 
@@ -34,36 +34,82 @@ struct GmpvMenuEntry
 	GMenu *submenu;
 };
 
-static GMenu *build_menu_from_track_list(	const GSList *list,
+static void split_track_list(	const GPtrArray *track_list,
+				GPtrArray **audio_tracks,
+				GPtrArray **video_tracks,
+				GPtrArray **subtitle_tracks );
+static GMenu *build_menu_from_track_list(	const GPtrArray *list,
 						const gchar *action,
 						const gchar *load_action );
 static void build_menu(GMenu *menu, const GmpvMenuEntry *entries, gboolean flat);
-static GMenu *build_video_track_menu(const GSList *list);
-static GMenu *build_audio_track_menu(const GSList *list);
-static GMenu *build_subtitle_track_menu(const GSList *list);
+static GMenu *build_video_track_menu(const GPtrArray *list);
+static GMenu *build_audio_track_menu(const GPtrArray *list);
+static GMenu *build_subtitle_track_menu(const GPtrArray *list);
+
+static void split_track_list(	const GPtrArray *track_list,
+				GPtrArray **audio_tracks,
+				GPtrArray **video_tracks,
+				GPtrArray **subtitle_tracks )
+{
+	guint track_list_len = track_list?track_list->len:0;
+
+	g_assert(audio_tracks && video_tracks && subtitle_tracks);
+
+	/* The contents of these array are shallow-copied from track_list and
+	 * therefore only the container should be freed.
+	 */
+	*audio_tracks = g_ptr_array_new();
+	*video_tracks = g_ptr_array_new();
+	*subtitle_tracks = g_ptr_array_new();
+
+	for(guint i = 0; i < track_list_len; i++)
+	{
+		GmpvTrack *track = g_ptr_array_index(track_list, i);
 
-static GMenu *build_menu_from_track_list(	const GSList *list,
+		switch(track->type)
+		{
+			case TRACK_TYPE_AUDIO:
+			g_ptr_array_add(*audio_tracks, track);
+			break;
+
+			case TRACK_TYPE_VIDEO:
+			g_ptr_array_add(*video_tracks, track);
+			break;
+
+			case TRACK_TYPE_SUBTITLE:
+			g_ptr_array_add(*subtitle_tracks, track);
+			break;
+
+			default:
+			g_assert_not_reached();
+			break;
+		}
+	}
+}
+
+static GMenu *build_menu_from_track_list(	const GPtrArray *list,
 						const gchar *action,
 						const gchar *load_action )
 {
 	GMenu *menu = g_menu_new();
-	const GSList *iter = list;
 	const glong max_len = 32;
 	gchar *detailed_action;
 
+	g_assert(list);
+
 	detailed_action = g_strdup_printf("%s(@x 0)", action);
 
 	g_menu_append(menu, _("None"), detailed_action);
 	g_free(detailed_action);
 
-	while(iter)
+	for(guint i = 0; i < list->len; i++)
 	{
 		GmpvTrack *entry;
 		glong entry_title_len;
 		gchar *entry_title;
 		gchar *title;
 
-		entry = iter->data;
+		entry = g_ptr_array_index(list, i);
 
 		/* For simplicity, also dup the default string used when the
 		 * track has no title.
@@ -94,8 +140,6 @@ static GMenu *build_menu_from_track_list(	const GSList *list,
 
 		g_menu_append(menu, title, detailed_action);
 
-		iter = g_slist_next(iter);
-
 		g_free(detailed_action);
 		g_free(entry_title);
 		g_free(title);
@@ -157,13 +201,13 @@ static void build_menu(GMenu *menu, const GmpvMenuEntry *entries, gboolean flat)
 	}
 }
 
-static GMenu *build_video_track_menu(const GSList *list)
+static GMenu *build_video_track_menu(const GPtrArray *list)
 {
 	return	build_menu_from_track_list
 		(list, "app.set-video-track", NULL);
 }
 
-static GMenu *build_audio_track_menu(const GSList *list)
+static GMenu *build_audio_track_menu(const GPtrArray *list)
 {
 	return	build_menu_from_track_list
 		(	list,
@@ -171,7 +215,7 @@ static GMenu *build_audio_track_menu(const GSList *list)
 			"app.load-track('audio-add')" );
 }
 
-static GMenu *build_subtitle_track_menu(const GSList *list)
+static GMenu *build_subtitle_track_menu(const GPtrArray *list)
 {
 	return	build_menu_from_track_list
 		(	list,
@@ -179,14 +223,21 @@ static GMenu *build_subtitle_track_menu(const GSList *list)
 			"app.load-track('sub-add')" );
 }
 
-void gmpv_menu_build_full(	GMenu *menu,
-				const GSList *audio_list,
-				const GSList *video_list,
-				const GSList *sub_list )
+void gmpv_menu_build_full(GMenu *menu, const GPtrArray *track_list)
 {
-	GMenu *video_menu = build_video_track_menu(video_list);
-	GMenu *audio_menu = build_audio_track_menu(audio_list);
-	GMenu *sub_menu = build_subtitle_track_menu(sub_list);
+	GPtrArray *audio_tracks = NULL;
+	GPtrArray *video_tracks = NULL;
+	GPtrArray *subtitle_tracks = NULL;
+	GMenu *video_menu = NULL;
+	GMenu *audio_menu = NULL;
+	GMenu *subtitle_menu = NULL;
+
+	split_track_list
+		(track_list, &audio_tracks, &video_tracks, &subtitle_tracks);
+
+	video_menu = build_video_track_menu(video_tracks);
+	audio_menu = build_audio_track_menu(audio_tracks);
+	subtitle_menu = build_subtitle_track_menu(subtitle_tracks);
 
 	const GmpvMenuEntry entries[]
 		= {	{_("_File"), NULL, NULL},
@@ -198,7 +249,7 @@ void gmpv_menu_build_full(	GMenu *menu,
 			{_("_Preferences"), "app.show-preferences-dialog", NULL},
 			{_("_Video Track"), NULL, video_menu},
 			{_("_Audio Track"), NULL, audio_menu},
-			{_("S_ubtitle Track"), NULL, sub_menu},
+			{_("S_ubtitle Track"), NULL, subtitle_menu},
 			{_("_View"), NULL, NULL},
 			{_("_Toggle Controls"), "app.toggle-controls", NULL},
 			{_("_Toggle Playlist"), "app.toggle-playlist", NULL},
@@ -213,19 +264,29 @@ void gmpv_menu_build_full(	GMenu *menu,
 
 	build_menu(menu, entries, FALSE);
 
+	g_ptr_array_free(audio_tracks, FALSE);
+	g_ptr_array_free(video_tracks, FALSE);
+	g_ptr_array_free(subtitle_tracks, FALSE);
 	g_object_unref(video_menu);
 	g_object_unref(audio_menu);
-	g_object_unref(sub_menu);
+	g_object_unref(subtitle_menu);
 }
 
-void gmpv_menu_build_menu_btn(	GMenu *menu,
-				const GSList *audio_list,
-				const GSList *video_list,
-				const GSList *sub_list )
+void gmpv_menu_build_menu_btn(GMenu *menu, const GPtrArray *track_list)
 {
-	GMenu *video_menu = build_video_track_menu(video_list);
-	GMenu *audio_menu = build_audio_track_menu(audio_list);
-	GMenu *sub_menu = build_subtitle_track_menu(sub_list);
+	GPtrArray *audio_tracks = NULL;
+	GPtrArray *video_tracks = NULL;
+	GPtrArray *subtitle_tracks = NULL;
+	GMenu *video_menu = NULL;
+	GMenu *audio_menu = NULL;
+	GMenu *subtitle_menu = NULL;
+
+	split_track_list
+		(track_list, &audio_tracks, &video_tracks, &subtitle_tracks);
+
+	video_menu = build_video_track_menu(video_tracks);
+	audio_menu = build_audio_track_menu(audio_tracks);
+	subtitle_menu = build_subtitle_track_menu(subtitle_tracks);
 
 	const GmpvMenuEntry entries[]
 		= {	{NULL, "", NULL},
@@ -236,7 +297,7 @@ void gmpv_menu_build_menu_btn(	GMenu *menu,
 			{NULL, "", NULL},
 			{_("_Video Track"), NULL, video_menu},
 			{_("_Audio Track"), NULL, audio_menu},
-			{_("S_ubtitle Track"), NULL, sub_menu},
+			{_("S_ubtitle Track"), NULL, subtitle_menu},
 			{NULL, "", NULL},
 			{_("_Normal Size"), "app.set-video-size(@d 1)", NULL},
 			{_("_Double Size"), "app.set-video-size(@d 2)", NULL},
@@ -245,9 +306,12 @@ void gmpv_menu_build_menu_btn(	GMenu *menu,
 
 	build_menu(menu, entries, TRUE);
 
+	g_ptr_array_free(audio_tracks, FALSE);
+	g_ptr_array_free(video_tracks, FALSE);
+	g_ptr_array_free(subtitle_tracks, FALSE);
 	g_object_unref(video_menu);
 	g_object_unref(audio_menu);
-	g_object_unref(sub_menu);
+	g_object_unref(subtitle_menu);
 }
 
 void gmpv_menu_build_open_btn(GMenu *menu)
diff --git a/src/gmpv_menu.h b/src/gmpv_menu.h
index f4c22ce..0d9ce65 100644
--- a/src/gmpv_menu.h
+++ b/src/gmpv_menu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -25,14 +25,8 @@
 
 G_BEGIN_DECLS
 
-void gmpv_menu_build_full(	GMenu *gmpv_menu,
-			const GSList *audio_list,
-			const GSList *video_list,
-			const GSList *sub_list );
-void gmpv_menu_build_menu_btn(	GMenu *gmpv_menu,
-				const GSList *audio_list,
-				const GSList *video_list,
-				const GSList *sub_list );
+void gmpv_menu_build_full(GMenu *gmpv_menu, const GPtrArray *track_list);
+void gmpv_menu_build_menu_btn(GMenu *gmpv_menu, const GPtrArray *track_list);
 void gmpv_menu_build_open_btn(GMenu *gmpv_menu);
 void gmpv_menu_build_app_menu(GMenu *gmpv_menu);
 
diff --git a/src/gmpv_model.c b/src/gmpv_model.c
new file mode 100644
index 0000000..531b4c2
--- /dev/null
+++ b/src/gmpv_model.c
@@ -0,0 +1,1005 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <epoxy/gl.h>
+
+#include "gmpv_model.h"
+#include "gmpv_mpv.h"
+#include "gmpv_mpv_wrapper.h"
+
+enum
+{
+	PROP_INVALID,
+	PROP_MPV,
+	PROP_READY,
+	PROP_AID,
+	PROP_VID,
+	PROP_SID,
+	PROP_CHAPTERS,
+	PROP_CORE_IDLE,
+	PROP_IDLE_ACTIVE,
+	PROP_FULLSCREEN,
+	PROP_PAUSE,
+	PROP_LOOP,
+	PROP_DURATION,
+	PROP_MEDIA_TITLE,
+	PROP_METADATA,
+	PROP_PLAYLIST,
+	PROP_PLAYLIST_COUNT,
+	PROP_PLAYLIST_POS,
+	PROP_SPEED,
+	PROP_TRACK_LIST,
+	PROP_VOLUME,
+	N_PROPERTIES
+};
+
+struct _GmpvModel
+{
+	GObject parent;
+	GmpvMpv *mpv;
+	gboolean ready;
+	gboolean update_mpv_properties;
+	gchar *aid;
+	gchar *vid;
+	gchar *sid;
+	gint64 chapters;
+	gboolean core_idle;
+	gboolean idle_active;
+	gboolean fullscreen;
+	gboolean pause;
+	gchar *loop;
+	gdouble duration;
+	gchar *media_title;
+	GPtrArray *metadata;
+	GPtrArray *playlist;
+	gint64 playlist_count;
+	gint64 playlist_pos;
+	gdouble speed;
+	GPtrArray *track_list;
+	gdouble volume;
+};
+
+struct _GmpvModelClass
+{
+	GObjectClass parent_class;
+};
+
+static void constructed(GObject *object);
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static void set_mpv_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void g_value_set_by_type(GValue *gvalue, GType type, gpointer value);
+static GParamSpec *g_param_spec_by_type(	const gchar *name,
+						const gchar *nick,
+						const gchar *blurb,
+						GType type,
+						GParamFlags flags );
+static gboolean emit_frame_ready(gpointer data);
+static void opengl_cb_update_callback(gpointer opengl_cb_ctx);
+static void autofit_handler(GmpvMpv *mpv, gdouble ratio, gpointer data);
+static void mpv_init_handler(GmpvMpv *mpv, gpointer data);
+static void mpv_playback_restart_handler(GmpvMpv *mpv, gpointer data);
+static void mpv_prop_change_handler(	GmpvMpv *mpv,
+					const gchar *name,
+					gpointer value,
+					gpointer data );
+static void error_handler(GmpvMpv *mpv, const gchar* message, gpointer data);
+static void message_handler(GmpvMpv *mpv, const gchar* message, gpointer data);
+static void shutdown_handler(GmpvMpv *mpv, gpointer data);
+
+G_DEFINE_TYPE(GmpvModel, gmpv_model, G_TYPE_OBJECT)
+
+static void constructed(GObject *object)
+{
+	GmpvModel *model = GMPV_MODEL(object);
+
+	g_assert(model->mpv);
+
+	model->playlist = gmpv_mpv_get_playlist(model->mpv);
+	model->metadata = gmpv_mpv_get_metadata(model->mpv);
+
+	g_signal_connect(	model->mpv,
+				"autofit",
+				G_CALLBACK(autofit_handler),
+				model );
+	g_signal_connect(	model->mpv,
+				"mpv-init",
+				G_CALLBACK(mpv_init_handler),
+				model );
+	g_signal_connect(	model->mpv,
+				"mpv-playback-restart",
+				G_CALLBACK(mpv_playback_restart_handler),
+				model );
+	g_signal_connect(	model->mpv,
+				"mpv-prop-change",
+				G_CALLBACK(mpv_prop_change_handler),
+				model );
+	g_signal_connect(	model->mpv,
+				"error",
+				G_CALLBACK(error_handler),
+				model );
+	g_signal_connect(	model->mpv,
+				"message",
+				G_CALLBACK(message_handler),
+				model );
+	g_signal_connect(	model->mpv,
+				"shutdown",
+				G_CALLBACK(shutdown_handler),
+				model );
+}
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvModel *self = GMPV_MODEL(object);
+
+	switch(property_id)
+	{
+		case PROP_MPV:
+		self->mpv = g_value_get_pointer(value);
+		break;
+
+		case PROP_READY:
+		self->ready = g_value_get_boolean(value);
+		break;
+
+		case PROP_AID:
+		g_free(self->aid);
+		self->aid = g_value_dup_string(value);
+		break;
+
+		case PROP_VID:
+		g_free(self->vid);
+		self->vid = g_value_dup_string(value);
+		break;
+
+		case PROP_SID:
+		g_free(self->sid);
+		self->sid = g_value_dup_string(value);
+		break;
+
+		case PROP_CHAPTERS:
+		self->chapters = g_value_get_int64(value);
+		break;
+
+		case PROP_CORE_IDLE:
+		self->core_idle = g_value_get_boolean(value);
+		break;
+
+		case PROP_IDLE_ACTIVE:
+		self->idle_active = g_value_get_boolean(value);
+		break;
+
+		case PROP_FULLSCREEN:
+		self->fullscreen = g_value_get_boolean(value);
+		break;
+
+		case PROP_PAUSE:
+		self->pause = g_value_get_boolean(value);
+		break;
+
+		case PROP_LOOP:
+		self->loop = g_value_dup_string(value);
+		break;
+
+		case PROP_DURATION:
+		self->duration = g_value_get_double(value);
+		break;
+
+		case PROP_MEDIA_TITLE:
+		g_free(self->media_title);
+		self->media_title = g_value_dup_string(value);
+		break;
+
+		case PROP_METADATA:
+		self->metadata = gmpv_mpv_get_metadata(self->mpv);
+		break;
+
+		case PROP_PLAYLIST:
+		self->playlist = gmpv_mpv_get_playlist(self->mpv);
+		break;
+
+		case PROP_PLAYLIST_COUNT:
+		self->playlist_count = g_value_get_int64(value);
+		break;
+
+		case PROP_PLAYLIST_POS:
+		self->playlist_pos = g_value_get_int64(value);
+		break;
+
+		case PROP_SPEED:
+		self->speed = g_value_get_double(value);
+		break;
+
+		case PROP_TRACK_LIST:
+		self->track_list = gmpv_mpv_get_track_list(self->mpv);
+		break;
+
+		case PROP_VOLUME:
+		self->volume = g_value_get_double(value);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+
+	/* Do not propagate changes from mpv back to itself */
+	if(self->update_mpv_properties)
+	{
+		set_mpv_property(object, property_id, value, pspec);
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvModel *self = GMPV_MODEL(object);
+
+	switch(property_id)
+	{
+		case PROP_MPV:
+		g_value_set_pointer(value, self->mpv);
+		break;
+
+		case PROP_READY:
+		g_value_set_boolean(value, self->ready);
+		break;
+
+		case PROP_AID:
+		g_value_set_string(value, self->aid);
+		break;
+
+		case PROP_VID:
+		g_value_set_string(value, self->vid);
+		break;
+
+		case PROP_SID:
+		g_value_set_string(value, self->sid);
+		break;
+
+		case PROP_CHAPTERS:
+		g_value_set_int64(value, self->chapters);
+		break;
+
+		case PROP_CORE_IDLE:
+		g_value_set_boolean(value, self->core_idle);
+		break;
+
+		case PROP_IDLE_ACTIVE:
+		g_value_set_boolean(value, self->idle_active);
+		break;
+
+		case PROP_FULLSCREEN:
+		g_value_set_boolean(value, self->fullscreen);
+		break;
+
+		case PROP_PAUSE:
+		g_value_set_boolean(value, self->pause);
+		break;
+
+		case PROP_LOOP:
+		g_value_set_string(value, self->loop);
+		break;
+
+		case PROP_DURATION:
+		g_value_set_double(value, self->duration);
+		break;
+
+		case PROP_MEDIA_TITLE:
+		g_value_set_string(value, self->media_title);
+		break;
+
+		case PROP_METADATA:
+		g_value_set_pointer(value, self->metadata);
+		break;
+
+		case PROP_PLAYLIST:
+		g_value_set_pointer(value, self->playlist);
+		break;
+
+		case PROP_PLAYLIST_COUNT:
+		g_value_set_int64(value, self->playlist_count);
+		break;
+
+		case PROP_PLAYLIST_POS:
+		g_value_set_int64(value, self->idle_active?0:self->playlist_pos);
+		break;
+
+		case PROP_SPEED:
+		g_value_set_double(value, self->speed);
+		break;
+
+		case PROP_TRACK_LIST:
+		g_value_set_pointer(value, self->track_list);
+		break;
+
+		case PROP_VOLUME:
+		g_value_set_double(value, self->volume);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void set_mpv_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvModel *self = GMPV_MODEL(object);
+
+	switch(property_id)
+	{
+		case PROP_AID:
+		gmpv_mpv_set_property(	self->mpv,
+					"aid",
+					MPV_FORMAT_STRING,
+					&self->aid );
+		break;
+
+		case PROP_VID:
+		gmpv_mpv_set_property(	self->mpv,
+					"vid",
+					MPV_FORMAT_STRING,
+					&self->vid );
+		break;
+
+		case PROP_SID:
+		gmpv_mpv_set_property(	self->mpv,
+					"sid",
+					MPV_FORMAT_STRING,
+					&self->sid );
+		break;
+
+		case PROP_FULLSCREEN:
+		gmpv_mpv_set_property(	self->mpv,
+					"fullscreen",
+					MPV_FORMAT_FLAG,
+					&self->fullscreen );
+		break;
+
+		case PROP_PAUSE:
+		gmpv_mpv_set_property(	self->mpv,
+					"pause",
+					MPV_FORMAT_FLAG,
+					&self->pause );
+		break;
+
+		case PROP_LOOP:
+		gmpv_mpv_set_property(	self->mpv,
+					"loop",
+					MPV_FORMAT_STRING,
+					&self->loop );
+		break;
+
+		case PROP_MEDIA_TITLE:
+		gmpv_mpv_set_property(	self->mpv,
+					"media-title",
+					MPV_FORMAT_INT64,
+					&self->media_title );
+		break;
+
+		case PROP_PLAYLIST_POS:
+		gmpv_mpv_set_property(	self->mpv,
+					"playlist-pos",
+					MPV_FORMAT_INT64,
+					&self->playlist_pos );
+		break;
+
+		case PROP_SPEED:
+		gmpv_mpv_set_property(	self->mpv,
+					"speed",
+					MPV_FORMAT_DOUBLE,
+					&self->speed );
+		break;
+
+		case PROP_VOLUME:
+		gmpv_mpv_set_property(	self->mpv,
+					"volume",
+					MPV_FORMAT_DOUBLE,
+					&self->volume );
+		break;
+	}
+}
+
+static void g_value_set_by_type(GValue *gvalue, GType type, gpointer value)
+{
+	g_value_unset(gvalue);
+	g_value_init(gvalue, type);
+
+	switch(type)
+	{
+		case G_TYPE_STRING:
+		g_value_set_string(gvalue, *((const gchar **)value));
+		break;
+
+		case G_TYPE_BOOLEAN:
+		g_value_set_boolean(gvalue, *((gboolean *)value));
+		break;
+
+		case G_TYPE_INT64:
+		g_value_set_int64(gvalue, *((gint64 *)value));
+		break;
+
+		case G_TYPE_DOUBLE:
+		g_value_set_double(gvalue, *((gdouble *)value));
+		break;
+
+		case G_TYPE_POINTER:
+		g_value_set_pointer(gvalue, *((gpointer *)value));
+		break;
+
+		default:
+		g_assert_not_reached();
+		break;
+	}
+}
+
+static GParamSpec *g_param_spec_by_type(	const gchar *name,
+						const gchar *nick,
+						const gchar *blurb,
+						GType type,
+						GParamFlags flags )
+{
+	GParamSpec *result = NULL;
+
+	switch(type)
+	{
+		case G_TYPE_STRING:
+		result = g_param_spec_string(name, nick, blurb, NULL, flags);
+		break;
+
+		case G_TYPE_BOOLEAN:
+		result = g_param_spec_boolean(name, nick, blurb, FALSE, flags);
+		break;
+
+		case G_TYPE_INT64:
+		result = g_param_spec_int64(	name,
+						nick,
+						blurb,
+						G_MININT64,
+						G_MAXINT64,
+						0,
+						flags );
+		break;
+
+		case G_TYPE_DOUBLE:
+		result = g_param_spec_double(	name,
+						nick,
+						blurb,
+						-G_MAXDOUBLE,
+						G_MAXDOUBLE,
+						0.0,
+						flags );
+		break;
+
+		case G_TYPE_POINTER:
+		result = g_param_spec_pointer(name, nick, blurb, flags);
+		break;
+
+		default:
+		g_assert_not_reached();
+		break;
+	}
+
+	return result;
+}
+
+static gboolean emit_frame_ready(gpointer data)
+{
+	g_signal_emit_by_name(data, "frame-ready");
+
+	return FALSE;
+}
+
+static void opengl_cb_update_callback(gpointer data)
+{
+	g_idle_add_full(	G_PRIORITY_HIGH,
+				emit_frame_ready,
+				data,
+				NULL );
+}
+
+static void autofit_handler(GmpvMpv *mpv, gdouble ratio, gpointer data)
+{
+	g_signal_emit_by_name(data, "autofit", ratio);
+}
+
+static void mpv_init_handler(GmpvMpv *mpv, gpointer data)
+{
+	GMPV_MODEL(data)->ready = TRUE;
+	g_object_notify(data, "ready");
+}
+
+static void mpv_playback_restart_handler(GmpvMpv *mpv, gpointer data)
+{
+	g_signal_emit_by_name(data, "playback-restart");
+}
+
+static void mpv_prop_change_handler(	GmpvMpv *mpv,
+					const gchar *name,
+					gpointer value,
+					gpointer data )
+{
+	GObjectClass *klass;
+	GParamSpec *pspec;
+	GValue gvalue = G_VALUE_INIT;
+
+	klass = G_TYPE_INSTANCE_GET_CLASS(data, GMPV_TYPE_MODEL, GObjectClass);
+	pspec = g_object_class_find_property(klass, name);
+
+	if(pspec && value)
+	{
+		GMPV_MODEL(data)->update_mpv_properties = FALSE;
+
+		g_value_set_by_type(&gvalue, pspec->value_type, value);
+		g_object_set_property(data, name, &gvalue);
+
+		GMPV_MODEL(data)->update_mpv_properties = TRUE;
+	}
+
+}
+
+static void error_handler(GmpvMpv *mpv, const gchar *message, gpointer data)
+{
+	g_signal_emit_by_name(data, "error", message);
+}
+
+static void message_handler(GmpvMpv *mpv, const gchar* message, gpointer data)
+{
+	g_signal_emit_by_name(data, "message", message);
+}
+
+static void shutdown_handler(GmpvMpv *mpv, gpointer data)
+{
+	g_signal_emit_by_name(data, "shutdown");
+}
+
+static void gmpv_model_class_init(GmpvModelClass *klass)
+{
+	/* The "no" value of aid, vid, and sid cannot be represented with an
+	 * int64, so we need to observe them as string to receive notifications
+	 * for all possible values.
+	 */
+	const struct
+	{
+		const gchar *name;
+		guint id;
+		GType type;
+	}
+	mpv_props[] = {	{"aid", PROP_AID, G_TYPE_STRING},
+			{"vid", PROP_VID, G_TYPE_STRING},
+			{"sid", PROP_SID, G_TYPE_STRING},
+			{"chapters", PROP_CHAPTERS, G_TYPE_INT64},
+			{"core-idle", PROP_CORE_IDLE, G_TYPE_BOOLEAN},
+			{"idle-active", PROP_IDLE_ACTIVE, G_TYPE_BOOLEAN},
+			{"fullscreen", PROP_FULLSCREEN, G_TYPE_BOOLEAN},
+			{"pause", PROP_PAUSE, G_TYPE_BOOLEAN},
+			{"loop", PROP_LOOP, G_TYPE_STRING},
+			{"duration", PROP_DURATION, G_TYPE_DOUBLE},
+			{"media-title", PROP_MEDIA_TITLE, G_TYPE_STRING},
+			{"metadata", PROP_METADATA, G_TYPE_POINTER},
+			{"playlist", PROP_PLAYLIST, G_TYPE_POINTER},
+			{"playlist-count", PROP_PLAYLIST_COUNT, G_TYPE_INT64},
+			{"playlist-pos", PROP_PLAYLIST_POS, G_TYPE_INT64},
+			{"speed", PROP_SPEED, G_TYPE_DOUBLE},
+			{"track-list", PROP_TRACK_LIST, G_TYPE_POINTER},
+			{"volume", PROP_VOLUME, G_TYPE_DOUBLE},
+			{NULL, PROP_INVALID, 0} };
+
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	obj_class->constructed = constructed;
+	obj_class->set_property = set_property;
+	obj_class->get_property = get_property;
+
+	pspec = g_param_spec_pointer
+		(	"mpv",
+			"mpv",
+			"GmpvMpv instance to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_MPV, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"ready",
+			"Ready",
+			"Whether mpv is ready to receive commands",
+			FALSE,
+			G_PARAM_READABLE );
+	g_object_class_install_property(obj_class, PROP_READY, pspec);
+
+	for(int i = 0; mpv_props[i].name; i++)
+	{
+		pspec = g_param_spec_by_type(	mpv_props[i].name,
+						mpv_props[i].name,
+						mpv_props[i].name,
+						mpv_props[i].type,
+						G_PARAM_READWRITE );
+		g_object_class_install_property
+			(obj_class, mpv_props[i].id, pspec);
+	}
+
+	g_signal_new(	"playback-restart",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"frame-ready",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"autofit",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__DOUBLE,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_DOUBLE );
+	g_signal_new(	"message",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__STRING,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_STRING );
+	g_signal_new(	"error",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__STRING,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_STRING );
+	g_signal_new(	"shutdown",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+}
+
+static void gmpv_model_init(GmpvModel *model)
+{
+	model->mpv = NULL;
+	model->ready = FALSE;
+	model->update_mpv_properties = TRUE;
+	model->aid = NULL;
+	model->vid = NULL;
+	model->sid = NULL;
+	model->chapters = 0;
+	model->core_idle = FALSE;
+	model->idle_active = FALSE;
+	model->fullscreen = FALSE;
+	model->pause = TRUE;
+	model->loop = NULL;
+	model->duration = 0.0;
+	model->media_title = NULL;
+	model->metadata = NULL;
+	model->playlist = NULL;
+	model->playlist_count = 0;
+	model->playlist_pos = 0;
+	model->speed = 1.0;
+	model->track_list = NULL;
+	model->volume = 1.0;
+}
+
+GmpvModel *gmpv_model_new(GmpvMpv *mpv)
+{
+	return GMPV_MODEL(g_object_new(	gmpv_model_get_type(),
+					"mpv", mpv,
+					NULL ));
+}
+
+void gmpv_model_initialize(GmpvModel *model)
+{
+	gmpv_mpv_initialize(model->mpv);
+
+	gmpv_mpv_set_opengl_cb_callback
+		(model->mpv, opengl_cb_update_callback, model);
+}
+
+void gmpv_model_reset(GmpvModel *model)
+{
+	GMPV_MODEL(model)->ready = FALSE;
+	g_object_notify(G_OBJECT(model), "ready");
+
+	gmpv_mpv_reset(model->mpv);
+}
+
+void gmpv_model_quit(GmpvModel *model)
+{
+	GMPV_MODEL(model)->ready = FALSE;
+	g_object_notify(G_OBJECT(model), "ready");
+
+	gmpv_mpv_quit(model->mpv);
+}
+
+void gmpv_model_mouse(GmpvModel *model, gint x, gint y)
+{
+	gchar *x_str = g_strdup_printf("%d", x);
+	gchar *y_str = g_strdup_printf("%d", y);
+	const gchar *cmd[] = {"mouse", x_str, y_str, NULL};
+
+	g_debug("Set mouse location to (%s, %s)", x_str, y_str);
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_key_down(GmpvModel *model, const gchar* keystr)
+{
+	const gchar *cmd[] = {"keydown", keystr, NULL};
+
+	g_debug("Sent '%s' key down to mpv", keystr);
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_key_up(GmpvModel *model, const gchar* keystr)
+{
+	const gchar *cmd[] = {"keyup", keystr, NULL};
+
+	g_debug("Sent '%s' key up to mpv", keystr);
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_key_press(GmpvModel *model, const gchar* keystr)
+{
+	const gchar *cmd[] = {"keypress", keystr, NULL};
+
+	g_debug("Sent '%s' key press to mpv", keystr);
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_reset_keys(GmpvModel *model)
+{
+	g_debug("Sent global key up to mpv");
+	gmpv_mpv_command_string(model->mpv, "keyup");
+}
+
+void gmpv_model_play(GmpvModel *model)
+{
+	gmpv_mpv_set_property_flag(model->mpv, "pause", FALSE);
+}
+
+void gmpv_model_pause(GmpvModel *model)
+{
+	gmpv_mpv_set_property_flag(model->mpv, "pause", TRUE);
+}
+
+void gmpv_model_stop(GmpvModel *model)
+{
+	const gchar *cmd[] = {"stop", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_forward(GmpvModel *model)
+{
+	const gchar *cmd[] = {"seek", "10", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_rewind(GmpvModel *model)
+{
+	const gchar *cmd[] = {"seek", "-10", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_next_chapter(GmpvModel *model)
+{
+	const gchar *cmd[] = {"osd-msg", "cycle", "chapter", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_previous_chapter(GmpvModel *model)
+{
+	const gchar *cmd[] = {"osd-msg", "cycle", "chapter", "down", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_next_playlist_entry(GmpvModel *model)
+{
+	const gchar *cmd[] = {"osd-msg", "playlist-next", "weak", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_previous_playlist_entry(GmpvModel *model)
+{
+	const gchar *cmd[] = {"osd-msg", "playlist-prev", "weak", NULL};
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_seek(GmpvModel *model, gdouble value)
+{
+	gmpv_mpv_set_property(model->mpv, "time-pos", MPV_FORMAT_DOUBLE, &value);
+}
+
+void gmpv_model_seek_offset(GmpvModel *model, gdouble offset)
+{
+	const gchar *cmd[] = {"seek", NULL, NULL};
+	gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+	g_ascii_dtostr(buf, G_ASCII_DTOSTR_BUF_SIZE, offset);
+	cmd[1] = buf;
+
+	gmpv_mpv_command(model->mpv, cmd);
+}
+
+void gmpv_model_load_audio_track(GmpvModel *model, const gchar *filename)
+{
+	gmpv_mpv_load_track(model->mpv, filename, TRACK_TYPE_AUDIO);
+}
+
+void gmpv_model_load_subtitle_track(GmpvModel *model, const gchar *filename)
+{
+	gmpv_mpv_load_track(model->mpv, filename, TRACK_TYPE_SUBTITLE);
+}
+
+gdouble gmpv_model_get_time_position(GmpvModel *model)
+{
+	gdouble time_pos = 0.0;
+
+	if(!model->idle_active)
+	{
+		gmpv_mpv_get_property(	model->mpv,
+					"time-pos",
+					MPV_FORMAT_DOUBLE,
+					&time_pos );
+	}
+
+	/* time-pos may become negative during seeks */
+	return MAX(0, time_pos);
+}
+
+void gmpv_model_set_playlist_position(GmpvModel *model, gint64 position)
+{
+	if(position != model->playlist_pos)
+	{
+		gmpv_mpv_set_property(	model->mpv,
+					"playlist-pos",
+					MPV_FORMAT_INT64,
+					&position );
+	}
+}
+
+void gmpv_model_remove_playlist_entry(GmpvModel *model, gint64 position)
+{
+	const gchar *cmd[] = {"playlist_remove", NULL, NULL};
+	gchar *index_str = g_strdup_printf("%" G_GINT64_FORMAT, position);
+
+	cmd[1] = index_str;
+
+	gmpv_mpv_command(model->mpv, cmd);
+
+	g_free(index_str);
+}
+
+void gmpv_model_move_playlist_entry(GmpvModel *model, gint64 src, gint64 dst)
+{
+	const gchar *cmd[] =	{"playlist_move", NULL, NULL, NULL};
+	gchar *src_str =	g_strdup_printf
+				("%" G_GINT64_FORMAT, (src > dst)?--src:src);
+	gchar *dst_str =	g_strdup_printf
+				("%" G_GINT64_FORMAT, dst);
+
+	cmd[1] = src_str;
+	cmd[2] = dst_str;
+
+	gmpv_mpv_command(model->mpv, cmd);
+
+	g_free(src_str);
+	g_free(dst_str);
+}
+
+void gmpv_model_load_file(GmpvModel *model, const gchar *uri, gboolean append)
+{
+	gmpv_mpv_load(model->mpv, uri, append);
+
+	/* Start playing when replacing the playlist, ie. not appending, or
+	 * adding the first file to the playlist.
+	 */
+	if(!append || model->playlist->len == 1)
+	{
+		gmpv_model_play(model);
+	}
+}
+
+gboolean gmpv_model_get_use_opengl_cb(GmpvModel *model)
+{
+	return gmpv_mpv_get_use_opengl_cb(model->mpv);
+}
+
+void gmpv_model_initialize_gl(GmpvModel *model)
+{
+	gmpv_mpv_init_gl(model->mpv);
+}
+
+void gmpv_model_render_frame(GmpvModel *model, gint width, gint height)
+{
+	mpv_opengl_cb_context *opengl_ctx;
+
+	opengl_ctx = gmpv_mpv_get_opengl_cb_context(model->mpv);
+
+	if(opengl_ctx)
+	{
+		int fbo = -1;
+
+		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
+		mpv_opengl_cb_draw(opengl_ctx, fbo, width, (-1)*height);
+	}
+}
+
+void gmpv_model_get_video_geometry(	GmpvModel *model,
+					gint64 *width,
+					gint64 *height )
+{
+	gmpv_mpv_get_property(model->mpv, "dwidth", MPV_FORMAT_INT64, width);
+	gmpv_mpv_get_property(model->mpv, "dheight", MPV_FORMAT_INT64, height);
+}
+
+gchar *gmpv_model_get_current_path(GmpvModel *model)
+{
+	gchar *path = gmpv_mpv_get_property_string(model->mpv, "path");
+	gchar *buf = g_strdup(path);
+
+	mpv_free(path);
+
+	return buf;
+}
diff --git a/src/gmpv_model.h b/src/gmpv_model.h
new file mode 100644
index 0000000..f00c134
--- /dev/null
+++ b/src/gmpv_model.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MODEL_H
+#define MODEL_H
+
+#include <glib.h>
+
+#include "gmpv_mpv.h"
+
+G_BEGIN_DECLS
+
+#define GMPV_TYPE_MODEL (gmpv_model_get_type())
+
+G_DECLARE_FINAL_TYPE(GmpvModel, gmpv_model, GMPV, MODEL, GObject)
+
+GmpvModel *gmpv_model_new(GmpvMpv *mpv);
+void gmpv_model_initialize(GmpvModel *model);
+void gmpv_model_reset(GmpvModel *model);
+void gmpv_model_quit(GmpvModel *model);
+void gmpv_model_mouse(GmpvModel *model, gint x, gint y);
+void gmpv_model_key_down(GmpvModel *model, const gchar* keystr);
+void gmpv_model_key_up(GmpvModel *model, const gchar* keystr);
+void gmpv_model_key_press(GmpvModel *model, const gchar* keystr);
+void gmpv_model_reset_keys(GmpvModel *model);
+void gmpv_model_play(GmpvModel *model);
+void gmpv_model_pause(GmpvModel *model);
+void gmpv_model_stop(GmpvModel *model);
+void gmpv_model_forward(GmpvModel *model);
+void gmpv_model_rewind(GmpvModel *model);
+void gmpv_model_next_chapter(GmpvModel *model);
+void gmpv_model_previous_chapter(GmpvModel *model);
+void gmpv_model_next_playlist_entry(GmpvModel *model);
+void gmpv_model_previous_playlist_entry(GmpvModel *model);
+void gmpv_model_seek(GmpvModel *model, gdouble value);
+void gmpv_model_seek_offset(GmpvModel *model, gdouble offset);
+void gmpv_model_load_audio_track(GmpvModel *model, const gchar *filename);
+void gmpv_model_load_subtitle_track(GmpvModel *model, const gchar *filename);
+gdouble gmpv_model_get_time_position(GmpvModel *model);
+void gmpv_model_set_playlist_position(GmpvModel *model, gint64 position);
+void gmpv_model_remove_playlist_entry(GmpvModel *model, gint64 position);
+void gmpv_model_move_playlist_entry(GmpvModel *model, gint64 src, gint64 dst);
+void gmpv_model_load_file(GmpvModel *model, const gchar *uri, gboolean append);
+gboolean gmpv_model_get_use_opengl_cb(GmpvModel *model);
+void gmpv_model_initialize_gl(GmpvModel *model);
+void gmpv_model_render_frame(GmpvModel *model, gint width, gint height);
+void gmpv_model_get_video_geometry(	GmpvModel *model,
+					gint64 *width,
+					gint64 *height );
+gchar *gmpv_model_get_current_path(GmpvModel *model);
+
+G_END_DECLS
+
+#endif
diff --git a/src/gmpv_mpv.c b/src/gmpv_mpv.c
index eed14f9..db0f512 100644
--- a/src/gmpv_mpv.c
+++ b/src/gmpv_mpv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -27,7 +27,6 @@
 #include <gdk/gdk.h>
 #include <stdlib.h>
 #include <string.h>
-#include <execinfo.h>
 
 #include <epoxy/gl.h>
 #ifdef GDK_WINDOWING_X11
@@ -49,7 +48,7 @@
 #include "gmpv_mpv_opt.h"
 #include "gmpv_common.h"
 #include "gmpv_def.h"
-#include "gmpv_playlist.h"
+#include "gmpv_marshal.h"
 
 static void *GLAPIENTRY glMPGetNativeDisplay(const gchar *name);
 static void *get_proc_address(void *fn_ctx, const gchar *name);
@@ -61,13 +60,19 @@ static void get_inst_property(	GObject *object,
 				guint property_id,
 				GValue *value,
 				GParamSpec *pspec );
+static void load_from_playlist(GmpvMpv *mpv);
+static void load_scripts(GmpvMpv *mpv);
 static void wakeup_callback(void *data);
+static GmpvPlaylistEntry *parse_playlist_entry(mpv_node_list *node);
+static GmpvTrack *parse_track_entry(mpv_node_list *node);
 static void mpv_prop_change_handler(GmpvMpv *mpv, mpv_event_property* prop);
 static gboolean mpv_event_handler(gpointer data);
-static void update_playlist(GmpvMpv *mpv);
 static gint apply_args(mpv_handle *mpv_ctx, gchar *args);
 static void log_handler(GmpvMpv *mpv, mpv_event_log_message* message);
-static void load_input_conf(GmpvMpv *mpv, const gchar *input_conf);
+static void add_file_to_playlist(GmpvMpv *mpv, const gchar *uri);
+static void update_playlist(GmpvMpv *mpv);
+static void update_metadata(GmpvMpv *mpv);
+static void update_track_list(GmpvMpv *mpv);
 
 G_DEFINE_TYPE(GmpvMpv, gmpv_mpv, G_TYPE_OBJECT)
 
@@ -121,10 +126,6 @@ static void set_inst_property(	GObject *object,
 	{
 		self->wid = g_value_get_int64(value);
 	}
-	else if(property_id == PROP_PLAYLIST)
-	{
-		self->playlist = g_value_get_pointer(value);
-	}
 	else
 	{
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
@@ -142,14 +143,64 @@ static void get_inst_property(	GObject *object,
 	{
 		g_value_set_int64(value, self->wid);
 	}
-	else if(property_id == PROP_PLAYLIST)
+	else
 	{
-		g_value_set_pointer(value, self->playlist);
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+	}
+}
+
+static void load_from_playlist(GmpvMpv *mpv)
+{
+	GPtrArray * playlist = mpv->playlist;
+
+	for(guint i = 0; playlist && i < playlist->len; i++)
+	{
+		GmpvPlaylistEntry *entry;
+
+		entry = g_ptr_array_index(playlist, i);
+
+		/* Do not append on first iteration */
+		gmpv_mpv_load_file(mpv, entry->filename, i != 0);
+	}
+}
+
+static void load_scripts(GmpvMpv *mpv)
+{
+	gchar *path = get_scripts_dir_path();
+	GDir *dir = g_dir_open(path, 0, NULL);
+
+	if(dir)
+	{
+		const gchar *name;
+
+		do
+		{
+			gchar *full_path;
+
+			name = g_dir_read_name(dir);
+			full_path = g_build_filename(path, name, NULL);
+
+			if(g_file_test(full_path, G_FILE_TEST_IS_REGULAR))
+			{
+				const gchar *cmd[]
+					= {"load-script", full_path, NULL};
+
+				g_info("Loading script: %s", full_path);
+				mpv_command(mpv->mpv_ctx, cmd);
+			}
+
+			g_free(full_path);
+		}
+		while(name);
+
+		g_dir_close(dir);
 	}
 	else
 	{
-		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		g_warning("Failed to open scripts directory: %s", path);
 	}
+
+	g_free(path);
 }
 
 static void wakeup_callback(void *data)
@@ -157,6 +208,66 @@ static void wakeup_callback(void *data)
 	g_idle_add((GSourceFunc)mpv_event_handler, data);
 }
 
+static GmpvPlaylistEntry *parse_playlist_entry(mpv_node_list *node)
+{
+	const gchar *filename = NULL;
+	const gchar *title = NULL;
+
+	for(gint i = 0; i < node->num; i++)
+	{
+		if(g_strcmp0(node->keys[i], "filename") == 0)
+		{
+			filename = node->values[i].u.string;
+		}
+		else if(g_strcmp0(node->keys[i], "title") == 0)
+		{
+			title = node->values[i].u.string;
+		}
+	}
+
+	return gmpv_playlist_entry_new(filename, title);
+}
+
+static GmpvTrack *parse_track_entry(mpv_node_list *node)
+{
+	GmpvTrack *entry = gmpv_track_new();
+
+	for(gint i = 0; i < node->num; i++)
+	{
+		if(g_strcmp0(node->keys[i], "type") == 0)
+		{
+			const gchar *type = node->values[i].u.string;
+
+			if(g_strcmp0(type, "audio") == 0)
+			{
+				entry->type = TRACK_TYPE_AUDIO;
+			}
+			else if(g_strcmp0(type, "video") == 0)
+			{
+				entry->type = TRACK_TYPE_VIDEO;
+			}
+			else if(g_strcmp0(type, "sub") == 0)
+			{
+				entry->type = TRACK_TYPE_SUBTITLE;
+			}
+		}
+		else if(g_strcmp0(node->keys[i], "title") == 0)
+		{
+			entry->title = g_strdup(node->values[i].u.string);
+		}
+		else if(g_strcmp0(node->keys[i], "lang") == 0)
+		{
+			entry->lang = g_strdup(node->values[i].u.string);
+		}
+		else if(g_strcmp0(node->keys[i], "id") == 0)
+		{
+			entry->id = node->values[i].u.int64;
+		}
+	}
+
+	return entry;
+}
+
 static void mpv_prop_change_handler(GmpvMpv *mpv, mpv_event_property* prop)
 {
 	g_debug("Received mpv property change event for \"%s\"", prop->name);
@@ -172,9 +283,56 @@ static void mpv_prop_change_handler(GmpvMpv *mpv, mpv_event_property* prop)
 					MPV_FORMAT_FLAG,
 					&idle_active );
 
-		if(idle_active && !mpv->state.paused)
+		if(idle_active && !mpv->state.paused && !mpv->init_vo_config)
+		{
+			load_from_playlist(mpv);
+		}
+	}
+	else if(g_strcmp0(prop->name, "playlist") == 0)
+	{
+		gint64 playlist_count  = 0;
+		gboolean idle_active = FALSE;
+		gboolean was_empty = FALSE;
+
+		mpv_get_property(	mpv->mpv_ctx,
+					"playlist-count",
+					MPV_FORMAT_INT64,
+					&playlist_count );
+		mpv_get_property(	mpv->mpv_ctx,
+					"idle-active",
+					MPV_FORMAT_FLAG,
+					&idle_active );
+
+		was_empty = (mpv->playlist->len == 0);
+
+		if(!idle_active)
+		{
+			update_playlist(mpv);
+		}
+
+		/* Check if we're transitioning from empty playlist to non-empty
+		 * playlist.
+		 */
+		if(was_empty && mpv->playlist->len > 0)
+		{
+			gmpv_mpv_set_property_flag(mpv, "pause", FALSE);
+		}
+	}
+	else if(g_strcmp0(prop->name, "metadata") == 0)
+	{
+		update_metadata(mpv);
+	}
+	else if(g_strcmp0(prop->name, "track-list") == 0)
+	{
+		update_track_list(mpv);
+	}
+	else if(g_strcmp0(prop->name, "vo-configured") == 0)
+	{
+		if(mpv->init_vo_config)
 		{
-			gmpv_mpv_load(mpv, NULL, FALSE, TRUE);
+			mpv->init_vo_config = FALSE;
+			load_from_playlist(mpv);
+			load_scripts(mpv);
 		}
 	}
 }
@@ -202,7 +360,8 @@ static gboolean mpv_event_handler(gpointer data)
 
 			g_signal_emit_by_name(	mpv,
 						"mpv-prop-change",
-						prop->name );
+						prop->name,
+						prop->data );
 		}
 		else if(event->event_id == MPV_EVENT_IDLE)
 		{
@@ -212,7 +371,11 @@ static gboolean mpv_event_handler(gpointer data)
 
 				gmpv_mpv_set_property_flag
 					(mpv, "pause", TRUE);
-				gmpv_playlist_reset(mpv->playlist);
+			}
+
+			if(!mpv->state.init_load && !mpv->state.loaded)
+			{
+				g_signal_emit_by_name(mpv, "idle");
 			}
 
 			mpv->state.init_load = FALSE;
@@ -222,7 +385,7 @@ static gboolean mpv_event_handler(gpointer data)
 			mpv->state.loaded = TRUE;
 			mpv->state.init_load = FALSE;
 
-			update_playlist(mpv);
+			g_signal_emit_by_name(mpv, "load");
 		}
 		else if(event->event_id == MPV_EVENT_END_FILE)
 		{
@@ -246,9 +409,8 @@ static gboolean mpv_event_handler(gpointer data)
 						"abnormally. Reason: %s."),
 						err );
 
-				gmpv_mpv_set_property_flag
-					(mpv, "pause", TRUE);
-				g_signal_emit_by_name(mpv, "mpv-error", msg);
+				gmpv_mpv_set_property_flag(mpv, "pause", TRUE);
+				g_signal_emit_by_name(mpv, "error", msg);
 
 				g_free(msg);
 			}
@@ -258,6 +420,28 @@ static gboolean mpv_event_handler(gpointer data)
 			if(mpv->state.new_file)
 			{
 				gmpv_mpv_opt_handle_autofit(mpv);
+
+				g_signal_emit_by_name(	mpv,
+							"autofit",
+							mpv->autofit_ratio );
+			}
+		}
+		else if(event->event_id == MPV_EVENT_START_FILE)
+		{
+			gboolean vo_configured = FALSE;
+
+			mpv_get_property(	mpv->mpv_ctx,
+						"vo-configured",
+						MPV_FORMAT_FLAG,
+						&vo_configured );
+
+			/* If the vo is not configured yet, save the content of
+			 * mpv's playlist in mpv->playlist. This will be loaded
+			 * again when the vo is configured.
+			 */
+			if(!vo_configured)
+			{
+				update_playlist(mpv);
 			}
 		}
 		else if(event->event_id == MPV_EVENT_PLAYBACK_RESTART)
@@ -268,145 +452,34 @@ static gboolean mpv_event_handler(gpointer data)
 		{
 			log_handler(mpv, event->data);
 		}
-		else if(event->event_id == MPV_EVENT_SHUTDOWN
-		|| event->event_id == MPV_EVENT_NONE)
+		else if(event->event_id == MPV_EVENT_CLIENT_MESSAGE)
 		{
-			done = TRUE;
-		}
+			mpv_event_client_message *event_cmsg = event->data;
+			gchar* msg = strnjoinv(	" ",
+						event_cmsg->args,
+						(gsize)event_cmsg->num_args );
 
-		if(event)
-		{
-			if(mpv->event_callback)
-			{
-				mpv->event_callback
-					(event, mpv->event_callback_data);
-			}
-
-			if(mpv->mpv_ctx)
-			{
-				g_signal_emit_by_name
-					(mpv, "mpv-event", event->event_id);
-			}
-			else
-			{
-				done = TRUE;
-			}
+			g_signal_emit_by_name(mpv, "message", msg);
+			g_free(msg);
 		}
-	}
-
-	return FALSE;
-}
-
-static void update_playlist(GmpvMpv *mpv)
-{
-	/* The length of "playlist//filename" including null-terminator (19)
-	 * plus the number of digits in the maximum value of 64 bit int (19).
-	 */
-	const gsize filename_prop_str_size = 38;
-	GtkListStore *store = gmpv_playlist_get_store(mpv->playlist);
-	gchar *filename_prop_str = g_malloc(filename_prop_str_size);
-	gboolean iter_end = FALSE;
-	GtkTreeIter iter;
-	mpv_node mpv_playlist;
-	gint playlist_count;
-	gint i;
-
-	mpv_check_error(mpv_get_property(	mpv->mpv_ctx,
-						"playlist",
-						MPV_FORMAT_NODE,
-						&mpv_playlist ));
-	playlist_count = mpv_playlist.u.list->num;
-
-	gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
-
-	for(i = 0; i < playlist_count; i++)
-	{
-		mpv_node_list *prop_list = mpv_playlist.u.list->values[i].u.list;
-		gchar *uri = NULL;
-		gchar *title = NULL;
-		gchar *name = NULL;
-
-		for(gint j = 0; j < prop_list->num; j++)
+		else if(event->event_id == MPV_EVENT_SHUTDOWN)
 		{
-			const gchar *key = prop_list->keys[j];
-			const mpv_node value = prop_list->values[j];
+			g_signal_emit_by_name(mpv, "shutdown");
 
-			if(g_strcmp0(key, "filename") == 0)
-			{
-				g_assert(value.format == MPV_FORMAT_STRING);
-				uri = value.u.string;
-			}
-			else if(g_strcmp0(key, "title") == 0)
-			{
-				g_assert(value.format == MPV_FORMAT_STRING);
-				title = value.u.string;
-			}
+			done = TRUE;
 		}
-
-		name = title?g_strdup(title):get_name_from_path(uri);
-
-		/* Overwrite current entry if it doesn't match the new value */
-		if(!iter_end)
+		else if(event->event_id == MPV_EVENT_NONE)
 		{
-			gchar *old_name = NULL;
-			gchar *old_uri = NULL;
-			gboolean name_update;
-			gboolean uri_update;
-
-			gtk_tree_model_get
-				(	GTK_TREE_MODEL(store), &iter,
-					PLAYLIST_NAME_COLUMN, &old_name,
-					PLAYLIST_URI_COLUMN, &old_uri, -1 );
-
-			name_update = (g_strcmp0(name, old_name) != 0);
-			uri_update = (g_strcmp0(uri, old_uri) != 0);
-
-			/* Only set the name if either the title can be
-			 * retrieved or the name is unset. This preserves the
-			 * correct title if it becomes unavailable later such as
-			 * when restarting mpv.
-			 */
-			if(name_update && (!old_name || title || uri_update))
-			{
-				gtk_list_store_set
-					(	store, &iter,
-						PLAYLIST_NAME_COLUMN, name, -1 );
-			}
-
-			if(uri_update)
-			{
-				gtk_list_store_set
-					(	store, &iter,
-						PLAYLIST_URI_COLUMN, uri, -1 );
-			}
-
-			iter_end = !gtk_tree_model_iter_next
-					(GTK_TREE_MODEL(store), &iter);
-
-			g_free(old_name);
-			g_free(old_uri);
+			done = TRUE;
 		}
-		/* Append entries to the playlist if there are fewer entries in
-		 * the playlist widget than mpv's playlist.
-		 */
-		else
+
+		if(event && !mpv->mpv_ctx)
 		{
-			gmpv_playlist_append(mpv->playlist, name, uri);
+			done = TRUE;
 		}
-
-		g_free(name);
 	}
 
-	/* If there are more entries in the playlist widget than mpv's playlist,
-	 * remove the excess entries from the playlist widget.
-	 */
-	if(!iter_end)
-	{
-		while(gtk_list_store_remove(store, &iter));
-	}
-
-	g_free(filename_prop_str);
-	mpv_free_node_contents(&mpv_playlist);
+	return FALSE;
 }
 
 static gint apply_args(mpv_handle *mpv_ctx, gchar *args)
@@ -607,6 +680,102 @@ static void load_input_conf(GmpvMpv *mpv, const gchar *input_conf)
 	fclose(tmp_file);
 }
 
+static void add_file_to_playlist(GmpvMpv *mpv, const gchar *uri)
+{
+	GmpvPlaylistEntry *entry = gmpv_playlist_entry_new(uri, NULL);
+
+	g_ptr_array_add(mpv->playlist, entry);
+	g_signal_emit_by_name(mpv, "mpv-prop-change", "playlist", NULL);
+}
+
+static void update_playlist(GmpvMpv *mpv)
+{
+	const mpv_node_list *org_list;
+	mpv_node playlist;
+
+	g_ptr_array_set_size(mpv->playlist, 0);
+	gmpv_mpv_get_property(mpv, "playlist", MPV_FORMAT_NODE, &playlist);
+
+	org_list = playlist.u.list;
+
+	if(playlist.format == MPV_FORMAT_NODE_ARRAY)
+	{
+		for(gint i = 0; i < org_list->num; i++)
+		{
+			GmpvPlaylistEntry *entry;
+
+			entry = parse_playlist_entry(org_list->values[i].u.list);
+			g_ptr_array_add(mpv->playlist, entry);
+		}
+
+		mpv_free_node_contents(&playlist);
+	}
+}
+
+static void update_metadata(GmpvMpv *mpv)
+{
+	mpv_node_list *org_list = NULL;
+	mpv_node metadata;
+
+	g_ptr_array_set_size(mpv->metadata, 0);
+	gmpv_mpv_get_property(mpv, "metadata", MPV_FORMAT_NODE, &metadata);
+	org_list = metadata.u.list;
+
+	if(metadata.format == MPV_FORMAT_NODE_MAP && org_list->num > 0)
+	{
+		for(gint i = 0; i < org_list->num; i++)
+		{
+			const gchar *key;
+			mpv_node value;
+
+			key = org_list->keys[i];
+			value = org_list->values[i];
+
+			if(value.format == MPV_FORMAT_STRING)
+			{
+				GmpvMetadataEntry *entry;
+
+				entry =	gmpv_metadata_entry_new
+					(key, value.u.string);
+
+				g_ptr_array_add(mpv->metadata, entry);
+			}
+			else
+			{
+				g_warning(	"Ignored metadata field %s "
+						"with unexpected format %d",
+						key,
+						value.format );
+			}
+		}
+
+		mpv_free_node_contents(&metadata);
+	}
+}
+
+static void update_track_list(GmpvMpv *mpv)
+{
+	mpv_node_list *org_list = NULL;
+	mpv_node track_list;
+
+	g_ptr_array_set_size(mpv->track_list, 0);
+	gmpv_mpv_get_property(mpv, "track-list", MPV_FORMAT_NODE, &track_list);
+	org_list = track_list.u.list;
+
+	if(track_list.format == MPV_FORMAT_NODE_ARRAY)
+	{
+		for(gint i = 0; i < org_list->num; i++)
+		{
+			GmpvTrack *entry =	parse_track_entry
+						(org_list->values[i].u.list);
+
+			g_ptr_array_add(mpv->track_list, entry);
+		}
+
+		mpv_free_node_contents(&track_list);
+	}
+}
+
 static void gmpv_mpv_class_init(GmpvMpvClass* klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
@@ -625,13 +794,6 @@ static void gmpv_mpv_class_init(GmpvMpvClass* klass)
 			G_PARAM_READWRITE );
 	g_object_class_install_property(obj_class, PROP_WID, pspec);
 
-	pspec = g_param_spec_pointer
-		(	"playlist",
-			"Playlist",
-			"GmpvPlaylist to use for storage",
-			G_PARAM_READWRITE );
-	g_object_class_install_property(obj_class, PROP_PLAYLIST, pspec);
-
 	g_signal_new(	"mpv-init",
 			G_TYPE_FROM_CLASS(klass),
 			G_SIGNAL_RUN_FIRST,
@@ -641,7 +803,7 @@ static void gmpv_mpv_class_init(GmpvMpvClass* klass)
 			g_cclosure_marshal_VOID__VOID,
 			G_TYPE_NONE,
 			0 );
-	g_signal_new(	"mpv-error",
+	g_signal_new(	"error",
 			G_TYPE_FROM_CLASS(klass),
 			G_SIGNAL_RUN_FIRST,
 			0,
@@ -660,17 +822,37 @@ static void gmpv_mpv_class_init(GmpvMpvClass* klass)
 			g_cclosure_marshal_VOID__VOID,
 			G_TYPE_NONE,
 			0 );
-	g_signal_new(	"mpv-event",
+	g_signal_new(	"mpv-prop-change",
 			G_TYPE_FROM_CLASS(klass),
 			G_SIGNAL_RUN_FIRST,
 			0,
 			NULL,
 			NULL,
-			g_cclosure_marshal_VOID__ENUM,
+			g_cclosure_gen_marshal_VOID__STRING_POINTER,
 			G_TYPE_NONE,
-			1,
-			G_TYPE_INT );
-	g_signal_new(	"mpv-prop-change",
+			2,
+			G_TYPE_STRING,
+			G_TYPE_POINTER );
+
+	g_signal_new(	"idle",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"load",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"message",
 			G_TYPE_FROM_CLASS(klass),
 			G_SIGNAL_RUN_FIRST,
 			0,
@@ -680,13 +862,40 @@ static void gmpv_mpv_class_init(GmpvMpvClass* klass)
 			G_TYPE_NONE,
 			1,
 			G_TYPE_STRING );
+	g_signal_new(	"autofit",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__DOUBLE,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_DOUBLE );
+	g_signal_new(	"shutdown",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
 }
 
 static void gmpv_mpv_init(GmpvMpv *mpv)
 {
 	mpv->mpv_ctx = mpv_create();
 	mpv->opengl_ctx = NULL;
-	mpv->playlist = NULL;
+	mpv->playlist = g_ptr_array_new_full(	1,
+						(GDestroyNotify)
+						gmpv_playlist_entry_free );
+	mpv->metadata = g_ptr_array_new_full(	1,
+						(GDestroyNotify)
+						gmpv_metadata_entry_free );
+	mpv->track_list = g_ptr_array_new_full(	1,
+						(GDestroyNotify)
+						gmpv_track_free );
 	mpv->tmp_input_file = NULL;
 	mpv->log_level_list = NULL;
 	mpv->autofit_ratio = -1;
@@ -698,38 +907,18 @@ static void gmpv_mpv_init(GmpvMpv *mpv)
 	mpv->state.new_file = TRUE;
 	mpv->state.init_load = TRUE;
 
+	mpv->init_vo_config = TRUE;
 	mpv->force_opengl = FALSE;
+	mpv->use_opengl = FALSE;
 	mpv->glarea = NULL;
 	mpv->wid = -1;
-	mpv->event_callback_data = NULL;
 	mpv->opengl_cb_callback_data = NULL;
-	mpv->event_callback = NULL;
 	mpv->opengl_cb_callback = NULL;
 }
 
-GmpvMpv *gmpv_mpv_new(GmpvPlaylist *playlist, gint64 wid)
+GmpvMpv *gmpv_mpv_new(gint64 wid)
 {
-	return GMPV_MPV_OBJ(g_object_new(	gmpv_mpv_get_type(),
-						"playlist", playlist,
-						"wid", wid,
-						NULL ));
-}
-
-void mpv_check_error(int status)
-{
-	void *array[10];
-	size_t size;
-
-	if(status < 0)
-	{
-		size = (size_t)backtrace(array, 10);
-
-		g_critical("MPV API error: %s\n", mpv_error_string(status));
-
-		backtrace_symbols_fd(array, (int)size, STDERR_FILENO);
-
-		exit(EXIT_FAILURE);
-	}
+	return GMPV_MPV_OBJ(g_object_new(gmpv_mpv_get_type(), "wid", wid, NULL));
 }
 
 inline const GmpvMpvState *gmpv_mpv_get_state(GmpvMpv *mpv)
@@ -742,24 +931,34 @@ inline GmpvGeometry *gmpv_mpv_get_geometry(GmpvMpv *mpv)
 	return mpv->geometry;
 }
 
-inline gdouble gmpv_mpv_get_autofit_ratio(GmpvMpv *mpv)
+inline mpv_handle *gmpv_mpv_get_mpv_handle(GmpvMpv *mpv)
 {
-	return mpv->autofit_ratio;
+	return mpv->mpv_ctx;
 }
 
-inline GmpvPlaylist *gmpv_mpv_get_playlist(GmpvMpv *mpv)
+inline mpv_opengl_cb_context *gmpv_mpv_get_opengl_cb_context(GmpvMpv *mpv)
 {
-	return mpv->playlist;
+	return mpv->opengl_ctx;
 }
 
-inline mpv_handle *gmpv_mpv_get_mpv_handle(GmpvMpv *mpv)
+inline gboolean gmpv_mpv_get_use_opengl_cb(GmpvMpv *mpv)
 {
-	return mpv->mpv_ctx;
+	return mpv->use_opengl;
 }
 
-inline mpv_opengl_cb_context *gmpv_mpv_get_opengl_cb_context(GmpvMpv *mpv)
+GPtrArray *gmpv_mpv_get_metadata(GmpvMpv *mpv)
 {
-	return mpv->opengl_ctx;
+	return mpv->metadata;
+}
+
+GPtrArray *gmpv_mpv_get_playlist(GmpvMpv *mpv)
+{
+	return mpv->playlist;
+}
+
+GPtrArray *gmpv_mpv_get_track_list(GmpvMpv *mpv)
+{
+	return mpv->track_list;
 }
 
 void gmpv_mpv_initialize(GmpvMpv *mpv)
@@ -775,16 +974,18 @@ void gmpv_mpv_initialize(GmpvMpv *mpv)
 		const gchar *name;
 		const gchar *value;
 	}
-	options[] = {	{"osd-level", "1"},
+	options[] = {	{"vo", "opengl,vdpau,vaapi,xv,x11,opengl-cb,"},
+			{"osd-level", "1"},
 			{"softvol", "yes"},
-			{"force-window", "yes"},
+			{"force-window", "immediate"},
 			{"input-default-bindings", "yes"},
 			{"audio-client-name", ICON_NAME},
 			{"title", "${media-title}"},
 			{"autofit-larger", "75%"},
 			{"window-scale", "1"},
-			{"pause", "no"},
+			{"pause", "yes"},
 			{"ytdl", "yes"},
+			{"load-scripts", "no"},
 			{"osd-bar", "no"},
 			{"input-cursor", "no"},
 			{"cursor-autohide", "no"},
@@ -845,7 +1046,7 @@ void gmpv_mpv_initialize(GmpvMpv *mpv)
 		const gchar *msg
 			= _("Failed to apply one or more MPV options.");
 
-		g_signal_emit_by_name(mpv, "mpv-error", msg);
+		g_signal_emit_by_name(mpv, "error", msg);
 	}
 
 	if(mpv->force_opengl || mpv->wid <= 0)
@@ -862,26 +1063,35 @@ void gmpv_mpv_initialize(GmpvMpv *mpv)
 		mpv_set_option(mpv->mpv_ctx, "wid", MPV_FORMAT_INT64, &mpv->wid);
 	}
 
-	mpv_observe_property(mpv->mpv_ctx, 0, "aid", MPV_FORMAT_INT64);
+	mpv_observe_property(mpv->mpv_ctx, 0, "aid", MPV_FORMAT_STRING);
+	mpv_observe_property(mpv->mpv_ctx, 0, "vid", MPV_FORMAT_STRING);
+	mpv_observe_property(mpv->mpv_ctx, 0, "sid", MPV_FORMAT_STRING);
 	mpv_observe_property(mpv->mpv_ctx, 0, "chapters", MPV_FORMAT_INT64);
 	mpv_observe_property(mpv->mpv_ctx, 0, "core-idle", MPV_FORMAT_FLAG);
+	mpv_observe_property(mpv->mpv_ctx, 0, "idle-active", MPV_FORMAT_FLAG);
 	mpv_observe_property(mpv->mpv_ctx, 0, "fullscreen", MPV_FORMAT_FLAG);
 	mpv_observe_property(mpv->mpv_ctx, 0, "pause", MPV_FORMAT_FLAG);
+	mpv_observe_property(mpv->mpv_ctx, 0, "loop", MPV_FORMAT_STRING);
 	mpv_observe_property(mpv->mpv_ctx, 0, "duration", MPV_FORMAT_DOUBLE);
 	mpv_observe_property(mpv->mpv_ctx, 0, "media-title", MPV_FORMAT_STRING);
+	mpv_observe_property(mpv->mpv_ctx, 0, "metadata", MPV_FORMAT_NODE);
+	mpv_observe_property(mpv->mpv_ctx, 0, "playlist", MPV_FORMAT_NODE);
+	mpv_observe_property(mpv->mpv_ctx, 0, "playlist-count", MPV_FORMAT_INT64);
 	mpv_observe_property(mpv->mpv_ctx, 0, "playlist-pos", MPV_FORMAT_INT64);
+	mpv_observe_property(mpv->mpv_ctx, 0, "speed", MPV_FORMAT_DOUBLE);
 	mpv_observe_property(mpv->mpv_ctx, 0, "track-list", MPV_FORMAT_NODE);
+	mpv_observe_property(mpv->mpv_ctx, 0, "vo-configured", MPV_FORMAT_FLAG);
 	mpv_observe_property(mpv->mpv_ctx, 0, "volume", MPV_FORMAT_DOUBLE);
 	mpv_set_wakeup_callback(mpv->mpv_ctx, wakeup_callback, mpv);
-	mpv_check_error(mpv_initialize(mpv->mpv_ctx));
-
+	mpv_initialize(mpv->mpv_ctx);
 
 	mpv_version = gmpv_mpv_get_property_string(mpv, "mpv-version");
 	current_vo = gmpv_mpv_get_property_string(mpv, "current-vo");
+	mpv->use_opengl = !current_vo;
 
 	g_info("Using %s", mpv_version);
 
-	if(current_vo && !GDK_IS_X11_DISPLAY(gdk_display_get_default()))
+	if(!mpv->use_opengl && !GDK_IS_X11_DISPLAY(gdk_display_get_default()))
 	{
 		g_info(	"The chosen vo is %s but the display is not X11; "
 			"forcing --vo=opengl-cb and resetting",
@@ -906,8 +1116,7 @@ void gmpv_mpv_initialize(GmpvMpv *mpv)
 					MPV_FORMAT_DOUBLE,
 					&volume );
 
-		/* The vo should be opengl-cb if current_vo is NULL*/
-		if(!current_vo)
+		if(mpv->use_opengl)
 		{
 			mpv->opengl_ctx =	mpv_get_sub_api
 						(	mpv->mpv_ctx,
@@ -976,16 +1185,12 @@ void gmpv_mpv_reset(GmpvMpv *mpv)
 	/* Reset mpv->mpv_ctx */
 	mpv->state.ready = FALSE;
 
-	mpv_check_error(gmpv_mpv_command(mpv, quit_cmd));
+	gmpv_mpv_command(mpv, quit_cmd);
 	gmpv_mpv_quit(mpv);
 
 	mpv->mpv_ctx = mpv_create();
 	gmpv_mpv_initialize(mpv);
 
-	gmpv_mpv_set_event_callback
-		(	mpv,
-			mpv->event_callback,
-			mpv->event_callback_data );
 	gmpv_mpv_set_opengl_cb_callback
 		(	mpv,
 			mpv->opengl_cb_callback,
@@ -997,17 +1202,9 @@ void gmpv_mpv_reset(GmpvMpv *mpv)
 	{
 		if(mpv->state.loaded)
 		{
-			gint rc;
-
-			rc =	mpv_request_event
-				(mpv->mpv_ctx, MPV_EVENT_FILE_LOADED, 0);
-			mpv_check_error(rc);
-
-			gmpv_mpv_load(mpv, NULL, FALSE, TRUE);
-
-			rc =	mpv_request_event
-				(mpv->mpv_ctx, MPV_EVENT_FILE_LOADED, 1);
-			mpv_check_error(rc);
+			mpv_request_event(mpv->mpv_ctx, MPV_EVENT_FILE_LOADED, 0);
+			load_from_playlist(mpv);
+			mpv_request_event(mpv->mpv_ctx, MPV_EVENT_FILE_LOADED, 1);
 		}
 
 		if(playlist_pos_rc >= 0 && playlist_pos > 0)
@@ -1048,169 +1245,101 @@ void gmpv_mpv_quit(GmpvMpv *mpv)
 	mpv->mpv_ctx = NULL;
 }
 
-void gmpv_mpv_load(	GmpvMpv *mpv,
-			const gchar *uri,
-			gboolean append,
-			gboolean update )
+void gmpv_mpv_load_track(GmpvMpv *mpv, const gchar *uri, TrackType type)
 {
-	const gchar *load_cmd[] = {"loadfile", NULL, NULL, NULL};
-	GtkListStore *playlist_store = gmpv_playlist_get_store(mpv->playlist);
-	GtkTreeIter iter;
-	gboolean empty;
-
-	g_info(	"Loading file (append=%s, update=%s): %s",
-		append?"TRUE":"FALSE",
-		update?"TRUE":"FALSE",
-		uri?:"<PLAYLIST_ITEMS>" );
-
-	empty = !gtk_tree_model_get_iter_first
-			(GTK_TREE_MODEL(playlist_store), &iter);
-
-	load_cmd[2] = (append && !empty)?"append":"replace";
+	const gchar *cmd[3] = {NULL};
+	gchar *path = g_filename_from_uri(uri, NULL, NULL);
 
-	if(!append && uri && update)
+	if(type == TRACK_TYPE_AUDIO)
 	{
-		mpv->state.new_file = TRUE;
-		mpv->state.loaded = FALSE;
+		cmd[0] = "audio-add";
 	}
-
-	if(!uri)
+	else if(type == TRACK_TYPE_SUBTITLE)
 	{
-		gboolean append = FALSE;
-		gboolean rc;
-
-		if(!mpv->state.init_load)
-		{
-			gmpv_mpv_set_property_flag(mpv, "pause", FALSE);
-		}
+		cmd[0] = "sub-add";
+	}
+	else
+	{
+		g_assert_not_reached();
+	}
 
-		rc = gtk_tree_model_get_iter_first
-			(GTK_TREE_MODEL(playlist_store), &iter);
+	cmd[1] = path?:uri;
 
-		while(rc)
-		{
-			gchar *uri;
+	g_debug("Loading external track %s with type %d", cmd[1], type);
+	gmpv_mpv_command(mpv, cmd);
 
-			gtk_tree_model_get(	GTK_TREE_MODEL(playlist_store),
-						&iter,
-						PLAYLIST_URI_COLUMN,
-						&uri,
-						-1 );
+	g_free(path);
+}
 
-			/* append = FALSE only on first iteration */
-			gmpv_mpv_load(mpv, uri, append, FALSE);
+void gmpv_mpv_load_file(GmpvMpv *mpv, const gchar *uri, gboolean append)
+{
+	gchar *path = get_path_from_uri(uri);
+	const gchar *load_cmd[] = {"loadfile", path, NULL, NULL};
+	gint64 playlist_count = 0;
 
-			append = TRUE;
+	g_assert(uri);
+	g_info(	"Loading file (append=%s): %s", append?"TRUE":"FALSE", uri);
 
-			rc = gtk_tree_model_iter_next
-				(GTK_TREE_MODEL(playlist_store), &iter);
+	mpv_get_property(	mpv->mpv_ctx,
+				"playlist-count",
+				MPV_FORMAT_INT64,
+				&playlist_count );
 
-			g_free(uri);
-		}
-	}
+	load_cmd[2] = (append && playlist_count > 0)?"append":"replace";
 
-	if(uri && playlist_store)
+	if(!append)
 	{
-		gchar *path = get_path_from_uri(uri);
-
-		load_cmd[1] = path;
-
-		if(!append)
-		{
-			mpv->state.loaded = FALSE;
-
-			if(!mpv->state.init_load)
-			{
-				gmpv_mpv_set_property_flag
-					(mpv, "pause", FALSE);
-			}
-		}
+		mpv->state.new_file = TRUE;
+		mpv->state.loaded = FALSE;
 
-		if(update)
+		if(!mpv->state.init_load)
 		{
-			gchar *name = get_name_from_path(path);
-
-			gmpv_playlist_append(mpv->playlist, name, uri);
-
-			g_free(name);
+			gmpv_mpv_set_property_flag(mpv, "pause", FALSE);
 		}
-
-		g_assert(mpv->mpv_ctx);
-
-		mpv_check_error(mpv_request_event(	mpv->mpv_ctx,
-							MPV_EVENT_END_FILE,
-							0 ));
-
-		mpv_check_error(mpv_command(mpv->mpv_ctx, load_cmd));
-
-		mpv_check_error(mpv_request_event(	mpv->mpv_ctx,
-							MPV_EVENT_END_FILE,
-							1 ));
-
-		g_free(path);
 	}
-}
 
-void gmpv_mpv_free(gpointer data)
-{
-	mpv_free(data);
+	g_assert(mpv->mpv_ctx);
+	mpv_request_event(mpv->mpv_ctx, MPV_EVENT_END_FILE, 0);
+	mpv_command(mpv->mpv_ctx, load_cmd);
+	mpv_request_event(mpv->mpv_ctx, MPV_EVENT_END_FILE, 1);
+
+	g_free(path);
 }
 
-void gmpv_mpv_load_list(	GmpvMpv *mpv,
-				const gchar **uri_list,
-				gboolean append,
-				gboolean update )
+void gmpv_mpv_load(GmpvMpv *mpv, const gchar *uri, gboolean append)
 {
-	static const char *const sub_exts[] = SUBTITLE_EXTS;
+	const gchar *subtitle_exts[] = SUBTITLE_EXTS;
 
-	for(gint i = 0; uri_list[i]; i++)
+	if(extension_matches(uri, subtitle_exts))
 	{
-		const gchar *ext = strrchr(uri_list[i], '.');
-		gboolean subtitle = FALSE;
-
-		/* Only start checking the extension if there is at
-		 * least one character after the dot.
-		 */
-		if(ext && ++ext)
-		{
-			const gchar *const *cur = sub_exts;
-
-			/* Check if the file extension matches one of the
-			 * supported subtitle formats.
-			 */
-			while(*cur && g_strcmp0(ext, *(cur++)) != 0);
+		gmpv_mpv_load_track(mpv, uri, TRACK_TYPE_SUBTITLE);
+	}
+	else
+	{
+		gboolean idle_active = FALSE;
 
-			subtitle = !!(*cur);
-		}
+		mpv_get_property(	mpv->mpv_ctx,
+					"idle-active",
+					MPV_FORMAT_FLAG,
+					&idle_active );
 
-		/* Only attempt to load file as subtitle if there
-		 * already is a file loaded. Try to load the file as a
-		 * media file otherwise.
-		 */
-		if(ext && subtitle && gmpv_mpv_get_state(mpv)->loaded)
+		if(idle_active)
 		{
-			const gchar *cmd[] = {"sub-add", NULL, NULL};
-			gchar *path;
-
-			/* Convert to path if possible to get rid of
-			 * percent encoding.
-			 */
-			path = g_filename_from_uri(uri_list[i], NULL, NULL);
-			cmd[1] = path?:uri_list[i];
-
-			g_debug("Loading external subtitle: %s", cmd[1]);
-			gmpv_mpv_command(mpv, cmd);
+			if(!append)
+			{
+				g_ptr_array_set_size(mpv->playlist, 0);
+			}
 
-			g_free(path);
+			add_file_to_playlist(mpv, uri);
 		}
 		else
 		{
-			gboolean empty = gmpv_playlist_empty(mpv->playlist);
-
-			gmpv_mpv_load(	mpv,
-					uri_list[i],
-					((append && !empty) || i != 0),
-					TRUE );
+			gmpv_mpv_load_file(mpv, uri, append);
 		}
 	}
 }
+
+void gmpv_mpv_free(gpointer data)
+{
+	mpv_free(data);
+}
diff --git a/src/gmpv_mpv.h b/src/gmpv_mpv.h
index 866feae..bd9e5c4 100644
--- a/src/gmpv_mpv.h
+++ b/src/gmpv_mpv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016 gnome-mpv
+ * Copyright (c) 2014, 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -25,8 +25,8 @@
 #include <mpv/client.h>
 #include <mpv/opengl_cb.h>
 
-#include "gmpv_playlist.h"
 #include "gmpv_geometry.h"
+#include "gmpv_common.h"
 
 G_BEGIN_DECLS
 
@@ -45,25 +45,22 @@ struct _GmpvMpvState
 	gboolean init_load;
 };
 
-GmpvMpv *gmpv_mpv_new(GmpvPlaylist *playlist, gint64 wid);
+GmpvMpv *gmpv_mpv_new(gint64 wid);
 const GmpvMpvState *gmpv_mpv_get_state(GmpvMpv *mpv);
 GmpvGeometry *gmpv_mpv_get_geometry(GmpvMpv *mpv);
-gdouble gmpv_mpv_get_autofit_ratio(GmpvMpv *mpv);
-GmpvPlaylist *gmpv_mpv_get_playlist(GmpvMpv *mpv);
 mpv_handle *gmpv_mpv_get_mpv_handle(GmpvMpv *mpv);
 mpv_opengl_cb_context *gmpv_mpv_get_opengl_cb_context(GmpvMpv *mpv);
+gboolean gmpv_mpv_get_use_opengl_cb(GmpvMpv *mpv);
+GPtrArray *gmpv_mpv_get_metadata(GmpvMpv *mpv);
+GPtrArray *gmpv_mpv_get_playlist(GmpvMpv *mpv);
+GPtrArray *gmpv_mpv_get_track_list(GmpvMpv *mpv);
 void gmpv_mpv_initialize(GmpvMpv *mpv);
 void gmpv_mpv_init_gl(GmpvMpv *mpv);
 void gmpv_mpv_reset(GmpvMpv *mpv);
 void gmpv_mpv_quit(GmpvMpv *mpv);
-void gmpv_mpv_load(	GmpvMpv *mpv,
-			const gchar *uri,
-			gboolean append,
-			gboolean update );
-void gmpv_mpv_load_list(	GmpvMpv *mpv,
-				const gchar **uri_list,
-				gboolean append,
-				gboolean update );
+void gmpv_mpv_load_track(GmpvMpv *mpv, const gchar *uri, TrackType type);
+void gmpv_mpv_load_file(GmpvMpv *mpv, const gchar *uri, gboolean append);
+void gmpv_mpv_load(GmpvMpv *mpv, const gchar *uri, gboolean append);
 void gmpv_mpv_free(gpointer data);
 
 G_END_DECLS
diff --git a/src/gmpv_mpv_opt.c b/src/gmpv_mpv_opt.c
index 1db783d..f6c2a05 100644
--- a/src/gmpv_mpv_opt.c
+++ b/src/gmpv_mpv_opt.c
@@ -479,9 +479,7 @@ void gmpv_mpv_opt_handle_msg_level(GmpvMpv *mpv)
 	}
 
 	for(i = 0; level_map[i].level != min_level; i++);
-
-	mpv_check_error
-		(mpv_request_log_messages(mpv->mpv_ctx, level_map[i].name));
+	mpv_request_log_messages(mpv->mpv_ctx, level_map[i].name);
 
 	mpv_free(optbuf);
 	g_strfreev(tokens);
diff --git a/src/gmpv_mpv_private.h b/src/gmpv_mpv_private.h
index 0136736..eb485c6 100644
--- a/src/gmpv_mpv_private.h
+++ b/src/gmpv_mpv_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -20,6 +20,8 @@
 #ifndef MPV_OBJ_PRIVATE_H
 #define MPV_OBJ_PRIVATE_H
 
+#include <gtk/gtk.h>
+
 #include "gmpv_mpv_opt.h"
 
 G_BEGIN_DECLS
@@ -28,7 +30,6 @@ enum
 {
 	PROP_0,
 	PROP_WID,
-	PROP_PLAYLIST,
 	N_PROPERTIES
 };
 
@@ -38,17 +39,19 @@ struct _GmpvMpv
 	GmpvMpvState state;
 	mpv_handle *mpv_ctx;
 	mpv_opengl_cb_context *opengl_ctx;
-	GmpvPlaylist *playlist;
+	GPtrArray *playlist;
+	GPtrArray *metadata;
+	GPtrArray *track_list;
 	GtkGLArea *glarea;
 	gchar *tmp_input_file;
 	GSList *log_level_list;
 	gdouble autofit_ratio;
 	GmpvGeometry *geometry;
+	gboolean init_vo_config;
 	gboolean force_opengl;
+	gboolean use_opengl;
 	gint64 wid;
-	void *event_callback_data;
 	void *opengl_cb_callback_data;
-	void (*event_callback)(mpv_event *, void *data);
 	void (*opengl_cb_callback)(void *data);
 };
 
diff --git a/src/gmpv_mpv_wrapper.c b/src/gmpv_mpv_wrapper.c
index b2f425f..5a9b814 100644
--- a/src/gmpv_mpv_wrapper.c
+++ b/src/gmpv_mpv_wrapper.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -193,14 +193,6 @@ gint gmpv_mpv_set_property_flag(	GmpvMpv *mpv,
 	return rc;
 }
 
-void gmpv_mpv_set_event_callback(	GmpvMpv *mpv,
-					void (*func)(mpv_event *, void *),
-					void *data )
-{
-	mpv->event_callback = func;
-	mpv->event_callback_data = data;
-}
-
 void gmpv_mpv_set_opengl_cb_callback(	GmpvMpv *mpv,
 					mpv_opengl_cb_update_fn func,
 					void *data )
diff --git a/src/gmpv_open_loc_dialog.c b/src/gmpv_open_location_dialog.c
similarity index 68%
rename from src/gmpv_open_loc_dialog.c
rename to src/gmpv_open_location_dialog.c
index 9321676..fe0feab 100644
--- a/src/gmpv_open_loc_dialog.c
+++ b/src/gmpv_open_location_dialog.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016 gnome-mpv
+ * Copyright (c) 2014, 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -20,10 +20,10 @@
 #include <gdk/gdk.h>
 #include <glib/gi18n.h>
 
-#include "gmpv_open_loc_dialog.h"
+#include "gmpv_open_location_dialog.h"
 #include "gmpv_main_window.h"
 
-struct _GmpvOpenLocDialog
+struct _GmpvOpenLocationDialog
 {
 	GtkDialog parent_instance;
 	GtkWidget *content_area;
@@ -32,12 +32,12 @@ struct _GmpvOpenLocDialog
 	GtkWidget *loc_entry;
 };
 
-struct _GmpvOpenLocDialogClass
+struct _GmpvOpenLocationDialogClass
 {
 	GtkDialogClass parent_class;
 };
 
-G_DEFINE_TYPE(GmpvOpenLocDialog, gmpv_open_loc_dialog, GTK_TYPE_DIALOG)
+G_DEFINE_TYPE(GmpvOpenLocationDialog, gmpv_open_location_dialog, GTK_TYPE_DIALOG)
 
 static gboolean key_press_handler (GtkWidget *widget, GdkEventKey *event)
 {
@@ -57,18 +57,61 @@ static gboolean key_press_handler (GtkWidget *widget, GdkEventKey *event)
 		gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_ACCEPT);
 	}
 
-	return	GTK_WIDGET_CLASS(gmpv_open_loc_dialog_parent_class)
+	return	GTK_WIDGET_CLASS(gmpv_open_location_dialog_parent_class)
 		->key_press_event (widget, event);
 }
 
-static void gmpv_open_loc_dialog_class_init(GmpvOpenLocDialogClass *klass)
+static GtkClipboard *get_clipboard(GmpvOpenLocationDialog *dlg)
+{
+	const gchar *const clipboard_names[] = {"CLIPBOARD", "PRIMARY", NULL};
+	GtkClipboard *clipboard = NULL;
+
+	for(gint i = 0; clipboard_names[i] && !clipboard; i++)
+	{
+		GdkAtom atom = gdk_atom_intern(clipboard_names[i], FALSE);
+
+		clipboard = gtk_clipboard_get(atom);
+
+		if(!gtk_clipboard_wait_is_text_available(clipboard))
+		{
+			clipboard = NULL;
+		}
+	}
+
+	return clipboard;
+}
+
+static void clipboard_text_received_handler(	GtkClipboard *clipboard,
+						const gchar *text,
+						gpointer data )
+{
+	GmpvOpenLocationDialog *dlg = data;
+
+	if(text && *text)
+	{
+		gtk_entry_set_text(GTK_ENTRY(dlg->loc_entry), text);
+	}
+
+	g_object_unref(dlg);
+}
+
+static void load_text_from_clipboard(GmpvOpenLocationDialog *dlg)
+{
+	g_object_ref(dlg);
+
+	gtk_clipboard_request_text(	get_clipboard(dlg),
+					clipboard_text_received_handler,
+					dlg );
+}
+
+static void gmpv_open_location_dialog_class_init(GmpvOpenLocationDialogClass *klass)
 {
 	GtkWidgetClass *wid_class = GTK_WIDGET_CLASS(klass);
 
 	wid_class->key_press_event = key_press_handler;
 }
 
-static void gmpv_open_loc_dialog_init(GmpvOpenLocDialog *dlg)
+static void gmpv_open_location_dialog_init(GmpvOpenLocationDialog *dlg)
 {
 	GdkGeometry geom;
 
@@ -122,7 +165,7 @@ static void gmpv_open_loc_dialog_init(GmpvOpenLocDialog *dlg)
 	gtk_dialog_set_default_response (GTK_DIALOG(dlg), GTK_RESPONSE_ACCEPT);
 }
 
-GtkWidget *gmpv_open_loc_dialog_new(GtkWindow *parent, const gchar *title)
+GtkWidget *gmpv_open_location_dialog_new(GtkWindow *parent, const gchar *title)
 {
 	GtkWidget *dlg;
 	GtkWidget *header_bar;
@@ -130,7 +173,7 @@ GtkWidget *gmpv_open_loc_dialog_new(GtkWindow *parent, const gchar *title)
 
 	csd_enabled = gmpv_main_window_get_csd_enabled(GMPV_MAIN_WINDOW(parent));
 
-	dlg = g_object_new(	gmpv_open_loc_dialog_get_type(),
+	dlg = g_object_new(	gmpv_open_location_dialog_get_type(),
 				"use-header-bar", csd_enabled,
 				"title", title,
 				NULL );
@@ -153,6 +196,8 @@ GtkWidget *gmpv_open_loc_dialog_new(GtkWindow *parent, const gchar *title)
 
 	}
 
+	load_text_from_clipboard(GMPV_OPEN_LOCATION_DIALOG(dlg));
+
 	gtk_widget_hide_on_delete(dlg);
 	gtk_window_set_transient_for(GTK_WINDOW(dlg), parent);
 	gtk_widget_show_all(dlg);
@@ -160,12 +205,12 @@ GtkWidget *gmpv_open_loc_dialog_new(GtkWindow *parent, const gchar *title)
 	return dlg;
 }
 
-const gchar *gmpv_open_loc_dialog_get_string(GmpvOpenLocDialog *dlg)
+const gchar *gmpv_open_location_dialog_get_string(GmpvOpenLocationDialog *dlg)
 {
 	return gtk_entry_get_text(GTK_ENTRY(dlg->loc_entry));
 }
 
-guint64 gmpv_open_loc_dialog_get_string_length(GmpvOpenLocDialog *dlg)
+guint64 gmpv_open_location_dialog_get_string_length(GmpvOpenLocationDialog *dlg)
 {
 	return gtk_entry_get_text_length(GTK_ENTRY(dlg->loc_entry));
 }
diff --git a/src/gmpv_open_loc_dialog.h b/src/gmpv_open_location_dialog.h
similarity index 59%
rename from src/gmpv_open_loc_dialog.h
rename to src/gmpv_open_location_dialog.h
index d0ee059..178f0bb 100644
--- a/src/gmpv_open_loc_dialog.h
+++ b/src/gmpv_open_location_dialog.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016 gnome-mpv
+ * Copyright (c) 2014, 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,8 +17,8 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef OPEN_LOC_DIALOG_H
-#define OPEN_LOC_DIALOG_H
+#ifndef OPEN_LOCATION_DIALOG_H
+#define OPEN_LOCATION_DIALOG_H
 
 #include <glib.h>
 #include <glib-object.h>
@@ -26,13 +26,13 @@
 
 G_BEGIN_DECLS
 
-#define GMPV_TYPE_OPEN_LOC_DIALOG (gmpv_open_loc_dialog_get_type ())
+#define GMPV_TYPE_OPEN_LOC_DIALOG (gmpv_open_location_dialog_get_type ())
 
-G_DECLARE_FINAL_TYPE(GmpvOpenLocDialog, gmpv_open_loc_dialog, GMPV, OPEN_LOC_DIALOG, GtkDialog)
+G_DECLARE_FINAL_TYPE(GmpvOpenLocationDialog, gmpv_open_location_dialog, GMPV, OPEN_LOCATION_DIALOG, GtkDialog)
 
-GtkWidget *gmpv_open_loc_dialog_new(GtkWindow *parent, const gchar *title);
-const gchar *gmpv_open_loc_dialog_get_string(GmpvOpenLocDialog *dlg);
-guint64 gmpv_open_loc_dialog_get_string_length(GmpvOpenLocDialog *dlg);
+GtkWidget *gmpv_open_location_dialog_new(GtkWindow *parent, const gchar *title);
+const gchar *gmpv_open_location_dialog_get_string(GmpvOpenLocationDialog *dlg);
+guint64 gmpv_open_location_dialog_get_string_length(GmpvOpenLocationDialog *dlg);
 
 G_END_DECLS
 
diff --git a/src/gmpv_playbackctl.c b/src/gmpv_playbackctl.c
deleted file mode 100644
index 81ffcd9..0000000
--- a/src/gmpv_playbackctl.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2015-2016 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib-object.h>
-#include <mpv/client.h>
-#include <gtk/gtk.h>
-
-#include "gmpv_playbackctl.h"
-#include "gmpv_control_box.h"
-#include "gmpv_common.h"
-#include "gmpv_mpv.h"
-#include "gmpv_mpv_wrapper.h"
-#include "gmpv_main_window.h"
-
-static void play_handler(GtkWidget *widget, gpointer data);
-static void stop_handler(GtkWidget *widget, gpointer data);
-static void seek_handler(GtkWidget *widget, gdouble value, gpointer data);
-static void forward_handler(GtkWidget *widget, gpointer data);
-static void rewind_handler(GtkWidget *widget, gpointer data);
-static void chapter_previous_handler(GtkWidget *widget, gpointer data);
-static void chapter_next_handler(GtkWidget *widget, gpointer data);
-static void volume_handler(GtkWidget *widget, gdouble value, gpointer data);
-static void fullscreen_handler(GtkWidget *button, gpointer data);
-
-static void play_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvApplication *app = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(app);
-
-	gmpv_mpv_set_property_flag
-		(	mpv,
-			"pause",
-			!gmpv_mpv_get_property_flag(mpv, "pause") );
-}
-
-static void stop_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvApplication *app = data;
-	const gchar *cmd[] = {"stop", NULL};
-
-	gmpv_mpv_command(gmpv_application_get_mpv(app), cmd);
-}
-
-static void seek_handler(GtkWidget *widget, gdouble value, gpointer data)
-{
-	seek(data, value);
-}
-
-static void forward_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvApplication *app = data;
-	const gchar *cmd[] = {"seek", "10", NULL};
-
-	gmpv_mpv_command(gmpv_application_get_mpv(app), cmd);
-}
-
-static void rewind_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvApplication *app = data;
-	const gchar *cmd[] = {"seek", "-10", NULL};
-
-	gmpv_mpv_command(gmpv_application_get_mpv(app), cmd);
-}
-
-static void chapter_previous_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvApplication *app = data;
-	const gchar *cmd[] = {"osd-msg", "cycle", "chapter", "down", NULL};
-
-	gmpv_mpv_command(gmpv_application_get_mpv(app), cmd);
-}
-
-static void chapter_next_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvApplication *app = data;
-	const gchar *cmd[] = {"osd-msg", "cycle", "chapter", NULL};
-
-	gmpv_mpv_command(gmpv_application_get_mpv(app), cmd);
-}
-
-static void volume_handler(GtkWidget *widget, gdouble value, gpointer data)
-{
-	GmpvMpv *mpv = gmpv_application_get_mpv(GMPV_APPLICATION(data));
-
-	value *= 100;
-
-	gmpv_mpv_set_property(mpv, "volume", MPV_FORMAT_DOUBLE, &value);
-}
-
-static void fullscreen_handler(GtkWidget *widget, gpointer data)
-{
-	GmpvMainWindow *wnd =	gmpv_application_get_main_window
-				(GMPV_APPLICATION(data));
-
-	gmpv_main_window_toggle_fullscreen(wnd);
-}
-
-void gmpv_playbackctl_connect_signals(GmpvApplication *app)
-{
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(app);
-	GmpvControlBox *control_box = gmpv_main_window_get_control_box(wnd);
-
-	const struct
-	{
-		const gchar *name;
-		GCallback handler;
-	}
-	signals_map[] = {	{"play-button-clicked",
-				G_CALLBACK(play_handler)},
-				{"stop-button-clicked",
-				G_CALLBACK(stop_handler)},
-				{"forward-button-clicked",
-				G_CALLBACK(forward_handler)},
-				{"rewind-button-clicked",
-				G_CALLBACK(rewind_handler)},
-				{"previous-button-clicked",
-				G_CALLBACK(chapter_previous_handler)},
-				{"next-button-clicked",
-				G_CALLBACK(chapter_next_handler)},
-				{"fullscreen-button-clicked",
-				G_CALLBACK(fullscreen_handler)},
-				{"seek",
-				G_CALLBACK(seek_handler)},
-				{"volume-changed",
-				G_CALLBACK(volume_handler)},
-				{NULL, NULL} };
-
-	for(gint i = 0; signals_map[i].name; i++)
-	{
-		g_signal_connect(	control_box,
-					signals_map[i].name,
-					signals_map[i].handler,
-					app );
-	}
-}
diff --git a/src/gmpv_playbackctl.h b/src/gmpv_playbackctl.h
deleted file mode 100644
index cd9e611..0000000
--- a/src/gmpv_playbackctl.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015-2016 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PLAYBACKCTL_H
-#define PLAYBACKCTL_H
-
-#include <glib.h>
-#include "gmpv_application.h"
-
-G_BEGIN_DECLS
-
-void gmpv_playbackctl_connect_signals(GmpvApplication *app);
-
-G_END_DECLS
-
-#endif
diff --git a/src/gmpv_playlist.c b/src/gmpv_playlist.c
deleted file mode 100644
index 9b10018..0000000
--- a/src/gmpv_playlist.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2014-2016 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include "gmpv_playlist.h"
-#include "gmpv_marshal.h"
-
-struct _GmpvPlaylist
-{
-	GObject parent;
-	GtkListStore *store;
-	gboolean move_dest;
-};
-
-struct _GmpvPlaylistClass
-{
-	GObjectClass parent_class;
-};
-
-static void row_inserted_handler(	GtkTreeModel *tree_model,
-					GtkTreePath *path,
-					GtkTreeIter *iter,
-					gpointer data );
-static void row_deleted_handler(	GtkTreeModel *tree_model,
-					GtkTreePath *path,
-					gpointer data );
-
-G_DEFINE_TYPE(GmpvPlaylist, gmpv_playlist, G_TYPE_OBJECT)
-
-static void row_inserted_handler(	GtkTreeModel *tree_model,
-					GtkTreePath *path,
-					GtkTreeIter *iter,
-					gpointer data )
-{
-	GmpvPlaylist *pl = data;
-	const gint dest = gtk_tree_path_get_indices(path)[0];
-
-	pl->move_dest = dest;
-
-	g_signal_emit_by_name(pl, "row-inserted", dest);
-}
-
-static void row_deleted_handler(	GtkTreeModel *tree_model,
-					GtkTreePath *path,
-					gpointer data )
-{
-	GmpvPlaylist *pl = data;
-	const gint src = gtk_tree_path_get_indices(path)[0];
-	const gint dest = pl->move_dest;
-
-	if(dest >= 0)
-	{
-		g_signal_emit_by_name(pl, "row-reordered", src, dest);
-
-		pl->move_dest = -1;
-	}
-	else
-	{
-		g_signal_emit_by_name(pl, "row-deleted", src);
-	}
-}
-
-static void gmpv_playlist_class_init(GmpvPlaylistClass *klass)
-{
-	g_signal_new(	"row-inserted",
-			G_TYPE_FROM_CLASS(klass),
-			G_SIGNAL_RUN_FIRST,
-			0,
-			NULL,
-			NULL,
-			g_cclosure_marshal_VOID__INT,
-			G_TYPE_NONE,
-			1,
-			G_TYPE_INT );
-	g_signal_new(	"row-deleted",
-			G_TYPE_FROM_CLASS(klass),
-			G_SIGNAL_RUN_FIRST,
-			0,
-			NULL,
-			NULL,
-			g_cclosure_marshal_VOID__INT,
-			G_TYPE_NONE,
-			1,
-			G_TYPE_INT );
-	g_signal_new(	"row-reordered",
-			G_TYPE_FROM_CLASS(klass),
-			G_SIGNAL_RUN_FIRST,
-			0,
-			NULL,
-			NULL,
-			g_cclosure_gen_marshal_VOID__INT_INT,
-			G_TYPE_NONE,
-			2,
-			G_TYPE_INT,
-			G_TYPE_INT );
-}
-
-static void gmpv_playlist_init(GmpvPlaylist *pl)
-{
-	pl->store = gtk_list_store_new(	3,
-					G_TYPE_STRING,
-					G_TYPE_STRING,
-					G_TYPE_INT );
-
-	pl->move_dest = -1;
-
-	g_signal_connect(	pl->store,
-				"row-inserted",
-				G_CALLBACK(row_inserted_handler),
-				pl );
-	g_signal_connect(	pl->store,
-				"row-deleted",
-				G_CALLBACK(row_deleted_handler),
-				pl );
-}
-
-GmpvPlaylist *gmpv_playlist_new()
-{
-	return GMPV_PLAYLIST(g_object_new(gmpv_playlist_get_type(), NULL));
-}
-
-GtkListStore *gmpv_playlist_get_store(GmpvPlaylist *pl)
-{
-	return pl->store;
-}
-
-void gmpv_playlist_append(GmpvPlaylist *pl, const gchar *name, const gchar *uri)
-{
-	GtkTreeIter iter;
-
-	gtk_list_store_append(pl->store, &iter);
-	gtk_list_store_set(pl->store, &iter, PLAYLIST_NAME_COLUMN, name, -1);
-	gtk_list_store_set(pl->store, &iter, PLAYLIST_URI_COLUMN, uri, -1);
-
-	pl->move_dest = -1;
-}
-
-void gmpv_playlist_remove(GmpvPlaylist *pl, gint pos)
-{
-	GtkTreeIter iter;
-	gboolean rc;
-
-	rc = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pl->store), &iter);
-
-	while(rc && --pos >= 0)
-	{
-		rc = gtk_tree_model_iter_next
-			(GTK_TREE_MODEL(pl->store), &iter);
-	}
-
-	if(rc)
-	{
-		gtk_list_store_remove(pl->store, &iter);
-	}
-}
-
-void gmpv_playlist_clear(GmpvPlaylist *pl)
-{
-	gtk_list_store_clear(pl->store);
-}
-
-gboolean gmpv_playlist_empty(GmpvPlaylist *pl)
-{
-	GtkTreeIter iter;
-
-	return !gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pl->store), &iter);
-}
-
-void gmpv_playlist_set_indicator_pos(GmpvPlaylist *pl, gint pos)
-{
-	GtkTreeIter iter;
-	gboolean rc;
-
-	rc = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pl->store), &iter);
-
-	while(rc)
-	{
-		const PangoWeight weight =	(pos-- == 0)?
-						PANGO_WEIGHT_BOLD:
-						PANGO_WEIGHT_NORMAL;
-
-		gtk_list_store_set(	pl->store,
-					&iter,
-					PLAYLIST_WEIGHT_COLUMN, weight,
-					-1 );
-
-		rc = gtk_tree_model_iter_next(GTK_TREE_MODEL(pl->store), &iter);
-	}
-}
-
-void gmpv_playlist_reset(GmpvPlaylist *pl)
-{
-	gmpv_playlist_set_indicator_pos(pl, 0);
-}
diff --git a/src/gmpv_playlist.h b/src/gmpv_playlist.h
deleted file mode 100644
index 2dbbed3..0000000
--- a/src/gmpv_playlist.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014-2016 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PLAYLIST_H
-#define PLAYLIST_H
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GMPV_TYPE_PLAYLIST (gmpv_playlist_get_type ())
-
-G_DECLARE_FINAL_TYPE(GmpvPlaylist, gmpv_playlist, GMPV, PLAYLIST, GObject)
-
-enum PlaylistStoreColumn
-{
-	PLAYLIST_NAME_COLUMN,
-	PLAYLIST_URI_COLUMN,
-	PLAYLIST_WEIGHT_COLUMN,
-	PLAYLIST_N_COLUMNS
-};
-
-typedef enum PlaylistStoreColumn PlaylistStoreColumn;
-
-GmpvPlaylist *gmpv_playlist_new(void);
-GtkListStore *gmpv_playlist_get_store(GmpvPlaylist *pl);
-void gmpv_playlist_set_indicator_pos(GmpvPlaylist *pl, gint pos);
-void gmpv_playlist_append(GmpvPlaylist *pl, const gchar *name, const gchar *uri);
-void gmpv_playlist_remove(GmpvPlaylist *pl, gint pos);
-void gmpv_playlist_clear(GmpvPlaylist *pl);
-gboolean gmpv_playlist_empty(GmpvPlaylist *pl);
-void gmpv_playlist_reset(GmpvPlaylist *pl);
-
-G_END_DECLS
-
-#endif
diff --git a/src/gmpv_playlist_widget.c b/src/gmpv_playlist_widget.c
index 6733456..4d398a6 100644
--- a/src/gmpv_playlist_widget.c
+++ b/src/gmpv_playlist_widget.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -25,22 +25,31 @@
 #include <glib/gi18n.h>
 
 #include "gmpv_playlist_widget.h"
-#include "gmpv_playlist.h"
 #include "gmpv_marshal.h"
+#include "gmpv_common.h"
 #include "gmpv_def.h"
 
 enum
 {
 	PROP_0,
-	PROP_STORE,
+	PROP_PLAYLIST_COUNT,
 	N_PROPERTIES
 };
 
+enum PlaylistColumn
+{
+	PLAYLIST_NAME_COLUMN,
+	PLAYLIST_URI_COLUMN,
+	PLAYLIST_WEIGHT_COLUMN,
+	PLAYLIST_N_COLUMNS
+};
+
 struct _GmpvPlaylistWidget
 {
 	GtkScrolledWindow parent_instance;
+	gint64 playlist_count;
+	GtkListStore *store;
 	GtkWidget *tree_view;
-	GmpvPlaylist *store;
 	GtkTreeViewColumn *title_column;
 	GtkCellRenderer *title_renderer;
 	gint last_x;
@@ -53,15 +62,15 @@ struct _GmpvPlaylistWidgetClass
 	GtkScrolledWindowClass parent_class;
 };
 
-static void gmpv_playlist_widget_constructed(GObject *object);
-static void gmpv_playlist_widget_set_property(	GObject *object,
-						guint property_id,
-						const GValue *value,
-						GParamSpec *pspec );
-static void gmpv_playlist_widget_get_property(	GObject *object,
-						guint property_id,
-						GValue *value,
-						GParamSpec *pspec );
+static void constructed(GObject *object);
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
 static void drag_begin_handler(	GtkWidget *widget,
 				GdkDragContext *context,
 				gpointer data );
@@ -86,10 +95,12 @@ static void row_activated_handler(	GtkTreeView *tree_view,
 					GtkTreePath *path,
 					GtkTreeViewColumn *column,
 					gpointer data );
-static void row_deleted_handler(GmpvPlaylist *pl, gint pos, gpointer data);
-static void row_reodered_handler(	GmpvPlaylist *pl,
-					gint src,
-					gint dest,
+static void row_inserted_handler(	GtkTreeModel *tree_model,
+					GtkTreePath *path,
+					GtkTreeIter *iter,
+					gpointer data );
+static void row_deleted_handler(	GtkTreeModel *tree_model,
+					GtkTreePath *path,
 					gpointer data );
 static gboolean mouse_press_handler(	GtkWidget *widget,
 					GdkEvent *event,
@@ -98,14 +109,17 @@ static gchar *get_uri_selected(GmpvPlaylistWidget *wgt);
 
 G_DEFINE_TYPE(GmpvPlaylistWidget, gmpv_playlist_widget, GTK_TYPE_SCROLLED_WINDOW)
 
-static void gmpv_playlist_widget_constructed(GObject *object)
+static void constructed(GObject *object)
 {
 	GmpvPlaylistWidget *self = GMPV_PLAYLIST_WIDGET(object);
 	GtkTargetEntry targets[] = DND_TARGETS;
 
-	self->tree_view
-		= gtk_tree_view_new_with_model
-			(GTK_TREE_MODEL(gmpv_playlist_get_store(self->store)));
+	self->store = gtk_list_store_new(	3,
+						G_TYPE_STRING,
+						G_TYPE_STRING,
+						G_TYPE_INT );
+	self->tree_view =	gtk_tree_view_new_with_model
+				(GTK_TREE_MODEL(self->store));
 
 	g_signal_connect(	self->tree_view,
 				"button-press-event",
@@ -132,12 +146,12 @@ static void gmpv_playlist_widget_constructed(GObject *object)
 				G_CALLBACK(row_activated_handler),
 				self );
 	g_signal_connect(	self->store,
-				"row-deleted",
-				G_CALLBACK(row_deleted_handler),
+				"row-inserted",
+				G_CALLBACK(row_inserted_handler),
 				self );
 	g_signal_connect(	self->store,
-				"row-reordered",
-				G_CALLBACK(row_reodered_handler),
+				"row-deleted",
+				G_CALLBACK(row_deleted_handler),
 				self );
 
 	gtk_tree_view_enable_model_drag_source(	GTK_TREE_VIEW(self->tree_view),
@@ -164,17 +178,16 @@ static void gmpv_playlist_widget_constructed(GObject *object)
 	G_OBJECT_CLASS(gmpv_playlist_widget_parent_class)->constructed(object);
 }
 
-static void gmpv_playlist_widget_set_property(	GObject *object,
-						guint property_id,
-						const GValue *value,
-						GParamSpec *pspec )
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
 {
 	GmpvPlaylistWidget *self = GMPV_PLAYLIST_WIDGET(object);
 
-	if(property_id == PROP_STORE)
+	if(property_id == PROP_PLAYLIST_COUNT)
 	{
-		self->store = g_value_get_pointer(value);
-
+		self->playlist_count = g_value_get_int64(value);
 	}
 	else
 	{
@@ -182,16 +195,16 @@ static void gmpv_playlist_widget_set_property(	GObject *object,
 	}
 }
 
-static void gmpv_playlist_widget_get_property(	GObject *object,
-						guint property_id,
-						GValue *value,
-						GParamSpec *pspec )
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
 {
 	GmpvPlaylistWidget *self = GMPV_PLAYLIST_WIDGET(object);
 
-	if(property_id == PROP_STORE)
+	if(property_id == PROP_PLAYLIST_COUNT)
 	{
-		g_value_set_pointer(value, self->store);
+		g_value_set_int64(value, self->playlist_count);
 	}
 	else
 	{
@@ -351,7 +364,7 @@ static void drag_data_received_handler(	GtkWidget *widget,
 		gboolean insert_before;
 		gboolean dest_row_exist;
 
-		store = gmpv_playlist_get_store(wgt->store);
+		store = wgt->store;
 		raw_data = gtk_selection_data_get_data(sel_data);
 		src_path =	gtk_tree_path_new_from_string
 				((const gchar *)raw_data);
@@ -418,7 +431,7 @@ static void drag_data_received_handler(	GtkWidget *widget,
 		}
 
 		g_signal_emit_by_name(	wgt,
-					"row-reordered",
+					"rows-reordered",
 					src_index+(src_index>dest_index),
 					dest_index+!insert_before );
 
@@ -467,17 +480,27 @@ static void row_activated_handler(	GtkTreeView *tree_view,
 	g_signal_emit_by_name(data, "row-activated", index);
 }
 
-static void row_deleted_handler(GmpvPlaylist *pl, gint pos, gpointer data)
+static void row_inserted_handler(	GtkTreeModel *tree_model,
+					GtkTreePath *path,
+					GtkTreeIter *iter,
+					gpointer data )
 {
-	g_signal_emit_by_name(data, "row-deleted", pos);
+	const gint pos = gtk_tree_path_get_indices(path)[0];
+
+	GMPV_PLAYLIST_WIDGET(data)->playlist_count++;
+	g_signal_emit_by_name(data, "row-inserted", pos);
+	g_object_notify(data, "playlist-count");
 }
 
-static void row_reodered_handler(	GmpvPlaylist *pl,
-					gint src,
-					gint dest,
+static void row_deleted_handler(	GtkTreeModel *tree_model,
+					GtkTreePath *path,
 					gpointer data )
 {
-	g_signal_emit_by_name(data, "row-reordered", src, dest);
+	const gint pos = gtk_tree_path_get_indices(path)[0];
+
+	GMPV_PLAYLIST_WIDGET(data)->playlist_count--;
+	g_signal_emit_by_name(data, "row-deleted", pos);
+	g_object_notify(data, "playlist-count");
 }
 
 static gboolean mouse_press_handler(	GtkWidget *widget,
@@ -534,7 +557,6 @@ static gchar *get_uri_selected(GmpvPlaylistWidget *wgt)
 {
 	GtkTreeIter iter;
 	GtkTreePath *path = NULL;
-	GtkTreeModel *model = NULL;
 	gchar *result = NULL;
 	gboolean rc = FALSE;
 
@@ -542,14 +564,16 @@ static gchar *get_uri_selected(GmpvPlaylistWidget *wgt)
 
 	if(path)
 	{
-		model = GTK_TREE_MODEL(gmpv_playlist_get_store(wgt->store));
-		rc = gtk_tree_model_get_iter(model, &iter, path);
+		rc =	gtk_tree_model_get_iter
+			(GTK_TREE_MODEL(wgt->store), &iter, path);
 	}
 
 	if(rc)
 	{
-		gtk_tree_model_get
-			(model, &iter, PLAYLIST_URI_COLUMN, &result, -1);
+		gtk_tree_model_get(	GTK_TREE_MODEL(wgt->store),
+					&iter,
+					PLAYLIST_URI_COLUMN, &result,
+					-1 );
 	}
 
 	return result;
@@ -560,16 +584,19 @@ static void gmpv_playlist_widget_class_init(GmpvPlaylistWidgetClass *klass)
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 	GParamSpec *pspec = NULL;
 
-	obj_class->constructed = gmpv_playlist_widget_constructed;
-	obj_class->set_property = gmpv_playlist_widget_set_property;
-	obj_class->get_property = gmpv_playlist_widget_get_property;
+	obj_class->constructed = constructed;
+	obj_class->set_property = set_property;
+	obj_class->get_property = get_property;
 
-	pspec = g_param_spec_pointer
-		(	"store",
-			"Store",
-			"GmpvPlaylist used to store playlist items",
-			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
-	g_object_class_install_property(obj_class, PROP_STORE, pspec);
+	pspec = g_param_spec_int64
+		(	"playlist-count",
+			"Playlist count",
+			"The number of items in the playlist",
+			0,
+			G_MAXINT64,
+			0,
+			G_PARAM_READABLE );
+	g_object_class_install_property(obj_class, PROP_PLAYLIST_COUNT, pspec);
 
 	g_signal_new(	"row-activated",
 			G_TYPE_FROM_CLASS(klass),
@@ -581,6 +608,16 @@ static void gmpv_playlist_widget_class_init(GmpvPlaylistWidgetClass *klass)
 			G_TYPE_NONE,
 			1,
 			G_TYPE_INT );
+	g_signal_new(	"row-inserted",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__INT,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_INT );
 	g_signal_new(	"row-deleted",
 			G_TYPE_FROM_CLASS(klass),
 			G_SIGNAL_RUN_FIRST,
@@ -591,7 +628,7 @@ static void gmpv_playlist_widget_class_init(GmpvPlaylistWidgetClass *klass)
 			G_TYPE_NONE,
 			1,
 			G_TYPE_INT );
-	g_signal_new(	"row-reordered",
+	g_signal_new(	"rows-reordered",
 			G_TYPE_FROM_CLASS(klass),
 			G_SIGNAL_RUN_FIRST,
 			0,
@@ -606,6 +643,7 @@ static void gmpv_playlist_widget_class_init(GmpvPlaylistWidgetClass *klass)
 
 static void gmpv_playlist_widget_init(GmpvPlaylistWidget *wgt)
 {
+	wgt->playlist_count = 0;
 	wgt->title_renderer = gtk_cell_renderer_text_new();
 	wgt->title_column
 		= gtk_tree_view_column_new_with_attributes
@@ -622,16 +660,44 @@ static void gmpv_playlist_widget_init(GmpvPlaylistWidget *wgt)
 		(wgt->title_column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
 }
 
-GtkWidget *gmpv_playlist_widget_new(GmpvPlaylist *store)
+GtkWidget *gmpv_playlist_widget_new()
 {
-	return GTK_WIDGET(g_object_new(	gmpv_playlist_widget_get_type(),
-					"store", store,
-					NULL ));
+	return GTK_WIDGET(g_object_new(gmpv_playlist_widget_get_type(), NULL));
+}
+
+gboolean gmpv_playlist_widget_empty(GmpvPlaylistWidget *wgt)
+{
+	GtkTreeIter iter;
+
+	return !gtk_tree_model_get_iter_first(GTK_TREE_MODEL(wgt->store), &iter);
+}
+
+void gmpv_playlist_widget_set_indicator_pos(	GmpvPlaylistWidget *wgt,
+							gint pos )
+{
+	GtkTreeIter iter;
+	gboolean rc;
+
+	rc = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(wgt->store), &iter);
+
+	while(rc)
+	{
+		const PangoWeight weight =	(pos-- == 0)?
+						PANGO_WEIGHT_BOLD:
+						PANGO_WEIGHT_NORMAL;
+
+		gtk_list_store_set(	wgt->store,
+					&iter,
+					PLAYLIST_WEIGHT_COLUMN, weight,
+					-1 );
+
+		rc = gtk_tree_model_iter_next(GTK_TREE_MODEL(wgt->store), &iter);
+	}
 }
 
 void gmpv_playlist_widget_remove_selected(GmpvPlaylistWidget *wgt)
 {
-	GtkTreePath *path;
+	GtkTreePath *path = NULL;
 
 	gtk_tree_view_get_cursor
 		(	GTK_TREE_VIEW(wgt->tree_view),
@@ -640,15 +706,15 @@ void gmpv_playlist_widget_remove_selected(GmpvPlaylistWidget *wgt)
 
 	if(path)
 	{
-		gint index;
-		gchar *index_str;
-
-		index = gtk_tree_path_get_indices(path)[0];
-		index_str = g_strdup_printf("%d", index);
+		GtkTreeIter iter;
+		GtkTreeModel *model;
 
-		gmpv_playlist_remove(wgt->store, index);
+		model = GTK_TREE_MODEL(wgt->store);
 
-		g_free(index_str);
+		if(gtk_tree_model_get_iter(model, &iter, path))
+		{
+			gtk_list_store_remove(wgt->store, &iter);
+		}
 	}
 }
 
@@ -658,7 +724,117 @@ void gmpv_playlist_widget_queue_draw(GmpvPlaylistWidget *wgt)
 	gtk_widget_queue_draw(wgt->tree_view);
 }
 
-GmpvPlaylist *gmpv_playlist_widget_get_store(GmpvPlaylistWidget *wgt)
+void gmpv_playlist_widget_update_contents(	GmpvPlaylistWidget *wgt,
+						GPtrArray* playlist )
+{
+	GtkListStore *store = wgt->store;
+	gboolean iter_end = FALSE;
+	GtkTreeIter iter;
+
+	g_assert(playlist);
+
+	iter_end = !gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
+
+	for(guint i = 0; i < playlist->len; i++)
+	{
+		GmpvPlaylistEntry *entry = g_ptr_array_index(playlist, i);
+		gchar *uri = entry->filename;
+		gchar *title = entry->title;
+		gchar *name = title?g_strdup(title):get_name_from_path(uri);
+
+		/* Overwrite current entry if it doesn't match the new value */
+		if(!iter_end)
+		{
+			gchar *old_name = NULL;
+			gchar *old_uri = NULL;
+			gboolean name_update;
+			gboolean uri_update;
+
+			gtk_tree_model_get
+				(	GTK_TREE_MODEL(store), &iter,
+					PLAYLIST_NAME_COLUMN, &old_name,
+					PLAYLIST_URI_COLUMN, &old_uri, -1 );
+
+			name_update = (g_strcmp0(name, old_name) != 0);
+			uri_update = (g_strcmp0(uri, old_uri) != 0);
+
+			/* Only set the name if either the title can be
+			 * retrieved or the name is unset. This preserves the
+			 * correct title if it becomes unavailable later such as
+			 * when restarting mpv.
+			 */
+			if(name_update && (!old_name || title || uri_update))
+			{
+				gtk_list_store_set
+					(	store, &iter,
+						PLAYLIST_NAME_COLUMN, name, -1 );
+			}
+
+			if(uri_update)
+			{
+				gtk_list_store_set
+					(	store, &iter,
+						PLAYLIST_URI_COLUMN, uri, -1 );
+			}
+
+			iter_end = !gtk_tree_model_iter_next
+					(GTK_TREE_MODEL(store), &iter);
+
+			g_free(old_name);
+			g_free(old_uri);
+		}
+		/* Append entries to the playlist if there are fewer entries in
+		 * the playlist widget than given playlist.
+		 */
+		else
+		{
+			gtk_list_store_append(store, &iter);
+			gtk_list_store_set(	store, &iter,
+						PLAYLIST_NAME_COLUMN, name,
+						-1 );
+			gtk_list_store_set(	store, &iter,
+						PLAYLIST_URI_COLUMN, uri,
+						-1 );
+		}
+
+		g_free(name);
+	}
+
+	/* If there are more entries in the playlist widget than given playlist,
+	 * remove the excess entries from the playlist widget.
+	 */
+	if(!iter_end)
+	{
+		while(gtk_list_store_remove(store, &iter));
+	}
+}
+
+GPtrArray *gmpv_playlist_widget_get_contents(GmpvPlaylistWidget *wgt)
 {
-	return wgt->store;
+	gboolean rc = TRUE;
+	GtkTreeModel *model = GTK_TREE_MODEL(wgt->store);
+	GtkTreeIter iter;
+	GPtrArray *result = NULL;
+
+	rc = gtk_tree_model_get_iter_first(model, &iter);
+	result = g_ptr_array_new_full(	1,
+					(GDestroyNotify)
+					gmpv_playlist_entry_free );
+
+	while(rc)
+	{
+		gchar *uri = NULL;
+		gchar *name = NULL;
+
+		gtk_tree_model_get(	model, &iter,
+					PLAYLIST_URI_COLUMN, &uri,
+					PLAYLIST_NAME_COLUMN, &name,
+					-1 );
+
+		g_ptr_array_add(result, gmpv_playlist_entry_new(uri, name));
+
+		rc = gtk_tree_model_iter_next(model, &iter);
+	}
+
+	return result;
 }
diff --git a/src/gmpv_playlist_widget.h b/src/gmpv_playlist_widget.h
index 6e8a5dc..19e1a0b 100644
--- a/src/gmpv_playlist_widget.h
+++ b/src/gmpv_playlist_widget.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -24,18 +24,20 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include "gmpv_playlist.h"
-
 G_BEGIN_DECLS
 
 #define GMPV_TYPE_PLAYLIST_WIDGET (gmpv_playlist_widget_get_type ())
 
 G_DECLARE_FINAL_TYPE(GmpvPlaylistWidget, gmpv_playlist_widget, GMPV, PLAYLIST_WIDGET, GtkScrolledWindow)
 
-GtkWidget *gmpv_playlist_widget_new(GmpvPlaylist *store);
+GtkWidget *gmpv_playlist_widget_new(void);
+gboolean gmpv_playlist_widget_empty(GmpvPlaylistWidget *wgt);
+void gmpv_playlist_widget_set_indicator_pos(GmpvPlaylistWidget *wgt, gint pos);
 void gmpv_playlist_widget_remove_selected(GmpvPlaylistWidget *wgt);
 void gmpv_playlist_widget_queue_draw(GmpvPlaylistWidget *wgt);
-GmpvPlaylist *gmpv_playlist_widget_get_store(GmpvPlaylistWidget *wgt);
+void gmpv_playlist_widget_update_contents(	GmpvPlaylistWidget *wgt,
+						GPtrArray* playlist );
+GPtrArray *gmpv_playlist_widget_get_contents(GmpvPlaylistWidget *wgt);
 
 G_END_DECLS
 
diff --git a/src/gmpv_plugins_manager.c b/src/gmpv_plugins_manager.c
index c77c9ac..90b1916 100644
--- a/src/gmpv_plugins_manager.c
+++ b/src/gmpv_plugins_manager.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -21,6 +21,7 @@
 
 #include "gmpv_plugins_manager.h"
 #include "gmpv_plugins_manager_item.h"
+#include "gmpv_file_chooser.h"
 #include "gmpv_common.h"
 
 enum
@@ -140,13 +141,19 @@ static void add_handler(GtkButton *button, gpointer data)
 
 	dialog = gmpv_file_chooser_new(	_("Add Lua Script"),
 					pmgr->parent_window,
-					GTK_FILE_CHOOSER_ACTION_OPEN,
-					_("Open"),
-					_("Cancel") );
-	filter = gtk_file_filter_new();
+					GTK_FILE_CHOOSER_ACTION_OPEN );
+	filter = NULL;
 	chooser = GTK_FILE_CHOOSER(dialog);
 
+	filter = gtk_file_filter_new();
+	gtk_file_filter_set_name(filter, _("All Files"));
+	gtk_file_filter_add_pattern(filter, "*");
+	gtk_file_chooser_add_filter(chooser, filter);
+
+	filter = gtk_file_filter_new();
+	gtk_file_filter_set_name(filter, _("Lua Scripts"));
 	gtk_file_filter_add_mime_type(filter, "text/x-lua");
+	gtk_file_chooser_add_filter(chooser, filter);
 	gtk_file_chooser_set_filter(chooser, filter);
 
 	if(gmpv_file_chooser_run(dialog) == GTK_RESPONSE_ACCEPT)
diff --git a/src/gmpv_pref_dialog.c b/src/gmpv_pref_dialog.c
index f818063..1a14bee 100644
--- a/src/gmpv_pref_dialog.c
+++ b/src/gmpv_pref_dialog.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 gnome-mpv
+ * Copyright (c) 2014-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -292,6 +292,9 @@ static void gmpv_pref_dialog_init(GmpvPrefDialog *dlg)
 			{_("Enable dark theme"),
 			"dark-theme-enable",
 			ITEM_TYPE_CHECK_BOX},
+			{_("Use floating controls in windowed mode"),
+			"always-use-floating-controls",
+			ITEM_TYPE_CHECK_BOX},
 			{_("Remember last file's location"),
 			"last-folder-enable",
 			ITEM_TYPE_CHECK_BOX},
diff --git a/src/gmpv_shortcuts_window.c b/src/gmpv_shortcuts_window.c
index a40bc86..7af28fe 100644
--- a/src/gmpv_shortcuts_window.c
+++ b/src/gmpv_shortcuts_window.c
@@ -55,6 +55,8 @@ static void gmpv_shortcuts_window_init(GmpvShortcutsWindow *wnd)
 	const ShortcutEntry general[]
 		= {	{"<Ctrl>o", _("Open file")},
 			{"<Ctrl>l", _("Open location")},
+			{"<Ctrl><Shift>o", _("Add file to playlist")},
+			{"<Ctrl><Shift>l", _("Add location to playlist")},
 			{"<Ctrl>p", _("Show preferences dialog")},
 			{"<Ctrl>h", _("Toggle controls")},
 			{"F9", _("Toggle playlist")},
diff --git a/src/gmpv_shortcuts_window.h b/src/gmpv_shortcuts_window.h
index 78d50a3..9ebd865 100644
--- a/src/gmpv_shortcuts_window.h
+++ b/src/gmpv_shortcuts_window.h
@@ -20,6 +20,8 @@
 #ifndef SHORTCUTS_WINDOW_H
 #define SHORTCUTS_WINDOW_H
 
+#if GTK_CHECK_VERSION(3, 20, 0)
+
 #include <glib.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
@@ -35,3 +37,5 @@ GtkWidget *gmpv_shortcuts_window_new(GtkWindow *parent);
 G_END_DECLS
 
 #endif
+
+#endif
diff --git a/src/gmpv_track.c b/src/gmpv_track.c
deleted file mode 100644
index dbbfabb..0000000
--- a/src/gmpv_track.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2015 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "gmpv_track.h"
-
-GmpvTrack *gmpv_track_new(void)
-{
-	GmpvTrack *entry = g_malloc(sizeof(GmpvTrack));
-
-	entry->type = TRACK_TYPE_INVALID;
-	entry->title = NULL;
-	entry->lang = NULL;
-	entry->id = 0;
-
-	return entry;
-}
-
-void gmpv_track_free(GmpvTrack *entry)
-{
-	if(entry)
-	{
-		g_free(entry->title);
-		g_free(entry->lang);
-		g_free(entry);
-	}
-}
diff --git a/src/gmpv_track.h b/src/gmpv_track.h
deleted file mode 100644
index 6810a4a..0000000
--- a/src/gmpv_track.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2015 gnome-mpv
- *
- * This file is part of GNOME MPV.
- *
- * GNOME MPV is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GNOME MPV is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRACK_H
-#define TRACK_H
-
-#include <glib.h>
-
-typedef enum TrackType TrackType;
-typedef struct GmpvTrack GmpvTrack;
-
-enum TrackType
-{
-	TRACK_TYPE_INVALID,
-	TRACK_TYPE_AUDIO,
-	TRACK_TYPE_VIDEO,
-	TRACK_TYPE_SUBTITLE
-};
-
-struct GmpvTrack
-{
-	TrackType type;
-	gint64 id;
-	gchar *title;
-	gchar *lang;
-};
-
-GmpvTrack *gmpv_track_new(void);
-void gmpv_track_free(GmpvTrack *entry);
-
-#endif
diff --git a/src/gmpv_video_area.c b/src/gmpv_video_area.c
index 586548f..6a9dbbf 100644
--- a/src/gmpv_video_area.c
+++ b/src/gmpv_video_area.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -30,6 +30,13 @@
 #include <gdk/gdkx.h>
 #endif
 
+enum
+{
+	PROP_0,
+	PROP_TITLE,
+	N_PROPERTIES
+};
+
 struct _GmpvVideoArea
 {
 	GtkOverlay parent_instance;
@@ -50,6 +57,14 @@ struct _GmpvVideoAreaClass
 	GtkOverlayClass parent_class;
 };
 
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
 static void set_cursor_visible(GmpvVideoArea *area, gboolean visible);
 static gboolean timeout_handler(gpointer data);
 static gboolean motion_notify_handler(GtkWidget *widget, GdkEventMotion *event);
@@ -59,6 +74,48 @@ static gboolean fs_control_crossing_handler(	GtkWidget *widget,
 
 G_DEFINE_TYPE(GmpvVideoArea, gmpv_video_area, GTK_TYPE_OVERLAY)
 
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvVideoArea *self = GMPV_VIDEO_AREA(object);
+
+	switch(property_id)
+	{
+		case PROP_TITLE:
+		g_object_set_property(	G_OBJECT(self->header_bar),
+					pspec->name,
+					value );
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvVideoArea *self = GMPV_VIDEO_AREA(object);
+
+	switch(property_id)
+	{
+		case PROP_TITLE:
+		g_object_get_property(	G_OBJECT(self->header_bar),
+					pspec->name,
+					value );
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
 static void set_cursor_visible(GmpvVideoArea *area, gboolean visible)
 {
 	GdkWindow *window;
@@ -87,21 +144,29 @@ static gboolean timeout_handler(gpointer data)
 	GmpvControlBox *control_box = GMPV_CONTROL_BOX(area->control_box);
 	GmpvHeaderBar *header_bar = GMPV_HEADER_BAR(area->header_bar);
 
-	if(area->fullscreen
+	if(control_box
 	&& !area->fs_control_hover
 	&& !gmpv_control_box_get_volume_popup_visible(control_box)
 	&& !gmpv_header_bar_get_open_button_popup_visible(header_bar)
 	&& !gmpv_header_bar_get_menu_button_popup_visible(header_bar))
 	{
-		set_cursor_visible(area, FALSE);
 		gtk_revealer_set_reveal_child
 			(GTK_REVEALER(area->control_box_revealer), FALSE);
 		gtk_revealer_set_reveal_child
 			(GTK_REVEALER(area->header_bar_revealer), FALSE);
 
+		set_cursor_visible(area, !area->fullscreen);
+		area->timeout_tag = 0;
+	}
+	else if(!control_box)
+	{
 		area->timeout_tag = 0;
 	}
 
+	/* Try again later if timeout_tag has not been cleared. This means that
+	 * either one of the popups is visible or the cursor is hovering over
+	 * the control box, preventing it from being hidden.
+	 */
 	return (area->timeout_tag != 0);
 }
 
@@ -113,12 +178,12 @@ static gboolean motion_notify_handler(GtkWidget *widget, GdkEventMotion *event)
 	cursor = gdk_cursor_new_from_name(gdk_display_get_default(), "default");
 	gdk_window_set_cursor(gtk_widget_get_window(widget), cursor);
 
-	if(area->fullscreen)
+	if(area->control_box)
 	{
 		gtk_revealer_set_reveal_child
 			(GTK_REVEALER(area->control_box_revealer), TRUE);
 		gtk_revealer_set_reveal_child
-			(GTK_REVEALER(area->header_bar_revealer), TRUE);
+			(GTK_REVEALER(area->header_bar_revealer), area->fullscreen);
 	}
 
 	if(area->timeout_tag > 0)
@@ -134,6 +199,15 @@ static gboolean motion_notify_handler(GtkWidget *widget, GdkEventMotion *event)
 		->motion_notify_event(widget, event);
 }
 
+static gboolean render_handler(	GtkGLArea *gl_area,
+				GdkGLContext *context,
+				gpointer data )
+{
+	g_signal_emit_by_name(data, "render");
+
+	return FALSE;
+}
+
 static void notify_handler(	GObject *gobject,
 				GParamSpec *pspec,
 				gpointer data )
@@ -168,9 +242,31 @@ static gboolean fs_control_crossing_handler(	GtkWidget *widget,
 
 static void gmpv_video_area_class_init(GmpvVideoAreaClass *klass)
 {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 	GtkWidgetClass *wgt_class = GTK_WIDGET_CLASS(klass);
+	GParamSpec *pspec = NULL;
 
+	obj_class->set_property = set_property;
+	obj_class->get_property = get_property;
 	wgt_class->motion_notify_event = motion_notify_handler;
+
+	g_signal_new(	"render",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+
+	pspec = g_param_spec_string
+		(	"title",
+			"Title",
+			"The title of the header bar",
+			NULL,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(obj_class, PROP_TITLE, pspec);
 }
 
 static void gmpv_video_area_init(GmpvVideoArea *area)
@@ -224,6 +320,10 @@ static void gmpv_video_area_init(GmpvVideoArea *area)
 	gtk_widget_hide(area->header_bar_revealer);
 	gtk_widget_set_no_show_all(area->header_bar_revealer, TRUE);
 
+	g_signal_connect(	area->gl_area,
+				"render",
+				G_CALLBACK(render_handler),
+				area );
 	g_signal_connect(	area->header_bar_revealer,
 				"notify::reveal-child",
 				G_CALLBACK(notify_handler),
@@ -259,15 +359,10 @@ GtkWidget *gmpv_video_area_new()
 }
 
 void gmpv_video_area_update_track_list(	GmpvVideoArea *area,
-					const GSList *audio_list,
-					const GSList *video_list,
-					const GSList *sub_list )
+					const GPtrArray *track_list )
 {
 	gmpv_header_bar_update_track_list
-		(	GMPV_HEADER_BAR(area->header_bar),
-			audio_list,
-			video_list,
-			sub_list );
+		(GMPV_HEADER_BAR(area->header_bar), track_list);
 }
 
 void gmpv_video_area_set_fullscreen_state(	GmpvVideoArea *area,
@@ -277,7 +372,6 @@ void gmpv_video_area_set_fullscreen_state(	GmpvVideoArea *area,
 	{
 		area->fullscreen = fullscreen;
 
-		gtk_widget_set_visible(area->control_box_revealer, fullscreen);
 		gtk_widget_hide(area->header_bar_revealer);
 		set_cursor_visible(area, !fullscreen);
 
@@ -322,6 +416,11 @@ void gmpv_video_area_set_use_opengl(GmpvVideoArea *area, gboolean use_opengl)
 			use_opengl?area->gl_area:area->draw_area );
 }
 
+void gmpv_video_area_queue_render(GmpvVideoArea *area)
+{
+	gtk_gl_area_queue_render(GTK_GL_AREA(area->gl_area));
+}
+
 GtkDrawingArea *gmpv_video_area_get_draw_area(GmpvVideoArea *area)
 {
 	return GTK_DRAWING_AREA(area->draw_area);
diff --git a/src/gmpv_video_area.h b/src/gmpv_video_area.h
index 2550908..b3626db 100644
--- a/src/gmpv_video_area.h
+++ b/src/gmpv_video_area.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2016-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -30,14 +30,13 @@ G_DECLARE_FINAL_TYPE(GmpvVideoArea, gmpv_video_area, GMPV, VIDEO_AREA, GtkOverla
 
 GtkWidget *gmpv_video_area_new(void);
 void gmpv_video_area_update_track_list(	GmpvVideoArea *hdr,
-					const GSList *audio_list,
-					const GSList *video_list,
-					const GSList *sub_list );
+					const GPtrArray *track_list );
 void gmpv_video_area_set_fullscreen_state(	GmpvVideoArea *area,
 						gboolean fullscreen );
 void gmpv_video_area_set_control_box(	GmpvVideoArea *area,
 					GtkWidget *control_box );
 void gmpv_video_area_set_use_opengl(GmpvVideoArea *area, gboolean use_opengl);
+void gmpv_video_area_queue_render(GmpvVideoArea *area);
 GtkDrawingArea *gmpv_video_area_get_draw_area(GmpvVideoArea *area);
 GtkGLArea *gmpv_video_area_get_gl_area(GmpvVideoArea *area);
 gint64 gmpv_video_area_get_xid(GmpvVideoArea *area);
diff --git a/src/gmpv_view.c b/src/gmpv_view.c
new file mode 100644
index 0000000..f7028f0
--- /dev/null
+++ b/src/gmpv_view.c
@@ -0,0 +1,1566 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "gmpv_view.h"
+#include "gmpv_file_chooser.h"
+#include "gmpv_open_location_dialog.h"
+#include "gmpv_pref_dialog.h"
+#include "gmpv_shortcuts_window.h"
+#include "gmpv_authors.h"
+#include "gmpv_marshal.h"
+#include "gmpv_common.h"
+#include "gmpv_def.h"
+
+enum
+{
+	PROP_0,
+	PROP_WINDOW,
+	PROP_PLAYLIST_COUNT,
+	PROP_PAUSE,
+	PROP_TITLE,
+	PROP_VOLUME,
+	PROP_DURATION,
+	PROP_PLAYLIST_POS,
+	PROP_TRACK_LIST,
+	PROP_CHAPTERS_ENABLED,
+	PROP_CONTROL_BOX_ENABLED,
+	PROP_FULLSCREEN,
+	N_PROPERTIES
+};
+
+struct _GmpvView
+{
+	GObject parent;
+	GmpvMainWindow *wnd;
+
+	/* Properties */
+	gint playlist_count;
+	gboolean pause;
+	gchar *title;
+	gdouble volume;
+	gdouble duration;
+	gint playlist_pos;
+	GPtrArray *track_list;
+	gboolean chapters_enabled;
+	gboolean control_box_enabled;
+	gboolean fullscreen;
+};
+
+struct _GmpvViewClass
+{
+	GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE(GmpvView, gmpv_view, G_TYPE_OBJECT)
+
+static void constructed(GObject *object);
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static void load_css(GmpvView *view);
+static void save_playlist(GmpvView *view, GFile *file, GError **error);
+static void show_message_dialog(	GmpvMainWindow *wnd,
+					GtkMessageType type,
+					const gchar *title,
+					const gchar *prefix,
+					const gchar *msg );
+
+/* Property changes */
+static void play_button_handler(GtkButton *button, gpointer data);
+static void stop_button_handler(GtkButton *button, gpointer data);
+static void next_button_handler(GtkButton *button, gpointer data);
+static void previous_button_handler(GtkButton *button, gpointer data);
+static void forward_button_handler(GtkButton *button, gpointer data);
+static void rewind_button_handler(GtkButton *button, gpointer data);
+static void seek_handler(GtkWidget *widget, gdouble value,  gpointer data);
+
+/* Dialog responses */
+static void open_dialog_response_handler(	GtkDialog *dialog,
+						gint response_id,
+						gpointer data );
+static void open_location_dialog_response_handler(	GtkDialog *dialog,
+							gint response_id,
+							gpointer data );
+static void open_audio_track_dialog_response_handler(	GtkDialog *dialog,
+							gint response_id,
+							gpointer data );
+static void open_subtitle_track_dialog_response_handler(	GtkDialog *dialog,
+								gint response_id,
+								gpointer data );
+static void preferences_dialog_response_handler(	GtkDialog *dialog,
+							gint response_id,
+							gpointer data );
+
+/* User inputs */
+static void key_press_handler(	GmpvMainWindow *wnd,
+				GdkEvent *event,
+				gpointer data );
+static void key_release_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data );
+static void button_press_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data );
+static void button_release_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data );
+static void motion_notify_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data );
+static void scroll_handler(	GmpvMainWindow *wnd,
+				GdkEvent *event,
+				gpointer data );
+
+static void render_handler(GmpvVideoArea *area, gpointer data);
+static gboolean draw_handler(GtkWidget *widget, cairo_t *cr, gpointer data);
+static void drag_data_handler(	GtkWidget *widget,
+				GdkDragContext *context,
+				gint x,
+				gint y,
+				GtkSelectionData *sel_data,
+				guint info,
+				guint time,
+				gpointer data );
+static gboolean window_state_handler(	GtkWidget *widget,
+					GdkEvent *event,
+					gpointer data );
+static void grab_handler(GtkWidget *widget, gboolean was_grabbed, gpointer data);
+static gboolean delete_handler(	GtkWidget *widget,
+				GdkEvent *event,
+				gpointer data );
+static void playlist_row_activated_handler(	GmpvPlaylistWidget *playlist,
+						gint64 pos,
+						gpointer data );
+static void playlist_row_inserted_handler(	GmpvPlaylistWidget *widget,
+						gint pos,
+						gpointer data );
+static void playlist_row_deleted_handler(	GmpvPlaylistWidget *widget,
+						gint pos,
+						gpointer data );
+static void playlist_row_reordered_handler(	GmpvPlaylistWidget *widget,
+						gint src,
+						gint dest,
+						gpointer data );
+
+static void constructed(GObject *object)
+{
+	GmpvView *view = GMPV_VIEW(object);
+	GmpvVideoArea *video_area = gmpv_main_window_get_video_area(view->wnd);
+	GmpvPlaylistWidget *playlist = gmpv_main_window_get_playlist(view->wnd);
+	GmpvControlBox *control_box;
+	GSettings *settings = g_settings_new(CONFIG_ROOT);
+	gboolean csd_enable;
+	gboolean dark_theme_enable;
+
+	csd_enable = g_settings_get_boolean
+				(settings, "csd-enable");
+	dark_theme_enable = g_settings_get_boolean
+				(settings, "dark-theme-enable");
+	control_box = gmpv_main_window_get_control_box(view->wnd);
+
+	gmpv_main_window_load_state(view->wnd);
+	load_css(view);
+	gtk_widget_show_all(GTK_WIDGET(view->wnd));
+
+	if(csd_enable)
+	{
+		gmpv_control_box_set_fullscreen_button_visible(control_box, FALSE);
+	}
+
+	gmpv_control_box_set_chapter_enabled(control_box, FALSE);
+
+	g_object_set(	gtk_settings_get_default(),
+			"gtk-application-prefer-dark-theme",
+			dark_theme_enable,
+			NULL );
+
+	g_object_unref(settings);
+
+	g_object_bind_property(	view, "title",
+				view->wnd, "title",
+				G_BINDING_DEFAULT );
+	g_object_bind_property(	view, "volume",
+				control_box, "volume",
+				G_BINDING_BIDIRECTIONAL );
+	g_object_bind_property(	playlist, "playlist-count",
+				view, "playlist-count",
+				G_BINDING_DEFAULT );
+
+	g_signal_connect(	control_box,
+				"play-button-clicked",
+				G_CALLBACK(play_button_handler),
+				view );
+	g_signal_connect(	control_box,
+				"stop-button-clicked",
+				G_CALLBACK(stop_button_handler),
+				view );
+	g_signal_connect(	control_box,
+				"next-button-clicked",
+				G_CALLBACK(next_button_handler),
+				view );
+	g_signal_connect(	control_box,
+				"previous-button-clicked",
+				G_CALLBACK(previous_button_handler),
+				view );
+	g_signal_connect(	control_box,
+				"forward-button-clicked",
+				G_CALLBACK(forward_button_handler),
+				view );
+	g_signal_connect(	control_box,
+				"rewind-button-clicked",
+				G_CALLBACK(rewind_button_handler),
+				view );
+	g_signal_connect(	control_box,
+				"seek",
+				G_CALLBACK(seek_handler),
+				view );
+
+	g_signal_connect(	view->wnd,
+				"key-press-event",
+				G_CALLBACK(key_press_handler),
+				view );
+	g_signal_connect(	view->wnd,
+				"key-release-event",
+				G_CALLBACK(key_release_handler),
+				view );
+	g_signal_connect(	video_area,
+				"render",
+				G_CALLBACK(render_handler),
+				view );
+	g_signal_connect(	video_area,
+				"button-press-event",
+				G_CALLBACK(button_press_handler),
+				view );
+	g_signal_connect(	video_area,
+				"button-release-event",
+				G_CALLBACK(button_release_handler),
+				view );
+	g_signal_connect(	video_area,
+				"motion-notify-event",
+				G_CALLBACK(motion_notify_handler),
+				view );
+	g_signal_connect(	video_area,
+				"scroll-event",
+				G_CALLBACK(scroll_handler),
+				view );
+
+	g_signal_connect_after(	view->wnd,
+				"draw",
+				G_CALLBACK(draw_handler),
+				view );
+	g_signal_connect(	video_area,
+				"drag-data-received",
+				G_CALLBACK(drag_data_handler),
+				view );
+	g_signal_connect(	playlist,
+				"drag-data-received",
+				G_CALLBACK(drag_data_handler),
+				view );
+	g_signal_connect(	view->wnd,
+				"window-state-event",
+				G_CALLBACK(window_state_handler),
+				view );
+	g_signal_connect(	view->wnd,
+				"grab-notify",
+				G_CALLBACK(grab_handler),
+				view );
+	g_signal_connect(	view->wnd,
+				"delete-event",
+				G_CALLBACK(delete_handler),
+				view );
+	g_signal_connect(	playlist,
+				"row-activated",
+				G_CALLBACK(playlist_row_activated_handler),
+				view );
+	g_signal_connect(	playlist,
+				"row-inserted",
+				G_CALLBACK(playlist_row_inserted_handler),
+				view );
+	g_signal_connect(	playlist,
+				"row-deleted",
+				G_CALLBACK(playlist_row_deleted_handler),
+				view );
+	g_signal_connect(	playlist,
+				"rows-reordered",
+				G_CALLBACK(playlist_row_reordered_handler),
+				view );
+}
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvView *self = GMPV_VIEW(object);
+	GmpvControlBox* control_box = NULL;
+
+	if(self->wnd)
+	{
+		 control_box = gmpv_main_window_get_control_box(self->wnd);
+	}
+
+	switch(property_id)
+	{
+		case PROP_WINDOW:
+		self->wnd = g_value_get_pointer(value);
+		break;
+
+		case PROP_PLAYLIST_COUNT:
+		self->playlist_count = g_value_get_int(value);
+		gmpv_control_box_set_enabled
+			(control_box, self->playlist_count > 0);
+
+		if(self->playlist_count <= 0)
+		{
+			gmpv_view_reset(self);
+		}
+		break;
+
+		case PROP_PAUSE:
+		self->pause = g_value_get_boolean(value);
+		gmpv_control_box_set_playing_state(control_box, !self->pause);
+		break;
+
+		case PROP_TITLE:
+		g_free(self->title);
+		self->title = g_value_dup_string(value);
+		break;
+
+		case PROP_VOLUME:
+		self->volume = g_value_get_double(value);
+		break;
+
+		case PROP_DURATION:
+		self->duration = g_value_get_double(value);
+		gmpv_control_box_set_seek_bar_duration
+			(control_box, (gint)self->duration);
+		break;
+
+		case PROP_PLAYLIST_POS:
+		self->playlist_pos = g_value_get_int(value);
+		GmpvPlaylistWidget *playlist = gmpv_main_window_get_playlist(self->wnd);
+		gmpv_playlist_widget_set_indicator_pos(playlist, self->playlist_pos);
+		break;
+
+		case PROP_TRACK_LIST:
+		self->track_list = g_value_get_pointer(value);
+		gmpv_main_window_update_track_list(self->wnd, self->track_list);
+		break;
+
+		case PROP_CHAPTERS_ENABLED:
+		self->chapters_enabled = g_value_get_boolean(value);
+		gmpv_control_box_set_chapter_enabled
+			(control_box, self->chapters_enabled);
+		break;
+
+		case PROP_CONTROL_BOX_ENABLED:
+		self->control_box_enabled = g_value_get_boolean(value);
+		gmpv_control_box_set_enabled
+			(control_box, self->control_box_enabled);
+		break;
+
+		case PROP_FULLSCREEN:
+		self->fullscreen = g_value_get_boolean(value);
+		gmpv_main_window_set_fullscreen(self->wnd, self->fullscreen);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvView *self = GMPV_VIEW(object);
+
+	switch(property_id)
+	{
+		case PROP_WINDOW:
+		g_value_set_pointer(value, self->wnd);
+		break;
+
+		case PROP_PLAYLIST_COUNT:
+		g_value_set_int(value, self->playlist_count);
+		break;
+
+		case PROP_PAUSE:
+		g_value_set_boolean(value, self->pause);
+		break;
+
+		case PROP_TITLE:
+		g_value_set_string(value, self->title);
+		break;
+
+		case PROP_VOLUME:
+		g_value_set_double(value, self->volume);
+		break;
+
+		case PROP_DURATION:
+		g_value_set_double(value, self->duration);
+		break;
+
+		case PROP_PLAYLIST_POS:
+		g_value_set_int(value, self->playlist_pos);
+		break;
+
+		case PROP_TRACK_LIST:
+		g_value_set_pointer(value, self->track_list);
+		break;
+
+		case PROP_CHAPTERS_ENABLED:
+		g_value_set_boolean(value, self->chapters_enabled);
+		break;
+
+		case PROP_CONTROL_BOX_ENABLED:
+		g_value_set_boolean(value, self->control_box_enabled);
+		break;
+
+		case PROP_FULLSCREEN:
+		g_value_set_boolean(value, self->fullscreen);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void load_css(GmpvView *view)
+{
+	const gchar *style;
+	GtkCssProvider *style_provider;
+	gboolean css_loaded;
+
+	style = ".gmpv-vid-area{background-color: black}";
+	style_provider = gtk_css_provider_new();
+	css_loaded =	gtk_css_provider_load_from_data
+			(style_provider, style, -1, NULL);
+
+	if(!css_loaded)
+	{
+		g_warning ("Failed to apply background color css");
+	}
+
+	gtk_style_context_add_provider_for_screen
+		(	gtk_window_get_screen(GTK_WINDOW(view->wnd)),
+			GTK_STYLE_PROVIDER(style_provider),
+			GTK_STYLE_PROVIDER_PRIORITY_APPLICATION );
+
+	g_object_unref(style_provider);
+}
+
+static void save_playlist(GmpvView *view, GFile *file, GError **error)
+{
+	GmpvPlaylistWidget *wgt = gmpv_main_window_get_playlist(view->wnd);
+	GPtrArray *playlist = gmpv_playlist_widget_get_contents(wgt);
+	gboolean rc = TRUE;
+	GOutputStream *dest_stream = NULL;
+
+	if(file)
+	{
+		GFileOutputStream *file_stream;
+
+		file_stream = g_file_replace(	file,
+						NULL,
+						FALSE,
+						G_FILE_CREATE_NONE,
+						NULL,
+						error );
+		dest_stream = G_OUTPUT_STREAM(file_stream);
+		rc = !!dest_stream;
+	}
+
+	for(guint i = 0; rc && i < playlist->len; i++)
+	{
+		gsize written;
+
+		GmpvPlaylistEntry *entry = g_ptr_array_index(playlist, i);
+
+		rc = g_output_stream_printf(	dest_stream,
+						&written,
+						NULL,
+						NULL,
+						"%s\n",
+						entry->filename);
+	}
+
+	if(dest_stream)
+	{
+		g_output_stream_close(dest_stream, NULL, error);
+	}
+
+	g_ptr_array_free(playlist, TRUE);
+}
+
+void show_message_dialog(	GmpvMainWindow *wnd,
+				GtkMessageType type,
+				const gchar *title,
+				const gchar *prefix,
+				const gchar *msg )
+{
+	GtkWidget *dialog;
+	GtkWidget *msg_area;
+	GList *children;
+
+	if(prefix)
+	{
+		gchar *prefix_escaped = g_markup_printf_escaped("%s", prefix);
+		gchar *msg_escaped = g_markup_printf_escaped("%s", msg);
+
+		dialog =	gtk_message_dialog_new_with_markup
+				(	GTK_WINDOW(wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					type,
+					GTK_BUTTONS_OK,
+					"<b>[%s]</b> %s",
+					prefix_escaped,
+					msg_escaped );
+
+		g_free(prefix_escaped);
+		g_free(msg_escaped);
+	}
+	else
+	{
+		dialog =	gtk_message_dialog_new
+				(	GTK_WINDOW(wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					type,
+					GTK_BUTTONS_OK,
+					"%s",
+					msg );
+	}
+
+	msg_area =	gtk_message_dialog_get_message_area
+			(GTK_MESSAGE_DIALOG(dialog));
+	children = gtk_container_get_children(GTK_CONTAINER(msg_area));
+
+	for(GList *iter = children; iter; iter = g_list_next(iter))
+	{
+		if(GTK_IS_LABEL(iter->data))
+		{
+			gtk_label_set_line_wrap_mode
+				(GTK_LABEL(iter->data), PANGO_WRAP_WORD_CHAR);
+		}
+	}
+
+	g_list_free(children);
+
+	g_signal_connect(	dialog,
+				"response",
+				G_CALLBACK(gtk_widget_destroy),
+				NULL );
+
+	gtk_window_set_title(GTK_WINDOW(dialog), title);
+	gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+	gtk_widget_show_all(dialog);
+}
+
+static void play_button_handler(GtkButton *button, gpointer data)
+{
+	g_signal_emit_by_name(data, "button-clicked::play");
+}
+
+static void stop_button_handler(GtkButton *button, gpointer data)
+{
+	g_signal_emit_by_name(data, "button-clicked::stop");
+}
+
+static void next_button_handler(GtkButton *button, gpointer data)
+{
+	g_signal_emit_by_name(data, "button-clicked::next");
+}
+
+static void previous_button_handler(GtkButton *button, gpointer data)
+{
+	g_signal_emit_by_name(data, "button-clicked::previous");
+}
+
+static void forward_button_handler(GtkButton *button, gpointer data)
+{
+	g_signal_emit_by_name(data, "button-clicked::forward");
+}
+
+static void rewind_button_handler(GtkButton *button, gpointer data)
+{
+	g_signal_emit_by_name(data, "button-clicked::rewind");
+}
+
+static void seek_handler(GtkWidget *widget, gdouble value, gpointer data)
+{
+	g_signal_emit_by_name(data, "seek", value);
+}
+
+static void open_dialog_response_handler(	GtkDialog *dialog,
+						gint response_id,
+						gpointer data )
+{
+	GPtrArray *args = data;
+	GmpvView *view = g_ptr_array_index(args, 0);
+	gboolean *append = g_ptr_array_index(args, 1);
+
+	if(response_id == GTK_RESPONSE_ACCEPT)
+	{
+		GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
+		GSList *uri_slist = gtk_file_chooser_get_filenames(chooser);
+
+		if(uri_slist)
+		{
+			const gchar **uris = gslist_to_array(uri_slist);
+
+			g_signal_emit_by_name(view, "file-open", uris, *append);
+			g_free(uris);
+		}
+
+		g_slist_free_full(uri_slist, g_free);
+	}
+
+	gmpv_file_chooser_destroy(dialog);
+
+	g_free(append);
+	g_ptr_array_free(args, TRUE);
+}
+
+static void open_location_dialog_response_handler(	GtkDialog *dialog,
+							gint response_id,
+							gpointer data )
+{
+	GPtrArray *args = data;
+	GmpvView *view = g_ptr_array_index(args, 0);
+	gboolean *append = g_ptr_array_index(args, 1);
+
+	if(response_id == GTK_RESPONSE_ACCEPT)
+	{
+		GmpvOpenLocationDialog *location_dialog;
+		const gchar *uris[2];
+
+		location_dialog = GMPV_OPEN_LOCATION_DIALOG(dialog);
+		uris[0] = gmpv_open_location_dialog_get_string(location_dialog);
+		uris[1] = NULL;
+
+		g_signal_emit_by_name(view, "file-open", uris, *append);
+	}
+
+	gtk_widget_destroy(GTK_WIDGET(dialog));
+
+	g_free(append);
+	g_ptr_array_free(args, TRUE);
+}
+
+static void open_audio_track_dialog_response_handler(	GtkDialog *dialog,
+							gint response_id,
+							gpointer data )
+{
+	if(response_id == GTK_RESPONSE_ACCEPT)
+	{
+		GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
+		GSList *uri_list = gtk_file_chooser_get_filenames(chooser);
+
+		for(GSList *iter = uri_list; iter; iter = g_slist_next(iter))
+		{
+			g_signal_emit_by_name(data, "audio-track-load", *iter);
+		}
+
+		g_slist_free_full(uri_list, g_free);
+	}
+
+	gmpv_file_chooser_destroy(GMPV_FILE_CHOOSER(dialog));
+}
+
+static void open_subtitle_track_dialog_response_handler(	GtkDialog *dialog,
+								gint response_id,
+								gpointer data )
+{
+	if(response_id == GTK_RESPONSE_ACCEPT)
+	{
+		GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
+		GSList *uri_list = gtk_file_chooser_get_filenames(chooser);
+
+		for(GSList *iter = uri_list; iter; iter = g_slist_next(iter))
+		{
+			g_signal_emit_by_name(data, "subtitle-track-load", *iter);
+		}
+
+		g_slist_free_full(uri_list, g_free);
+	}
+
+	gmpv_file_chooser_destroy(GMPV_FILE_CHOOSER(dialog));
+}
+
+static void preferences_dialog_response_handler(	GtkDialog *dialog,
+							gint response_id,
+							gpointer data )
+{
+	if(response_id == GTK_RESPONSE_ACCEPT)
+	{
+		GmpvView *view;
+		GSettings *settings;
+		gboolean csd_enable;
+		gboolean dark_theme_enable;
+		gboolean always_floating;
+
+		view = data;
+		settings = g_settings_new(CONFIG_ROOT);
+		csd_enable = g_settings_get_boolean(settings, "csd-enable");
+		dark_theme_enable =	g_settings_get_boolean
+					(settings, "dark-theme-enable");
+		always_floating =	g_settings_get_boolean
+					(settings, "always-use-floating-controls");
+
+		if(gmpv_main_window_get_csd_enabled(view->wnd) != csd_enable)
+		{
+			show_message_dialog(	view->wnd,
+						GTK_MESSAGE_INFO,
+						g_get_application_name(),
+						NULL,
+						_("Enabling or disabling "
+						"client-side decorations "
+						"requires restarting to "
+						"take effect.") );
+		}
+
+		g_object_set(	gtk_settings_get_default(),
+				"gtk-application-prefer-dark-theme",
+				dark_theme_enable,
+				NULL );
+		g_object_set(	view->wnd,
+				"always-use-floating-controls",
+				always_floating,
+				NULL );
+
+		gtk_widget_queue_draw(GTK_WIDGET(view->wnd));
+		g_signal_emit_by_name(data, "preferences-updated");
+
+		g_object_unref(settings);
+	}
+
+	gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+static void key_press_handler(	GmpvMainWindow *wnd,
+				GdkEvent *event,
+				gpointer data )
+{
+	g_signal_emit_by_name(data, "key-press-event", event);
+}
+
+static void key_release_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data )
+{
+	g_signal_emit_by_name(data, "key-release-event", event);
+}
+
+static void button_press_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data )
+{
+	g_signal_emit_by_name(data, "button-press-event", event);
+}
+
+static void button_release_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data )
+{
+	g_signal_emit_by_name(data, "button-release-event", event);
+}
+
+static void motion_notify_handler(	GmpvMainWindow *wnd,
+					GdkEvent *event,
+					gpointer data )
+{
+	g_signal_emit_by_name(data, "motion-notify-event", event);
+}
+
+static void scroll_handler(	GmpvMainWindow *wnd,
+				GdkEvent *event,
+				gpointer data )
+{
+	g_signal_emit_by_name(data, "scroll-event", event);
+}
+
+static void render_handler(GmpvVideoArea *area, gpointer data)
+{
+	g_signal_emit_by_name(data, "render");
+}
+
+static gboolean draw_handler(GtkWidget *widget, cairo_t *cr, gpointer data)
+{
+	GmpvView *view = data;
+	GmpvPlaylistWidget *playlist = gmpv_main_window_get_playlist(view->wnd);
+	guint signal_id = g_signal_lookup("draw", GMPV_TYPE_MAIN_WINDOW);
+
+	g_signal_handlers_disconnect_matched(	widget,
+						G_SIGNAL_MATCH_ID|
+						G_SIGNAL_MATCH_DATA,
+						signal_id,
+						0,
+						0,
+						NULL,
+						view );
+
+	if(gmpv_playlist_widget_empty(playlist))
+	{
+		GmpvControlBox *control_box;
+
+		control_box = gmpv_main_window_get_control_box(view->wnd);
+
+		gmpv_control_box_set_enabled(control_box, FALSE);
+	}
+
+	g_signal_emit_by_name(view, "ready");
+
+	return FALSE;
+}
+
+static void drag_data_handler(	GtkWidget *widget,
+				GdkDragContext *context,
+				gint x,
+				gint y,
+				GtkSelectionData *sel_data,
+				guint info,
+				guint time,
+				gpointer data )
+{
+	GmpvView *view = data;
+	gchar *type = gdk_atom_name(gtk_selection_data_get_target(sel_data));
+	const guchar *raw_data = gtk_selection_data_get_data(sel_data);
+	gchar **uri_list = gtk_selection_data_get_uris(sel_data);
+	gboolean append = GMPV_IS_PLAYLIST_WIDGET(widget);
+
+	if(g_strcmp0(type, "PLAYLIST_PATH") == 0)
+	{
+		GtkTreePath *path =	gtk_tree_path_new_from_string
+					((const gchar *)raw_data);
+		gint pos = gtk_tree_path_get_indices(path)[0];
+
+		g_assert(path);
+
+		g_signal_emit_by_name(view, "playlist-item-activated", pos);
+
+		gtk_tree_path_free(path);
+	}
+	else
+	{
+		if(!uri_list)
+		{
+			uri_list = g_malloc(2*sizeof(gchar *));
+			uri_list[0] = g_strdup((gchar *)raw_data);
+			uri_list[1] = NULL;
+		}
+
+		g_signal_emit_by_name(view, "file-open", uri_list, append);
+	}
+
+	g_strfreev(uri_list);
+	g_free(type);
+}
+
+static gboolean window_state_handler(	GtkWidget *widget,
+					GdkEvent *event,
+					gpointer data )
+{
+	GmpvView *view = data;
+	GdkEventWindowState *state = (GdkEventWindowState *)event;
+
+	if(state->changed_mask&GDK_WINDOW_STATE_FULLSCREEN)
+	{
+		view->fullscreen =	state->new_window_state&
+					GDK_WINDOW_STATE_FULLSCREEN;
+
+		g_object_notify(data, "fullscreen");
+	}
+
+	return FALSE;
+}
+
+static void grab_handler(GtkWidget *widget, gboolean was_grabbed, gpointer data)
+{
+	g_signal_emit_by_name(data, "grab-notify", was_grabbed);
+}
+
+static gboolean delete_handler(	GtkWidget *widget,
+				GdkEvent *event,
+				gpointer data )
+{
+	if(!gmpv_main_window_get_fullscreen(GMPV_MAIN_WINDOW(widget)))
+	{
+		gmpv_main_window_save_state(GMPV_MAIN_WINDOW(widget));
+	}
+
+	g_signal_emit_by_name(data, "delete-notify");
+
+	return TRUE;
+}
+
+static void playlist_row_activated_handler(	GmpvPlaylistWidget *playlist,
+						gint64 pos,
+						gpointer data )
+{
+	g_signal_emit_by_name(data, "playlist-item-activated", pos);
+}
+
+static void playlist_row_inserted_handler(	GmpvPlaylistWidget *widget,
+						gint pos,
+						gpointer data )
+{
+	g_signal_emit_by_name(data, "playlist-item-inserted", pos);
+}
+
+static void playlist_row_deleted_handler(	GmpvPlaylistWidget *widget,
+						gint pos,
+						gpointer data )
+{
+	if(gmpv_playlist_widget_empty(widget))
+	{
+		gmpv_view_reset(data);
+	}
+
+	g_signal_emit_by_name(data, "playlist-item-deleted", pos);
+}
+
+static void playlist_row_reordered_handler(	GmpvPlaylistWidget *widget,
+						gint src,
+						gint dest,
+						gpointer data )
+{
+	g_signal_emit_by_name(data, "playlist-reordered", src, dest);
+}
+
+static void gmpv_view_class_init(GmpvViewClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	object_class->constructed = constructed;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+
+	pspec = g_param_spec_pointer
+		(	"window",
+			"Window",
+			"The GmpvMainWindow to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_WINDOW, pspec);
+
+	pspec = g_param_spec_int
+		(	"playlist-count",
+			"Playlist count",
+			"The number of items in playlist",
+			0,
+			G_MAXINT,
+			0,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_PLAYLIST_COUNT, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"pause",
+			"Pause",
+			"Whether or not the player is paused",
+			FALSE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_PAUSE, pspec);
+
+	pspec = g_param_spec_string
+		(	"title",
+			"Title",
+			"The title of the window",
+			_("GNOME MPV"),
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_TITLE, pspec);
+
+	pspec = g_param_spec_double
+		(	"volume",
+			"Volume",
+			"The volume the volume button is set to",
+			0.0,
+			G_MAXDOUBLE,
+			0.0,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_VOLUME, pspec);
+
+	pspec = g_param_spec_double
+		(	"duration",
+			"Duration",
+			"The duration the seek bar is using",
+			0.0,
+			G_MAXDOUBLE,
+			0.0,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_DURATION, pspec);
+
+	pspec = g_param_spec_int
+		(	"playlist-pos",
+			"Playlist position",
+			"The position of the current item in playlist",
+			0,
+			G_MAXINT,
+			0,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_PLAYLIST_POS, pspec);
+
+	pspec = g_param_spec_pointer
+		(	"track-list",
+			"Track list",
+			"The list of tracks in the playing file",
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_TRACK_LIST, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"chapters-enabled",
+			"Chapters enabled",
+			"Whether or not the chapter controls are enabled",
+			FALSE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_CHAPTERS_ENABLED, pspec);
+
+	pspec = g_param_spec_boolean
+		(	"fullscreen",
+			"Fullscreen",
+			"Whether or not the player is current in fullscreen mode",
+			FALSE,
+			G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_FULLSCREEN, pspec);
+
+	/* Controls-related signals */
+	g_signal_new(	"button-clicked",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST|G_SIGNAL_DETAILED,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"seek",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__DOUBLE,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_DOUBLE );
+	g_signal_new(	"volume-changed",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__DOUBLE,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_DOUBLE );
+
+	/* User input signals */
+	g_signal_new(	"key-press-event",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER);
+	g_signal_new(	"key-release-event",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER );
+	g_signal_new(	"button-press-event",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER );
+	g_signal_new(	"button-release-event",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER );
+	g_signal_new(	"motion-notify-event",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER );
+	g_signal_new(	"scroll-event",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER );
+
+	g_signal_new(	"ready",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"render",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"preferences-updated",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"audio-track-load",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__STRING,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_STRING );
+	g_signal_new(	"subtitle-track-load",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__STRING,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_STRING );
+	g_signal_new(	"file-open",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_gen_marshal_VOID__POINTER_BOOLEAN,
+			G_TYPE_NONE,
+			2,
+			G_TYPE_POINTER,
+			G_TYPE_BOOLEAN );
+	g_signal_new(	"grab-notify",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__BOOLEAN,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_BOOLEAN );
+	g_signal_new(	"delete-notify",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__VOID,
+			G_TYPE_NONE,
+			0 );
+	g_signal_new(	"playlist-item-activated",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__INT,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_INT );
+	g_signal_new(	"playlist-item-inserted",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__INT,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_INT );
+	g_signal_new(	"playlist-item-deleted",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__INT,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_INT );
+	g_signal_new(	"playlist-reordered",
+			G_TYPE_FROM_CLASS(klass),
+			G_SIGNAL_RUN_FIRST,
+			0,
+			NULL,
+			NULL,
+			g_cclosure_gen_marshal_VOID__INT_INT,
+			G_TYPE_NONE,
+			2,
+			G_TYPE_INT,
+			G_TYPE_INT );
+}
+
+static void gmpv_view_init(GmpvView *view)
+{
+	view->wnd = NULL;
+	view->playlist_count = 0;
+	view->pause = FALSE;
+	view->title = NULL;
+	view->volume = 0.0;
+	view->duration = 0.0;
+	view->playlist_pos = 0;
+	view->chapters_enabled = FALSE;
+	view->fullscreen = FALSE;
+}
+
+GmpvView *gmpv_view_new(GmpvMainWindow *wnd)
+{
+	return GMPV_VIEW(g_object_new(	gmpv_view_get_type(),
+					"window", wnd,
+					NULL ));
+}
+
+GmpvMainWindow *gmpv_view_get_main_window(GmpvView *view)
+{
+	return view->wnd;
+}
+
+void gmpv_view_show_open_dialog(GmpvView *view, gboolean append)
+{
+	GmpvFileChooser *chooser;
+	GPtrArray *args;
+	gboolean *append_buf;
+
+	chooser = gmpv_file_chooser_new(	append?
+						_("Add File to Playlist"):
+						_("Open File"),
+						GTK_WINDOW(view->wnd),
+						GTK_FILE_CHOOSER_ACTION_OPEN );
+	args = g_ptr_array_new();
+	append_buf = g_malloc(sizeof(gboolean));
+	*append_buf = append;
+
+	g_ptr_array_add(args, view);
+	g_ptr_array_add(args, append_buf);
+
+	g_signal_connect(	chooser,
+				"response",
+				G_CALLBACK(open_dialog_response_handler),
+				args );
+
+	gmpv_file_chooser_set_default_filters(chooser, TRUE, TRUE, TRUE, TRUE);
+	gmpv_file_chooser_show(chooser);
+}
+
+void gmpv_view_show_open_location_dialog(GmpvView *view, gboolean append)
+{
+	GtkWidget *dlg;
+	GPtrArray *args;
+	gboolean *append_buf;
+
+	dlg = gmpv_open_location_dialog_new(	GTK_WINDOW(view->wnd),
+						append?
+						_("Add Location to Playlist"):
+						_("Open Location") );
+	args = g_ptr_array_sized_new(2);
+	append_buf = g_malloc(sizeof(gboolean));
+
+	*append_buf = append;
+
+	g_ptr_array_add(args, view);
+	g_ptr_array_add(args, append_buf);
+
+	g_signal_connect
+		(	dlg,
+			"response",
+			G_CALLBACK(open_location_dialog_response_handler),
+			args );
+
+	gtk_widget_show_all(dlg);
+}
+
+void gmpv_view_show_open_audio_track_dialog(GmpvView *view)
+{
+	GmpvFileChooser *chooser =	gmpv_file_chooser_new
+					(	_("Load Audio Track…"),
+						GTK_WINDOW(view->wnd),
+						GTK_FILE_CHOOSER_ACTION_OPEN );
+
+	g_signal_connect
+		(	chooser,
+			"response",
+			G_CALLBACK(open_audio_track_dialog_response_handler),
+			view );
+
+	gmpv_file_chooser_set_default_filters
+		(chooser, TRUE, FALSE, FALSE, FALSE);
+
+	gmpv_file_chooser_show(chooser);
+}
+
+void gmpv_view_show_open_subtitle_track_dialog(GmpvView *view)
+{
+	GmpvFileChooser *chooser =	gmpv_file_chooser_new
+					(	_("Load Subtitle Track…"),
+						GTK_WINDOW(view->wnd),
+						GTK_FILE_CHOOSER_ACTION_OPEN );
+
+	g_signal_connect
+		(	chooser,
+			"response",
+			G_CALLBACK(open_subtitle_track_dialog_response_handler),
+			view );
+
+	gmpv_file_chooser_set_default_filters
+		(chooser, FALSE, FALSE, FALSE, TRUE);
+
+	gmpv_file_chooser_show(chooser);
+}
+
+void gmpv_view_show_save_playlist_dialog(GmpvView *view)
+{
+	GFile *dest_file;
+	GmpvFileChooser *file_chooser;
+	GtkFileChooser *gtk_chooser;
+	GError *error;
+
+	dest_file = NULL;
+	file_chooser =	gmpv_file_chooser_new
+			(	_("Save Playlist"),
+				GTK_WINDOW(view->wnd),
+				GTK_FILE_CHOOSER_ACTION_SAVE );
+	gtk_chooser = GTK_FILE_CHOOSER(file_chooser);
+	error = NULL;
+
+	gtk_file_chooser_set_current_name(gtk_chooser, "playlist.m3u");
+
+	if(gmpv_file_chooser_run(file_chooser) == GTK_RESPONSE_ACCEPT)
+	{
+		/* There should be only one file selected. */
+		dest_file = gtk_file_chooser_get_file(gtk_chooser);
+	}
+
+	gmpv_file_chooser_destroy(file_chooser);
+
+	if(dest_file)
+	{
+		save_playlist(view, dest_file, &error);
+		g_object_unref(dest_file);
+	}
+
+	if(error)
+	{
+		show_message_dialog(	view->wnd,
+					GTK_MESSAGE_ERROR,
+					_("Error"),
+					NULL,
+					error->message );
+
+		g_error_free(error);
+	}
+}
+
+void gmpv_view_show_preferences_dialog(GmpvView *view)
+{
+	GtkWidget *pref_dialog = gmpv_pref_dialog_new(GTK_WINDOW(view->wnd));
+
+	g_signal_connect_after(	pref_dialog,
+				"response",
+				G_CALLBACK(preferences_dialog_response_handler),
+				view );
+
+	gtk_widget_show_all(pref_dialog);
+}
+
+void gmpv_view_show_shortcuts_dialog(GmpvView *view)
+{
+#if GTK_CHECK_VERSION(3, 20, 0)
+	GtkWidget *wnd = gmpv_shortcuts_window_new(GTK_WINDOW(view->wnd));
+
+	gtk_widget_show_all(wnd);
+#endif
+}
+
+void gmpv_view_show_about_dialog(GmpvView *view)
+{
+	const gchar *const authors[] = AUTHORS;
+
+	gtk_show_about_dialog(	GTK_WINDOW(view->wnd),
+				"logo-icon-name",
+				ICON_NAME,
+				"version",
+				VERSION,
+				"comments",
+				_("A GTK frontend for MPV"),
+				"website",
+				"https://github.com/gnome-mpv/gnome-mpv",
+				"license-type",
+				GTK_LICENSE_GPL_3_0,
+				"copyright",
+				"\u00A9 2014-2017 The GNOME MPV authors",
+				"authors",
+				authors,
+				"translator-credits",
+				_("translator-credits"),
+				NULL );
+}
+
+void gmpv_view_show_message_dialog(	GmpvView *view,
+					GtkMessageType type,
+					const gchar *title,
+					const gchar *prefix,
+					const gchar *msg )
+{
+	show_message_dialog(view->wnd, type, title, prefix, msg);
+}
+
+void gmpv_view_present(GmpvView *view)
+{
+	gtk_window_present(GTK_WINDOW(view->wnd));
+}
+
+void gmpv_view_quit(GmpvView *view)
+{
+	gtk_window_close(GTK_WINDOW(view->wnd));
+}
+
+void gmpv_view_reset(GmpvView *view)
+{
+	gmpv_main_window_reset(view->wnd);
+}
+
+void gmpv_view_queue_render(GmpvView *view)
+{
+	GmpvVideoArea *area = gmpv_main_window_get_video_area(view->wnd);
+
+	gmpv_video_area_queue_render(area);
+}
+
+void gmpv_view_make_gl_context_current(GmpvView *view)
+{
+	GmpvVideoArea *video_area = gmpv_main_window_get_video_area(view->wnd);
+	GtkGLArea *gl_area = gmpv_video_area_get_gl_area(video_area);
+
+	gtk_widget_realize(GTK_WIDGET(gl_area));
+	gtk_gl_area_make_current(gl_area);
+}
+
+void gmpv_view_set_use_opengl_cb(GmpvView *view, gboolean use_opengl_cb)
+{
+	GmpvVideoArea *area = gmpv_main_window_get_video_area(view->wnd);
+
+	gmpv_video_area_set_use_opengl(area, use_opengl_cb);
+}
+
+gint gmpv_view_get_scale_factor(GmpvView *view)
+{
+	GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(view->wnd));
+
+	return gdk_window_get_scale_factor(gdk_window);
+}
+
+void gmpv_view_get_video_area_geometry(GmpvView *view, gint *width, gint *height)
+{
+	GmpvVideoArea *area = gmpv_main_window_get_video_area(view->wnd);
+	GtkAllocation allocation;
+
+	gtk_widget_get_allocation(GTK_WIDGET(area), &allocation);
+
+	*width = allocation.width;
+	*height = allocation.height;
+}
+
+void gmpv_view_resize_video_area(GmpvView *view, gint width, gint height)
+{
+	gmpv_main_window_resize_video_area(view->wnd, width, height);
+}
+
+void gmpv_view_set_fullscreen(GmpvView *view, gboolean fullscreen)
+{
+	g_object_set(view, "fullscreen", fullscreen, NULL);
+	gmpv_main_window_set_fullscreen(view->wnd, fullscreen);
+}
+
+void gmpv_view_set_time_position(GmpvView *view, gdouble position)
+{
+	GmpvControlBox *control_box;
+
+	control_box = gmpv_main_window_get_control_box(view->wnd);
+	gmpv_control_box_set_seek_bar_pos(control_box, position);
+}
+
+void gmpv_view_update_playlist(GmpvView *view, GPtrArray *playlist)
+{
+	if(playlist)
+	{
+		GmpvPlaylistWidget *pl = gmpv_main_window_get_playlist(view->wnd);
+
+		gmpv_playlist_widget_update_contents(pl, playlist);
+	}
+}
+
+void gmpv_view_set_playlist_pos(GmpvView *view, gint64 pos)
+{
+	g_object_set(view, "playlist-pos", pos, NULL);
+}
diff --git a/src/gmpv_view.h b/src/gmpv_view.h
new file mode 100644
index 0000000..caae668
--- /dev/null
+++ b/src/gmpv_view.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef VIEW_H
+#define VIEW_H
+
+#include <glib.h>
+
+#include "gmpv_application.h"
+
+G_BEGIN_DECLS
+
+#define GMPV_TYPE_VIEW (gmpv_view_get_type())
+
+G_DECLARE_FINAL_TYPE(GmpvView, gmpv_view, GMPV, VIEW, GObject)
+
+GmpvView *gmpv_view_new(GmpvMainWindow *wnd);
+GmpvMainWindow *gmpv_view_get_main_window(GmpvView *view);
+void gmpv_view_show_open_dialog(GmpvView *view, gboolean append);
+void gmpv_view_show_open_location_dialog(GmpvView *view, gboolean append);
+void gmpv_view_show_open_audio_track_dialog(GmpvView *view);
+void gmpv_view_show_open_subtitle_track_dialog(GmpvView *view);
+void gmpv_view_show_save_playlist_dialog(GmpvView *view);
+void gmpv_view_show_preferences_dialog(GmpvView *view);
+void gmpv_view_show_shortcuts_dialog(GmpvView *view);
+void gmpv_view_show_about_dialog(GmpvView *view);
+void gmpv_view_show_message_dialog(	GmpvView *view,
+					GtkMessageType type,
+					const gchar *title,
+					const gchar *prefix,
+					const gchar *msg );
+void gmpv_view_present(GmpvView *view);
+void gmpv_view_quit(GmpvView *view);
+void gmpv_view_reset(GmpvView *view);
+void gmpv_view_queue_render(GmpvView *view);
+void gmpv_view_make_gl_context_current(GmpvView *view);
+void gmpv_view_set_use_opengl_cb(GmpvView *view, gboolean use_opengl_cb);
+gint gmpv_view_get_scale_factor(GmpvView *view);
+void gmpv_view_get_video_area_geometry(GmpvView *view, gint *width, gint *height);
+void gmpv_view_resize_video_area(GmpvView *view, gint width, gint height);
+void gmpv_view_set_fullscreen(GmpvView *view, gboolean fullscreen);
+void gmpv_view_set_time_position(GmpvView *view, gdouble position);
+void gmpv_view_update_playlist(GmpvView *view, GPtrArray *playlist);
+void gmpv_view_set_playlist_pos(GmpvView *view, gint64 pos);
+
+G_END_DECLS
+
+#endif
diff --git a/src/media_keys/gmpv_media_keys.c b/src/media_keys/gmpv_media_keys.c
index 46312c4..564667d 100644
--- a/src/media_keys/gmpv_media_keys.c
+++ b/src/media_keys/gmpv_media_keys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -21,10 +21,10 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
+#include "gmpv_application_private.h"
 #include "gmpv_main_window.h"
 #include "gmpv_media_keys.h"
-#include "gmpv_mpv.h"
-#include "gmpv_mpv_wrapper.h"
+#include "gmpv_model.h"
 #include "gmpv_def.h"
 
 static gboolean delete_handler(	GtkWidget *widget,
@@ -100,49 +100,38 @@ static void media_key_press_handler(	GDBusProxy *proxy,
 
 	if(g_strcmp0(gmpv_application, APP_ID) == 0)
 	{
-		GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
+		GmpvModel *model = GMPV_APPLICATION(inst->gmpv_ctx)->model;
 
 		if(g_strcmp0(key, "Next") == 0)
 		{
-			const gchar *cmd[] = {"playlist_next", "weak", NULL};
-
-			gmpv_mpv_command(mpv, cmd);
+			gmpv_model_next_playlist_entry(model);
 		}
 		else if(g_strcmp0(key, "Previous") == 0)
 		{
-			const gchar *cmd[] = {"playlist_prev", "weak", NULL};
-
-			gmpv_mpv_command(mpv, cmd);
+			gmpv_model_previous_playlist_entry(model);
 		}
 		else if(g_strcmp0(key, "Pause") == 0)
 		{
-			gmpv_mpv_set_property_flag(mpv, "pause", TRUE);
+			gmpv_model_pause(model);
 		}
 		else if(g_strcmp0(key, "Stop") == 0)
 		{
-			const gchar *cmd[] = {"stop", NULL};
-
-			gmpv_mpv_command(mpv, cmd);
+			gmpv_model_stop(model);
 		}
 		else if(g_strcmp0(key, "Play") == 0)
 		{
-			gboolean paused;
-
-			paused = gmpv_mpv_get_property_flag(mpv, "pause");
+			gboolean pause = FALSE;
 
-			gmpv_mpv_set_property_flag(mpv, "pause", !paused);
+			g_object_get(model, "pause", &pause, NULL);
+			(pause?gmpv_model_play:gmpv_model_pause)(model);
 		}
 		else if(g_strcmp0(key, "FastForward") == 0)
 		{
-			const gchar *cmd[] = {"seek", "10", NULL};
-
-			gmpv_mpv_command(mpv, cmd);
+			gmpv_model_forward(model);
 		}
 		else if(g_strcmp0(key, "Rewind") == 0)
 		{
-			const gchar *cmd[] = {"seek", "-10", NULL};
-
-			gmpv_mpv_command(mpv, cmd);
+			gmpv_model_rewind(model);
 		}
 	}
 }
@@ -168,7 +157,7 @@ static void proxy_ready_handler(	GObject *source_object,
 				-1,
 				NULL,
 				NULL,
-				inst );
+				NULL );
 }
 
 static void session_ready_handler(	GObject *source_object,
@@ -179,6 +168,22 @@ static void session_ready_handler(	GObject *source_object,
 
 	inst->session_bus_conn = g_bus_get_finish(res, NULL);
 
+	/* The MediaKeys plugin for gnome-settings-daemon <= 3.24.1 used the
+	 * bus name org.gnome.SettingsDaemon despite the documentation stating
+	 * that org.gnome.SettingsDaemon.MediaKeys should be used.
+	 * gnome-settings-daemon > 3.24.1 changed the bus name to match the
+	 * documentation. To remain compatible with older versions, create
+	 * proxies for both names.
+	 */
+	g_dbus_proxy_new(	inst->session_bus_conn,
+				G_DBUS_PROXY_FLAGS_NONE,
+				NULL,
+				"org.gnome.SettingsDaemon.MediaKeys",
+				"/org/gnome/SettingsDaemon/MediaKeys",
+				"org.gnome.SettingsDaemon.MediaKeys",
+				NULL,
+				proxy_ready_handler,
+				inst );
 	g_dbus_proxy_new(	inst->session_bus_conn,
 				G_DBUS_PROXY_FLAGS_NONE,
 				NULL,
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..d2ee9dd
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,125 @@
+gnome = import('gnome')
+
+sources = [
+  'gmpv_application.c',
+  'gmpv_application_action.c',
+  'gmpv_common.c',
+  'gmpv_control_box.c',
+  'gmpv_controller.c',
+  'gmpv_controller_input.c',
+  'gmpv_file_chooser.c',
+  'gmpv_header_bar.c',
+  'gmpv_main.c',
+  'gmpv_main_window.c',
+  'gmpv_menu.c',
+  'gmpv_model.c',
+  'gmpv_mpv.c',
+  'gmpv_mpv_opt.c',
+  'gmpv_mpv_wrapper.c',
+  'gmpv_open_location_dialog.c',
+  'gmpv_playlist_widget.c',
+  'gmpv_plugins_manager.c',
+  'gmpv_plugins_manager_item.c',
+  'gmpv_pref_dialog.c',
+  'gmpv_seek_bar.c',
+  'gmpv_shortcuts_window.c',
+  'gmpv_video_area.c',
+  'gmpv_view.c',
+
+  'media_keys/gmpv_media_keys.c',
+
+  'mpris/gmpv_mpris.c',
+  'mpris/gmpv_mpris_module.c',
+  'mpris/gmpv_mpris_base.c',
+  'mpris/gmpv_mpris_player.c',
+  'mpris/gmpv_mpris_track_list.c'
+]
+
+sources += custom_target('authors',
+  input: '../AUTHORS',
+  output: 'gmpv_authors.h',
+  command: [
+    find_program('generate_authors.py'),
+    '@INPUT@', '@OUTPUT@'
+  ]
+)
+
+sources += gnome.genmarshal('gmpv_marshal',
+  sources: '../data/gmpv_marshal.lst',
+  prefix: 'g_cclosure_gen_marshal',
+)
+
+libgtk = dependency('gtk+-3.0', version: '>= 3.18')
+localedir = join_paths(get_option('prefix'), get_option('localedir'))
+cflags = [
+  '-DG_SETTINGS_ENABLE_BACKEND',
+  '-DPACKAGE_LOCALEDIR="@0@"'.format(localedir),
+  '-DVERSION="@0@"'.format(meson.project_version()),
+  '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()),
+  '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_44',
+  '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_44',
+]
+
+if get_option('buildtype') == 'release'
+  cflags += [
+    '-DG_DISABLE_ASSERT=1',
+    '-DG_DISABLE_CHECKS=1',
+    '-DG_DISABLE_CAST_CHECKS=1'
+  ]
+endif
+
+if libgtk.version().version_compare('>= 3.20')
+  cflags += [
+    '-DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_20',
+    '-DGDK_VERSION_MAX_ALLOWED=GDK_VERSION_3_20'
+  ]
+  sources += 'gmpv_shortcuts_window.c'
+else
+  cflags += [
+    '-DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_18',
+    '-DGDK_VERSION_MAX_ALLOWED=GDK_VERSION_3_18'
+  ]
+endif
+
+if target_machine.system() == 'windows'
+  libgio = dependency('gio-2.0', version: '>= 2.44')
+else
+  libgio = dependency('gio-unix-2.0', version: '>= 2.44')
+endif
+
+generated_gdbus_sources = gnome.gdbus_codegen(
+  'gmpv_mpris_gdbus',
+  '../data/gmpv_mpris_gdbus.xml',
+  namespace: 'gmpv_mpris'
+)
+
+includes = []
+extra_libs = []
+if libgio.version().version_compare('<= 2.51.2')
+  # We want to be warning free and due to https://bugzilla.gnome.org/show_bug.cgi?id=778581
+  # gdbus-codegen caused this warning previous to this release.
+  extra_libs += static_library('mpris-gdbus',
+    generated_gdbus_sources,
+    c_args: cflags + ['-Wno-conversion'],
+    dependencies: libgio,
+    include_directories: include_directories('..'),
+  )
+else
+  sources += generated_gdbus_sources
+  # FIXME: Our invocation of `gdbus-codegen` creates an include of `src/...`
+  # https://github.com/mesonbuild/meson/issues/1387
+  includes = include_directories('..')
+endif
+
+executable('gnome-mpv', sources,
+  dependencies: [
+    libgtk,
+    libgio,
+    dependency('mpv', version: '>= 1.20'),
+    dependency('epoxy')
+  ],
+  link_with: extra_libs,
+  include_directories: includes,
+  c_args: cflags,
+  install: true
+)
diff --git a/src/mpris/gmpv_mpris.c b/src/mpris/gmpv_mpris.c
index a52bb20..78ec1c4 100644
--- a/src/mpris/gmpv_mpris.c
+++ b/src/mpris/gmpv_mpris.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -27,7 +27,7 @@
 #include "gmpv_mpris.h"
 #include "gmpv_mpris_base.h"
 #include "gmpv_mpris_player.h"
-#include "gmpv_main_window.h"
+#include "gmpv_mpris_track_list.h"
 #include "gmpv_def.h"
 
 static void name_acquired_handler(	GDBusConnection *connection,
@@ -36,9 +36,7 @@ static void name_acquired_handler(	GDBusConnection *connection,
 static void name_lost_handler(	GDBusConnection *connection,
 				const gchar *name,
 				gpointer data );
-static gboolean delete_handler(	GtkWidget *widget,
-				GdkEvent *event,
-				gpointer data );
+static gboolean shutdown_handler(GtkApplication *app, gpointer data);
 static void unregister(gmpv_mpris *inst);
 
 static void name_acquired_handler(	GDBusConnection *connection,
@@ -48,9 +46,16 @@ static void name_acquired_handler(	GDBusConnection *connection,
 	gmpv_mpris *inst = data;
 
 	inst->session_bus_conn = connection;
-
-	gmpv_mpris_base_register(inst);
-	gmpv_mpris_player_register(inst);
+	inst->base = GMPV_MPRIS_MODULE(gmpv_mpris_base_new(	inst->gmpv_ctx,
+								connection ));
+	inst->player = GMPV_MPRIS_MODULE(gmpv_mpris_player_new(	inst->gmpv_ctx,
+								connection ));
+	inst->track_list = GMPV_MPRIS_MODULE(gmpv_mpris_track_list_new(	inst->gmpv_ctx,
+									connection ));
+
+	gmpv_mpris_module_register_interface(inst->base);
+	gmpv_mpris_module_register_interface(inst->player);
+	gmpv_mpris_module_register_interface(inst->track_list);
 }
 
 static void name_lost_handler(	GDBusConnection *connection,
@@ -60,14 +65,11 @@ static void name_lost_handler(	GDBusConnection *connection,
 	unregister(data);
 }
 
-static gboolean delete_handler(	GtkWidget *widget,
-				GdkEvent *event,
-				gpointer data )
+static gboolean shutdown_handler(GtkApplication *app, gpointer data)
 {
 	gmpv_mpris *inst = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(inst->gmpv_ctx);
 
-	g_signal_handler_disconnect(wnd, inst->shutdown_sig_id);
+	g_signal_handler_disconnect(app, inst->shutdown_sig_id);
 
 	unregister(inst);
 	g_bus_unown_name(inst->name_id);
@@ -78,58 +80,9 @@ static gboolean delete_handler(	GtkWidget *widget,
 
 static void unregister(gmpv_mpris *inst)
 {
-	if(inst->base_reg_id > 0)
-	{
-		gmpv_mpris_base_unregister(inst);
-	}
-
-	if(inst->player_reg_id > 0)
-	{
-		gmpv_mpris_player_unregister(inst);
-	}
-}
-
-void gmpv_mpris_emit_prop_changed(	gmpv_mpris *inst,
-					const gchar *iface_name,
-					const gmpv_mpris_prop *prop_list )
-{
-	const gmpv_mpris_prop *current;
-	GVariantBuilder builder;
-	GVariant *sig_args;
-
-	g_debug("Preparing property change event");
-
-	current = prop_list;
-
-	g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
-
-	while(current && current->name != NULL)
-	{
-		g_debug("Adding property \"%s\"", current->name);
-
-		g_variant_builder_add(	&builder,
-					"{sv}",
-					current->name,
-					current->value );
-
-		current++;
-	}
-
-	sig_args = g_variant_new(	"(sa{sv}as)",
-					iface_name,
-					&builder,
-					NULL );
-
-	g_debug("Emitting property change event on interface %s", iface_name);
-
-	g_dbus_connection_emit_signal
-		(	inst->session_bus_conn,
-			NULL,
-			MPRIS_OBJ_ROOT_PATH,
-			"org.freedesktop.DBus.Properties",
-			"PropertiesChanged",
-			sig_args,
-			NULL );
+	gmpv_mpris_module_unregister_interface(inst->base);
+	gmpv_mpris_module_unregister_interface(inst->player);
+	gmpv_mpris_module_unregister_interface(inst->track_list);
 }
 
 GVariant *gmpv_mpris_build_g_variant_string_array(const gchar** list)
@@ -150,11 +103,9 @@ GVariant *gmpv_mpris_build_g_variant_string_array(const gchar** list)
 void gmpv_mpris_init(GmpvApplication *gmpv_ctx)
 {
 	gmpv_mpris *inst;
-	GmpvMainWindow* main_window;
 	gchar *name;
 
 	inst = g_malloc(sizeof(gmpv_mpris));
-	main_window = gmpv_application_get_main_window(gmpv_ctx);
 
 	/* sizeof(pid_t) can theoretically be larger than sizeof(gint64), but
 	 * even then the chance of collision would be minimal.
@@ -164,20 +115,17 @@ void gmpv_mpris_init(GmpvApplication *gmpv_ctx)
 			ABS((gint64)getpid()) );
 
 	inst->gmpv_ctx = gmpv_ctx;
+	inst->base = NULL;
+	inst->player = NULL;
+	inst->track_list = NULL;
 	inst->name_id = 0;
-	inst->base_reg_id = 0;
-	inst->player_reg_id = 0;
 	inst->shutdown_sig_id = 0;
-	inst->base_sig_id_list = NULL;
-	inst->player_sig_id_list = NULL;
 	inst->pending_seek = -1;
-	inst->base_prop_table = NULL;
-	inst->player_prop_table = NULL;
 	inst->session_bus_conn = NULL;
 	inst->shutdown_sig_id =	g_signal_connect
-				(	main_window,
-					"delete-event",
-					G_CALLBACK(delete_handler),
+				(	gmpv_ctx,
+					"shutdown",
+					G_CALLBACK(shutdown_handler),
 					inst );
 	inst->name_id = g_bus_own_name(	G_BUS_TYPE_SESSION,
 					name,
diff --git a/src/mpris/gmpv_mpris.h b/src/mpris/gmpv_mpris.h
index ad73fa7..d13fecd 100644
--- a/src/mpris/gmpv_mpris.h
+++ b/src/mpris/gmpv_mpris.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -24,6 +24,7 @@
 #include <glib.h>
 
 #include "gmpv_application.h"
+#include "gmpv_mpris_module.h"
 
 typedef struct gmpv_mpris gmpv_mpris;
 typedef struct gmpv_mpris_prop gmpv_mpris_prop;
@@ -31,27 +32,18 @@ typedef struct gmpv_mpris_prop gmpv_mpris_prop;
 struct gmpv_mpris
 {
 	GmpvApplication* gmpv_ctx;
+	GmpvMprisModule *base;
+	GmpvMprisModule *player;
+	GmpvMprisModule *track_list;
 	guint name_id;
-	guint base_reg_id;
 	guint player_reg_id;
 	gulong shutdown_sig_id;
-	gulong *base_sig_id_list;
 	gulong *player_sig_id_list;
 	gdouble pending_seek;
-	GHashTable *base_prop_table;
 	GHashTable *player_prop_table;
 	GDBusConnection *session_bus_conn;
 };
 
-struct gmpv_mpris_prop
-{
-	gchar *name;
-	GVariant *value;
-};
-
-void gmpv_mpris_emit_prop_changed(	gmpv_mpris *inst,
-					const gchar *iface_name,
-					const gmpv_mpris_prop *prop_list );
 GVariant *gmpv_mpris_build_g_variant_string_array(const gchar** list);
 void gmpv_mpris_init(GmpvApplication *gmpv_ctx);
 
diff --git a/src/mpris/gmpv_mpris_base.c b/src/mpris/gmpv_mpris_base.c
index c14714a..30d9f1a 100644
--- a/src/mpris/gmpv_mpris_base.c
+++ b/src/mpris/gmpv_mpris_base.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,14 +23,45 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
-#include "gmpv_application.h"
-#include "gmpv_main_window.h"
+#include "gmpv_application_private.h"
+#include "gmpv_view.h"
 #include "gmpv_mpris.h"
+#include "gmpv_mpris_module.h"
 #include "gmpv_mpris_base.h"
 #include "gmpv_mpris_gdbus.h"
 #include "gmpv_def.h"
 
-static void prop_table_init(gmpv_mpris *inst);
+enum
+{
+	PROP_0,
+	PROP_APP,
+	N_PROPERTIES
+};
+
+
+struct _GmpvMprisBase
+{
+	GmpvMprisModule parent;
+	GmpvApplication *app;
+	guint reg_id;
+};
+
+struct _GmpvMprisBaseClass
+{
+	GmpvMprisModuleClass parent_class;
+};
+
+static void register_interface(GmpvMprisModule *module);
+static void unregister_interface(GmpvMprisModule *module);
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
 static void method_handler(	GDBusConnection *connection,
 				const gchar *sender,
 				const gchar *object_path,
@@ -54,33 +85,107 @@ static gboolean set_prop_handler(	GDBusConnection *connection,
 					GVariant *value,
 					GError **error,
 					gpointer data );
-static gboolean window_state_handler(	GtkWidget *widget,
-					GdkEvent *event,
-					gpointer data );
+static void fullscreen_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
 static GVariant *get_supported_uri_schemes(void);
 static GVariant *get_supported_mime_types(void);
+static void gmpv_mpris_base_class_init(GmpvMprisBaseClass *klass);
+static void gmpv_mpris_base_init(GmpvMprisBase *base);
 
-static void prop_table_init(gmpv_mpris *inst)
+G_DEFINE_TYPE(GmpvMprisBase, gmpv_mpris_base, GMPV_TYPE_MPRIS_MODULE);
+
+static void register_interface(GmpvMprisModule *module)
 {
-	const gpointer default_values[]
-		= {	"CanQuit", g_variant_new_boolean(TRUE),
+	GmpvMprisBase *base;
+	GmpvView *view;
+	GDBusInterfaceVTable vtable;
+	GDBusInterfaceInfo *iface;
+	GDBusConnection *conn;
+
+	base = GMPV_MPRIS_BASE(module);
+	view = base->app->view;
+
+	g_object_get(module, "conn", &conn, "iface", &iface, NULL);
+
+	gmpv_mpris_module_connect_signal
+		(	module,
+			view,
+			"notify::fullscreen",
+			G_CALLBACK(fullscreen_handler),
+			module );
+
+	gmpv_mpris_module_set_properties
+		(	module,
+			"CanQuit", g_variant_new_boolean(TRUE),
 			"CanSetFullscreen", g_variant_new_boolean(TRUE),
 			"CanRaise", g_variant_new_boolean(TRUE),
 			"Fullscreen", g_variant_new_boolean(FALSE),
-			"HasTrackList", g_variant_new_boolean(FALSE),
+			"HasTrackList", g_variant_new_boolean(TRUE),
 			"Identity", g_variant_new_string(g_get_application_name()),
-			"DesktopEntry", g_variant_new_string(ICON_NAME),
+			"DesktopEntry", g_variant_new_string(APP_ID),
 			"SupportedUriSchemes", get_supported_uri_schemes(),
 			"SupportedMimeTypes", get_supported_mime_types(),
-			NULL };
+			NULL );
+
+	vtable.method_call = (GDBusInterfaceMethodCallFunc)method_handler;
+	vtable.get_property = (GDBusInterfaceGetPropertyFunc)get_prop_handler;
+	vtable.set_property = (GDBusInterfaceSetPropertyFunc)set_prop_handler;
+
+	base->reg_id =	g_dbus_connection_register_object
+			(	conn,
+				MPRIS_OBJ_ROOT_PATH,
+				iface,
+				&vtable,
+				module,
+				NULL,
+				NULL );
+}
+
+static void unregister_interface(GmpvMprisModule *module)
+{
+	GmpvMprisBase *base = GMPV_MPRIS_BASE(module);
+	GDBusConnection *conn = NULL;
+
+	g_object_get(module, "conn", &conn, NULL);
+	g_dbus_connection_unregister_object(conn, base->reg_id);
+}
 
-	gint i;
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisBase *self = GMPV_MPRIS_BASE(object);
 
-	for(i = 0; default_values[i]; i += 2)
+	switch(property_id)
 	{
-		g_hash_table_insert(	inst->base_prop_table,
-					default_values[i],
-					default_values[i+1] );
+		case PROP_APP:
+		self->app = g_value_get_pointer(value);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisBase *self = GMPV_MPRIS_BASE(object);
+
+	switch(property_id)
+	{
+		case PROP_APP:
+		g_value_set_pointer(value, self->app);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
 	}
 }
 
@@ -93,18 +198,15 @@ static void method_handler(	GDBusConnection *connection,
 				GDBusMethodInvocation *invocation,
 				gpointer data )
 {
-	gmpv_mpris *inst = data;
+	GmpvMprisBase *base = data;
 
 	if(g_strcmp0(method_name, "Raise") == 0)
 	{
-		GmpvMainWindow *wnd =	gmpv_application_get_main_window
-					(inst->gmpv_ctx);
-
-		gtk_window_present(GTK_WINDOW(wnd));
+		gmpv_view_present(base->app->view);
 	}
 	else if(g_strcmp0(method_name, "Quit") == 0)
 	{
-		gmpv_application_quit(inst->gmpv_ctx);
+		gmpv_application_quit(base->app);
 	}
 
 	g_dbus_method_invocation_return_value
@@ -119,11 +221,9 @@ static GVariant *get_prop_handler(	GDBusConnection *connection,
 					GError **error,
 					gpointer data )
 {
-	gmpv_mpris *inst = data;
-	GVariant *value;
+	GVariant *value = NULL;
 
-	value = g_hash_table_lookup(	inst->base_prop_table,
-					property_name );
+	gmpv_mpris_module_get_properties(data, property_name, &value, NULL);
 
 	return value?g_variant_ref(value):NULL;
 }
@@ -137,54 +237,42 @@ static gboolean set_prop_handler(	GDBusConnection *connection,
 					GError **error,
 					gpointer data )
 {
-	gmpv_mpris *inst = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(inst->gmpv_ctx);
+	GmpvMprisBase *base = data;
 
-	if(g_strcmp0(property_name, "Fullscreen") == 0
-	&& g_variant_get_boolean(value) != gmpv_main_window_get_fullscreen(wnd))
+	if(g_strcmp0(property_name, "Fullscreen") == 0)
 	{
-		gmpv_main_window_toggle_fullscreen(wnd);
+		gmpv_view_set_fullscreen
+			(base->app->view, g_variant_get_boolean(value));
 	}
 	else
 	{
-		g_hash_table_replace(	((gmpv_mpris *) data)->base_prop_table,
-					g_strdup(property_name),
-					g_variant_ref(value) );
+		gmpv_mpris_module_set_properties(	data,
+							property_name, value,
+							NULL );
 	}
 
 	return TRUE; /* This function should always succeed */
 }
 
-static gboolean window_state_handler(	GtkWidget *widget,
-					GdkEvent *event,
-					gpointer data )
+static void fullscreen_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	gmpv_mpris *inst = data;
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(inst->gmpv_ctx);
-	GdkEventWindowState *window_state_event = (GdkEventWindowState *)event;
-
-	if(window_state_event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
-	{
-		GDBusInterfaceInfo *iface;
-		GVariant *value;
-		gmpv_mpris_prop *prop_list;
-
-		iface = gmpv_mpris_org_mpris_media_player2_interface_info();
-		value =	g_variant_new_boolean
-			(gmpv_main_window_get_fullscreen(wnd));
+	GmpvMprisModule *module = data;
+	GVariant *old_value = NULL;
+	gboolean fullscreen = FALSE;
 
-		g_hash_table_replace(	inst->base_prop_table,
-					g_strdup("Fullscreen"),
-					g_variant_ref(value) );
+	gmpv_mpris_module_get_properties(module, "Fullscreen", &old_value, NULL);
+	g_object_get(object, "fullscreen", &fullscreen, NULL);
 
-		prop_list =	(gmpv_mpris_prop[])
-				{	{"Fullscreen", value},
-					{NULL, NULL} };
-
-		gmpv_mpris_emit_prop_changed(inst, iface->name, prop_list);
+	if(g_variant_get_boolean(old_value) != fullscreen)
+	{
+		gmpv_mpris_module_set_properties
+			(	GMPV_MPRIS_MODULE(data),
+				"Fullscreen", g_variant_new_boolean(fullscreen),
+				NULL );
 	}
 
-	return FALSE;
 }
 
 static GVariant *get_supported_uri_schemes(void)
@@ -201,66 +289,41 @@ static GVariant *get_supported_mime_types(void)
 	return gmpv_mpris_build_g_variant_string_array(mime_types);
 }
 
-void gmpv_mpris_base_register(gmpv_mpris *inst)
+static void gmpv_mpris_base_class_init(GmpvMprisBaseClass *klass)
 {
-	GmpvMainWindow *wnd;
-	GDBusInterfaceVTable vtable;
-	GDBusInterfaceInfo *iface;
-
-	wnd = gmpv_application_get_main_window(inst->gmpv_ctx);
-	iface = gmpv_mpris_org_mpris_media_player2_interface_info();
-
-	inst->base_prop_table =	g_hash_table_new_full
-				(	g_str_hash,
-					g_str_equal,
-					NULL,
-					(GDestroyNotify)g_variant_unref );
-	inst->base_sig_id_list = g_malloc(2*sizeof(gulong));
-
-	inst->base_sig_id_list[0] =	g_signal_connect
-					(	wnd,
-						"window-state-event",
-						G_CALLBACK(window_state_handler),
-						inst );
-	inst->base_sig_id_list[1] = 0;
-
-	prop_table_init(inst);
-
-	vtable.method_call = (GDBusInterfaceMethodCallFunc)method_handler;
-	vtable.get_property = (GDBusInterfaceGetPropertyFunc)get_prop_handler;
-	vtable.set_property = (GDBusInterfaceSetPropertyFunc)set_prop_handler;
-
-	inst->base_reg_id =	g_dbus_connection_register_object
-				(	inst->session_bus_conn,
-					MPRIS_OBJ_ROOT_PATH,
-					iface,
-					&vtable,
-					inst,
-					NULL,
-					NULL );
+	GmpvMprisModuleClass *module_class = GMPV_MPRIS_MODULE_CLASS(klass);
+	GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	module_class->register_interface = register_interface;
+	module_class->unregister_interface = unregister_interface;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+
+	pspec = g_param_spec_pointer
+		(	"app",
+			"Application",
+			"The GmpvApplication to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_APP, pspec);
 }
 
-void gmpv_mpris_base_unregister(gmpv_mpris *inst)
+static void gmpv_mpris_base_init(GmpvMprisBase *base)
 {
-	gulong *current_sig_id = inst->base_sig_id_list;
-
-	if(current_sig_id)
-	{
-		while(current_sig_id && *current_sig_id > 0)
-		{
-			GmpvMainWindow *wnd;
-
-			wnd = gmpv_application_get_main_window(inst->gmpv_ctx);
-			g_signal_handler_disconnect(wnd, *current_sig_id);
+	base->app = NULL;
+	base->reg_id = 0;
+}
 
-			current_sig_id++;
-		}
+GmpvMprisBase *gmpv_mpris_base_new(GmpvApplication *app, GDBusConnection *conn)
+{
+	GDBusInterfaceInfo *iface;
 
-		g_dbus_connection_unregister_object(	inst->session_bus_conn,
-							inst->base_reg_id );
+	iface = gmpv_mpris_org_mpris_media_player2_interface_info();
 
-		g_hash_table_remove_all(inst->base_prop_table);
-		g_hash_table_unref(inst->base_prop_table);
-		g_clear_pointer(&inst->base_sig_id_list, g_free);
-	}
+	return GMPV_MPRIS_BASE(g_object_new(	gmpv_mpris_base_get_type(),
+						"app", app,
+						"conn", conn,
+						"iface", iface,
+						NULL ));
 }
+
diff --git a/src/mpris/gmpv_mpris_base.h b/src/mpris/gmpv_mpris_base.h
index 151cd7b..e898aa9 100644
--- a/src/mpris/gmpv_mpris_base.h
+++ b/src/mpris/gmpv_mpris_base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -22,7 +22,13 @@
 
 #include "gmpv_mpris.h"
 
-void gmpv_mpris_base_register(gmpv_mpris *inst);
-void gmpv_mpris_base_unregister(gmpv_mpris *inst);
+G_BEGIN_DECLS
+
+#define GMPV_TYPE_MPRIS_BASE (gmpv_mpris_base_get_type())
+G_DECLARE_FINAL_TYPE(GmpvMprisBase, gmpv_mpris_base, GMPV, MPRIS_BASE, GmpvMprisModule)
+
+GmpvMprisBase *gmpv_mpris_base_new(GmpvApplication *app, GDBusConnection *conn);
+
+G_END_DECLS
 
 #endif
diff --git a/src/mpris/gmpv_mpris_module.c b/src/mpris/gmpv_mpris_module.c
new file mode 100644
index 0000000..2fd61dc
--- /dev/null
+++ b/src/mpris/gmpv_mpris_module.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gmpv_mpris_module.h"
+#include "gmpv_application.h"
+#include "gmpv_def.h"
+
+typedef struct _GmpvSignalHandlerInfo GmpvSignalHandlerInfo;
+typedef struct _GmpvMprisModulePrivate GmpvMprisModulePrivate;
+
+enum
+{
+	PROP_0,
+	PROP_CONN,
+	PROP_IFACE,
+	N_PROPERTIES
+};
+
+struct _GmpvSignalHandlerInfo
+{
+	gpointer instance;
+	gulong id;
+};
+
+struct _GmpvMprisModulePrivate
+{
+	GDBusConnection *conn;
+	GDBusInterfaceInfo *iface;
+	GSList *signal_ids;
+	GHashTable *prop_table;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(GmpvMprisModule, gmpv_mpris_module, G_TYPE_OBJECT)
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static void dispose(GObject *object);
+static void finalize(GObject *object);
+static void disconnect_signal(GmpvSignalHandlerInfo *info);
+static void gmpv_mpris_module_class_init(GmpvMprisModuleClass *klass);
+static void gmpv_mpris_module_init(GmpvMprisModule *module);
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisModulePrivate *priv;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(object, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+
+	switch(property_id)
+	{
+		case PROP_CONN:
+		priv->conn = g_value_get_pointer(value);
+		break;
+
+		case PROP_IFACE:
+		priv->iface = g_value_get_pointer(value);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisModulePrivate *priv;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(object, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+
+	switch(property_id)
+	{
+		case PROP_CONN:
+		g_value_set_pointer(value, priv->conn);
+		break;
+
+		case PROP_IFACE:
+		g_value_set_pointer(value, priv->iface);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void dispose(GObject *object)
+{
+	GmpvMprisModulePrivate *priv;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(object, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+
+	g_hash_table_unref(priv->prop_table);
+
+	G_OBJECT_GET_CLASS(object)->dispose(object);
+}
+
+static void finalize(GObject *object)
+{
+	GmpvMprisModulePrivate *priv;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(object, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+
+	g_slist_free_full(priv->signal_ids, (GDestroyNotify)disconnect_signal);
+
+	G_OBJECT_GET_CLASS(object)->finalize(object);
+}
+
+static void disconnect_signal(GmpvSignalHandlerInfo *info)
+{
+	g_signal_handler_disconnect(info->instance, info->id);
+}
+
+static void gmpv_mpris_module_class_init(GmpvMprisModuleClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	pspec = g_param_spec_pointer
+		(	"conn",
+			"Connection",
+			"Connection to the session bus",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_CONN, pspec);
+
+	pspec = g_param_spec_pointer
+		(	"iface",
+			"Interface",
+			"The GDBusInterfaceInfo of the interface",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_IFACE, pspec);
+}
+
+static void gmpv_mpris_module_init(GmpvMprisModule *module)
+{
+	GmpvMprisModulePrivate *priv;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(module, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+
+	priv->conn = NULL;
+	priv->iface = NULL;
+	priv->signal_ids = NULL;
+	priv->prop_table =	g_hash_table_new_full
+				(	g_str_hash,
+					g_str_equal,
+					g_free,
+					(GDestroyNotify)
+					g_variant_unref );
+}
+
+void gmpv_mpris_module_connect_signal(	GmpvMprisModule *module,
+					gpointer instance,
+					const gchar *detailed_signal,
+					GCallback handler,
+					gpointer data )
+{
+	GmpvMprisModulePrivate *priv;
+	GmpvSignalHandlerInfo *info;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(module, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+	info = g_malloc(sizeof(GmpvSignalHandlerInfo));
+
+	info->instance = instance;
+	info->id = g_signal_connect(instance, detailed_signal, handler, data);
+
+	priv->signal_ids = g_slist_prepend(priv->signal_ids, info);
+}
+
+void gmpv_mpris_module_get_properties(GmpvMprisModule *module, ...)
+{
+	GmpvMprisModulePrivate *priv;
+	va_list arg;
+	gchar *name;
+	GVariant **value_ptr;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(module, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+
+	va_start(arg, module);
+
+	for(	name = va_arg(arg, gchar *),
+		value_ptr = va_arg(arg, GVariant **);
+		name && value_ptr;
+		name = va_arg(arg, gchar *),
+		value_ptr = va_arg(arg, GVariant **) )
+	{
+		*value_ptr = g_hash_table_lookup(priv->prop_table, name);
+	}
+}
+
+void gmpv_mpris_module_set_properties_full(	GmpvMprisModule *module,
+						gboolean send_new_value,
+						... )
+{
+	GmpvMprisModulePrivate *priv;
+	GVariantBuilder builder;
+	va_list arg;
+	gchar *name;
+	GVariant *value;
+	const gchar *builder_type_string;
+	const gchar *elem_type_string;
+	GVariant *sig_args;
+
+	priv =	G_TYPE_INSTANCE_GET_PRIVATE
+		(module, GMPV_TYPE_MPRIS_MODULE, GmpvMprisModulePrivate);
+	builder_type_string = send_new_value?"a{sv}":"as";
+	elem_type_string = builder_type_string+1;
+
+	g_debug("Preparing property change event");
+	g_variant_builder_init(&builder, G_VARIANT_TYPE(builder_type_string));
+
+	va_start(arg, send_new_value);
+
+	for(	name = va_arg(arg, gchar *),
+		value = va_arg(arg, GVariant *);
+		name && value;
+		name = va_arg(arg, gchar *),
+		value = va_arg(arg, GVariant *) )
+	{
+		g_hash_table_replace(	priv->prop_table,
+					g_strdup(name),
+					g_variant_ref_sink(value) );
+
+		g_debug("Adding property \"%s\"", name);
+		g_variant_builder_add(&builder, elem_type_string, name, value);
+	}
+
+	sig_args = g_variant_new(	"(sa{sv}as)",
+					priv->iface->name,
+					send_new_value?&builder:NULL,
+					send_new_value?NULL:&builder );
+
+	g_debug(	"Emitting property change event on interface %s",
+			priv->iface->name );
+	g_dbus_connection_emit_signal
+		(	priv->conn,
+			NULL,
+			MPRIS_OBJ_ROOT_PATH,
+			"org.freedesktop.DBus.Properties",
+			"PropertiesChanged",
+			sig_args,
+			NULL );
+}
+
+void gmpv_mpris_module_register_interface(GmpvMprisModule *module)
+{
+	if(module)
+	{
+		GmpvMprisModuleClass *klass;
+
+		g_return_if_fail(GMPV_IS_MPRIS_MODULE(module));
+		klass = GMPV_MPRIS_MODULE_GET_CLASS(module);
+
+		g_return_if_fail(klass->register_interface);
+		klass->register_interface(module);
+	}
+}
+
+void gmpv_mpris_module_unregister_interface(GmpvMprisModule *module)
+{
+	if(module)
+	{
+		GmpvMprisModuleClass *klass;
+
+		g_return_if_fail(GMPV_IS_MPRIS_MODULE(module));
+		klass = GMPV_MPRIS_MODULE_GET_CLASS(module);
+
+		g_return_if_fail(klass->unregister_interface);
+		klass->unregister_interface(module);
+	}
+}
+
diff --git a/src/mpris/gmpv_mpris_module.h b/src/mpris/gmpv_mpris_module.h
new file mode 100644
index 0000000..6de69d2
--- /dev/null
+++ b/src/mpris/gmpv_mpris_module.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MPRIS_MODULE_H
+#define MPRIS_MODULE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GMPV_TYPE_MPRIS_MODULE gmpv_mpris_module_get_type()
+G_DECLARE_DERIVABLE_TYPE(GmpvMprisModule, gmpv_mpris_module, GMPV, MPRIS_MODULE, GObject)
+
+struct _GmpvMprisModuleClass
+{
+	GObjectClass parent_interface;
+	void (*register_interface)(GmpvMprisModule *module);
+	void (*unregister_interface)(GmpvMprisModule *module);
+};
+
+void gmpv_mpris_module_connect_signal(	GmpvMprisModule *module,
+					gpointer instance,
+					const gchar *detailed_signal,
+					GCallback handler,
+					gpointer data );
+#define gmpv_mpris_module_set_properties(module, ...)\
+	gmpv_mpris_module_set_properties_full(module, TRUE, __VA_ARGS__)
+void gmpv_mpris_module_get_properties(GmpvMprisModule *module, ...);
+void gmpv_mpris_module_set_properties_full(	GmpvMprisModule *module,
+						gboolean send_new_value,
+						... );
+void gmpv_mpris_module_register_interface(GmpvMprisModule *module);
+void gmpv_mpris_module_unregister_interface(GmpvMprisModule *module);
+
+G_END_DECLS
+
+#endif
diff --git a/src/mpris/gmpv_mpris_player.c b/src/mpris/gmpv_mpris_player.c
index 2118a4d..a6b12e3 100644
--- a/src/mpris/gmpv_mpris_player.c
+++ b/src/mpris/gmpv_mpris_player.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -23,19 +23,46 @@
 #include <mpv/client.h>
 #include <string.h>
 
-#include "gmpv_application.h"
+#include "gmpv_mpris_player.h"
+#include "gmpv_application_private.h"
+#include "gmpv_common.h"
 #include "gmpv_main_window.h"
 #include "gmpv_mpris.h"
 #include "gmpv_mpris_player.h"
 #include "gmpv_mpris_gdbus.h"
-#include "gmpv_mpv.h"
-#include "gmpv_mpv_wrapper.h"
 #include "gmpv_def.h"
 
-static void prop_table_init(gmpv_mpris *inst);
-static void emit_prop_changed(	gmpv_mpris *inst,
-				const gmpv_mpris_prop *prop_list );
-static void append_metadata_tags(GVariantBuilder *builder, mpv_node_list *list);
+enum
+{
+	PROP_0,
+	PROP_APP,
+	N_PROPERTIES
+};
+
+struct _GmpvMprisPlayer
+{
+	GmpvMprisModule parent;
+	GmpvApplication *app;
+	guint reg_id;
+};
+
+struct _GmpvMprisPlayerClass
+{
+	GmpvMprisModuleClass parent_class;
+};
+
+static void register_interface(GmpvMprisModule *module);
+static void unregister_interface(GmpvMprisModule *module);
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static void append_metadata_tags(GVariantBuilder *builder, GPtrArray *list);
 static void method_handler(	GDBusConnection *connection,
 				const gchar *sender,
 				const gchar *object_path,
@@ -59,22 +86,99 @@ static gboolean set_prop_handler(	GDBusConnection *connection,
 					GVariant *value,
 					GError **error,
 					gpointer data );
-static void playback_status_update_handler(gmpv_mpris *inst);
-static void playlist_update_handler(gmpv_mpris *inst);
-static void speed_update_handler(gmpv_mpris *inst);
-static void metadata_update_handler(gmpv_mpris *inst);
-static void volume_update_handler(gmpv_mpris *inst);
-static void mpv_init_handler(GmpvMainWindow *wnd, gpointer data);
-static void mpv_playback_restart_handler(GmpvMainWindow *wnd, gpointer data);
-static void mpv_prop_change_handler(	GmpvMainWindow *wnd,
-					gchar *name,
+static void update_playback_status(GmpvMprisPlayer *player);
+static void update_playlist_state(GmpvMprisPlayer *player);
+
+static void idle_active_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data );
+static void core_idle_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static void playlist_pos_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data );
+static void playlist_count_handler(	GObject *object,
+					GParamSpec *pspec,
 					gpointer data );
+static void speed_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static void metadata_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static void volume_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static void playback_restart_handler(GmpvModel *model, gpointer data);
+
+static void gmpv_mpris_player_class_init(GmpvMprisPlayerClass *klass);
+static void gmpv_mpris_player_init(GmpvMprisPlayer *player);
+
+G_DEFINE_TYPE(GmpvMprisPlayer, gmpv_mpris_player, GMPV_TYPE_MPRIS_MODULE);
 
-static void prop_table_init(gmpv_mpris *inst)
+static void register_interface(GmpvMprisModule *module)
 {
-	/* Position is retrieved from mpv on-demand */
-	const gpointer default_values[]
-		= {	"PlaybackStatus", g_variant_new_string("Stopped"),
+	GmpvMprisPlayer *player = GMPV_MPRIS_PLAYER(module);
+	GmpvModel *model = player->app->model;
+	GDBusConnection *conn;
+	GDBusInterfaceInfo *iface;
+	GDBusInterfaceVTable vtable;
+
+	g_object_get(module, "conn", &conn, "iface", &iface, NULL);
+
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::core-idle",
+			G_CALLBACK(core_idle_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::idle-active",
+			G_CALLBACK(idle_active_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::playlist-pos",
+			G_CALLBACK(playlist_pos_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::playlist-count",
+			G_CALLBACK(playlist_count_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::speed",
+			G_CALLBACK(speed_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::metadata",
+			G_CALLBACK(metadata_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"notify::volume",
+			G_CALLBACK(volume_handler),
+			player );
+	gmpv_mpris_module_connect_signal
+		(	module,
+			model,
+			"playback-restart",
+			G_CALLBACK(playback_restart_handler),
+			player );
+
+	gmpv_mpris_module_set_properties
+		(	module,
+			"PlaybackStatus", g_variant_new_string("Stopped"),
 			"Rate", g_variant_new_double(1.0),
 			"Metadata", g_variant_new("a{sv}", NULL),
 			"Volume", g_variant_new_double(1.0),
@@ -86,27 +190,70 @@ static void prop_table_init(gmpv_mpris *inst)
 			"CanPause", g_variant_new_boolean(TRUE),
 			"CanSeek", g_variant_new_boolean(FALSE),
 			"CanControl", g_variant_new_boolean(TRUE),
-			NULL };
+			NULL );
 
-	gint i;
+	vtable.method_call = (GDBusInterfaceMethodCallFunc)method_handler;
+	vtable.get_property = (GDBusInterfaceGetPropertyFunc)get_prop_handler;
+	vtable.set_property = (GDBusInterfaceSetPropertyFunc)set_prop_handler;
+
+	player->reg_id = g_dbus_connection_register_object
+				(	conn,
+					MPRIS_OBJ_ROOT_PATH,
+					iface,
+					&vtable,
+					player,
+					NULL,
+					NULL );
+}
 
-	for(i = 0; default_values[i]; i += 2)
+static void unregister_interface(GmpvMprisModule *module)
+{
+	GmpvMprisPlayer *player = GMPV_MPRIS_PLAYER(module);
+	GDBusConnection *conn = NULL;
+
+	g_object_get(module, "conn", &conn, NULL);
+	g_dbus_connection_unregister_object(conn, player->reg_id);
+}
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisPlayer *self = GMPV_MPRIS_PLAYER(object);
+
+	switch(property_id)
 	{
-		g_hash_table_insert(	inst->player_prop_table,
-					default_values[i],
-					default_values[i+1] );
+		case PROP_APP:
+		self->app = g_value_get_pointer(value);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
 	}
 }
 
-static void emit_prop_changed(gmpv_mpris *inst, const gmpv_mpris_prop *prop_list)
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
 {
-	GDBusInterfaceInfo *iface;
+	GmpvMprisPlayer *self = GMPV_MPRIS_PLAYER(object);
 
-	iface = gmpv_mpris_org_mpris_media_player2_player_interface_info();
-	gmpv_mpris_emit_prop_changed(inst, iface->name, prop_list);
+	switch(property_id)
+	{
+		case PROP_APP:
+		g_value_set_pointer(value, self->app);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
 }
 
-static void append_metadata_tags(GVariantBuilder *builder, mpv_node_list *list)
+static void append_metadata_tags(GVariantBuilder *builder, GPtrArray *list)
 {
 	const struct
 	{
@@ -123,34 +270,34 @@ static void append_metadata_tags(GVariantBuilder *builder, mpv_node_list *list)
 			{"Title", "xesam:title", FALSE},
 			{NULL, NULL, FALSE} };
 
-	g_assert(list);
+	const guint list_len = list?list->len:0;
 
-	for(gint i = 0; i < list->num; i++)
+	for(guint i = 0; i < list_len; i++)
 	{
-		GVariantBuilder tag_builder;
-		mpv_node mpv_value = list->values[i];
-		const gchar *mpv_key = list->keys[i];
 		const gchar *tag_name;
 		GVariant *tag_value;
+		GmpvMetadataEntry *entry = g_ptr_array_index(list, i);
 		gboolean is_array = TRUE;
-		gboolean valid = TRUE;
 		gint j = -1;
 
-		g_assert(mpv_key);
-
+		/* Translate applicable mpv tag names to MPRIS2-compatible tag
+		 * names.
+		 */
 		while(	tag_map[++j].mpv_name &&
-			g_ascii_strcasecmp(mpv_key, tag_map[j].mpv_name) != 0 );
-		tag_name = tag_map[j].mpv_name?tag_map[j].tag_name:mpv_key;
+			g_ascii_strcasecmp(entry->key, tag_map[j].mpv_name) != 0 );
+		tag_name = tag_map[j].mpv_name?tag_map[j].tag_name:entry->key;
 		is_array = tag_map[j].mpv_name?tag_map[j].is_array:FALSE;
 
-		if(!is_array && mpv_value.format == MPV_FORMAT_STRING)
+		if(!is_array)
 		{
-			tag_value = g_variant_new_string(mpv_value.u.string);
+			tag_value = g_variant_new_string(entry->value);
 		}
-		else if(is_array && mpv_value.format == MPV_FORMAT_STRING)
+		else if(is_array)
 		{
-			GVariant *elem_value = 	g_variant_new_string
-						(mpv_value.u.string);
+			GVariantBuilder tag_builder;
+			GVariant *elem_value;
+
+			elem_value = g_variant_new_string(entry->value);
 
 			g_variant_builder_init
 				(&tag_builder, G_VARIANT_TYPE("as"));
@@ -159,28 +306,9 @@ static void append_metadata_tags(GVariantBuilder *builder, mpv_node_list *list)
 
 			tag_value = g_variant_new("as", &tag_builder);
 		}
-		else
-		{
-			valid = FALSE;
-		}
-
-		if(valid)
-		{
-			g_debug(	"Adding metadata tag \"%s\" "
-					"with type %d",
-					tag_name,
-					mpv_value.format );
 
-			g_variant_builder_add
-				(builder, "{sv}", tag_name, tag_value);
-		}
-		else
-		{
-			g_warning(	"Ignoring metadata entry \"%s\" "
-					"with unsupported format %d",
-					tag_name,
-					mpv_value.format );
-		}
+		g_debug("Adding metadata tag \"%s\"", tag_name);
+		g_variant_builder_add(builder, "{sv}", tag_name, tag_value);
 	}
 }
 
@@ -193,107 +321,59 @@ static void method_handler(	GDBusConnection *connection,
 				GDBusMethodInvocation *invocation,
 				gpointer data )
 {
-	gmpv_mpris *inst = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
+	GmpvMprisPlayer *player = data;
+	GmpvModel *model = player->app->model;
 
 	if(g_strcmp0(method_name, "Next") == 0)
 	{
-		const gchar *cmd[] = {"playlist_next", "weak", NULL};
-
-		gmpv_mpv_command(mpv, cmd);
+		gmpv_model_next_playlist_entry(model);
 	}
 	else if(g_strcmp0(method_name, "Previous") == 0)
 	{
-		const gchar *cmd[] = {"playlist_prev", "weak", NULL};
-
-		gmpv_mpv_command(mpv, cmd);
+		gmpv_model_previous_playlist_entry(model);
 	}
 	else if(g_strcmp0(method_name, "Pause") == 0)
 	{
-		gmpv_mpv_set_property_flag(mpv, "pause", TRUE);
+		gmpv_model_pause(model);
 	}
 	else if(g_strcmp0(method_name, "PlayPause") == 0)
 	{
-		gboolean paused;
+		gboolean pause = TRUE;
 
-		paused = gmpv_mpv_get_property_flag(mpv, "pause");
-
-		gmpv_mpv_set_property_flag(mpv, "pause", !paused);
+		g_object_get(G_OBJECT(model), "pause", &pause, NULL);
+		(pause?gmpv_model_play:gmpv_model_pause)(model);
 	}
 	else if(g_strcmp0(method_name, "Stop") == 0)
 	{
-		const gchar *cmd[] = {"stop", NULL};
-
-		gmpv_mpv_command(mpv, cmd);
+		gmpv_model_stop(model);
 	}
 	else if(g_strcmp0(method_name, "Play") == 0)
 	{
-		gmpv_mpv_set_property_flag(mpv, "pause", FALSE);
+		gmpv_model_play(model);
 	}
 	else if(g_strcmp0(method_name, "Seek") == 0)
 	{
 		gint64 offset_us;
-		gdouble position;
 
 		g_variant_get(parameters, "(x)", &offset_us);
-
-		gmpv_mpv_get_property(	mpv,
-					"time-pos",
-					MPV_FORMAT_DOUBLE,
-					&position );
-
-		position += (gdouble)offset_us/1.0e6;
-
-		gmpv_mpv_set_property(	mpv,
-					"time-pos",
-					MPV_FORMAT_DOUBLE,
-					&position );
-
-		g_dbus_connection_emit_signal
-			(	inst->session_bus_conn,
-				NULL,
-				MPRIS_OBJ_ROOT_PATH,
-				interface_name,
-				"Seeked",
-				g_variant_new("(x)", (gint64)(position*1e6)),
-				NULL );
+		gmpv_model_seek_offset(model, (gdouble)offset_us/1.0e6);
 	}
 	else if(g_strcmp0(method_name, "SetPosition") == 0)
 	{
 		const gchar *prefix = MPRIS_TRACK_ID_PREFIX;
 		const gsize prefix_len = strlen(prefix);
-		gint64 index;
-		gint64 old_index;
-		gint64 time_us;
-		const gchar *track_id;
+		gint64 time_us = -1;
+		const gchar *track_id = NULL;
 
 		g_variant_get(parameters, "(&ox)", &track_id, &time_us);
 
 		if(strncmp(track_id, prefix, prefix_len) == 0)
 		{
-			inst->pending_seek = (gdouble)time_us/1.0e6;
-			index = g_ascii_strtoll(track_id+prefix_len, NULL, 0);
-
-			gmpv_mpv_get_property(	mpv,
-						"playlist-pos",
-						MPV_FORMAT_INT64,
-						&old_index );
-
-			if(index != old_index)
-			{
-				gmpv_mpv_set_property(	mpv,
-							"playlist-pos",
-							MPV_FORMAT_INT64,
-							&index );
-			}
-			else
-			{
-				GmpvMainWindow *wnd;
-
-				wnd =	gmpv_application_get_main_window
-					(inst->gmpv_ctx);
-				mpv_playback_restart_handler(wnd, inst);
-			}
+			gint64 index =	g_ascii_strtoll
+					(track_id+prefix_len, NULL, 0);
+
+			gmpv_model_set_playlist_position(model, index);
+			gmpv_model_seek(model, (gdouble)time_us/1.0e6);
 		}
 	}
 	else if(g_strcmp0(method_name, "OpenUri") == 0)
@@ -301,7 +381,7 @@ static void method_handler(	GDBusConnection *connection,
 		const gchar *uri;
 
 		g_variant_get(parameters, "(&s)", &uri);
-		gmpv_mpv_load(mpv, uri, FALSE, TRUE);
+		gmpv_model_load_file(model, uri, FALSE);
 	}
 
 	g_dbus_method_invocation_return_value
@@ -316,28 +396,23 @@ static GVariant *get_prop_handler(	GDBusConnection *connection,
 					GError **error,
 					gpointer data )
 {
-	gmpv_mpris *inst = data;
+	GmpvMprisPlayer *player = data;
 	GVariant *value;
 
 	if(g_strcmp0(property_name, "Position") == 0)
 	{
-		GmpvMpv *mpv;
-		mpv_handle *mpv_ctx;
+		GmpvModel *model;
 		gdouble position;
-		gint rc;
-
-		mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
-		mpv_ctx = gmpv_mpv_get_mpv_handle(mpv);
-		rc = mpv_get_property(	mpv_ctx,
-					"time-pos",
-					MPV_FORMAT_DOUBLE,
-					&position );
-		value = g_variant_new_int64((gint64)((rc >= 0)*position*1e6));
+
+		model = player->app->model;
+		position = gmpv_model_get_time_position(model);
+		value = g_variant_new_int64((gint64)(position*1e6));
 	}
 	else
 	{
-		value = g_hash_table_lookup(	inst->player_prop_table,
-						property_name );
+		gmpv_mpris_module_get_properties(	GMPV_MPRIS_MODULE(data),
+							property_name, &value,
+							NULL );
 	}
 
 	return value?g_variant_ref(value):NULL;
@@ -352,58 +427,46 @@ static gboolean set_prop_handler(	GDBusConnection *connection,
 					GError **error,
 					gpointer data )
 {
-	gmpv_mpris *inst = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
+	GmpvMprisPlayer *player = data;
+	GmpvModel *model = player->app->model;
 
 	if(g_strcmp0(property_name, "Rate") == 0)
 	{
-		gdouble rate = g_variant_get_double(value);
-
-		gmpv_mpv_set_property(	mpv,
-					"speed",
-					MPV_FORMAT_DOUBLE,
-					&rate );
+		g_object_set(	G_OBJECT(model),
+				"speed", g_variant_get_double(value),
+				NULL );
 	}
 	else if(g_strcmp0(property_name, "Volume") == 0)
 	{
-		gdouble volume = 100*g_variant_get_double(value);
-
-		gmpv_mpv_set_property(	mpv,
-					"volume",
-					MPV_FORMAT_DOUBLE,
-					&volume );
+		g_object_set(	G_OBJECT(model),
+				"volume", 100*g_variant_get_double(value),
+				NULL );
 	}
 
-	g_hash_table_replace(	inst->player_prop_table,
-				g_strdup(property_name),
-				g_variant_ref(value) );
+	gmpv_mpris_module_set_properties(	GMPV_MPRIS_MODULE(data),
+						property_name, value,
+						NULL );
 
 	return TRUE; /* This function should always succeed */
 }
 
-static void playback_status_update_handler(gmpv_mpris *inst)
+static void update_playback_status(GmpvMprisPlayer *player)
 {
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
+	GmpvModel *model = player->app->model;
 	const gchar *state;
-	gmpv_mpris_prop *prop_list;
-	GVariant *state_value;
-	GVariant *can_seek_value;
 	gint idle_active;
 	gint core_idle;
 	gboolean can_seek;
 
-	gmpv_mpv_get_property(mpv, "idle-active", MPV_FORMAT_FLAG, &idle_active);
-	gmpv_mpv_get_property(mpv, "core-idle", MPV_FORMAT_FLAG, &core_idle);
+	g_object_get(	G_OBJECT(model),
+			"idle-active", &idle_active,
+			"core-idle", &core_idle,
+			NULL );
 
 	if(!core_idle && !idle_active)
 	{
-		GmpvMainWindow *wnd =	gmpv_application_get_main_window
-					(inst->gmpv_ctx);
-
 		state = "Playing";
 		can_seek = TRUE;
-
-		mpv_playback_restart_handler(wnd, inst);
 	}
 	else if(core_idle && idle_active)
 	{
@@ -416,109 +479,98 @@ static void playback_status_update_handler(gmpv_mpris *inst)
 		can_seek = TRUE;
 	}
 
-	state_value = g_variant_new_string(state);
-	can_seek_value = g_variant_new_boolean(can_seek);
-
-	g_hash_table_replace(	inst->player_prop_table,
-				"PlaybackStatus",
-				g_variant_ref(state_value) );
-
-	g_hash_table_replace(	inst->player_prop_table,
-				"CanSeek",
-				g_variant_ref(can_seek_value) );
-
-	prop_list =	(gmpv_mpris_prop[])
-			{	{"PlaybackStatus", state_value},
-				{"CanSeek", can_seek_value},
-				{NULL, NULL} };
-
-	emit_prop_changed(inst, prop_list);
+	gmpv_mpris_module_set_properties(	GMPV_MPRIS_MODULE(player),
+						"PlaybackStatus",
+						g_variant_new_string(state),
+						"CanSeek",
+						g_variant_new_boolean(can_seek),
+						NULL );
 }
 
-static void playlist_update_handler(gmpv_mpris *inst)
+static void update_playlist_state(GmpvMprisPlayer *player)
 {
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
-	gmpv_mpris_prop *prop_list;
-	GVariant *can_prev_value;
-	GVariant *can_next_value;
+	GmpvModel *model = player->app->model;
 	gboolean can_prev;
 	gboolean can_next;
 	gint64 playlist_count;
 	gint64 playlist_pos;
 	gint rc = 0;
 
-	rc |= gmpv_mpv_get_property(	mpv,
-					"playlist-count",
-					MPV_FORMAT_INT64,
-					&playlist_count );
-	rc |= gmpv_mpv_get_property(	mpv,
-					"playlist-pos",
-					MPV_FORMAT_INT64,
-					&playlist_pos );
+	g_object_get(	G_OBJECT(model),
+			"playlist-count", &playlist_count,
+			"playlist-pos", &playlist_pos,
+			NULL );
 
 	can_prev = (rc >= 0 && playlist_pos > 0);
 	can_next = (rc >= 0 && playlist_pos < playlist_count-1);
-	can_prev_value = g_variant_new_boolean(can_prev);
-	can_next_value = g_variant_new_boolean(can_next);
-
-	g_hash_table_replace (	inst->player_prop_table,
-				"CanGoPrevious",
-				g_variant_ref(can_prev_value) );
-
-	g_hash_table_replace (	inst->player_prop_table,
-				"CanGoNext",
-				g_variant_ref(can_next_value) );
 
-	prop_list =	(gmpv_mpris_prop[])
-			{	{"CanGoPrevious", can_prev_value},
-				{"CanGoNext", can_next_value},
-				{NULL, NULL} };
+	gmpv_mpris_module_set_properties(	GMPV_MPRIS_MODULE(player),
+						"CanGoPrevious",
+						g_variant_new_boolean(can_prev),
+						"CanGoNext",
+						g_variant_new_boolean(can_next),
+						NULL );
+}
 
-	emit_prop_changed(inst, prop_list);
+static void idle_active_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data )
+{
+	update_playback_status(data);
 }
 
-static void speed_update_handler(gmpv_mpris *inst)
+static void core_idle_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	gdouble speed;
-	GVariant *value;
-	gmpv_mpris_prop *prop_list;
+	update_playback_status(data);
+}
 
-	gmpv_mpv_get_property
-		(	gmpv_application_get_mpv(inst->gmpv_ctx),
-			"speed",
-			MPV_FORMAT_DOUBLE,
-			&speed );
+static void playlist_pos_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data )
+{
+	update_playlist_state(data);
+}
 
-	value = g_variant_new_double(speed);
+static void playlist_count_handler(	GObject *object,
+					GParamSpec *pspec,
+					gpointer data )
+{
+	update_playlist_state(data);
+}
 
-	g_hash_table_replace (	inst->player_prop_table,
-				"Rate",
-				g_variant_ref(value) );
+static void speed_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
+{
+	gdouble speed = 1.0;
 
-	prop_list =	(gmpv_mpris_prop[])
-			{{"Rate", value}, {NULL, NULL}};
+	g_object_get(object, "speed", &speed, NULL);
 
-	emit_prop_changed(inst, prop_list);
+	gmpv_mpris_module_set_properties(	GMPV_MPRIS_MODULE(data),
+						"Rate",
+						g_variant_new_double(speed),
+						NULL );
 }
 
-static void metadata_update_handler(gmpv_mpris *inst)
+static void metadata_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
-	GmpvMainWindow *wnd = gmpv_application_get_main_window(inst->gmpv_ctx);
-	gmpv_mpris_prop *prop_list;
-	mpv_node metadata;
+	GmpvModel *model = GMPV_MODEL(object);
+	GPtrArray *metadata = NULL;
 	GVariantBuilder builder;
-	GVariant *value;
+	gchar *path;
 	gchar *uri;
 	gchar *playlist_pos_str;
 	gchar *trackid;
-	gdouble duration;
-	gint64 playlist_pos;
-	gint rc;
+	gdouble duration = 0;
+	gint64 playlist_pos = 0;
 
 	g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
-
-	uri = gmpv_mpv_get_property_string(mpv, "path");
+	path = gmpv_model_get_current_path(model);
+	uri = g_filename_to_uri(path, NULL, NULL)?:g_strdup(path);
 
 	if(uri)
 	{
@@ -527,26 +579,21 @@ static void metadata_update_handler(gmpv_mpris *inst)
 					"xesam:url",
 					g_variant_new_string(uri) );
 
-		mpv_free(uri);
 	}
 
-	rc = gmpv_mpv_get_property(	mpv,
-					"duration",
-					MPV_FORMAT_DOUBLE,
-					&duration );
+	g_object_get(	model,
+			"duration", &duration,
+			"playlist-pos", &playlist_pos,
+			"metadata", &metadata,
+			NULL );
+
 	g_variant_builder_add(	&builder,
 				"{sv}",
 				"mpris:length",
 				g_variant_new_int64
-				((gint64)((rc >= 0)*duration*1e6)) );
-
-	rc = gmpv_mpv_get_property(	mpv,
-					"playlist-pos",
-					MPV_FORMAT_INT64,
-					&playlist_pos );
-	playlist_pos_str = g_strdup_printf(	"%" G_GINT64_FORMAT,
-						(rc >= 0)*playlist_pos );
+				((gint64)(duration*1e6)) );
 
+	playlist_pos_str = g_strdup_printf("%" G_GINT64_FORMAT, playlist_pos);
 	trackid = g_strconcat(	MPRIS_TRACK_ID_PREFIX,
 				playlist_pos_str,
 				NULL );
@@ -555,101 +602,49 @@ static void metadata_update_handler(gmpv_mpris *inst)
 				"mpris:trackid",
 				g_variant_new_object_path(trackid) );
 
-	rc = gmpv_mpv_get_property(	mpv,
-					"metadata",
-					MPV_FORMAT_NODE,
-					&metadata );
-
-	if(rc >= 0)
-	{
-		append_metadata_tags(&builder, metadata.u.list);
-		mpv_free_node_contents(&metadata);
-	}
+	append_metadata_tags(&builder, metadata);
 
-	value = g_variant_new("a{sv}", &builder);
-
-	g_hash_table_replace (	inst->player_prop_table,
-				"Metadata",
-				g_variant_ref(value) );
-
-	prop_list =	(gmpv_mpris_prop[])
-			{{"Metadata", value}, {NULL, NULL}};
-	emit_prop_changed(inst, prop_list);
-
-	mpv_playback_restart_handler(wnd, inst);
+	gmpv_mpris_module_set_properties(	GMPV_MPRIS_MODULE(data),
+						"Metadata",
+						g_variant_new("a{sv}", &builder),
+						NULL );
 
+	g_free(path);
+	g_free(uri);
 	g_free(playlist_pos_str);
 	g_free(trackid);
 }
 
-static void volume_update_handler(gmpv_mpris *inst)
+static void volume_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
 {
-	gmpv_mpris_prop *prop_list;
-	gdouble volume;
-	GVariant *value;
+	gdouble volume = 0.0;
 
-	gmpv_mpv_get_property
-		(	gmpv_application_get_mpv(inst->gmpv_ctx),
-			"volume",
-			MPV_FORMAT_DOUBLE,
-			&volume );
-
-	value = g_variant_new_double(volume/100.0);
-
-	g_hash_table_replace(	inst->player_prop_table,
-				"Volume",
-				g_variant_ref(value) );
-
-	prop_list =	(gmpv_mpris_prop[])
-			{{"Volume", value}, {NULL, NULL}};
-
-	emit_prop_changed(inst, prop_list);
-}
+	g_object_get(object, "volume", &volume, NULL);
 
-static void mpv_init_handler(GmpvMainWindow *wnd, gpointer data)
-{
-	gmpv_mpris *inst = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
-	mpv_handle *mpv_ctx = gmpv_mpv_get_mpv_handle(mpv);
-
-	mpv_observe_property(mpv_ctx, 0, "idle-active", MPV_FORMAT_FLAG);
-	mpv_observe_property(mpv_ctx, 0, "core-idle", MPV_FORMAT_FLAG);
-	mpv_observe_property(mpv_ctx, 0, "speed", MPV_FORMAT_DOUBLE);
-	mpv_observe_property(mpv_ctx, 0, "metadata", MPV_FORMAT_NODE);
-	mpv_observe_property(mpv_ctx, 0, "volume", MPV_FORMAT_DOUBLE);
-	mpv_observe_property(mpv_ctx, 0, "playlist-pos", MPV_FORMAT_INT64);
-	mpv_observe_property(mpv_ctx, 0, "playlist-count", MPV_FORMAT_INT64);
+	gmpv_mpris_module_set_properties
+		(	GMPV_MPRIS_MODULE(data),
+			"Volume",
+			g_variant_new_double(volume/100.0),
+			NULL );
 }
 
-static void mpv_playback_restart_handler(GmpvMainWindow *wnd, gpointer data)
+static void playback_restart_handler(GmpvModel *model, gpointer data)
 {
-	gmpv_mpris *inst = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
+	GDBusConnection *conn;
 	GDBusInterfaceInfo *iface;
 	gdouble position;
 
-	if(inst->pending_seek > 0)
-	{
-		position = inst->pending_seek;
-		inst->pending_seek = -1;
+	position = gmpv_model_get_time_position(model);
 
-		gmpv_mpv_set_property(	mpv,
-					"time-pos",
-					MPV_FORMAT_DOUBLE,
-					&position );
-	}
-	else
-	{
-		gmpv_mpv_get_property(	mpv,
-					"time-pos",
-					MPV_FORMAT_DOUBLE,
-					&position );
-	}
-
-	iface = gmpv_mpris_org_mpris_media_player2_player_interface_info();
+	g_object_get(	GMPV_MPRIS_MODULE(data),
+			"conn", &conn,
+			"iface", &iface,
+			NULL );
 
 	g_dbus_connection_emit_signal
-		(	inst->session_bus_conn,
+		(	conn,
 			NULL,
 			MPRIS_OBJ_ROOT_PATH,
 			iface->name,
@@ -658,111 +653,42 @@ static void mpv_playback_restart_handler(GmpvMainWindow *wnd, gpointer data)
 			NULL );
 }
 
-static void mpv_prop_change_handler(	GmpvMainWindow *wnd,
-					gchar *name,
-					gpointer data )
+static void gmpv_mpris_player_class_init(GmpvMprisPlayerClass *klass)
 {
-	gmpv_mpris *inst = data;
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
+	GmpvMprisModuleClass *module_class = GMPV_MPRIS_MODULE_CLASS(klass);
+	GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	module_class->register_interface = register_interface;
+	module_class->unregister_interface = unregister_interface;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+
+	pspec = g_param_spec_pointer
+		(	"app",
+			"Application",
+			"The GmpvApplication to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_APP, pspec);
+}
 
-	if(g_strcmp0(name, "core-idle") == 0
-	|| g_strcmp0(name, "idle-active") == 0)
-	{
-		playback_status_update_handler(inst);
-	}
-	else if(gmpv_mpv_get_state(mpv)->loaded)
-	{
-		if(g_strcmp0(name, "playlist-pos") == 0
-		|| g_strcmp0(name, "playlist-count") == 0)
-		{
-			playlist_update_handler(inst);
-		}
-		else if(g_strcmp0(name, "speed") == 0)
-		{
-			speed_update_handler(inst);
-		}
-		else if(g_strcmp0(name, "metadata") == 0)
-		{
-			metadata_update_handler(inst);
-		}
-		else if(g_strcmp0(name, "volume") == 0)
-		{
-			volume_update_handler(inst);
-		}
-	}
+static void gmpv_mpris_player_init(GmpvMprisPlayer *player)
+{
+	player->app = NULL;
+	player->reg_id = 0;
 }
 
-void gmpv_mpris_player_register(gmpv_mpris *inst)
+GmpvMprisPlayer *gmpv_mpris_player_new(	GmpvApplication *app,
+					GDBusConnection *conn )
 {
-	GmpvMpv *mpv = gmpv_application_get_mpv(inst->gmpv_ctx);
 	GDBusInterfaceInfo *iface;
-	GDBusInterfaceVTable vtable;
 
 	iface = gmpv_mpris_org_mpris_media_player2_player_interface_info();
 
-	inst->player_prop_table = g_hash_table_new_full
-					(	g_str_hash,
-						g_str_equal,
-						NULL,
-						(GDestroyNotify)
-						g_variant_unref );
-
-	inst->player_sig_id_list = g_malloc(4*sizeof(gulong));
-	inst->player_sig_id_list[0]
-		= g_signal_connect(	mpv,
-					"mpv-init",
-					G_CALLBACK(mpv_init_handler),
-					inst );
-	inst->player_sig_id_list[1]
-		= g_signal_connect(	mpv,
-					"mpv-playback-restart",
-					G_CALLBACK(mpv_playback_restart_handler),
-					inst );
-	inst->player_sig_id_list[2]
-		= g_signal_connect(	mpv,
-					"mpv-prop-change",
-					G_CALLBACK(mpv_prop_change_handler),
-					inst );
-	inst->player_sig_id_list[3] = 0;
-
-	mpv_init_handler(gmpv_application_get_main_window(inst->gmpv_ctx), inst);
-	prop_table_init(inst);
-
-	vtable.method_call = (GDBusInterfaceMethodCallFunc)method_handler;
-	vtable.get_property = (GDBusInterfaceGetPropertyFunc)get_prop_handler;
-	vtable.set_property = (GDBusInterfaceSetPropertyFunc)set_prop_handler;
-
-	inst->player_reg_id = g_dbus_connection_register_object
-				(	inst->session_bus_conn,
-					MPRIS_OBJ_ROOT_PATH,
-					iface,
-					&vtable,
-					inst,
-					NULL,
-					NULL );
+	return GMPV_MPRIS_PLAYER(g_object_new(	gmpv_mpris_player_get_type(),
+						"app", app,
+						"conn", conn,
+						"iface", iface,
+						NULL ));
 }
 
-void gmpv_mpris_player_unregister(gmpv_mpris *inst)
-{
-	gulong *current_sig_id = inst->player_sig_id_list;
-
-	if(current_sig_id)
-	{
-		GmpvMainWindow *wnd =	gmpv_application_get_main_window
-					(inst->gmpv_ctx);
-
-		while(current_sig_id && *current_sig_id > 0)
-		{
-			g_signal_handler_disconnect(wnd, *current_sig_id);
-
-			current_sig_id++;
-		}
-
-		g_dbus_connection_unregister_object(	inst->session_bus_conn,
-							inst->player_reg_id );
-
-		g_hash_table_remove_all(inst->player_prop_table);
-		g_hash_table_unref(inst->player_prop_table);
-		g_clear_pointer(&inst->player_sig_id_list, g_free);
-	}
-}
diff --git a/src/mpris/gmpv_mpris_player.h b/src/mpris/gmpv_mpris_player.h
index 79fd941..e38181f 100644
--- a/src/mpris/gmpv_mpris_player.h
+++ b/src/mpris/gmpv_mpris_player.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 gnome-mpv
+ * Copyright (c) 2015-2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -22,7 +22,14 @@
 
 #include "gmpv_mpris.h"
 
-void gmpv_mpris_player_register(gmpv_mpris *inst);
-void gmpv_mpris_player_unregister(gmpv_mpris *inst);
+G_BEGIN_DECLS
+
+#define GMPV_TYPE_MPRIS_PLAYER (gmpv_mpris_player_get_type())
+G_DECLARE_FINAL_TYPE(GmpvMprisPlayer, gmpv_mpris_player, GMPV, MPRIS_PLAYER, GmpvMprisModule)
+
+GmpvMprisPlayer *gmpv_mpris_player_new(	GmpvApplication *app,
+					GDBusConnection *conn );
+
+G_END_DECLS
 
 #endif
diff --git a/src/mpris/gmpv_mpris_track_list.c b/src/mpris/gmpv_mpris_track_list.c
new file mode 100644
index 0000000..732f68b
--- /dev/null
+++ b/src/mpris/gmpv_mpris_track_list.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2017 gnome-mpv
+ *
+ * This file is part of GNOME MPV.
+ *
+ * GNOME MPV is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME MPV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gmpv_mpris_track_list.h"
+#include "gmpv_mpris_gdbus.h"
+#include "gmpv_common.h"
+#include "gmpv_def.h"
+
+#include <glib/gprintf.h>
+
+enum
+{
+	PROP_0,
+	PROP_APP,
+	N_PROPERTIES
+};
+
+struct _GmpvMprisTrackList
+{
+	GmpvMprisModule parent;
+	GmpvApplication *app;
+	guint reg_id;
+};
+
+struct  _GmpvMprisTrackListClass
+{
+	GmpvMprisModuleClass parent_class;
+};
+
+static void register_interface(GmpvMprisModule *module);
+static void unregister_interface(GmpvMprisModule *module);
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec );
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec );
+static void method_handler(	GDBusConnection *connection,
+				const gchar *sender,
+				const gchar *object_path,
+				const gchar *interface_name,
+				const gchar *method_name,
+				GVariant *parameters,
+				GDBusMethodInvocation *invocation,
+				gpointer data );
+static GVariant *get_prop_handler(	GDBusConnection *connection,
+					const gchar *sender,
+					const gchar *object_path,
+					const gchar *interface_name,
+					const gchar *property_name,
+					GError **error,
+					gpointer data );
+static gboolean set_prop_handler(	GDBusConnection *connection,
+					const gchar *sender,
+					const gchar *object_path,
+					const gchar *interface_name,
+					const gchar *property_name,
+					GVariant *value,
+					GError **error,
+					gpointer data );
+static void playlist_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data );
+static gint64 track_id_to_index(const gchar *track_id);
+static GVariant *playlist_entry_to_variant(	GmpvPlaylistEntry *entry,
+						gint64 index );
+static GVariant *get_tracks_metadata(	GPtrArray *playlist,
+					const gchar **track_ids );
+static void gmpv_mpris_track_list_class_init(GmpvMprisTrackListClass *klass);
+static void gmpv_mpris_track_list_init(GmpvMprisTrackList *track_list);
+
+G_DEFINE_TYPE(GmpvMprisTrackList, gmpv_mpris_track_list, GMPV_TYPE_MPRIS_MODULE);
+
+static void register_interface(GmpvMprisModule *module)
+{
+	GmpvMprisTrackList *track_list = GMPV_MPRIS_TRACK_LIST(module);
+	GmpvModel *model = track_list->app->model;
+	GDBusConnection *conn;
+	GDBusInterfaceInfo *iface;
+	GDBusInterfaceVTable vtable;
+
+	g_object_get(module, "conn", &conn, "iface", &iface, NULL);
+
+	gmpv_mpris_module_connect_signal(	module,
+						model,
+						"notify::playlist",
+						G_CALLBACK(playlist_handler),
+						module );
+
+	gmpv_mpris_module_set_properties
+		(	module,
+			"Tracks", g_variant_new("ao", NULL),
+			"CanEditTracks", g_variant_new_boolean(FALSE),
+			NULL );
+
+	vtable.method_call = (GDBusInterfaceMethodCallFunc)method_handler;
+	vtable.get_property = (GDBusInterfaceGetPropertyFunc)get_prop_handler;
+	vtable.set_property = (GDBusInterfaceSetPropertyFunc)set_prop_handler;
+
+	track_list->reg_id = g_dbus_connection_register_object
+				(	conn,
+					MPRIS_OBJ_ROOT_PATH,
+					iface,
+					&vtable,
+					module,
+					NULL,
+					NULL );
+}
+
+static void unregister_interface(GmpvMprisModule *module)
+{
+	GmpvMprisTrackList *track_list = GMPV_MPRIS_TRACK_LIST(module);
+	GDBusConnection *conn = NULL;
+
+	g_object_get(module, "conn", &conn, NULL);
+	g_dbus_connection_unregister_object(conn, track_list->reg_id);
+}
+
+static void set_property(	GObject *object,
+				guint property_id,
+				const GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisTrackList *self = GMPV_MPRIS_TRACK_LIST(object);
+
+	switch(property_id)
+	{
+		case PROP_APP:
+		self->app = g_value_get_pointer(value);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void get_property(	GObject *object,
+				guint property_id,
+				GValue *value,
+				GParamSpec *pspec )
+{
+	GmpvMprisTrackList *self = GMPV_MPRIS_TRACK_LIST(object);
+
+	switch(property_id)
+	{
+		case PROP_APP:
+		g_value_set_pointer(value, self->app);
+		break;
+
+		default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
+
+static void method_handler(	GDBusConnection *connection,
+				const gchar *sender,
+				const gchar *object_path,
+				const gchar *interface_name,
+				const gchar *method_name,
+				GVariant *parameters,
+				GDBusMethodInvocation *invocation,
+				gpointer data )
+{
+	GmpvModel *model = GMPV_MPRIS_TRACK_LIST(data)->app->model;
+	GVariant *return_value = NULL;
+
+	if(g_strcmp0(method_name, "GetTracksMetadata") == 0)
+	{
+		GPtrArray *playlist = NULL;
+		const gchar **track_ids = NULL;
+
+		g_object_get(model, "playlist", &playlist, NULL);
+		g_variant_get(parameters, "(^a&o)", &track_ids);
+
+		return_value = get_tracks_metadata(playlist, track_ids);
+
+		g_free(track_ids);
+	}
+	else if(g_strcmp0(method_name, "GoTo") == 0)
+	{
+		const gchar *track_id;
+
+		g_variant_get(parameters, "(o)", &track_id, NULL);
+
+		if(g_str_has_prefix(track_id, MPRIS_TRACK_ID_PREFIX))
+		{
+			const gsize prefix_len = sizeof(MPRIS_TRACK_ID_PREFIX)-1;
+			gint64 playlist_pos =	g_ascii_strtoll
+						(track_id+prefix_len, NULL, 10);
+
+			g_object_set(model, "playlist-pos", playlist_pos, NULL);
+		}
+		else
+		{
+			g_warning(	"The GoTo MPRIS method was called with "
+					"invalid track ID: %s",
+					track_id );
+		}
+
+		return_value = g_variant_new("()", NULL);
+	}
+	else if(g_strcmp0(method_name, "AddTrack") == 0)
+	{
+		/* Not implemented */
+		g_warning(	"The %s MPRIS method was called even though "
+				"CanEditTracks property is FALSE",
+				method_name );
+
+		return_value = g_variant_new("()", NULL);
+	}
+	else if(g_strcmp0(method_name, "RemoveTrack") == 0)
+	{
+		/* Not implemented */
+		g_warning(	"The %s MPRIS method was called even though "
+				"CanEditTracks property is FALSE",
+				method_name );
+
+		return_value = g_variant_new("()", NULL);
+	}
+	else
+	{
+		g_critical("Attempted to call unknown method: %s", method_name);
+
+		return_value = g_variant_new("()", NULL);
+	}
+
+	g_dbus_method_invocation_return_value(invocation, return_value);
+}
+
+static GVariant *get_prop_handler(	GDBusConnection *connection,
+					const gchar *sender,
+					const gchar *object_path,
+					const gchar *interface_name,
+					const gchar *property_name,
+					GError **error,
+					gpointer data )
+{
+	GVariant *value = NULL;
+
+	gmpv_mpris_module_get_properties(	GMPV_MPRIS_MODULE(data),
+						property_name, &value,
+						NULL );
+
+	/* Call g_variant_ref() to prevent the value of the property in the
+	 * properties table from being freed.
+	 */
+	return value?g_variant_ref(value):NULL;
+}
+
+static gboolean set_prop_handler(	GDBusConnection *connection,
+					const gchar *sender,
+					const gchar *object_path,
+					const gchar *interface_name,
+					const gchar *property_name,
+					GVariant *value,
+					GError **error,
+					gpointer data )
+{
+	g_warning(	"Attempted to set property %s in "
+			"org.mpris.MediaPlayer2.TrackList, but the interface "
+			"only has read-only properties.",
+			property_name );
+
+	/* Always fail since the interface only has read-only properties */
+	return FALSE;
+}
+
+static void playlist_handler(	GObject *object,
+				GParamSpec *pspec,
+				gpointer data )
+{
+	gint64 playlist_pos = -1;
+	guint playlist_count = 0;
+	GPtrArray *playlist = NULL;
+	GDBusConnection *conn = NULL;
+	GDBusInterfaceInfo *iface = NULL;
+	gchar *current_track = NULL;
+	GVariant *tracks = NULL;
+	GVariant *signal_params = NULL;
+	GVariantBuilder builder;
+
+	g_object_get(	object,
+			"playlist-pos", &playlist_pos,
+			"playlist", &playlist,
+			NULL );
+	g_object_get(	data,
+			"conn", &conn,
+			"iface", &iface,
+			NULL );
+
+	playlist_count = playlist?playlist->len:0;
+
+	g_variant_builder_init(&builder, G_VARIANT_TYPE("ao"));
+
+	if(playlist_count <= 0
+	|| playlist_pos < 0
+	|| playlist_pos > playlist_count-1)
+	{
+		current_track = g_strdup(MPRIS_TRACK_ID_NO_TRACK);
+	}
+
+	for(gint64 i = 0; i < playlist_count; i++)
+	{
+		gchar *path = g_strdup_printf(	"%s%" G_GINT64_FORMAT,
+						MPRIS_TRACK_ID_PREFIX,
+						i );
+
+		if(i == playlist_pos)
+		{
+			current_track = g_strdup(path);
+		}
+
+		g_variant_builder_add_value
+			(&builder, g_variant_new_object_path(path));
+
+		g_free(path);
+	}
+
+	tracks = g_variant_new("ao", (playlist_count > 0)?&builder:NULL);
+	signal_params = g_variant_new("(@aoo)", tracks, current_track);
+
+	gmpv_mpris_module_set_properties_full(	GMPV_MPRIS_MODULE(data),
+						FALSE,
+						"Tracks", tracks,
+						NULL );
+
+	/* Only emit TrackListReplaced signal. TrackAdded, TrackRemoved, and
+	 * TrackMetadataChanged are currently unused.
+	 */
+	g_dbus_connection_emit_signal
+		(	conn,
+			NULL,
+			MPRIS_OBJ_ROOT_PATH,
+			iface->name,
+			"TrackListReplaced",
+			signal_params,
+			NULL );
+
+	g_free(current_track);
+}
+
+static gint64 track_id_to_index(const gchar *track_id)
+{
+	gint64 index = -1;
+	gchar *endptr = NULL;
+
+	if(g_str_has_prefix(track_id, MPRIS_TRACK_ID_PREFIX))
+	{
+		const gsize prefix_len = sizeof(MPRIS_TRACK_ID_PREFIX)-1;
+
+		index = g_ascii_strtoll(track_id+prefix_len, &endptr, 10);
+	}
+
+	if(endptr && *endptr)
+	{
+		g_warning("Failed to parse track ID: %s", track_id);
+	}
+
+	return index;
+}
+
+static GVariant *playlist_entry_to_variant(	GmpvPlaylistEntry *entry,
+						gint64 index )
+{
+	GVariantBuilder builder;
+	gchar *track_id = NULL;
+	gchar *title = NULL;
+	gchar *uri = NULL;
+	GVariant *elem_value = NULL;
+
+	g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+
+	track_id = g_strdup_printf(	"%s%" G_GINT64_FORMAT,
+					MPRIS_TRACK_ID_PREFIX,
+					index );
+	elem_value =	g_variant_new
+			(	"{sv}",
+				"mpris:trackid",
+				g_variant_new_string(track_id) );
+	g_variant_builder_add_value(&builder, elem_value);
+
+	title =	entry->title?
+		g_strdup(entry->title):
+		get_name_from_path(entry->filename);
+	elem_value =	g_variant_new
+			(	"{sv}",
+				"xesam:title",
+				g_variant_new_string(title) );
+	g_variant_builder_add_value(&builder, elem_value);
+
+	uri =	g_filename_to_uri(entry->filename, NULL, NULL)?:
+		g_strdup(entry->filename);
+	elem_value =	g_variant_new
+			(	"{sv}",
+				"xesam:uri",
+				g_variant_new_string(uri) );
+	g_variant_builder_add_value(&builder, elem_value);
+
+
+	g_free(track_id);
+	g_free(title);
+	g_free(uri);
+
+	return g_variant_new("a{sv}", &builder);
+}
+
+static GVariant *get_tracks_metadata(	GPtrArray *playlist,
+					const gchar **track_ids )
+{
+	GVariantBuilder builder;
+
+	g_assert(playlist);
+	g_assert(track_ids);
+
+	g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+	for(const gchar **iter = track_ids; *iter; iter++)
+	{
+		gint64 index = track_id_to_index(*iter);
+
+		if(index >= 0 && index < playlist->len)
+		{
+			GmpvPlaylistEntry *entry;
+			GVariant *elem;
+
+			entry = g_ptr_array_index(playlist, index);
+			elem = playlist_entry_to_variant(entry, index);
+
+			g_variant_builder_add_value(&builder, elem);
+		}
+		else
+		{
+			g_warning(	"Attempted to retrieve metadata of "
+					"non-existent track ID: %s",
+					*iter );
+		}
+	}
+
+	return g_variant_new("(aa{sv})", &builder);
+}
+
+static void gmpv_mpris_track_list_class_init(GmpvMprisTrackListClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	GmpvMprisModuleClass *module_class = GMPV_MPRIS_MODULE_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	module_class->register_interface = register_interface;
+	module_class->unregister_interface = unregister_interface;
+
+	pspec = g_param_spec_pointer
+		(	"app",
+			"Application",
+			"The GmpvApplication to use",
+			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
+	g_object_class_install_property(object_class, PROP_APP, pspec);
+}
+
+static void gmpv_mpris_track_list_init(GmpvMprisTrackList *track_list)
+{
+	track_list->app = NULL;
+	track_list->reg_id = 0;
+}
+
+GmpvMprisTrackList *gmpv_mpris_track_list_new(	GmpvApplication *app,
+						GDBusConnection *conn )
+{
+	GDBusInterfaceInfo *iface;
+	GObject *object;
+
+	iface = gmpv_mpris_org_mpris_media_player2_track_list_interface_info();
+	object = g_object_new(	gmpv_mpris_track_list_get_type(),
+				"app", app,
+				"conn", conn,
+				"iface", iface,
+				NULL );
+
+	return GMPV_MPRIS_TRACK_LIST(object);
+}
+
diff --git a/src/gmpv_shortcuts_window.h b/src/mpris/gmpv_mpris_track_list.h
similarity index 63%
copy from src/gmpv_shortcuts_window.h
copy to src/mpris/gmpv_mpris_track_list.h
index 78d50a3..a35c71a 100644
--- a/src/gmpv_shortcuts_window.h
+++ b/src/mpris/gmpv_mpris_track_list.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 gnome-mpv
+ * Copyright (c) 2017 gnome-mpv
  *
  * This file is part of GNOME MPV.
  *
@@ -17,20 +17,22 @@
  * along with GNOME MPV.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef SHORTCUTS_WINDOW_H
-#define SHORTCUTS_WINDOW_H
 
-#include <glib.h>
+#ifndef MPRIS_TRACK_LIST_H
+#define MPRIS_TRACK_LIST_H
+
+#include "gmpv_mpris_module.h"
+#include "gmpv_application_private.h"
+
 #include <glib-object.h>
-#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
-#define GMPV_TYPE_SHORTCUTS_WINDOW (gmpv_shortcuts_window_get_type ())
-
-G_DECLARE_FINAL_TYPE(GmpvShortcutsWindow, gmpv_shortcuts_window, GMPV, SHORTCUTS_WINDOW, GtkShortcutsWindow)
+#define GMPV_TYPE_MPRIS_TRACK_LIST (gmpv_mpris_track_list_get_type())
+G_DECLARE_FINAL_TYPE(GmpvMprisTrackList, gmpv_mpris_track_list, GMPV, MPRIS_TRACK_LIST, GmpvMprisModule)
 
-GtkWidget *gmpv_shortcuts_window_new(GtkWindow *parent);
+GmpvMprisTrackList *gmpv_mpris_track_list_new(	GmpvApplication *app,
+						GDBusConnection *conn );
 
 G_END_DECLS
 

-- 
gnome-mpv packaging



More information about the pkg-multimedia-commits mailing list