Merge master.
authorCarl Hetherington <cth@carlh.net>
Sun, 2 Jun 2013 22:03:08 +0000 (23:03 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 2 Jun 2013 22:03:08 +0000 (23:03 +0100)
24 files changed:
1  2 
cscript
platform/linux/control-12.04-32
platform/linux/control-12.04-64
platform/linux/control-12.10-32
platform/linux/control-12.10-64
platform/windows/installer.nsi.32.in
platform/windows/installer.nsi.64.in
src/lib/config.cc
src/lib/ffmpeg_decoder.cc
src/lib/film.cc
src/lib/filter_graph.cc
src/lib/image.cc
src/lib/subtitle.cc
src/lib/subtitle.h
src/lib/util.h
src/lib/video_content.cc
src/tools/dcpomatic.cc
src/tools/dcpomatic_server.cc
src/tools/wscript
src/wx/audio_plot.cc
src/wx/config_dialog.cc
src/wx/film_viewer.cc
test/wscript
wscript

diff --cc cscript
+++ b/cscript
@@@ -40,10 -39,10 +40,10 @@@ def package(env, target, version)
          else:
              cpu = 'amd64'
  
-         shutil.copyfile('builds/control-%s-%d' % (target.version, target.bits), 'debian/control')
+         shutil.copyfile('platform/linux/control-%s-%d' % (target.version, target.bits), 'debian/control')
          env.command('./waf dist')
          f = open('debian/files', 'w')
 -        print >>f,'dvdomatic_%s-1_%s.deb video extra' % (version, cpu)
 +        print >>f,'dcpomatic_%s-1_%s.deb video extra' % (version, cpu)
          shutil.rmtree('build/deb', ignore_errors=True)
  
          os.makedirs('build/deb')
index 0000000,0f52d03..dc10495
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,24 +1,24 @@@
 -Source: dvdomatic
++Source: dcpomatic
+ Section: video
+ Priority: extra
+ Maintainer: Carl Hetherington <cth@carlh.net>
+ Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7)
+ Standards-Version: 3.9.3
 -Homepage: http://carlh.net/software/dvdomatic
++Homepage: http://carlh.net/software/dcpomatic
 -Package: dvdomatic
++Package: dcpomatic
+ Architecture: i386
+ Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libsndfile1 (>= 1.0.25), libmagick++4 (>= 8:6.6.9.7), libxml++2.6-2 (>= 2.34.1)
+ Description: Generator of Digital Cinema Packages (DCPs)
 -  DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
++  DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+   files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
+   digital projectors.
 -Package: dvdomatic-dbg
++Package: dcpomatic-dbg
+ Architecture: i386
+ Section: debug
+ Priority: extra
 -Depends: ${dvdomatic:Depends}, ${misc:Depends}
 -Description: debugging symbols for dvdomatic
 -  This package contains the debugging symbols for dvdomatic.
++Depends: ${dcpomatic:Depends}, ${misc:Depends}
++Description: debugging symbols for dcpomatic
++  This package contains the debugging symbols for dcpomatic.
index 0000000,fa4b447..09c636e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,24 +1,24 @@@
 -Source: dvdomatic
++Source: dcpomatic
+ Section: video
+ Priority: extra
+ Maintainer: Carl Hetherington <cth@carlh.net>
+ Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7)
+ Standards-Version: 3.9.3
 -Homepage: http://carlh.net/software/dvdomatic
++Homepage: http://carlh.net/software/dcpomatic
 -Package: dvdomatic
++Package: dcpomatic
+ Architecture: amd64
+ Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libsndfile1 (>= 1.0.25), libmagick++4 (>= 8:6.6.9.7), libxml++2.6-2 (>= 2.34.1)
+ Description: Generator of Digital Cinema Packages (DCPs)
 -  DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
++  DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+   files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
+   digital projectors.
 -Package: dvdomatic-dbg
++Package: dcpomatic-dbg
+ Architecture: amd64
+ Section: debug
+ Priority: extra
 -Depends: ${dvdomatic:Depends}, ${misc:Depends}
 -Description: debugging symbols for dvdomatic
 -  This package contains the debugging symbols for dvdomatic.
++Depends: ${dcpomatic:Depends}, ${misc:Depends}
++Description: debugging symbols for dcpomatic
++  This package contains the debugging symbols for dcpomatic.
index 0000000,0e5fc1f..1330b3e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,23 +1,23 @@@
 -Source: dvdomatic
++Source: dcpomatic
+ Section: video
+ Priority: extra
+ Maintainer: Carl Hetherington <cth@carlh.net>
+ Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7)
+ Standards-Version: 3.9.3
 -Homepage: http://carlh.net/software/dvdomatic
++Homepage: http://carlh.net/software/dcpomatic
 -Package: dvdomatic
++Package: dcpomatic
+ Architecture: i386
+ Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.49.0 (>= 1.49.0), libboost-thread1.49.0 (>= 1.49.0), libsndfile1 (>= 1.0.25), libmagick++5 (>= 8:6.7.7.10), libxml++2.6-2 (>= 2.34.2)
+ Description: Generator of Digital Cinema Packages (DCPs)
 -  DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
++  DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+   files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
+   digital projectors.
 -Package: dvdomatic-dbg
++Package: dcpomatic-dbg
+ Architecture: i386
+ Section: debug
+ Priority: extra
 -Depends: ${dvdomatic:Depends}, ${misc:Depends}
 -Description: debugging symbols for dvdomatic
 -  This package contains the debugging symbols for dvdomatic.
++Depends: ${dcpomatic:Depends}, ${misc:Depends}
++Description: debugging symbols for dcpomatic
++  This package contains the debugging symbols for dcpomatic.
index 0000000,24e16b4..ea1c491
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,24 +1,24 @@@
 -Source: dvdomatic
++Source: dcpomatic
+ Section: video
+ Priority: extra
+ Maintainer: Carl Hetherington <cth@carlh.net>
+ Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7)
+ Standards-Version: 3.9.3
 -Homepage: http://carlh.net/software/dvdomatic
++Homepage: http://carlh.net/software/dcpomatic
 -Package: dvdomatic
++Package: dcpomatic
+ Architecture: amd64
+ Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.49.0 (>= 1.49.0), libboost-thread1.49.0 (>= 1.49.0), libsndfile1 (>= 1.0.25), libmagick++5 (>= 8:6.7.7.10), libxml++2.6-2 (>= 2.34.2)
+ Description: Generator of Digital Cinema Packages (DCPs)
 -  DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
++  DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+   files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
+   digital projectors.
 -Package: dvdomatic-dbg
++Package: dcpomatic-dbg
+ Architecture: amd64
+ Section: debug
+ Priority: extra
 -Depends: ${dvdomatic:Depends}, ${misc:Depends}
 -Description: debugging symbols for dvdomatic
 -  This package contains the debugging symbols for dvdomatic.
++Depends: ${dcpomatic:Depends}, ${misc:Depends}
++Description: debugging symbols for dcpomatic
++  This package contains the debugging symbols for dcpomatic.
index 0000000,81de3a2..6649047
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,144 +1,145 @@@
 -Name "DVD-o-matic"
+ !include "MUI2.nsh"
 -outFile "DVD-o-matic @version@ 32-bit Installer.exe"
 -!define MUI_ICON "%resources%/dvdomatic.ico"
 -!define MUI_UNICON "%resources%/dvdomatic.ico"
 -!define MUI_SPECIALBITMAP "%resources%/dvdomatic.bmp"
++Name "DCP-o-matic"
+ RequestExecutionLevel admin
 -InstallDir "$PROGRAMFILES\DVD-o-matic"
++outFile "DCP-o-matic @version@ 32-bit Installer.exe"
++!define MUI_ICON "%resources%/dcpomatic.ico"
++!define MUI_UNICON "%resources%/dcpomatic.ico"
++!define MUI_SPECIALBITMAP "%resources%/dcpomatic.bmp"
 -File "%binaries%/src/wx/dvdomatic-wx.dll"
 -File "%binaries%/src/lib/dvdomatic.dll"
 -File "%binaries%/src/tools/dvdomatic.exe"
 -File "%binaries%/src/tools/dvdomatic_batch.exe"
 -File "%binaries%/src/tools/servomatic_cli.exe"
 -File "%binaries%/src/tools/servomatic_gui.exe"
