| 198 | } |
| 199 | |
| 200 | void MatroskaWrapper::GetSubtitles(agi::fs::path const& filename, AssFile *target) { |
| 201 | MkvStdIO input(filename); |
| 202 | char err[2048]; |
| 203 | agi::scoped_holder<MatroskaFile*, decltype(&mkv_Close)> file(mkv_Open(&input, err, sizeof(err)), mkv_Close); |
| 204 | if (!file) throw MatroskaException(err); |
| 205 | |
| 206 | // Get info |
| 207 | unsigned tracks = mkv_GetNumTracks(file); |
| 208 | std::vector<unsigned> tracksFound; |
| 209 | std::vector<std::string> tracksNames; |
| 210 | |
| 211 | // Find tracks |
| 212 | for (auto track : boost::irange(0u, tracks)) { |
| 213 | auto trackInfo = mkv_GetTrackInfo(file, track); |
| 214 | if (trackInfo->Type != 0x11) continue; |
| 215 | |
| 216 | // Known subtitle format |
| 217 | std::string CodecID(trackInfo->CodecID); |
| 218 | if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") { |
| 219 | tracksFound.push_back(track); |
| 220 | tracksNames.emplace_back(agi::format("%d (%s %s)", track, CodecID, trackInfo->Language)); |
| 221 | if (trackInfo->Name) { |
| 222 | tracksNames.back() += ": "; |
| 223 | tracksNames.back() += trackInfo->Name; |
| 224 | } |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | // No tracks found |
| 229 | if (tracksFound.empty()) |
| 230 | throw MatroskaException("File has no recognised subtitle tracks."); |
| 231 | |
| 232 | unsigned trackToRead; |
| 233 | // Only one track found |
| 234 | if (tracksFound.size() == 1) |
| 235 | trackToRead = tracksFound[0]; |
| 236 | // Pick a track |
| 237 | else { |
| 238 | int choice = wxGetSingleChoiceIndex(_("Choose which track to read:"), _("Multiple subtitle tracks found"), to_wx(tracksNames)); |
| 239 | if (choice == -1) |
| 240 | throw agi::UserCancelException("canceled"); |
| 241 | |
| 242 | trackToRead = tracksFound[choice]; |
| 243 | } |
| 244 | |
| 245 | // Picked track |
| 246 | mkv_SetTrackMask(file, ~(1 << trackToRead)); |
| 247 | auto trackInfo = mkv_GetTrackInfo(file, trackToRead); |
| 248 | std::string CodecID(trackInfo->CodecID); |
| 249 | bool srt = CodecID == "S_TEXT/UTF8"; |
| 250 | bool ssa = CodecID == "S_TEXT/SSA"; |
| 251 | |
| 252 | AssParser parser(target, !ssa); |
| 253 | |
| 254 | // Read private data if it's ASS/SSA |
| 255 | if (!srt) { |
| 256 | // Read raw data |
| 257 | std::string priv((const char *)trackInfo->CodecPrivate, trackInfo->CodecPrivateSize); |
nothing calls this directly
no test coverage detected