1 #include "common/common_pch.h"
2 
3 #include <unordered_map>
4 
5 #include "common/bluray/util.h"
6 #include "common/debugging.h"
7 #include "common/id_info.h"
8 #include "common/mm_file_io.h"
9 #include "common/mm_mpls_multi_file_io.h"
10 #include "common/mm_mpls_multi_file_io_p.h"
11 #include "common/path.h"
12 #include "common/strings/formatting.h"
13 
14 namespace {
15 debugging_option_c s_debug{"mpls|mpls_multi_io"};
16 }
17 
mm_mpls_multi_file_io_c(std::vector<std::filesystem::path> const & file_names,std::string const & display_file_name,mtx::bluray::mpls::parser_cptr const & mpls_parser)18 mm_mpls_multi_file_io_c::mm_mpls_multi_file_io_c(std::vector<std::filesystem::path> const &file_names,
19                                                  std::string const &display_file_name,
20                                                  mtx::bluray::mpls::parser_cptr const &mpls_parser)
21   : mm_file_io_c{*new mm_mpls_multi_file_io_private_c{file_names, display_file_name, mpls_parser}}
22 {
23 }
24 
mm_mpls_multi_file_io_c(mm_mpls_multi_file_io_private_c & p)25 mm_mpls_multi_file_io_c::mm_mpls_multi_file_io_c(mm_mpls_multi_file_io_private_c &p)
26   : mm_file_io_c{p}
27 {
28 }
29 
~mm_mpls_multi_file_io_c()30 mm_mpls_multi_file_io_c::~mm_mpls_multi_file_io_c() { // NOLINT(modernize-use-equals-default) due to pimpl idiom requiring explicit dtor declaration somewhere
31 }
32 
33 std::vector<mtx::bluray::mpls::chapter_t> const &
get_chapters() const34 mm_mpls_multi_file_io_c::get_chapters()
35   const {
36   return p_func()->mpls_parser->get_chapters();
37 }
38 
39 mm_io_cptr
open_multi(std::string const & display_file_name)40 mm_mpls_multi_file_io_c::open_multi(std::string const &display_file_name) {
41   try {
42     mm_file_io_c in{display_file_name};
43     return open_multi(in);
44   } catch (mtx::mm_io::exception &) {
45     return mm_io_cptr{};
46   }
47 }
48 
49 mm_io_cptr
open_multi(mm_io_c & in)50 mm_mpls_multi_file_io_c::open_multi(mm_io_c &in) {
51   auto mpls_parser = std::make_shared<mtx::bluray::mpls::parser_c>();
52 
53   if (!mpls_parser->parse(in) || mpls_parser->get_playlist().items.empty()) {
54     mxdebug_if(s_debug, fmt::format("Not handling because {0}\n", mpls_parser->is_ok() ? "playlist is empty" : "parser not OK"));
55     return mm_io_cptr{};
56   }
57 
58   std::vector<std::filesystem::path> file_names;
59 
60   for (auto const &item : mpls_parser->get_playlist().items) {
61     auto file = mtx::bluray::find_other_file(mtx::fs::to_path(in.get_file_name()), mtx::fs::to_path("STREAM") / mtx::fs::to_path(fmt::format("{0}.{1}", item.clip_id, balg::to_lower_copy(item.codec_id))));
62     if (file.empty())
63       file = mtx::bluray::find_other_file(mtx::fs::to_path(in.get_file_name()), mtx::fs::to_path("STREAM") / mtx::fs::to_path(fmt::format("{0}.{1}", item.clip_id, "m2ts")));
64 
65     if (!file.empty())
66       file_names.push_back(file);
67 
68     mxdebug_if(s_debug, fmt::format("Item clip ID: {0} codec ID: {1}: have file? {2} file: {3}\n", item.clip_id, item.codec_id, !file.empty(), file.u8string()));
69   }
70 
71   mxdebug_if(s_debug, fmt::format("Number of files left: {0}\n", file_names.size()));
72 
73   if (file_names.empty())
74     return mm_io_cptr{};
75 
76   return mm_io_cptr{new mm_mpls_multi_file_io_c{file_names, file_names[0].u8string(), mpls_parser}};
77 }
78 
79 void
create_verbose_identification_info(mtx::id::info_c & info)80 mm_mpls_multi_file_io_c::create_verbose_identification_info(mtx::id::info_c &info) {
81   auto p = p_func();
82 
83   info.add(mtx::id::playlist,          true);
84   info.add(mtx::id::playlist_duration, p->mpls_parser->get_playlist().duration.to_ns());
85   info.add(mtx::id::playlist_size,     p->total_size);
86   info.add(mtx::id::playlist_chapters, p->mpls_parser->get_chapters().size());
87 
88   auto file_names = nlohmann::json::array();
89   for (auto &file : p->files)
90     file_names.push_back(file.u8string());
91 
92   info.add(mtx::id::playlist_file, file_names);
93 }
94 
95 std::string
get_file_name() const96 mm_mpls_multi_file_io_c::get_file_name()
97   const {
98   return p_func()->display_file_name;
99 }
100 
101 std::vector<std::filesystem::path> const &
get_file_names() const102 mm_mpls_multi_file_io_c::get_file_names()
103   const {
104   return p_func()->files;
105 }
106 
107 mtx::bluray::mpls::parser_c const &
get_mpls_parser() const108 mm_mpls_multi_file_io_c::get_mpls_parser()
109   const {
110   return *p_func()->mpls_parser;
111 }
112