Set up for the correct handling of UTF-8 with Windows
[dcpomatic.git] / src / lib / util.cc
index 2b5eb69fb07c64ff5aa1340f53b71e9adadc8c56..56f1b528643226f21b4ffd671baccbf3601221ac 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "util.h"
 #include "exceptions.h"
-#include "scaler.h"
 #include "dcp_content_type.h"
 #include "filter.h"
 #include "cinema_sound_processor.h"
 #include "audio_processor.h"
 #include "safe_stringstream.h"
 #include <dcp/util.h>
-#include <dcp/signer.h>
-#include <dcp/raw_convert.h>
+#include <dcp/picture_asset.h>
+#include <dcp/sound_asset.h>
+#include <dcp/subtitle_asset.h>
+#include <curl/curl.h>
 #include <glib.h>
 #include <pangomm/init.h>
 #include <boost/algorithm/string.hpp>
@@ -82,7 +83,6 @@ using boost::shared_ptr;
 using boost::thread;
 using boost::optional;
 using dcp::Size;
-using dcp::raw_convert;
 
 /** Path to our executable, required by the stacktrace stuff and filled
  *  in during App::onInit().
@@ -184,7 +184,7 @@ int
 addr2line (void const * const addr)
 {
        char addr2line_cmd[512] = { 0 };
-       sprintf (addr2line_cmd, "addr2line -f -p -e %.256s %p > %s", program_name.c_str(), addr, backtrace_file.string().c_str()); 
+       sprintf (addr2line_cmd, "addr2line -f -p -e %.256s %p > %s", program_name.c_str(), addr, backtrace_file.string().c_str());
        return system(addr2line_cmd);
 }
 
@@ -198,19 +198,19 @@ exception_handler(struct _EXCEPTION_POINTERS * info)
        FILE* f = fopen_boost (backtrace_file, "w");
        fprintf (f, "C-style exception %d\n", info->ExceptionRecord->ExceptionCode);
        fclose(f);
-       
+
        if (info->ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW) {
                CONTEXT* context = info->ContextRecord;
                SymInitialize (GetCurrentProcess (), 0, true);
-               
+
                STACKFRAME frame = { 0 };
-               
+
                /* setup initial stack frame */
 #if _WIN64
                frame.AddrPC.Offset    = context->Rip;
                frame.AddrStack.Offset = context->Rsp;
                frame.AddrFrame.Offset = context->Rbp;
-#else  
+#else
                frame.AddrPC.Offset    = context->Eip;
                frame.AddrStack.Offset = context->Esp;
                frame.AddrFrame.Offset = context->Ebp;
@@ -218,7 +218,7 @@ exception_handler(struct _EXCEPTION_POINTERS * info)
                frame.AddrPC.Mode      = AddrModeFlat;
                frame.AddrStack.Mode   = AddrModeFlat;
                frame.AddrFrame.Mode   = AddrModeFlat;
-               
+
                while (
                        StackWalk (
                                IMAGE_FILE_MACHINE_I386,
@@ -235,13 +235,13 @@ exception_handler(struct _EXCEPTION_POINTERS * info)
                        addr2line((void *) frame.AddrPC.Offset);
                }
        } else {
-#ifdef _WIN64          
+#ifdef _WIN64
                addr2line ((void *) info->ContextRecord->Rip);
-#else          
+#else
                addr2line ((void *) info->ContextRecord->Eip);
-#endif         
+#endif
        }
-       
+
        return EXCEPTION_CONTINUE_SEARCH;
 }
 #endif
@@ -273,25 +273,17 @@ terminate ()
                          << e.what() << std::endl;
        }
        catch (...) {
-               std::cerr << __FUNCTION__ << " caught unknown/unhandled exception." 
+               std::cerr << __FUNCTION__ << " caught unknown/unhandled exception."
                          << std::endl;
        }
 
        abort();
 }
 
-/** Call the required functions to set up DCP-o-matic's static arrays, etc.
- *  Must be called from the UI thread, if there is one.
- */
 void
-dcpomatic_setup ()
+dcpomatic_setup_path_encoding ()
 {
 #ifdef DCPOMATIC_WINDOWS
-       boost::filesystem::path p = g_get_user_config_dir ();
-       p /= "backtrace.txt";
-       set_backtrace_file (p);
-       SetUnhandledExceptionFilter(exception_handler);
-
        /* Dark voodoo which, I think, gets boost::filesystem::path to
           correctly convert UTF-8 strings to paths, and also paths
           back to UTF-8 strings (on path::string()).
@@ -306,8 +298,22 @@ dcpomatic_setup ()
        */
        std::locale::global (boost::locale::generator().generate (""));
        boost::filesystem::path::imbue (std::locale ());
-#endif 
-       
+#endif
+}
+
+/** Call the required functions to set up DCP-o-matic's static arrays, etc.
+ *  Must be called from the UI thread, if there is one.
+ */
+void
+dcpomatic_setup ()
+{
+#ifdef DCPOMATIC_WINDOWS
+       boost::filesystem::path p = g_get_user_config_dir ();
+       p /= "backtrace.txt";
+       set_backtrace_file (p);
+       SetUnhandledExceptionFilter(exception_handler);
+#endif
+
        avfilter_register_all ();
 
 #ifdef DCPOMATIC_OSX
@@ -323,15 +329,17 @@ dcpomatic_setup ()
 
        Pango::init ();
        dcp::init ();
-       
+
        Ratio::setup_ratios ();
+       PresetColourConversion::setup_colour_conversion_presets ();
        VideoContentScale::setup_scales ();
        DCPContentType::setup_dcp_content_types ();
-       Scaler::setup_scalers ();
        Filter::setup_filters ();
        CinemaSoundProcessor::setup_cinema_sound_processors ();
        AudioProcessor::setup_audio_processors ();
 
+       curl_global_init (CURL_GLOBAL_ALL);
+
        ui_thread = boost::this_thread::get_id ();
 }
 