++InstallDir "$PROGRAMFILES\DCP-o-matic"
+ !insertmacro MUI_PAGE_WELCOME
+ !insertmacro MUI_PAGE_LICENSE "../../../COPYING"
+ !insertmacro MUI_PAGE_DIRECTORY
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_PAGE_FINISH
+ !insertmacro MUI_UNPAGE_WELCOME
+ !insertmacro MUI_UNPAGE_CONFIRM
+ !insertmacro MUI_UNPAGE_INSTFILES
+ !insertmacro MUI_UNPAGE_FINISH
+  
+ !insertmacro MUI_LANGUAGE "English"
+ Section "install" "Installation info"
+  
+ SetOutPath "$INSTDIR\bin"
+ File "%deps%/bin/asdcp-libdcp.dll"
+ File "%deps%/bin/avcodec-55.dll"
+ File "%deps%/bin/avfilter-3.dll"
+ File "%deps%/bin/avformat-55.dll"
+ File "%deps%/bin/avutil-52.dll"
+ File "%deps%/bin/dcp.dll"
+ File "%deps%/bin/libintl-8.dll"
+ File "%deps%/bin/kumu-libdcp.dll"
+ File "%deps%/bin/libboost_chrono-mt.dll"
+ File "%deps%/bin/libboost_filesystem-mt.dll"
+ File "%deps%/bin/libboost_system-mt.dll"
+ File "%deps%/bin/libboost_thread_win32-mt.dll"
+ File "%deps%/bin/libboost_date_time-mt.dll"
+ File "%deps%/bin/libeay32.dll"
+ File "%deps%/bin/libgcc_s_sjlj-1.dll"
+ File "%deps%/bin/libgio-2.0-0.dll"
+ File "%deps%/bin/libglib-2.0-0.dll"
+ File "%deps%/bin/libgobject-2.0-0.dll"
+ File "%deps%/bin/libiconv-2.dll"
+ File "%deps%/bin/libjpeg-8.dll"
+ File "%deps%/bin/libMagick++-5.dll"
+ File "%deps%/bin/libMagickCore-5.dll"
+ File "%deps%/bin/libMagickWand-5.dll"
+ File "%deps%/bin/libopenjpeg-1.dll"
+ File "%deps%/bin/libpng15-15.dll"
+ File "%deps%/bin/libsigc-2.0-0.dll"
+ File "%deps%/bin/libsndfile-1.dll"
+ File "%deps%/bin/libssh.dll"
+ File "%deps%/bin/libstdc++-6.dll"
+ File "%deps%/bin/postproc-52.dll"
+ File "%deps%/bin/swresample-0.dll"
+ File "%deps%/bin/swscale-2.dll"
+ File "%deps%/bin/zlib1.dll"
+ File "%deps%/bin/libjpeg-8.dll"
+ File "%deps%/bin/wxbase294u_gcc_custom.dll"
+ File "%deps%/bin/wxmsw294u_core_gcc_custom.dll"
+ File "%deps%/bin/wxmsw294u_adv_gcc_custom.dll"
+ File "%deps%/bin/libcairo-2.dll"
+ File "%deps%/bin/libfreetype-6.dll"
+ File "%deps%/bin/libgthread-2.0-0.dll"
+ File "%deps%/bin/libpango-1.0-0.dll"
+ File "%deps%/bin/libgmodule-2.0-0.dll"
+ File "%deps%/bin/libpangocairo-1.0-0.dll"
+ File "%deps%/bin/libpangowin32-1.0-0.dll"
+ File "%deps%/bin/libtiff-5.dll"
+ File "%deps%/bin/libglibmm-2.4-1.dll"
+ File "%deps%/bin/libxml++-2.6-2.dll"
+ File "%deps%/bin/libxml2-2.dll"
+ File "%deps%/bin/libpixman-1-0.dll"
+ File "%deps%/bin/libfontconfig-1.dll"
+ File "%deps%/bin/libexpat-1.dll"
+ File "%deps%/bin/libbz2.dll"
++File "%deps%/bin/cxml.dll"
 -File "%binaries%/src/lib/mo/fr_FR/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/fr_FR/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/fr_FR/dvdomatic.mo"
++File "%binaries%/src/wx/dcpomatic-wx.dll"
++File "%binaries%/src/lib/dcpomatic.dll"
++File "%binaries%/src/tools/dcpomatic.exe"
++File "%binaries%/src/tools/dcpomatic_batch.exe"
++File "%binaries%/src/tools/dcpomatic_server_cli.exe"
++File "%binaries%/src/tools/dcpomatic_server.exe"
+ # I don't know why, but sometimes it seems that 
+ # delegates.xml must be in with the binaries, and
+ # sometimes in the $PROFILE.  Meh.
+ File "%deps%/etc/ImageMagick/delegates.xml"
+ SetOutPath "$PROFILE\.magick"
+ File "%deps%/etc/ImageMagick/delegates.xml"
+ SetOutPath "$INSTDIR\locale\fr\LC_MESSAGES"
 -File "%binaries%/src/lib/mo/it_IT/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/it_IT/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/it_IT/dvdomatic.mo"
++File "%binaries%/src/lib/mo/fr_FR/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/fr_FR/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/fr_FR/dcpomatic.mo"
+ SetOutPath "$INSTDIR\locale\it\LC_MESSAGES"
 -File "%binaries%/src/lib/mo/es_ES/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/es_ES/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/es_ES/dvdomatic.mo"
++File "%binaries%/src/lib/mo/it_IT/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/it_IT/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/it_IT/dcpomatic.mo"
+ SetOutPath "$INSTDIR\locale\es\LC_MESSAGES"
 -File "%binaries%/src/lib/mo/sv_SE/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/sv_SE/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/sv_SE/dvdomatic.mo"
++File "%binaries%/src/lib/mo/es_ES/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/es_ES/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/es_ES/dcpomatic.mo"
+ SetOutPath "$INSTDIR\locale\sv\LC_MESSAGES"
 -CreateShortCut "$DESKTOP\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" ""
 -CreateShortCut "$DESKTOP\DVD-o-matic batch converter.lnk" "$INSTDIR\bin\dvdomatic_batch.exe" ""
 -CreateShortCut "$DESKTOP\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" ""
++File "%binaries%/src/lib/mo/sv_SE/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/sv_SE/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/sv_SE/dcpomatic.mo"
 -CreateDirectory "$SMPROGRAMS\DVD-o-matic"
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\Uninstall DVD-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" "" "$INSTDIR\bin\dvdomatic.exe" 0
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic batch converter.lnk" "$INSTDIR\bin\dvdomatic_batch.exe" "" "$INSTDIR\bin\dvdomatic_batch.exe" 0
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" "$INSTDIR\bin\servomatic_gui.exe" 0
++CreateShortCut "$DESKTOP\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" ""
++CreateShortCut "$DESKTOP\DCP-o-matic batch converter.lnk" "$INSTDIR\bin\dcpomatic_batch.exe" ""
++CreateShortCut "$DESKTOP\DCP-o-matic encode server.lnk" "$INSTDIR\bin\dcpomatic_server.exe" ""
+  
 -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "DisplayName" "DVD-o-matic (remove only)"
 -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe"
++CreateDirectory "$SMPROGRAMS\DCP-o-matic"
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\Uninstall DCP-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" "" "$INSTDIR\bin\dcpomatic.exe" 0
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic batch converter.lnk" "$INSTDIR\bin\dcpomatic.exe" "" "$INSTDIR\bin\dcpomatic_batch.exe" 0
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic encode server.lnk" "$INSTDIR\bin\dcpomatic_server.exe" "" "$INSTDIR\bin\dcpomatic_server.exe" 0
+  
 -Delete "$DESKTOP\DVD-o-matic.lnk"
 -Delete "$DESKTOP\DVD-o-matic bach converter.lnk"
 -Delete "$DESKTOP\DVD-o-matic encode server.lnk"
 -Delete "$SMPROGRAMS\DVD-o-matic\*.*"
 -RmDir  "$SMPROGRAMS\DVD-o-matic"
 -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DVD-o-matic"
 -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic"
++WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "DisplayName" "DCP-o-matic (remove only)"
++WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe"
+  
+ WriteUninstaller "$INSTDIR\Uninstall.exe"
+  
+ SectionEnd
+  
+  
+ Section "Uninstall"
+  
+ RMDir /r "$INSTDIR\*.*"    
+ RMDir "$INSTDIR"
++Delete "$DESKTOP\DCP-o-matic.lnk"
++Delete "$DESKTOP\DCP-o-matic batch converter.lnk"
++Delete "$DESKTOP\DCP-o-matic encode server.lnk"
++Delete "$SMPROGRAMS\DCP-o-matic\*.*"
++RmDir  "$SMPROGRAMS\DCP-o-matic"
++DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DCP-o-matic"
++DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic"
+  
+ SectionEnd
index 0000000,f2d7970..fd12377
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,154 +1,155 @@@
 -Name "DVD-o-matic"
+ !include "MUI2.nsh"
+ !include "x64.nsh"
 -outFile "DVD-o-matic @version@ 64-bit Installer.exe"
 -!define MUI_ICON "%resources%/dvdomatic.ico"
 -!define MUI_UNICON "%resources%/dvdomatic.ico"
 -!define MUI_SPECIALBITMAP "%resources%/dvdomatic.bmp"
++Name "DCP-o-matic"
+ RequestExecutionLevel admin
 -InstallDir "$PROGRAMFILES\DVD-o-matic"
++outFile "DCP-o-matic @version@ 64-bit Installer.exe"
++!define MUI_ICON "%resources%/dcpomatic.ico"
++!define MUI_UNICON "%resources%/dcpomatic.ico"
++!define MUI_SPECIALBITMAP "%resources%/dcpomatic.bmp"
 -   StrCpy $INSTDIR "$PROGRAMFILES64\DVD-o-matic"
++InstallDir "$PROGRAMFILES\DCP-o-matic"
+ !insertmacro MUI_PAGE_WELCOME
+ !insertmacro MUI_PAGE_LICENSE "../../../COPYING"
+ !insertmacro MUI_PAGE_DIRECTORY
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_PAGE_FINISH
+ !insertmacro MUI_UNPAGE_WELCOME
+ !insertmacro MUI_UNPAGE_CONFIRM
+ !insertmacro MUI_UNPAGE_INSTFILES
+ !insertmacro MUI_UNPAGE_FINISH
+  
+ !insertmacro MUI_LANGUAGE "English"
+ Section "install" "Installation info"
+ ${If} ${RunningX64}
+    DetailPrint "Installer running on 64-bit host"
+    ; disable registry redirection (enable access to 64-bit portion of registry)
+    SetRegView 64
+    ; change install dir
 -File "%binaries%/src/wx/dvdomatic-wx.dll"
 -File "%binaries%/src/lib/dvdomatic.dll"
 -File "%binaries%/src/tools/dvdomatic.exe"
 -File "%binaries%/src/tools/dvdomatic_batch.exe"
 -File "%binaries%/src/tools/servomatic_cli.exe"
 -File "%binaries%/src/tools/servomatic_gui.exe"
++   StrCpy $INSTDIR "$PROGRAMFILES64\DCP-o-matic"
+ ${EndIf}
+ SetOutPath "$INSTDIR\bin"
+ File "%deps%/bin/asdcp-libdcp.dll"
+ File "%deps%/bin/avcodec-55.dll"
+ File "%deps%/bin/avfilter-3.dll"
+ File "%deps%/bin/avformat-55.dll"
+ File "%deps%/bin/avutil-52.dll"
+ File "%deps%/bin/dcp.dll"
+ File "%deps%/bin/libintl-8.dll"
+ File "%deps%/bin/kumu-libdcp.dll"
+ File "%deps%/bin/libboost_chrono-mt.dll"
+ File "%deps%/bin/libboost_filesystem-mt.dll"
+ File "%deps%/bin/libboost_system-mt.dll"
+ File "%deps%/bin/libboost_thread_win32-mt.dll"
+ File "%deps%/bin/libboost_date_time-mt.dll"
+ File "%deps%/bin/libeay32.dll"
+ File "%deps%/bin/libgcc_s_sjlj-1.dll"
+ File "%deps%/bin/libgio-2.0-0.dll"
+ File "%deps%/bin/libglib-2.0-0.dll"
+ File "%deps%/bin/libgobject-2.0-0.dll"
+ File "%deps%/bin/libiconv-2.dll"
+ File "%deps%/bin/libjpeg-8.dll"
+ File "%deps%/bin/libMagick++-5.dll"
+ File "%deps%/bin/libMagickCore-5.dll"
+ File "%deps%/bin/libMagickWand-5.dll"
+ File "%deps%/bin/libopenjpeg-1.dll"
+ File "%deps%/bin/libpng15-15.dll"
+ File "%deps%/bin/libsigc-2.0-0.dll"
+ File "%deps%/bin/libsndfile-1.dll"
+ File "%deps%/bin/libssh.dll"
+ File "%deps%/bin/libstdc++-6.dll"
+ File "%deps%/bin/postproc-52.dll"
+ File "%deps%/bin/swresample-0.dll"
+ File "%deps%/bin/swscale-2.dll"
+ File "%deps%/bin/zlib1.dll"
+ File "%deps%/bin/libjpeg-8.dll"
+ File "%deps%/bin/wxbase294u_gcc_custom.dll"
+ File "%deps%/bin/wxmsw294u_core_gcc_custom.dll"
+ File "%deps%/bin/wxmsw294u_adv_gcc_custom.dll"
+ File "%deps%/bin/libcairo-2.dll"
+ File "%deps%/bin/libfreetype-6.dll"
+ File "%deps%/bin/libgthread-2.0-0.dll"
+ File "%deps%/bin/libpango-1.0-0.dll"
+ File "%deps%/bin/libgmodule-2.0-0.dll"
+ File "%deps%/bin/libpangocairo-1.0-0.dll"
+ File "%deps%/bin/libpangowin32-1.0-0.dll"
+ File "%deps%/bin/libtiff-5.dll"
+ File "%deps%/bin/libglibmm-2.4-1.dll"
+ File "%deps%/bin/libxml++-2.6-2.dll"
+ File "%deps%/bin/libxml2-2.dll"
+ File "%deps%/bin/libpixman-1-0.dll"
+ File "%deps%/bin/libfontconfig-1.dll"
+ File "%deps%/bin/libexpat-1.dll"
+ File "%deps%/bin/libbz2.dll"
++File "%deps%/bin/cxml.dll"
 -File "%binaries%/src/lib/mo/fr_FR/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/fr_FR/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/fr_FR/dvdomatic.mo"
++File "%binaries%/src/wx/dcpomatic-wx.dll"
++File "%binaries%/src/lib/dcpomatic.dll"
++File "%binaries%/src/tools/dcpomatic.exe"
++File "%binaries%/src/tools/dcpomatic_batch.exe"
++File "%binaries%/src/tools/dcpomatic_server_cli.exe"
++File "%binaries%/src/tools/dcpomatic_server.exe"
+ # I don't know why, but sometimes it seems that 
+ # delegates.xml must be in with the binaries, and
+ # sometimes in the $PROFILE.  Meh.
+ File "%deps%/etc/ImageMagick/delegates.xml"
+ SetOutPath "$PROFILE\.magick"
+ File "%deps%/etc/ImageMagick/delegates.xml"
+ SetOutPath "$INSTDIR\locale\fr\LC_MESSAGES"
 -File "%binaries%/src/lib/mo/it_IT/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/it_IT/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/it_IT/dvdomatic.mo"
++File "%binaries%/src/lib/mo/fr_FR/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/fr_FR/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/fr_FR/dcpomatic.mo"
+ SetOutPath "$INSTDIR\locale\it\LC_MESSAGES"
 -File "%binaries%/src/lib/mo/es_ES/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/es_ES/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/es_ES/dvdomatic.mo"
++File "%binaries%/src/lib/mo/it_IT/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/it_IT/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/it_IT/dcpomatic.mo"
+ SetOutPath "$INSTDIR\locale\es\LC_MESSAGES"
 -File "%binaries%/src/lib/mo/sv_SE/libdvdomatic.mo"
 -File "%binaries%/src/wx/mo/sv_SE/libdvdomatic-wx.mo"
 -File "%binaries%/src/tools/mo/sv_SE/dvdomatic.mo"
