1 /*
2    mkvpropedit -- utility for editing properties of existing Matroska files
3 
4    Distributed under the GPL v2
5    see the file COPYING for details
6    or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
7 
8    Written by Moritz Bunkus <moritz@bunkus.org>.
9 */
10 
11 #include "common/common_pch.h"
12 
13 #include <ctime>
14 #include <iostream>
15 
16 #include <QDateTime>
17 
18 #include "common/date_time.h"
19 #include "common/logger.h"
20 #if defined(SYS_WINDOWS)
21 # include "common/logger/windows.h"
22 #endif // SYS_WINDOWS
23 #include "common/fs_sys_helpers.h"
24 #include "common/mm_io_x.h"
25 #include "common/mm_file_io.h"
26 #include "common/mm_proxy_io.h"
27 #include "common/mm_text_io.h"
28 #include "common/path.h"
29 #include "common/strings/formatting.h"
30 
31 namespace mtx::log {
32 
33 target_cptr target_c::s_default_logger;
34 
35 static QDateTime s_program_start_time;
36 
target_c()37 target_c::target_c()
38   : m_log_start{mtx::sys::get_current_time_millis()}
39 {
40 }
41 
42 std::string
format_line(std::string const & message)43 target_c::format_line(std::string const &message) {
44   auto timestamp = mtx::date_time::format(QDateTime::currentDateTime(), "%Y-%m-%d %H:%M:%S");
45   auto line      = fmt::format("[mtx] {0} +{1}ms {2}", timestamp, runtime(), message);
46 
47   if (message.size() && (message[message.size() - 1] != '\n'))
48     line += "\n";
49 
50   return line;
51 }
52 
53 target_c &
get_default_logger()54 target_c::get_default_logger() {
55   if (s_default_logger)
56     return *s_default_logger;
57 
58   auto var = mtx::sys::get_environment_variable("MTX_LOGGER");
59 
60   if (var.empty()) {
61 #if defined(SYS_WINDOWS)
62     var = "debug";
63 #else
64     var = "stderr";
65 #endif // SYS_WINDOWS
66   }
67 
68   auto spec = mtx::string::split(var, ":", 2);
69 
70   if (spec[0] == "file") {
71     auto file = (spec.size() > 1) && !spec[1].empty() ? spec[1] : "mkvtoolnix-debug.txt"s;
72 
73     set_default_logger(target_cptr{new file_target_c{mtx::fs::to_path(file)}});
74 
75 #if defined(SYS_WINDOWS)
76   } else if (spec[0] == "debug") {
77     set_default_logger(target_cptr{new windows_debug_target_c{}});
78 #endif // SYS_WINDOWS
79 
80   } else
81     set_default_logger(target_cptr{new stderr_target_c{}});
82 
83   return *s_default_logger;
84 }
85 
86 void
set_default_logger(target_cptr const & logger)87 target_c::set_default_logger(target_cptr const &logger) {
88   s_default_logger = logger;
89 }
90 
91 int64_t
runtime()92 target_c::runtime() {
93   return s_program_start_time.msecsTo(QDateTime::currentDateTime());
94 }
95 
96 // ----------------------------------------------------------------------
97 
file_target_c(std::filesystem::path file_name)98 file_target_c::file_target_c(std::filesystem::path file_name)
99   : target_c{}
100   , m_file_name{std::move(file_name)}
101 {
102   if (!mtx::fs::is_absolute(m_file_name))
103     m_file_name = std::filesystem::temp_directory_path() / mtx::fs::to_path(m_file_name);
104 
105   if (std::filesystem::is_regular_file(m_file_name)) {
106     std::error_code ec;
107     std::filesystem::remove(m_file_name, ec);
108   }
109 }
110 
111 void
log_line(std::string const & message)112 file_target_c::log_line(std::string const &message) {
113   try {
114     mm_text_io_c out(std::make_shared<mm_file_io_c>(m_file_name.u8string(), std::filesystem::is_regular_file(m_file_name) ? MODE_WRITE : MODE_CREATE));
115     out.setFilePointer(0, libebml::seek_end);
116     out.puts(format_line(message));
117   } catch (mtx::mm_io::exception &ex) {
118   }
119 }
120 
121 // ----------------------------------------------------------------------
122 
stderr_target_c()123 stderr_target_c::stderr_target_c()
124   : target_c{}
125 {
126 }
127 
128 void
log_line(std::string const & message)129 stderr_target_c::log_line(std::string const &message) {
130   std::cerr << message;
131 }
132 
133 // ----------------------------------------------------------------------
134 
135 void
init()136 init() {
137   s_program_start_time = QDateTime::currentDateTime();
138 }
139 
140 }
141