@@ -377,15 +385,15 @@ dcpomatic_setup_gettext_i18n (string lang)
        }
 
        setlocale (LC_ALL, "");
-       textdomain ("libdcpomatic");
+       textdomain ("libdcpomatic2");
 
 #if defined(DCPOMATIC_WINDOWS) || defined(DCPOMATIC_OSX)
-       bindtextdomain ("libdcpomatic", mo_path().string().c_str());
-       bind_textdomain_codeset ("libdcpomatic", "UTF8");
-#endif 
+       bindtextdomain ("libdcpomatic2", mo_path().string().c_str());
+       bind_textdomain_codeset ("libdcpomatic2", "UTF8");
+#endif
 
 #ifdef DCPOMATIC_LINUX
-       bindtextdomain ("libdcpomatic", POSIX_LOCALE_PREFIX);
+       bindtextdomain ("libdcpomatic2", LINUX_LOCALE_PREFIX);
 #endif
 }
 
@@ -427,32 +435,19 @@ md5_digest_head_tail (vector<boost::filesystem::path> files, boost::uintmax_t si
                }
 
                boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i]));
-               fseek (f, -this_time, SEEK_END);
+               dcpomatic_fseek (f, -this_time, SEEK_END);
                fread (p, 1, this_time, f);
                p += this_time;
                to_do -= this_time;
                fclose (f);
 
                --i;
-       }               
+       }
        digester.add (buffer.get(), size - to_do);
 
        return digester.get ();
 }
 
-/** @param An arbitrary audio frame rate.
- *  @return The appropriate DCP-approved frame rate (48kHz or 96kHz).
- */
-int
-dcp_audio_frame_rate (int fs)
-{
-       if (fs <= 48000) {
-               return 48000;
-       }
-
-       return 96000;
-}
-
 /** Round a number up to the nearest multiple of another number.
  *  @param c Index.
  *  @param s Array of numbers to round, indexed by c.
@@ -466,17 +461,6 @@ stride_round_up (int c, int const * stride, int t)
        return a - (a % t);
 }
 
-/** @param n A number.
- *  @param r Rounding `boundary' (must be a power of 2)
- *  @return n rounded to the nearest r
- */
-int
-round_to (float n, int r)
-{
-       DCPOMATIC_ASSERT (r == 1 || r == 2 || r == 4);
-       return int (n + float(r) / 2) &~ (r - 1);
-}
-
 /** Trip an assert if the caller is not in the UI thread */
 void
 ensure_ui_thread ()
@@ -513,12 +497,16 @@ audio_channel_name (int c)
 bool
 valid_image_file (boost::filesystem::path f)
 {
+       if (boost::starts_with (f.leaf().string(), "._")) {
+               return false;
+       }
+
        string ext = f.extension().string();
        transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
        return (
                ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" ||
                ext == ".png" || ext == ".bmp" || ext == ".tga" || ext == ".dpx" ||
-               ext == ".j2c" || ext == ".j2k"
+               ext == ".j2c" || ext == ".j2k" || ext == ".jp2"
                );
 }
 
@@ -527,7 +515,7 @@ valid_j2k_file (boost::filesystem::path f)
 {
        string ext = f.extension().string();
        transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
-       return (ext == ".j2k" || ext == ".j2c");
+       return (ext == ".j2k" || ext == ".j2c" || ext == ".jp2");
 }
 
 string
@@ -546,13 +534,13 @@ tidy_for_filename (string f)
 }
 
 dcp::Size
-fit_ratio_within (float ratio, dcp::Size full_frame, int round)
+fit_ratio_within (float ratio, dcp::Size full_frame)
 {
        if (ratio < full_frame.ratio ()) {
-               return dcp::Size (round_to (full_frame.height * ratio, round), full_frame.height);
+               return dcp::Size (rint (full_frame.height * ratio), full_frame.height);
        }
-       
-       return dcp::Size (full_frame.width, round_to (full_frame.width / ratio, round));
+
+       return dcp::Size (full_frame.width, rint (full_frame.width / ratio));
 }
 
 void *
@@ -564,18 +552,21 @@ wrapped_av_malloc (size_t s)
        }
        return p;
 }
-               
-ContentTimePeriod
+
+FFmpegSubtitlePeriod
 subtitle_period (AVSubtitle const & sub)
 {
        ContentTime const packet_time = ContentTime::from_seconds (static_cast<double> (sub.pts) / AV_TIME_BASE);
 
-       ContentTimePeriod period (
+       if (sub.end_display_time == static_cast<uint32_t> (-1)) {
+               /* End time is not known */
+               return FFmpegSubtitlePeriod (packet_time + ContentTime::from_seconds (sub.start_display_time / 1e3));
+       }
+
+       return FFmpegSubtitlePeriod (
                packet_time + ContentTime::from_seconds (sub.start_display_time / 1e3),
                packet_time + ContentTime::from_seconds (sub.end_display_time / 1e3)
                );
-
-       return period;
 }
 
 map<string, string>
@@ -586,7 +577,7 @@ split_get_request (string url)
                KEY,
                VALUE
        } state = AWAITING_QUESTION_MARK;
-       
+
        map<string, string> r;
        string k;
        string v;
@@ -623,3 +614,15 @@ split_get_request (string url)
 
        return r;
 }
+
+string
+video_asset_filename (shared_ptr<dcp::PictureAsset> asset)
+{
+       return "j2c_" + asset->id() + ".mxf";
+}
+
+string
+audio_asset_filename (shared_ptr<dcp::SoundAsset> asset)
+{
+       return "pcm_" + asset->id() + ".mxf";
+}