1 #include "core/command.hpp"
2 #include "core/controllerframe.hpp"
3 #include "core/dispatch.hpp"
4 #include "core/emustatus.hpp"
5 #include "core/mbranch.hpp"
6 #include "core/messages.hpp"
7 #include "core/movie.hpp"
8 #include "library/string.hpp"
10 movie_branches::movie_branches(movie_logic
& _mlogic
, emulator_dispatch
& _dispatch
, status_updater
& _supdater
)
11 : mlogic(_mlogic
), edispatch(_dispatch
), supdater(_supdater
)
15 std::string
movie_branches::name(const std::string
& internal
)
19 return "(Default branch)";
22 std::set
<std::string
> movie_branches::enumerate()
24 std::set
<std::string
> r
;
27 for(auto& i
: mlogic
.get_mfile().branches
)
32 std::string
movie_branches::get()
36 return mlogic
.get_mfile().current_branch();
39 void movie_branches::set(const std::string
& branch
)
41 moviefile
& mf
= mlogic
.get_mfile();
42 if(!mlogic
.get_movie().readonly_mode())
43 (stringfmt() << "Branches are only switchable in readonly mode.").throwex();
44 if(!mf
.branches
.count(branch
))
45 (stringfmt() << "Branch '" << name(branch
) << "' does not exist.").throwex();
46 if(!mlogic
.get_movie().compatible(mf
.branches
[branch
]))
47 (stringfmt() << "Branch '" << name(branch
) << "' differs in past.").throwex();
48 //Ok, execute the switch.
49 mf
.input
= &mf
.branches
[branch
];
50 mlogic
.get_movie().set_movie_data(mf
.input
);
51 edispatch
.mbranch_change();
53 messages
<< "Switched to branch '" << name(branch
) << "'" << std::endl
;
56 void movie_branches::_new(const std::string
& branch
, const std::string
& from
)
58 moviefile
& mf
= mlogic
.get_mfile();
59 if(mf
.branches
.count(branch
))
60 (stringfmt() << "Branch '" << name(branch
) << "' already exists.").throwex();
61 mf
.fork_branch(from
, branch
);
62 messages
<< "Created branch '" << name(branch
) << "'" << std::endl
;
63 edispatch
.mbranch_change();
66 void movie_branches::rename(const std::string
& oldn
, const std::string
& newn
)
68 moviefile
& mf
= mlogic
.get_mfile();
71 if(!mf
.branches
.count(oldn
))
72 (stringfmt() << "Branch '" << name(oldn
) << "' does not exist.").throwex();
73 if(mf
.branches
.count(newn
))
74 (stringfmt() << "Branch '" << name(newn
) << "' already exists.").throwex();
75 mf
.fork_branch(oldn
, newn
);
76 if(mlogic
.get_mfile().current_branch() == oldn
) {
77 mf
.input
= &mf
.branches
[newn
];
78 mlogic
.get_movie().set_movie_data(mf
.input
);
80 mf
.branches
.erase(oldn
);
81 messages
<< "Renamed branch '" << name(oldn
) << "' to '" << name(newn
) << "'" << std::endl
;
82 edispatch
.mbranch_change();
86 void movie_branches::_delete(const std::string
& branch
)
88 moviefile
& mf
= mlogic
.get_mfile();
89 if(!mf
.branches
.count(branch
))
90 (stringfmt() << "Branch '" << name(branch
) << "' does not exist.").throwex();
91 if(mlogic
.get_mfile().current_branch() == branch
)
92 (stringfmt() << "Can't delete current branch '" << name(branch
) << "'.").throwex();
93 mlogic
.get_mfile().branches
.erase(branch
);
94 messages
<< "Deleted branch '" << name(branch
) << "'" << std::endl
;
95 edispatch
.mbranch_change();
98 std::set
<std::string
> movie_branches::_movie_branches(const std::string
& filename
)
100 moviefile::branch_extractor
e(filename
);
101 return e
.enumerate();
104 void movie_branches::import_branch(const std::string
& filename
, const std::string
& ibranch
,
105 const std::string
& branchname
, int mode
)
107 auto& mv
= mlogic
.get_mfile();
108 if(mv
.branches
.count(branchname
) && &mv
.branches
[branchname
] == mv
.input
)
109 (stringfmt() << "Can't overwrite current branch.").throwex();
111 portctrl::frame_vector
v(mv
.input
->get_types());
112 if(mode
== MBRANCH_IMPORT_TEXT
|| mode
== MBRANCH_IMPORT_BINARY
) {
113 std::ifstream
file(filename
, (mode
== MBRANCH_IMPORT_BINARY
) ? std::ios_base::binary
:
116 (stringfmt() << "Can't open '" << filename
<< "' for reading.").throwex();
117 portctrl::frame_vector::notify_freeze
freeze(v
);
118 if(mode
== MBRANCH_IMPORT_BINARY
) {
119 uint64_t stride
= v
.get_stride();
120 uint64_t pageframes
= v
.get_frames_per_page();
123 size_t pagesize
= stride
* pageframes
;
125 v
.resize(vsize
+ pageframes
);
126 unsigned char* contents
= v
.get_page_buffer(pagenum
++);
127 file
.read(reinterpret_cast<char*>(contents
), pagesize
);
128 vsize
+= (file
.gcount() / stride
);
134 portctrl::frame tmpl
= v
.blank_frame(false);
136 std::getline(file
, line
);
138 if(line
.length() == 0)
140 tmpl
.deserialize(line
.c_str());
144 } else if(mode
== MBRANCH_IMPORT_MOVIE
) {
145 moviefile::branch_extractor
e(filename
);
148 bool created
= !mv
.branches
.count(branchname
);
150 mv
.branches
[branchname
] = v
;
153 mv
.branches
.erase(branchname
);
157 void movie_branches::export_branch(const std::string
& filename
, const std::string
& branchname
, bool binary
)
159 auto& mv
= mlogic
.get_mfile();
160 if(!mv
.branches
.count(branchname
))
161 (stringfmt() << "Branch '" << branchname
<< "' does not exist.").throwex();
162 auto& v
= mv
.branches
[branchname
];
163 std::ofstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::out
);
165 (stringfmt() << "Can't open '" << filename
<< "' for writing.").throwex();
167 uint64_t stride
= v
.get_stride();
168 uint64_t pageframes
= v
.get_frames_per_page();
169 uint64_t vsize
= v
.size();
172 uint64_t count
= (vsize
> pageframes
) ? pageframes
: vsize
;
173 size_t bytes
= count
* stride
;
174 unsigned char* content
= v
.get_page_buffer(pagenum
++);
175 file
.write(reinterpret_cast<char*>(content
), bytes
);
179 char buf
[MAX_SERIALIZED_SIZE
];
180 for(uint64_t i
= 0; i
< v
.size(); i
++) {
182 file
<< buf
<< std::endl
;
186 (stringfmt() << "Can't write to '" << filename
<< "'.").throwex();