Merge master.
authorCarl Hetherington <cth@carlh.net>
Wed, 3 Sep 2014 23:05:04 +0000 (00:05 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 3 Sep 2014 23:05:04 +0000 (00:05 +0100)
19 files changed:
ChangeLog
debian/changelog
platform/osx/make_dmg.sh
src/lib/film.cc
src/lib/internet.cc
src/lib/ratio.cc
src/lib/ratio.h
src/lib/ui_signaller.h
src/tools/dcpomatic.cc
src/tools/dcpomatic_batch.cc
src/wx/dcp_panel.cc
src/wx/dolby_certificate_dialog.cc
src/wx/dolby_certificate_dialog.h
src/wx/doremi_certificate_dialog.cc
src/wx/doremi_certificate_dialog.h
src/wx/job_manager_view.cc
src/wx/job_manager_view.h
src/wx/wx_util.cc
src/wx/wx_util.h

index bdfdadfef8e7eb7b072633771838ce766010999c..ca321f9720eb0e0055b13ff470d1be2832051a10 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2014-09-03  Carl Hetherington  <cth@carlh.net>
+
+       * Version 1.73.2 released.
+
+2014-09-03  Carl Hetherington  <cth@carlh.net>
+
+       * Fix server certificate downloads on OS X (#376).
+
+2014-09-02  Carl Hetherington  <cth@carlh.net>
+
+       * Improve behaviour of batch converter window when it is shrunk (#338).
+
+2014-09-01  Carl Hetherington  <cth@carlh.net>
+
+       * Version 1.73.1 released.
+
 2014-08-31  Carl Hetherington  <cth@carlh.net>
 
        * Remove configurable CPL <Creator> and use "DCP-o-matic (version) (git)"
index a671a9e8dd38df8a602e17b626ab8b705cbb2b66..99cdc4f584e257115a9bf41656bfbcdd3a4f69b8 100644 (file)
@@ -1,8 +1,4 @@
-<<<<<<< HEAD
 dcpomatic (2.0.4-1) UNRELEASED; urgency=low
-=======
-dcpomatic (1.73.0-1) UNRELEASED; urgency=low
->>>>>>> origin/master
 
   * New upstream release.
   * New upstream release.
index 2e6b444b2960e6d00f760f0ba86766c8012eb471..a14f3cf8c3ad41ccac515dd90c6b0aae0227ad78 100644 (file)
@@ -134,7 +134,7 @@ cp icons/keys.png "$WORK/$resources"
 
 # i18n: DCP-o-matic .mo files
 for lang in de_DE es_ES fr_FR it_IT sv_SE nl_NL; do
-  mkdir "$WORK/$resources/$lang/LC_MESSAGES"
+  mkdir -p "$WORK/$resources/$lang/LC_MESSAGES"
   cp build/src/lib/mo/$lang/*.mo "$WORK/$resources/$lang/LC_MESSAGES"
   cp build/src/wx/mo/$lang/*.mo "$WORK/$resources/$lang/LC_MESSAGES"
   cp build/src/tools/mo/$lang/*.mo "$WORK/$resources/$lang/LC_MESSAGES"
index 577c29e3a55afeb8a7c85e29883c2bf7c30bcff6..475dd68448628afba155ac59981b133f1b1e84f7 100644 (file)
@@ -591,18 +591,22 @@ Film::isdcf_name (bool if_created_now) const
                d << "_" << container()->isdcf_name();
        }
 
-       /* XXX: this only works for content which has been scaled to a given ratio,
-          and uses the first bit of content only.
-       */
+       /* XXX: this uses the first bit of content only */
 
        /* The standard says we don't do this for trailers, for some strange reason */
        if (dcp_content_type() && dcp_content_type()->libdcp_kind() != dcp::TRAILER) {
                ContentList cl = content ();
                Ratio const * content_ratio = 0;
-               for (ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) {
+               for (ContentList::iterator i = cl.begin(); i != cl.end(); ++i) {
                        shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
-                       if (vc && (content_ratio == 0 || vc->scale().ratio() != content_ratio)) {
-                               content_ratio = vc->scale().ratio();
+                       if (vc) {
+                               /* Here's the first piece of video content */
+                               if (vc->scale().ratio ()) {
+                                       content_ratio = vc->scale().ratio ();
+                               } else {
+                                       content_ratio = Ratio::from_ratio (vc->video_size().ratio ());
+                               }
+                               break;
                        }
                }
                
index c28e650fdd92f4514bb850dacd13c7869b040ad4..1c61e96e3bebe3eeced3e1a9a3717ff737675fde 100644 (file)
@@ -56,6 +56,8 @@ get_from_zip_url (string url, string file, function<void (boost::filesystem::pat
        curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, get_from_zip_url_data);
        curl_easy_setopt (curl, CURLOPT_WRITEDATA, f);
        curl_easy_setopt (curl, CURLOPT_FTP_USE_EPSV, 0);
+       /* Maximum time is 20s */
+       curl_easy_setopt (curl, CURLOPT_TIMEOUT, 20);
 
        CURLcode const cr = curl_easy_perform (curl);
 
@@ -117,6 +119,8 @@ ftp_ls (string url)
                url += "/";
        }
        curl_easy_setopt (curl, CURLOPT_URL, url.c_str ());
+       /* 20s timeout */
+       curl_easy_setopt (curl, CURLOPT_TIMEOUT, 20);
 
        string ls_raw;
        struct curl_slist* commands = 0;
index bb69636584167d12b19d358e99d5a25193394d76..fc36415c50638e161e73c8bd1df1ed19d3e01e99 100644 (file)
@@ -56,3 +56,20 @@ Ratio::from_id (string i)
 
        return *j;
 }
+
+/** @return Ratio corresponding to a given fractional ratio (+/- 0.01), or 0 */
+Ratio const *
+Ratio::from_ratio (float r)
+{
+       vector<Ratio const *>::iterator j = _ratios.begin ();
+       while (j != _ratios.end() && fabs ((*j)->ratio() - r) > 0.01) {
+               ++j;
+       }
+
+       if (j == _ratios.end ()) {
+               return 0;
+       }
+
+       return *j;
+}
+   
index 22fc7662c9c9cf28d2a625d45256f8cfcaf789a7..69e3726c83f201e91cf48e5b955e215c6eea8d2c 100644 (file)
@@ -52,6 +52,7 @@ public:
 
        static void setup_ratios ();
        static Ratio const * from_id (std::string i);
+       static Ratio const * from_ratio (float r);
        static std::vector<Ratio const *> all () {
                return _ratios;
        }
index 1d62547f61f79f5019f506b3a5b81712bc49167b..ee4d230d407e566114ae57b491700196c19d21c5 100644 (file)
@@ -54,8 +54,15 @@ public:
                }
        }
 
+       /* Do something next time the UI is idle */
+       template <typename T>
+       void when_idle (T f) {
+               _service.post (f);
+       }
+
        /** Call this in the UI when it is idle */
        size_t ui_idle () {
+               /* This executes any functors that have been post()ed to _service */
                return _service.poll ();
        }
 
index 8763e35cb2abc2e2000323c2dd06ba62787f0595..3bef7bce300f663be2ca9340f7e8d4f9313d6dab 100644 (file)
@@ -802,12 +802,21 @@ class App : public wxApp
                return true;
        }
 
+       /* An unhandled exception has occurred inside the main event loop */
        bool OnExceptionInMainLoop ()
        {
-               error_dialog (0, _("An unknown exception occurred.  Please report this problem to the DCP-o-matic author (carl@dcpomatic.com)."));
+               try {
+                       throw;
+               } catch (exception& e) {
+                       error_dialog (0, wxString::Format (_("An exception occurred (%s).  Please report this problem to the DCP-o-matic author (carl@dcpomatic.com)."), e.what ()));
+               } catch (...) {
+                       error_dialog (0, _("An unknown exception occurred.  Please report this problem to the DCP-o-matic author (carl@dcpomatic.com)."));
+               }
+
+               /* This will terminate the program */
                return false;
        }
-               
+       
        void OnUnhandledException ()
        {
                error_dialog (0, _("An unknown exception occurred.  Please report this problem to the DCP-o-matic author (carl@dcpomatic.com)."));
index 49b341443e4bebaeae755563deae93299efd1d74..de255e65edaeab43959800f8639232f87b5272ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2014 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
@@ -28,6 +28,7 @@
 #include "lib/film.h"
 #include "lib/job_manager.h"
 #include "wx/wx_util.h"
+#include "wx/about_dialog.h"
 #include "wx/wx_ui_signaller.h"
 #include "wx/job_manager_view.h"
 
@@ -61,6 +62,7 @@ class Frame : public wxFrame
 public:
        Frame (wxString const & title)
                : wxFrame (NULL, -1, title)
+               , _sizer (new wxBoxSizer (wxVERTICAL))
        {
                wxMenuBar* bar = new wxMenuBar;
                setup_menu (bar);
@@ -75,24 +77,29 @@ public:
                s->Add (panel, 1, wxEXPAND);
                SetSizer (s);
 
-               wxSizer* sizer = new wxBoxSizer (wxVERTICAL);
-
                JobManagerView* job_manager_view = new JobManagerView (panel, JobManagerView::PAUSE);
-               sizer->Add (job_manager_view, 1, wxALL | wxEXPAND, 6);
+               _sizer->Add (job_manager_view, 1, wxALL | wxEXPAND, 6);
 
                wxSizer* buttons = new wxBoxSizer (wxHORIZONTAL);
                wxButton* add = new wxButton (panel, wxID_ANY, _("Add Film..."));
                add->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&Frame::add_film, this));
                buttons->Add (add, 1, wxALL, 6);
 
-               sizer->Add (buttons, 0, wxALL, 6);
+               _sizer->Add (buttons, 0, wxALL, 6);
 
-               panel->SetSizer (sizer);
+               panel->SetSizer (_sizer);
 
                Bind (wxEVT_CLOSE_WINDOW, boost::bind (&Frame::close, this, _1));
+               Bind (wxEVT_SIZE, boost::bind (&Frame::sized, this, _1));
        }
 
 private:
+       void sized (wxSizeEvent& ev)
+       {
+               _sizer->Layout ();
+               ev.Skip ();
+       }
+       
        bool should_close ()
        {
                if (!JobManager::instance()->work_to_do ()) {
@@ -135,34 +142,9 @@ private:
 
        void help_about ()
        {
-               wxAboutDialogInfo info;
-               info.SetName (_("DCP-o-matic Batch Converter"));
-               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);
+               AboutDialog* d = new AboutDialog (this);
+               d->ShowModal ();
+               d->Destroy ();
        }
 
        void add_film ()
@@ -200,6 +182,7 @@ private:
        }
 
        boost::optional<boost::filesystem::path> _last_parent;
+       wxSizer* _sizer;
 };
 
 static const wxCmdLineEntryDesc command_line_description[] = {
index ce02c46c8663296b5752da7e0768b008962dc4d0..d68edefc897c0d6e9d3031a59dfe87b0d7e2d904 100644 (file)
@@ -311,7 +311,9 @@ DCPPanel::film_changed (int p)
 void
 DCPPanel::film_content_changed (int property)
 {
-       if (property == FFmpegContentProperty::AUDIO_STREAM || property == SubtitleContentProperty::USE_SUBTITLES) {
+       if (property == FFmpegContentProperty::AUDIO_STREAM ||
+           property == SubtitleContentProperty::USE_SUBTITLES ||
+           property == VideoContentProperty::VIDEO_SCALE) {
                setup_dcp_name ();
        }
 }
index a05a3bbc79ff58b73caecc48a70e1afb67bc0038..5e094844de59697771c0af68827733ceddebf983 100644 (file)
@@ -21,6 +21,7 @@
 #include <curl/curl.h>
 #include "lib/compose.hpp"
 #include "lib/internet.h"
+#include "lib/ui_signaller.h"
 #include "dolby_certificate_dialog.h"
 #include "wx_util.h"
 
@@ -74,8 +75,17 @@ DolbyCertificateDialog::setup_countries ()
        
        _country->Append (_("Fetching..."));
        _country->SetSelection (0);
-       run_gui_loop ();
-       
+
+#ifdef DCPOMATIC_OSX
+       /* See DoremiCertificateDialog for discussion about this daft delay */
+       wxMilliSleep (200);
+#endif
+       ui_signaller->when_idle (boost::bind (&DolbyCertificateDialog::finish_setup_countries, this));
+}
+
+void
+DolbyCertificateDialog::finish_setup_countries ()
+{
        list<string> const countries = get_dir ("");
        _country->Clear ();
        for (list<string>::const_iterator i = countries.begin(); i != countries.end(); ++i) {
@@ -89,8 +99,16 @@ DolbyCertificateDialog::country_selected ()
        _cinema->Clear ();
        _cinema->Append (_("Fetching..."));
        _cinema->SetSelection (0);
-       run_gui_loop ();
-       
+
+#ifdef DCPOMATIC_OSX
+       wxMilliSleep (200);
+#endif 
+       ui_signaller->when_idle (boost::bind (&DolbyCertificateDialog::finish_country_selected, this));
+}
+
+void
+DolbyCertificateDialog::finish_country_selected ()
+{
        list<string> const cinemas = get_dir (wx_to_std (_country->GetStringSelection()));
        _cinema->Clear ();
        for (list<string>::const_iterator i = cinemas.begin(); i != cinemas.end(); ++i) {
@@ -104,8 +122,16 @@ DolbyCertificateDialog::cinema_selected ()
        _serial->Clear ();
        _serial->Append (_("Fetching..."));
        _serial->SetSelection (0);
-       run_gui_loop ();
 
+#ifdef DCPOMATIC_OSX
+       wxMilliSleep (200);
+#endif
+       ui_signaller->when_idle (boost::bind (&DolbyCertificateDialog::finish_cinema_selected, this));
+}
+
+void
+DolbyCertificateDialog::finish_cinema_selected ()
+{
        string const dir = String::compose ("%1/%2", wx_to_std (_country->GetStringSelection()), wx_to_std (_cinema->GetStringSelection()));
        list<string> const zips = get_dir (dir);
 
@@ -129,8 +155,17 @@ void
 DolbyCertificateDialog::download ()
 {
        _message->SetLabel (_("Downloading certificate"));
-       run_gui_loop ();
 
+#ifdef DCPOMATIC_OSX
+       wxMilliSleep (200);
+#endif
+
+       ui_signaller->when_idle (boost::bind (&DolbyCertificateDialog::finish_download, this));
+}
+
+void
+DolbyCertificateDialog::finish_download ()
+{
        string const zip = string_client_data (_serial->GetClientObject (_serial->GetSelection ()));
 
        string const file = String::compose (
index 194150363cb11e8504c464ab8a6f187678f1dee4..e9bbffda0ccadb8105d669dd6c56397478f16dba 100644 (file)
@@ -27,9 +27,13 @@ public:
 
 private:
        void download ();
+       void finish_download ();
        void setup_countries ();
+       void finish_setup_countries ();
        void country_selected ();
+       void finish_country_selected ();
        void cinema_selected ();
+       void finish_cinema_selected ();
        void serial_selected ();
        std::list<std::string> get_dir (std::string) const;
 
index b4cd14eaf200af95b740816e4a0c1db182a8b4e8..4b5d58b375536c475a26c6612e03bd0ae4c26351 100644 (file)
@@ -21,6 +21,7 @@
 #include <zip.h>
 #include "lib/compose.hpp"
 #include "lib/util.h"
+#include "lib/ui_signaller.h"
 #include "lib/internet.h"
 #include "doremi_certificate_dialog.h"
 #include "wx_util.h"
@@ -51,8 +52,18 @@ DoremiCertificateDialog::download ()
        }
 
        _message->SetLabel (_("Downloading certificate"));
-       run_gui_loop ();
 
+#ifdef DCPOMATIC_OSX   
+       /* This is necessary on OS X, otherwise the SetLabel() above has no visible effect */
+       wxMilliSleep (200);
+#endif 
+
+       ui_signaller->when_idle (boost::bind (&DoremiCertificateDialog::finish_download, this, serial));
+}
+
+void
+DoremiCertificateDialog::finish_download (string serial)
+{
        /* Try dcp2000, imb and ims prefixes (see mantis #375) */
 
        optional<string> error = get_from_zip_url (
index 28118472692e663a4172b46323f5b6afa96863d6..b249736eca9a39f64a725a362d4514c48a26ed82 100644 (file)
@@ -28,5 +28,7 @@ private:
        void download ();
         void set_sensitivity ();
 
+       void finish_download (std::string serial);
+
        wxTextCtrl* _serial;
 };
index df9c6f5f1d996dfcbccff08753d71b5789c007c6..5146243b412b0ede27ed94a132475d1a7fbcbbc4 100644 (file)
@@ -202,14 +202,24 @@ JobManagerView::JobManagerView (wxWindow* parent, Buttons buttons)
        _panel->SetSizer (_table);
 
        SetScrollRate (0, 32);
+       EnableScrolling (false, true);
 
        Bind (wxEVT_TIMER, boost::bind (&JobManagerView::periodic, this));
        _timer.reset (new wxTimer (this));
        _timer->Start (1000);
-       
+
+       Bind (wxEVT_SIZE, boost::bind (&JobManagerView::sized, this, _1));
        JobManager::instance()->JobAdded.connect (bind (&JobManagerView::job_added, this, _1));
 }
 
+void
+JobManagerView::sized (wxSizeEvent& ev)
+{
+       _table->FitInside (_panel);
+       _table->Layout ();
+       ev.Skip ();
+}
+
 void
 JobManagerView::job_added (weak_ptr<Job> j)
 {
index c4bb1e2189b6e32850a0694c52e65121c957a316..83ce4ee5abb9d837eee80cd90df3800bb9892c80 100644 (file)
@@ -43,6 +43,7 @@ public:
 private:
        void job_added (boost::weak_ptr<Job>);
        void periodic ();
+       void sized (wxSizeEvent &);
 
        wxPanel* _panel;
        wxFlexGridSizer* _table;
index 94a08f37289625eaf4c660ab4ba5c81d6b5cab36..cf8b75dd24b78a66a6c0c7438514ca2b57bd2292 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
@@ -312,14 +312,6 @@ wx_get (wxSpinCtrlDouble* w)
        return w->GetValue ();
 }
 
-void
-run_gui_loop ()
-{
-       while (wxTheApp->Pending ()) {
-               wxTheApp->Dispatch ();
-       }
-}
-
 /** @param s String of the form Context|String
  *  @return translation, or String if no translation is available.
  */
index 6dfc0bf5c5bbb9b4dcf3ef017f8d9af9ed45b5e9..f0e20be9598b015cb13fb8700220d0dfc3308d18 100644 (file)
@@ -63,7 +63,6 @@ extern wxStaticText* add_label_to_grid_bag_sizer (wxGridBagSizer *, wxWindow *,
 extern std::string wx_to_std (wxString);
 extern wxString std_to_wx (std::string);
 extern void dcpomatic_setup_i18n ();
-extern void run_gui_loop ();
 extern wxString context_translation (wxString);
 
 /** @class ThreadedStaticText