++File "%binaries%/src/lib/mo/es_ES/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/es_ES/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/es_ES/dcpomatic.mo"
+ SetOutPath "$INSTDIR\locale\sv\LC_MESSAGES"
 -CreateShortCut "$DESKTOP\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" ""
 -CreateShortCut "$DESKTOP\DVD-o-matic batch converter.lnk" "$INSTDIR\bin\dvdomatic_batch.exe" ""
 -CreateShortCut "$DESKTOP\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" ""
++File "%binaries%/src/lib/mo/sv_SE/libdcpomatic.mo"
++File "%binaries%/src/wx/mo/sv_SE/libdcpomatic-wx.mo"
++File "%binaries%/src/tools/mo/sv_SE/dcpomatic.mo"
 -CreateDirectory "$SMPROGRAMS\DVD-o-matic"
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\Uninstall DVD-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" "" "$INSTDIR\bin\dvdomatic.exe" 0
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic batch converter.lnk" "$INSTDIR\bin\dvdomatic.exe" "" "$INSTDIR\bin\dvdomatic_batch.exe" 0
 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" "$INSTDIR\bin\servomatic_gui.exe" 0
++CreateShortCut "$DESKTOP\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" ""
++CreateShortCut "$DESKTOP\DCP-o-matic batch converter.lnk" "$INSTDIR\bin\dcpomatic_batch.exe" ""
++CreateShortCut "$DESKTOP\DCP-o-matic encode server.lnk" "$INSTDIR\bin\dcpomatic_server.exe" ""
+  
 -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "DisplayName" "DVD-o-matic (remove only)"
 -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe"
++CreateDirectory "$SMPROGRAMS\DCP-o-matic"
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\Uninstall DCP-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" "" "$INSTDIR\bin\dcpomatic.exe" 0
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic batch converter.lnk" "$INSTDIR\bin\dcpomatic.exe" "" "$INSTDIR\bin\dcpomatic_batch.exe" 0
++CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic encode server.lnk" "$INSTDIR\bin\dcpomatic_server.exe" "" "$INSTDIR\bin\dcpomatic_server.exe" 0
+  
 -Delete "$DESKTOP\DVD-o-matic.lnk"
 -Delete "$DESKTOP\DVD-o-matic batch converter.lnk"
 -Delete "$DESKTOP\DVD-o-matic encode server.lnk"
 -Delete "$SMPROGRAMS\DVD-o-matic\*.*"
 -RmDir  "$SMPROGRAMS\DVD-o-matic"
 -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DVD-o-matic"
 -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic"
++WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "DisplayName" "DCP-o-matic (remove only)"
++WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe"
+  
+ WriteUninstaller "$INSTDIR\Uninstall.exe"
+  
+ SectionEnd
+  
+  
+ Section "Uninstall"
+  
+ RMDir /r "$INSTDIR\*.*"    
+ RMDir "$INSTDIR"
++Delete "$DESKTOP\DCP-o-matic.lnk"
++Delete "$DESKTOP\DCP-o-matic batch converter.lnk"
++Delete "$DESKTOP\DCP-o-matic encode server.lnk"
++Delete "$SMPROGRAMS\DCP-o-matic\*.*"
++RmDir  "$SMPROGRAMS\DCP-o-matic"
++DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DCP-o-matic"
++DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic"
+  
+ SectionEnd
@@@ -189,11 -122,9 +189,13 @@@ Config::file (bool old) cons
  {
        boost::filesystem::path p;
        p /= g_get_user_config_dir ();
 -      p /= N_(".dvdomatic");
+       boost::system::error_code ec;
+       boost::filesystem::create_directory (p, ec);
 +      if (old) {
 +              p /= ".dvdomatic";
 +      } else {
 +              p /= ".dcpomatic.xml";
 +      }
        return p.string ();
  }
  
