Esempio n. 1
0
/////////////
// Open file
void MatroskaWrapper::Open(wxString filename) {
    // Make sure it's closed first
    Close();

    // Open
    char err[2048];
    input = new MkvStdIO(filename);
    if (input->fp) {
        file = mkv_Open(input,err,sizeof(err));

        // Failed parsing
        if (!file) {
            delete input;
            throw wxString(_T("MatroskaParser error: ") + wxString(err,wxConvUTF8)).c_str();
        }

        Parse();
    }

    // Failed opening
    else {
        delete input;
        throw _T("Unable to open Matroska file for parsing.");
    }
}
Esempio n. 2
0
bool MatroskaWrapper::HasSubtitles(agi::fs::path const& filename) {
	char err[2048];
	try {
		MkvStdIO input(filename);
		agi::scoped_holder<MatroskaFile*, decltype(&mkv_Close)> file(mkv_Open(&input, err, sizeof(err)), mkv_Close);
		if (!file) return false;

		// Find tracks
		auto tracks = mkv_GetNumTracks(file);
		for (auto track : boost::irange(0u, tracks)) {
			auto trackInfo = mkv_GetTrackInfo(file, track);

			if (trackInfo->Type == 0x11 && !trackInfo->CompEnabled) {
				std::string CodecID(trackInfo->CodecID);
				if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8")
					return true;
			}
		}
	}
	catch (...) {
		// We don't care about why we couldn't read subtitles here
	}

	return false;
}
Esempio n. 3
0
MatroskaFile *openMatroskaFile(char *filePath, StdIoStream *ioStream)
{
	char err_msg[256];

	/* fill in I/O object */ 
	ioStream->base.read = (int(*)(struct InputStream *, ulonglong, void *, int))StdIoRead;
	ioStream->base.scan = (longlong(*)(struct InputStream *, ulonglong, unsigned int))StdIoScan;
	ioStream->base.getcachesize = (unsigned int (*)(struct InputStream *))StdIoGetCacheSize; 
	ioStream->base.geterror = (const char *(*)(struct InputStream *))StdIoGetLastError;
	ioStream->base.memalloc = (void *(*)(struct InputStream *, size_t))StdIoMalloc;
	ioStream->base.memrealloc = (void *(*)(struct InputStream *, void *, size_t))StdIoRealloc;
	ioStream->base.memfree = (void(*)(struct InputStream *, void *))StdIoFree;
	ioStream->base.progress = (int (*)(struct InputStream *, uint64_t, uint64_t))StdIoProgress;

	/* open source file */ 
	ioStream->fp = fopen(filePath,"r"); 
	if (ioStream->fp == NULL) { 
		fprintf(stderr, "Can't open '%s': %s\n", filePath, strerror(errno)); 
		return NULL; 
	} 

	setvbuf(ioStream->fp, NULL, _IOFBF, CACHESIZE); 

	/* initialize matroska parser */ 
	MatroskaFile *mf = mkv_Open(&ioStream->base, /* pointer to I/O object */ 
					   //		  0, /* starting position in the file */ 
					   //		  0,
					   		  err_msg, sizeof(err_msg)); /* error message is returned here */ 

	if (mf == NULL) 
	{ 
		fclose(ioStream->fp); 
		fprintf(stderr, "Can't parse Matroska file: %s\n", err_msg); 
		return NULL; 
	} 

	return mf;	
}
Esempio n. 4
0
void MatroskaWrapper::GetSubtitles(agi::fs::path const& filename, AssFile *target) {
	MkvStdIO input(filename);
	char err[2048];
	agi::scoped_holder<MatroskaFile*, decltype(&mkv_Close)> file(mkv_Open(&input, err, sizeof(err)), mkv_Close);
	if (!file) throw MatroskaException(err);

	// Get info
	unsigned tracks = mkv_GetNumTracks(file);
	std::vector<unsigned> tracksFound;
	std::vector<std::string> tracksNames;

	// Find tracks
	for (auto track : boost::irange(0u, tracks)) {
		auto trackInfo = mkv_GetTrackInfo(file, track);
		if (trackInfo->Type != 0x11 || trackInfo->CompEnabled) continue;

		// Known subtitle format
		std::string CodecID(trackInfo->CodecID);
		if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") {
			tracksFound.push_back(track);
			tracksNames.emplace_back(agi::format("%d (%s %s)", track, CodecID, trackInfo->Language));
			if (trackInfo->Name) {
				tracksNames.back() += ": ";
				tracksNames.back() += trackInfo->Name;
			}
		}
	}

	// No tracks found
	if (tracksFound.empty())
		throw MatroskaException("File has no recognised subtitle tracks.");

	unsigned trackToRead;
	// Only one track found
	if (tracksFound.size() == 1)
		trackToRead = tracksFound[0];
	// Pick a track
	else {
		int choice = wxGetSingleChoiceIndex(_("Choose which track to read:"), _("Multiple subtitle tracks found"), to_wx(tracksNames));
		if (choice == -1)
			throw agi::UserCancelException("canceled");

		trackToRead = tracksFound[choice];
	}

	// Picked track
	mkv_SetTrackMask(file, ~(1 << trackToRead));
	auto trackInfo = mkv_GetTrackInfo(file, trackToRead);
	std::string CodecID(trackInfo->CodecID);
	bool srt = CodecID == "S_TEXT/UTF8";
	bool ssa = CodecID == "S_TEXT/SSA";

	AssParser parser(target, !ssa);

	// Read private data if it's ASS/SSA
	if (!srt) {
		// Read raw data
		std::string priv((const char *)trackInfo->CodecPrivate, trackInfo->CodecPrivateSize);

		// Load into file
		boost::char_separator<char> sep("\r\n");
		for (auto const& cur : boost::tokenizer<boost::char_separator<char>>(priv, sep))
			parser.AddLine(cur);
	}
	// Load default if it's SRT
	else {
		target->LoadDefault(false, OPT_GET("Subtitle Format/SRT/Default Style Catalog")->GetString());
		parser.AddLine("[Events]");
	}

	// Read timecode scale
	auto segInfo = mkv_GetFileInfo(file);
	int64_t timecodeScale = mkv_TruncFloat(trackInfo->TimecodeScale) * segInfo->TimecodeScale;

	// Progress bar
	auto totalTime = double(segInfo->Duration) / timecodeScale;
	DialogProgress progress(nullptr, _("Parsing Matroska"), _("Reading subtitles from Matroska file."));
	progress.Run([&](agi::ProgressSink *ps) { read_subtitles(ps, file, &input, srt, totalTime, &parser); });
}