Simple merge
diff --cc src/lib/film.cc
@@@ -159,18 -203,26 +159,22 @@@ Film::Film (Film const & o
  string
  Film::video_state_identifier () const
  {
 -      assert (format ());
 +      assert (container ());
        LocaleGuard lg;
  
 -      pair<string, string> f = Filter::ffmpeg_strings (filters());
 -
        stringstream s;
 -      s << format()->id()
 -        << "_" << content_digest()
 -        << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom
 -        << "_" << _dcp_frame_rate
 -        << "_" << f.first << "_" << f.second
 +      s << container()->id()
 +        << "_" << _playlist->video_digest()
 +        << "_" << _dcp_video_frame_rate
          << "_" << scaler()->id()
          << "_" << j2k_bandwidth()
 -        << "_" << boost::lexical_cast<int> (colour_lut());
 +        << "_" << lexical_cast<int> (colour_lut());
  
 -      if (dcp_ab()) {
+       if (trim_type() == ENCODE) {
+               s << "_" << trim_start() << "_" << trim_end();
+       }
 +      if (ab()) {
                pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
                s << "ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
        }
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/lib/util.h
Simple merge
index 18a128a,0000000..84dee81
mode 100644,000000..100644
--- /dev/null
@@@ -1,220 -1,0 +1,222 @@@
 +/*
 +    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
 +
 +    This program is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 2 of the License, or
 +    (at your option) any later version.
 +
 +    This program is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program; if not, write to the Free Software
 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 +
 +*/
 +
 +#include <libcxml/cxml.h>
 +#include "video_content.h"
 +#include "video_decoder.h"
 +#include "ratio.h"
 +
 +#include "i18n.h"
 +
 +int const VideoContentProperty::VIDEO_SIZE     = 0;
 +int const VideoContentProperty::VIDEO_FRAME_RATE = 1;
 +int const VideoContentProperty::VIDEO_CROP     = 2;
 +int const VideoContentProperty::VIDEO_RATIO    = 3;
 +
 +using std::string;
 +using std::stringstream;
 +using std::setprecision;
 +using boost::shared_ptr;
 +using boost::lexical_cast;
 +using boost::optional;
 +
 +VideoContent::VideoContent (shared_ptr<const Film> f, Time s, ContentVideoFrame len)
 +      : Content (f, s)
 +      , _video_length (len)
++      , _video_frame_rate (0)
 +      , _ratio (0)
 +{
 +
 +}
 +
 +VideoContent::VideoContent (shared_ptr<const Film> f, boost::filesystem::path p)
 +      : Content (f, p)
 +      , _video_length (0)
++      , _video_frame_rate (0)
 +      , _ratio (0)
 +{
 +
 +}
 +
 +VideoContent::VideoContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
 +      : Content (f, node)
 +{
 +      _video_length = node->number_child<ContentVideoFrame> ("VideoLength");
 +      _video_size.width = node->number_child<int> ("VideoWidth");
 +      _video_size.height = node->number_child<int> ("VideoHeight");
 +      _video_frame_rate = node->number_child<float> ("VideoFrameRate");
 +      _crop.left = node->number_child<int> ("LeftCrop");
 +      _crop.right = node->number_child<int> ("RightCrop");
 +      _crop.top = node->number_child<int> ("TopCrop");
 +      _crop.bottom = node->number_child<int> ("BottomCrop");
 +      optional<string> r = node->optional_string_child ("Ratio");
 +      if (r) {
 +              _ratio = Ratio::from_id (r.get ());
 +      }
 +}
 +
 +VideoContent::VideoContent (VideoContent const & o)
 +      : Content (o)
 +      , _video_length (o._video_length)
 +      , _video_size (o._video_size)
 +      , _video_frame_rate (o._video_frame_rate)
 +      , _ratio (o._ratio)
 +{
 +
 +}
 +
 +void
 +VideoContent::as_xml (xmlpp::Node* node) const
 +{
 +      boost::mutex::scoped_lock lm (_mutex);
 +      node->add_child("VideoLength")->add_child_text (lexical_cast<string> (_video_length));
 +      node->add_child("VideoWidth")->add_child_text (lexical_cast<string> (_video_size.width));
 +      node->add_child("VideoHeight")->add_child_text (lexical_cast<string> (_video_size.height));
 +      node->add_child("VideoFrameRate")->add_child_text (lexical_cast<string> (_video_frame_rate));
 +      node->add_child("LeftCrop")->add_child_text (boost::lexical_cast<string> (_crop.left));
 +      node->add_child("RightCrop")->add_child_text (boost::lexical_cast<string> (_crop.right));
 +      node->add_child("TopCrop")->add_child_text (boost::lexical_cast<string> (_crop.top));
 +      node->add_child("BottomCrop")->add_child_text (boost::lexical_cast<string> (_crop.bottom));
 +      if (_ratio) {
 +              node->add_child("Ratio")->add_child_text (_ratio->id ());
 +      }
 +}
 +
 +void
 +VideoContent::take_from_video_decoder (shared_ptr<VideoDecoder> d)
 +{
 +      /* These decoder calls could call other content methods which take a lock on the mutex */
 +      libdcp::Size const vs = d->video_size ();
 +      float const vfr = d->video_frame_rate ();
 +      
 +        {
 +                boost::mutex::scoped_lock lm (_mutex);
 +                _video_size = vs;
 +              _video_frame_rate = vfr;
 +        }
 +        
 +        signal_changed (VideoContentProperty::VIDEO_SIZE);
 +        signal_changed (VideoContentProperty::VIDEO_FRAME_RATE);
 +}
 +
 +
 +string
 +VideoContent::information () const
 +{
 +      if (video_size().width == 0 || video_size().height == 0) {
 +              return "";
 +      }
 +      
 +      stringstream s;
 +
 +      s << String::compose (
 +              _("%1x%2 pixels (%3:1)"),
 +              video_size().width,
 +              video_size().height,
 +              setprecision (3), float (video_size().width) / video_size().height
 +              );
 +      
 +      return s.str ();
 +}
 +
 +void
 +VideoContent::set_crop (Crop c)
 +{
 +      {
 +              boost::mutex::scoped_lock lm (_mutex);
 +              _crop = c;
 +      }
 +      signal_changed (VideoContentProperty::VIDEO_CROP);
 +}
 +
 +void
 +VideoContent::set_left_crop (int c)
 +{
 +      {
 +              boost::mutex::scoped_lock lm (_mutex);
 +              
 +              if (_crop.left == c) {
 +                      return;
 +              }
 +              
 +              _crop.left = c;
 +      }
 +      
 +      signal_changed (VideoContentProperty::VIDEO_CROP);
 +}
 +
 +void
 +VideoContent::set_right_crop (int c)
 +{
 +      {
 +              boost::mutex::scoped_lock lm (_mutex);
 +              if (_crop.right == c) {
 +                      return;
 +              }
 +              
 +              _crop.right = c;
 +      }
 +      
 +      signal_changed (VideoContentProperty::VIDEO_CROP);
 +}
 +
 +void
 +VideoContent::set_top_crop (int c)
 +{
 +      {
 +              boost::mutex::scoped_lock lm (_mutex);
 +              if (_crop.top == c) {
 +                      return;
 +              }
 +              
 +              _crop.top = c;
 +      }
 +      
 +      signal_changed (VideoContentProperty::VIDEO_CROP);
 +}
 +
 +void
 +VideoContent::set_bottom_crop (int c)
 +{
 +      {
 +              boost::mutex::scoped_lock lm (_mutex);
 +              if (_crop.bottom == c) {
 +                      return;
 +              }
 +              
 +              _crop.bottom = c;
 +      }
 +
 +      signal_changed (VideoContentProperty::VIDEO_CROP);
 +}
 +
 +void
 +VideoContent::set_ratio (Ratio const * r)
 +{
 +      {
 +              boost::mutex::scoped_lock lm (_mutex);
 +              if (_ratio == r) {
 +                      return;
 +              }
 +
 +              _ratio = r;
 +      }
 +
 +      signal_changed (VideoContentProperty::VIDEO_RATIO);
 +}
index 8d3de53,0000000..ebd6478
mode 100644,000000..100644
--- /dev/null
@@@ -1,533 -1,0 +1,551 @@@
-       ID_file_quit,
-       ID_edit_preferences,
 +/*
 +    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 +
 +    This program is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 2 of the License, or
 +    (at your option) any later version.
 +
 +    This program is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program; if not, write to the Free Software
 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 +
 +*/
 +
 +#include <iostream>
 +#include <fstream>
 +#include <boost/filesystem.hpp>
 +#ifdef __WXMSW__
 +#include <shellapi.h>
 +#endif
++#ifdef __WXOSX__
++#include <ApplicationServices/ApplicationServices.h>
++#endif
 +#include <wx/aboutdlg.h>
 +#include <wx/stdpaths.h>
 +#include <wx/cmdline.h>
 +#include "wx/film_viewer.h"
 +#include "wx/film_editor.h"
 +#include "wx/job_manager_view.h"
 +#include "wx/config_dialog.h"
 +#include "wx/job_wrapper.h"
 +#include "wx/wx_util.h"
 +#include "wx/new_film_dialog.h"
 +#include "wx/properties_dialog.h"
 +#include "wx/wx_ui_signaller.h"
 +#include "lib/film.h"
 +#include "lib/config.h"
 +#include "lib/util.h"
 +#include "lib/version.h"
 +#include "lib/ui_signaller.h"
 +#include "lib/log.h"
 +
 +using std::cout;
 +using std::string;
 +using std::wstring;
 +using std::stringstream;
 +using std::map;
 +using std::make_pair;
 +using std::exception;
 +using std::ofstream;
 +using boost::shared_ptr;
 +
 +static FilmEditor* film_editor = 0;
 +static FilmViewer* film_viewer = 0;
 +static shared_ptr<Film> film;
 +static std::string log_level;
 +static std::string film_to_load;
 +static std::string film_to_create;
 +static wxMenu* jobs_menu = 0;
 +
 +static void set_menu_sensitivity ();
 +
 +class FilmChangedDialog
 +{
 +public:
 +      FilmChangedDialog ()
 +      {
 +              _dialog = new wxMessageDialog (
 +                      0,
 +                      wxString::Format (_("Save changes to film \"%s\" before closing?"), std_to_wx (film->name ()).data()),
 +                      _("Film changed"),
 +                      wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION
 +                      );
 +      }
 +
 +      ~FilmChangedDialog ()
 +      {
 +              _dialog->Destroy ();
 +      }
 +
 +      int run ()
 +      {
 +              return _dialog->ShowModal ();
 +      }
 +
 +private:      
 +      wxMessageDialog* _dialog;
 +};
 +
 +
 +void
 +maybe_save_then_delete_film ()
 +{
 +      if (!film) {
 +              return;
 +      }
 +                      
 +      if (film->dirty ()) {
 +              FilmChangedDialog d;
 +              switch (d.run ()) {
 +              case wxID_NO:
 +                      break;
 +              case wxID_YES:
 +                      film->write_metadata ();
 +                      break;
 +              }
 +      }
 +      
 +      film.reset ();
 +}
 +
 +enum Sensitivity {
 +      ALWAYS,
 +      NEEDS_FILM
 +};
 +
 +map<wxMenuItem*, Sensitivity> menu_items;
 +      
 +void
 +add_item (wxMenu* menu, wxString text, int id, Sensitivity sens)
 +{
 +      wxMenuItem* item = menu->Append (id, text);
 +      menu_items.insert (make_pair (item, sens));
 +}
 +
 +void
 +set_menu_sensitivity ()
 +{
 +      for (map<wxMenuItem*, Sensitivity>::iterator i = menu_items.begin(); i != menu_items.end(); ++i) {
 +              if (i->second == NEEDS_FILM) {
 +                      i->first->Enable (film != 0);
 +              } else {
 +                      i->first->Enable (true);
 +              }
 +      }
 +}
 +
 +enum {
 +      ID_file_new = 1,
 +      ID_file_open,
 +      ID_file_save,
 +      ID_file_properties,
-       ID_help_about
 +      ID_jobs_make_dcp,
 +      ID_jobs_send_dcp_to_tms,
 +      ID_jobs_show_dcp,
 +      ID_jobs_analyse_audio,
-       add_item (file, _("&Quit"), ID_file_quit, ALWAYS);
 +};
 +
 +void
 +setup_menu (wxMenuBar* m)
 +{
 +      wxMenu* file = new wxMenu;
 +      add_item (file, _("New..."), ID_file_new, ALWAYS);
 +      add_item (file, _("&Open..."), ID_file_open, ALWAYS);
 +      file->AppendSeparator ();
 +      add_item (file, _("&Save"), ID_file_save, NEEDS_FILM);
 +      file->AppendSeparator ();
 +      add_item (file, _("&Properties..."), ID_file_properties, NEEDS_FILM);
++#ifndef __WXOSX__     
 +      file->AppendSeparator ();
-       add_item (edit, _("&Preferences..."), ID_edit_preferences, ALWAYS);
++#endif        
++      add_item (file, _("&Exit"), wxID_EXIT, ALWAYS);
 +
++#ifdef __WXOSX__      
++      add_item (file, _("&Preferences..."), wxID_PREFERENCES, ALWAYS);
++#else
 +      wxMenu* edit = new wxMenu;
-       add_item (help, _("About"), ID_help_about, ALWAYS);
++      add_item (edit, _("&Preferences..."), wxID_PREFERENCES, ALWAYS);
++#endif        
 +
 +      jobs_menu = new wxMenu;
 +      add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM);
 +      add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM);
 +      add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM);
 +      jobs_menu->AppendSeparator ();
 +      add_item (jobs_menu, _("&Analyse audio"), ID_jobs_analyse_audio, NEEDS_FILM);
 +
 +      wxMenu* help = new wxMenu;
-               Connect (ID_file_quit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_quit));
-               Connect (ID_edit_preferences, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::edit_preferences));
++#ifdef __WXOSX__      
++      add_item (help, _("About DVD-o-matic"), wxID_ABOUT, ALWAYS);
++#else 
++      add_item (help, _("About"), wxID_ABOUT, ALWAYS);
++#endif        
 +
 +      m->Append (file, _("&File"));
++#ifndef __WXOSX__     
 +      m->Append (edit, _("&Edit"));
++#endif        
 +      m->Append (jobs_menu, _("&Jobs"));
 +      m->Append (help, _("&Help"));
 +}
 +
 +bool
 +window_closed (wxCommandEvent &)
 +{
 +      maybe_save_then_delete_film ();
 +      return false;
 +}
 +
 +class Frame : public wxFrame
 +{
 +public:
 +      Frame (wxString const & title)
 +              : wxFrame (NULL, -1, title)
 +      {
 +              wxMenuBar* bar = new wxMenuBar;
 +              setup_menu (bar);
 +              SetMenuBar (bar);
 +
 +              Connect (ID_file_new, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_new));
 +              Connect (ID_file_open, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_open));
 +              Connect (ID_file_save, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_save));
 +              Connect (ID_file_properties, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_properties));
-               Connect (ID_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about));
++              Connect (wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_exit));
++              Connect (wxID_PREFERENCES, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::edit_preferences));
 +              Connect (ID_jobs_make_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_make_dcp));
 +              Connect (ID_jobs_send_dcp_to_tms, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_send_dcp_to_tms));
 +              Connect (ID_jobs_show_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_show_dcp));
 +              Connect (ID_jobs_analyse_audio, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_analyse_audio));
-       void file_quit (wxCommandEvent &)
++              Connect (wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about));
 +
 +              Connect (wxID_ANY, wxEVT_MENU_OPEN, wxMenuEventHandler (Frame::menu_opened));
 +
 +              film_editor = new FilmEditor (film, this);
 +              film_viewer = new FilmViewer (film, this);
 +              JobManagerView* job_manager_view = new JobManagerView (this, static_cast<JobManagerView::Buttons> (0));
 +
 +              wxBoxSizer* right_sizer = new wxBoxSizer (wxVERTICAL);
 +              right_sizer->Add (film_viewer, 2, wxEXPAND | wxALL, 6);
 +              right_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
 +
 +              wxBoxSizer* main_sizer = new wxBoxSizer (wxHORIZONTAL);
 +              main_sizer->Add (film_editor, 1, wxEXPAND | wxALL, 6);
 +              main_sizer->Add (right_sizer, 2, wxEXPAND | wxALL, 6);
 +
 +              set_menu_sensitivity ();
 +
 +              film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1));
 +              if (film) {
 +                      file_changed (film->directory ());
 +              } else {
 +                      file_changed ("");
 +              }
 +
 +              set_film ();
 +              SetSizer (main_sizer);
 +      }
 +
 +private:
 +
 +      void menu_opened (wxMenuEvent& ev)
 +      {
 +              if (ev.GetMenu() != jobs_menu) {
 +                      return;
 +              }
 +
 +              bool const have_dcp = film && film->have_dcp();
 +              jobs_menu->Enable (ID_jobs_send_dcp_to_tms, have_dcp);
 +              jobs_menu->Enable (ID_jobs_show_dcp, have_dcp);
 +      }
 +
 +      void set_film ()
 +      {
 +              film_viewer->set_film (film);
 +              film_editor->set_film (film);
 +              set_menu_sensitivity ();
 +      }
 +
 +      void file_changed (string f)
 +      {
 +              stringstream s;
 +              s << wx_to_std (_("DCP-o-matic"));
 +              if (!f.empty ()) {
 +                      s << " - " << f;
 +              }
 +              
 +              SetTitle (std_to_wx (s.str()));
 +      }
 +      
 +      void file_new (wxCommandEvent &)
 +      {
 +              NewFilmDialog* d = new NewFilmDialog (this);
 +              int const r = d->ShowModal ();
 +              
 +              if (r == wxID_OK) {
 +
 +                      if (boost::filesystem::exists (d->get_path()) && !boost::filesystem::is_empty(d->get_path())) {
 +                              if (!confirm_dialog (
 +                                          this,
 +                                          std_to_wx (
 +                                                  String::compose (wx_to_std (_("The directory %1 already exists and is not empty.  "
 +                                                                                "Are you sure you want to use it?")),
 +                                                                   d->get_path().c_str())
 +                                                  )
 +                                          )) {
 +                                      return;
 +                              }
 +                      }
 +                      
 +                      maybe_save_then_delete_film ();
 +                      film.reset (new Film (d->get_path ()));
 +                      film->write_metadata ();
 +                      film->log()->set_level (log_level);
 +                      film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string());
 +                      set_film ();
 +              }
 +              
 +              d->Destroy ();
 +      }
 +
 +      void file_open (wxCommandEvent &)
 +      {
 +              wxDirDialog* c = new wxDirDialog (this, _("Select film to open"), wxStandardPaths::Get().GetDocumentsDir(), wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST);
 +              int r;
 +              while (1) {
 +                      r = c->ShowModal ();
 +                      if (r == wxID_OK && c->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
 +                              error_dialog (this, _("You did not select a folder.  Make sure that you select a folder before clicking Open."));
 +                      } else {
 +                              break;
 +                      }
 +              }
 +                      
 +              if (r == wxID_OK) {
 +                      maybe_save_then_delete_film ();
 +                      try {
 +                              film.reset (new Film (wx_to_std (c->GetPath ())));
 +                              film->log()->set_level (log_level);
 +                              set_film ();
 +                      } catch (std::exception& e) {
 +                              wxString p = c->GetPath ();
 +                              wxCharBuffer b = p.ToUTF8 ();
 +                              error_dialog (this, wxString::Format (_("Could not open film at %s (%s)"), p.data(), std_to_wx (e.what()).data()));
 +                      }
 +              }
 +
 +              c->Destroy ();
 +      }
 +
 +      void file_save (wxCommandEvent &)
 +      {
 +              film->write_metadata ();
 +      }
 +
 +      void file_properties (wxCommandEvent &)
 +      {
 +              PropertiesDialog* d = new PropertiesDialog (this, film);
 +              d->ShowModal ();
 +              d->Destroy ();
 +      }
 +      
++      void file_exit (wxCommandEvent &)
 +      {
 +              maybe_save_then_delete_film ();
 +              Close (true);
 +      }
 +
 +      void edit_preferences (wxCommandEvent &)
 +      {
 +              ConfigDialog* d = new ConfigDialog (this);
 +              d->ShowModal ();
 +              d->Destroy ();
 +              Config::instance()->write ();
 +      }
 +
 +      void jobs_make_dcp (wxCommandEvent &)
 +      {
 +              JobWrapper::make_dcp (this, film);
 +      }
 +      
 +      void jobs_send_dcp_to_tms (wxCommandEvent &)
 +      {
 +              film->send_dcp_to_tms ();
 +      }
 +
 +      void jobs_show_dcp (wxCommandEvent &)
 +      {
 +#ifdef __WXMSW__
 +              string d = film->directory();
 +              wstring w;
 +              w.assign (d.begin(), d.end());
 +              ShellExecute (0, L"open", w.c_str(), 0, 0, SW_SHOWDEFAULT);
 +#else
 +              int r = system ("which nautilus");
 +              if (WEXITSTATUS (r) == 0) {
 +                      system (string ("nautilus " + film->directory()).c_str ());
 +              } else {
 +                      int r = system ("which konqueror");
 +                      if (WEXITSTATUS (r) == 0) {
 +                              system (string ("konqueror " + film->directory()).c_str ());
 +                      }
 +              }
 +#endif                
 +      }
 +
 +      void jobs_analyse_audio (wxCommandEvent &)
 +      {
 +              film->analyse_audio ();
 +      }
 +      
 +      void help_about (wxCommandEvent &)
 +      {
 +              wxAboutDialogInfo info;
 +              info.SetName (_("DCP-o-matic"));
 +              if (strcmp (dcpomatic_git_commit, "release") == 0) {
 +                      info.SetVersion (std_to_wx (String::compose ("version %1", dcpomatic_version)));
 +              } else {
 +                      info.SetVersion (std_to_wx (String::compose ("version %1 git %2", dcpomatic_version, dcpomatic_git_commit)));
 +              }
 +              info.SetDescription (_("Free, open-source DCP generation from almost anything."));
 +              info.SetCopyright (_("(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen"));
 +
 +              wxArrayString authors;
 +              authors.Add (wxT ("Carl Hetherington"));
 +              authors.Add (wxT ("Terrence Meiczinger"));
 +              authors.Add (wxT ("Paul Davis"));
 +              authors.Add (wxT ("Ole Laursen"));
 +              info.SetDevelopers (authors);
 +
 +              wxArrayString translators;
 +              translators.Add (wxT ("Olivier Perriere"));
 +              translators.Add (wxT ("Lilian Lefranc"));
 +              translators.Add (wxT ("Thierry Journet"));
 +              translators.Add (wxT ("Massimiliano Broggi"));
 +              translators.Add (wxT ("Manuel AC"));
 +              translators.Add (wxT ("Adam Klotblixt"));
 +              info.SetTranslators (translators);
 +              
 +              info.SetWebSite (wxT ("http://carlh.net/software/dcpomatic"));
 +              wxAboutBox (info);
 +      }
 +};
 +
 +#if wxMINOR_VERSION == 9
 +static const wxCmdLineEntryDesc command_line_description[] = {
 +      { wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
 +      { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
 +        { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
 +      { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
 +};
 +#else
 +static const wxCmdLineEntryDesc command_line_description[] = {
 +      { wxCMD_LINE_OPTION, wxT("l"), wxT("log"), wxT("set log level (silent, verbose or timing)"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
 +      { wxCMD_LINE_SWITCH, wxT("n"), wxT("new"), wxT("create new film"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
 +        { wxCMD_LINE_PARAM, 0, 0, wxT("film to load or create"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
 +      { wxCMD_LINE_NONE, wxT(""), wxT(""), wxT(""), wxCmdLineParamType (0), 0 }
 +};
 +#endif
 +
 +class App : public wxApp
 +{
 +      bool OnInit ()
 +      {
 +              if (!wxApp::OnInit()) {
 +                      return false;
 +              }
 +              
 +#ifdef DCPOMATIC_POSIX                
 +              unsetenv ("UBUNTU_MENUPROXY");
++#endif
++
++#ifdef __WXOSX__              
++              ProcessSerialNumber serial;
++              GetCurrentProcess (&serial);
++              TransformProcessType (&serial, kProcessTransformToForegroundApplication);
 +#endif                
 +
 +              wxInitAllImageHandlers ();
 +
 +              /* Enable i18n; this will create a Config object
 +                 to look for a force-configured language.  This Config
 +                 object will be wrong, however, because dcpomatic_setup
 +                 hasn't yet been called and there aren't any scalers, filters etc.
 +                 set up yet.
 +              */
 +              dcpomatic_setup_i18n ();
 +
 +              /* Set things up, including scalers / filters etc.
 +                 which will now be internationalised correctly.
 +              */
 +              dcpomatic_setup ();
 +
 +              /* Force the configuration to be re-loaded correctly next
 +                 time it is needed.
 +              */
 +              Config::drop ();
 +
 +              if (!film_to_load.empty() && boost::filesystem::is_directory (film_to_load)) {
 +                      try {
 +                              film.reset (new Film (film_to_load));
 +                              film->read_metadata ();
 +                              film->log()->set_level (log_level);
 +                      } catch (exception& e) {
 +                              error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), film_to_load, e.what())));
 +                      }
 +              }
 +
 +              if (!film_to_create.empty ()) {
 +                      film.reset (new Film (film_to_create));
 +                      film->write_metadata ();
 +                      film->log()->set_level (log_level);
 +                      film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
 +              }
 +
 +              Frame* f = new Frame (_("DCP-o-matic"));
 +              SetTopWindow (f);
 +              f->Maximize ();
 +              f->Show ();
 +
 +              ui_signaller = new wxUISignaller (this);
 +              this->Connect (-1, wxEVT_IDLE, wxIdleEventHandler (App::idle));
 +
 +              return true;
 +      }
 +
 +      void OnInitCmdLine (wxCmdLineParser& parser)
 +      {
 +              parser.SetDesc (command_line_description);
 +              parser.SetSwitchChars (wxT ("-"));
 +      }
 +
 +      bool OnCmdLineParsed (wxCmdLineParser& parser)
 +      {
 +              if (parser.GetParamCount() > 0) {
 +                      if (parser.Found (wxT ("new"))) {
 +                              film_to_create = wx_to_std (parser.GetParam (0));
 +                      } else {
 +                              film_to_load = wx_to_std (parser.GetParam(0));
 +                      }
 +              }
 +
 +              wxString log;
 +              if (parser.Found (wxT ("log"), &log)) {
 +                      log_level = wx_to_std (log);
 +              }
 +
 +              return true;
 +      }
 +
 +      void idle (wxIdleEvent &)
 +      {
 +              ui_signaller->ui_idle ();
 +      }
 +};
 +
 +IMPLEMENT_APP (App)
index 152e063,0000000..d3a3531
mode 100644,000000..100644
--- /dev/null
@@@ -1,174 -1,0 +1,177 @@@
- #endif                
 +/*
 +    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 +
 +    This program is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 2 of the License, or
 +    (at your option) any later version.
 +
 +    This program is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program; if not, write to the Free Software
 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 +
 +*/
 +
 +#include <boost/thread.hpp>
 +#include <wx/taskbar.h>
 +#include <wx/icon.h>
 +#include "wx_util.h"
 +#include "lib/util.h"
 +#include "lib/server.h"
 +#include "lib/config.h"
 +
 +using std::cout;
 +using std::string;
 +using boost::shared_ptr;
 +using boost::thread;
 +using boost::bind;
 +
 +enum {
 +      ID_status = 1,
 +      ID_quit,
 +      ID_timer
 +};
 +
 +class MemoryLog : public Log
 +{
 +public:
 +
 +      string get () const {
 +              boost::mutex::scoped_lock (_mutex);
 +              return _log;
 +      }
 +
 +private:
 +      void do_log (string m)
 +      {
 +              _log = m;
 +      }
 +
 +      string _log;    
 +};
 +
 +static shared_ptr<MemoryLog> memory_log (new MemoryLog);
 +
 +class StatusDialog : public wxDialog
 +{
 +public:
 +      StatusDialog ()
 +              : wxDialog (0, wxID_ANY, _("DCP-o-matic encode server"), wxDefaultPosition, wxSize (600, 80), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
 +              , _timer (this, ID_timer)
 +      {
 +              _sizer = new wxFlexGridSizer (1, 6, 6);
 +              _sizer->AddGrowableCol (0, 1);
 +
 +              _text = new wxTextCtrl (this, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
 +              _sizer->Add (_text, 1, wxEXPAND);
 +
 +              SetSizer (_sizer);
 +              _sizer->Layout ();
 +
 +              Connect (ID_timer, wxEVT_TIMER, wxTimerEventHandler (StatusDialog::update));
 +              _timer.Start (1000);
 +      }
 +
 +private:
 +      void update (wxTimerEvent &)
 +      {
 +              _text->ChangeValue (std_to_wx (memory_log->get ()));
 +              _sizer->Layout ();
 +      }
 +
 +      wxFlexGridSizer* _sizer;
 +      wxTextCtrl* _text;
 +      wxTimer _timer;
 +};
 +
 +class TaskBarIcon : public wxTaskBarIcon
 +{
 +public:
 +      TaskBarIcon ()
 +      {
 +#ifdef __WXMSW__              
 +              wxIcon icon (std_to_wx ("taskbar_icon"));
 +#endif
 +#ifdef __WXGTK__
 +              wxInitAllImageHandlers();
 +              wxBitmap bitmap (wxString::Format (wxT ("%s/taskbar_icon.png"), POSIX_ICON_PREFIX), wxBITMAP_TYPE_PNG);
 +              wxIcon icon;
 +              icon.CopyFromBitmap (bitmap);
++#endif
++#ifndef __WXOSX__
++              /* XXX: fix this for OS X */
 +              SetIcon (icon, std_to_wx ("DCP-o-matic encode server"));
++#endif                
 +
 +              Connect (ID_status, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (TaskBarIcon::status));
 +              Connect (ID_quit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (TaskBarIcon::quit));
 +      }
 +      
 +      wxMenu* CreatePopupMenu ()
 +      {
 +              wxMenu* menu = new wxMenu;
 +              menu->Append (ID_status, std_to_wx ("Status..."));
 +              menu->Append (ID_quit, std_to_wx ("Quit"));
 +              return menu;
 +      }
 +
 +private:
 +      void status (wxCommandEvent &)
 +      {
 +              StatusDialog* d = new StatusDialog;
 +              d->Show ();
 +      }
 +
 +      void quit (wxCommandEvent &)
 +      {
 +              wxTheApp->ExitMainLoop ();
 +      }
 +};
 +
 +class App : public wxApp
 +{
 +public:
 +      App ()
 +              : wxApp ()
 +              , _thread (0)
 +              , _icon (0)
 +      {}
 +
 +private:      
 +      
 +      bool OnInit ()
 +      {
 +              if (!wxApp::OnInit ()) {
 +                      return false;
 +              }
 +              
 +              dcpomatic_setup ();
 +
 +              _icon = new TaskBarIcon;
 +              _thread = new thread (bind (&App::main_thread, this));
 +              
 +              return true;
 +      }
 +
 +      int OnExit ()
 +      {
 +              delete _icon;
 +              return wxApp::OnExit ();
 +      }
 +
 +      void main_thread ()
 +      {
 +              Server server (memory_log);
 +              server.run (Config::instance()->num_local_encoding_threads ());
 +      }
 +
 +      boost::thread* _thread;
 +      TaskBarIcon* _icon;
 +};
 +
 +IMPLEMENT_APP (App)
@@@ -13,20 -13,20 +13,20 @@@ def build(bld)
          obj.target = t
  
      if not bld.env.DISABLE_GUI:
 -        for t in ['dvdomatic', 'dvdomatic_batch', 'servomatic_gui']:
 +        for t in ['dcpomatic', 'dcpomatic_batch', 'dcpomatic_server']:
              obj = bld(features = 'cxx cxxprogram')
 -            obj.uselib = 'DCP OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC'
 +            obj.uselib = 'DCP CXML OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC'
              obj.includes = ['..']
 -            obj.use    = ['libdvdomatic', 'libdvdomatic-wx']
 +            obj.use    = ['libdcpomatic', 'libdcpomatic-wx']
              obj.source = '%s.cc' % t
              if bld.env.TARGET_WINDOWS:
-                 obj.source += ' ../../windows/dcpomatic.rc'
 -                obj.source += ' ../../platform/windows/dvdomatic.rc'
++                obj.source += ' ../../platform/windows/dcpomatic.rc'
              obj.target = t
  
 -        i18n.po_to_mo(os.path.join('src', 'tools'), 'dvdomatic', bld)
 +        i18n.po_to_mo(os.path.join('src', 'tools'), 'dcpomatic', bld)
  
  def pot(bld):
 -    i18n.pot(os.path.join('src', 'tools'), 'dvdomatic.cc', 'dvdomatic')
 +    i18n.pot(os.path.join('src', 'tools'), 'dcpomatic.cc', 'dcpomatic')
  
  def pot_merge(bld):
 -    i18n.pot_merge(os.path.join('src', 'tools'), 'dvdomatic')
 +    i18n.pot_merge(os.path.join('src', 'tools'), 'dcpomatic')
Simple merge
Simple merge
@@@ -364,10 -412,11 +365,11 @@@ FilmViewer::process_video (shared_ptr<c
  
        _got_frame = true;
  
 -      double const fps = _decoders.video->frames_per_second ();
 +      double const fps = _film->dcp_video_frame_rate ();
-       _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps / TIME_HZ))));
+       /* Count frame number from 1 ... not sure if this is the best idea */
 -      _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps)) + 1));
++      _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps / TIME_HZ)) + 1));
  
 -      double w = t;
 +      double w = static_cast<double>(t) / TIME_HZ;
        int const h = (w / 3600);
        w -= h * 3600;
        int const m = (w / 60);
diff --cc test/wscript
Simple merge
diff --cc wscript
+++ b/wscript
@@@ -51,9 -52,11 +52,11 @@@ def configure(conf)
      conf.env.DISABLE_GUI = conf.options.disable_gui
      conf.env.STATIC = conf.options.static
      conf.env.VERSION = VERSION
+     conf.env.TARGET_OSX = conf.options.osx
+     conf.env.TARGET_LINUX = not conf.options.target_windows and not conf.options.osx
  
      if conf.options.enable_debug:
 -        conf.env.append_value('CXXFLAGS', ['-g', '-DDVDOMATIC_DEBUG'])
 +        conf.env.append_value('CXXFLAGS', ['-g', '-DDCPOMATIC_DEBUG'])
      else:
          conf.env.append_value('CXXFLAGS', '-O2')
  
@@@ -192,27 -195,17 +195,17 @@@ def build(bld)
      bld.recurse('src')
      bld.recurse('test')
      if bld.env.TARGET_WINDOWS:
-         bld.recurse('windows')
-     d = { 'PREFIX' : '${PREFIX' }
-     obj = bld(features = 'subst')
-     obj.source = 'dcpomatic.desktop.in'
-     obj.target = 'dcpomatic.desktop'
-     obj.dict = d
-     obj = bld(features = 'subst')
-     obj.source = 'dcpomatic_batch.desktop.in'
-     obj.target = 'dcpomatic_batch.desktop'
-     obj.dict = d
-     bld.install_files('${PREFIX}/share/applications', ['dcpomatic.desktop', 'dcpomatic_batch.desktop'])
+         bld.recurse('platform/windows')
+     if bld.env.TARGET_LINUX:
+         bld.recurse('platform/linux')
+     if bld.env.TARGET_OSX:
+         bld.recurse('platform/osx')
  
      for r in ['22x22', '32x32', '48x48', '64x64', '128x128']:
 -        bld.install_files('${PREFIX}/share/icons/hicolor/%s/apps' % r, 'icons/%s/dvdomatic.png' % r)
 +        bld.install_files('${PREFIX}/share/icons/hicolor/%s/apps' % r, 'icons/%s/dcpomatic.png' % r)
  
      if not bld.env.TARGET_WINDOWS:
 -        bld.install_files('${PREFIX}/share/dvdomatic', 'icons/taskbar_icon.png')
 +        bld.install_files('${PREFIX}/share/dcpomatic', 'icons/taskbar_icon.png')
  
      bld.add_post_fun(post)