/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "common.h" #include "sabbu.h" #include "gui_status_bar.h" #include "stringutils.h" #include "kryTextFileReader.h" #include "krySubSSA.h" #include "krySubReader.h" #include "krySubReaderSRT.h" #include "krySubReaderSSA.h" extern struct sabbu app; krySubReaderSRT::krySubReaderSRT(char *filename) : krySubReader(filename) { } krySubReaderSRT::~krySubReaderSRT() { this->m_line_parts.ForEach((GFunc) kry_free_minimal, NULL); this->m_line_parts.Clear(); } gboolean krySubReaderSRT::ProcessLineIndex(char *buffer) { for(int i = strlen(buffer) - 1; i >= 0 && (buffer[i] == ' ' || buffer[i] == '\t'); i--) buffer[i] = 0; char *lastchar; strtol(buffer, &lastchar, 10); if(lastchar[0] != 0) return FALSE; return TRUE; } gboolean krySubReaderSRT::ProcessLineTime(char *buffer, kryEventDetailed *event) { char *time_start_str = string_read_token(&buffer, ' ', TRUE); long time_start = -1; if(time_start_str) { time_start = time_string_to_mili(time_start_str, -1, TRUE); kry_free(time_start_str); } if(time_start_str == NULL || time_start == -1) { this->AddError(new kryTextParseError(this->GetLineNumber(), _("Error parsing start time"))); return FALSE; } char *arrow = string_read_token(&buffer, ' ', TRUE); gboolean is_arrow = FALSE; if(arrow) { is_arrow = !strcmp(arrow, "-->"); kry_free(arrow); } if(arrow == NULL || !is_arrow) { this->AddError(new kryTextParseError(this->GetLineNumber(), _("Error parsing arrow between times"))); return FALSE; } char *time_end_str = string_read_token_end(&buffer); long time_end = -1; if(time_end_str) { time_end = time_string_to_mili(time_end_str, -1, TRUE); kry_free(time_end_str); } if(time_end_str == NULL || time_end == -1) { this->AddError(new kryTextParseError(this->GetLineNumber(), _("Error parsing end time"))); return FALSE; } event->SetTime(time_start, time_end); return TRUE; } gboolean krySubReaderSRT::ProcessLineText(char *buffer, kryEventDetailed *event) { if(buffer[0] != 0) { this->m_line_parts.Add(kry_strdup(buffer)); return TRUE; } if(this->m_line_parts.GetLength() == 0) { event->SetText(""); this->AddEvent(event); this->m_line_type = LINE_INDEX; return TRUE; } int offset = 0; int length = 0; kryListIterator iter; this->m_line_parts.GetIterator(&iter); while(char *line = iter.GetNext()) length += strlen(line); length += ((this->m_line_parts.GetLength() - 1)); char *line_text = (char *) kry_malloc(length + 1); line_text[length] = 0; this->m_line_parts.GetIterator(&iter); while(char *line = iter.GetNext()) { if(offset > 0) { line_text[offset] = 10; offset++; } int part_len = strlen(line); memcpy(line_text + offset, line, part_len); offset += part_len; } event->SetText(line_text); kry_free(line_text); this->m_line_parts.ForEach((GFunc) kry_free_minimal, NULL); this->m_line_parts.Clear(); this->AddEvent(event); this->m_line_type = LINE_INDEX; return TRUE; } /* * Reads script data from the given file. * filename: the file to read * subscript: pointer to the structure where the data will be stored (structure must be created via script_new functin) * * Returns * SCRIPT_OK if the file is successfully read. * SCRIPT_ERROR if a fatal error occured while reading */ enum krySubReader::retval krySubReaderSRT::ReadScript (kryScript *script, kryList *error_list) { double prev_progress = 0; char *buffer = NULL; kryList lines; kryEventDetailed *line = NULL; this->m_line_type = LINE_INDEX; this->m_errors = error_list; this->m_script = script; script->SetFilename(this->GetFilename()); if(!this->Open()) return krySubReader::SCRIPT_ERROR; while(TRUE) { char *ptr; int len; if(buffer) { kry_free(buffer); buffer = NULL; } buffer = this->GetLine(); if(!buffer) break; len = strlen(buffer); // don't update too often if(this->GetProgress() - prev_progress > 0.05) { gui_status_bar_set_progress(app.ui.status_bar, this->GetProgress()); prev_progress = this->GetProgress(); } ptr = string_ignore_whitespce(buffer); if(line == NULL) { line = new kryEventDetailed(); line->SetEffect(""); line->SetName(""); line->SetText(""); } if(this->m_line_type == LINE_INDEX && ptr[0] == 0) continue; if(this->m_script->GetEventCount() >= 3 && this->m_line_type == LINE_TIME && ptr[0] == 0) { this->AddError(new kryTextParseError(this->GetLineNumber(), _("Expecting time range, but blank line was found instead"))); delete line; line = NULL; this->m_line_type = LINE_INDEX; continue; } gboolean rv = FALSE; if(this->m_line_type == LINE_INDEX) { rv = this->ProcessLineIndex(ptr); this->m_line_type = LINE_TIME; } else if(this->m_line_type == LINE_TIME) { rv = this->ProcessLineTime(ptr, line); this->m_line_type = LINE_TEXT; } else if(this->m_line_type == LINE_TEXT) { rv = this->ProcessLineText(ptr, line); if(this->m_line_type == LINE_INDEX) line = NULL; } if(!rv && this->m_script->GetEventCount() < 3) { delete line; this->Close(); return krySubReader::SCRIPT_WRONGFORMAT; } } if(buffer) kry_free(buffer); if(this->m_script->GetEventCount() == 0) return krySubReader::SCRIPT_WRONGFORMAT; if(!script->GetStyle("Default")) script->AddDefaultStyle(); this->Close(); this->m_script->SetType(KRY_FORMAT_SRT); this->m_script->SetEncoding(this->GetEncoding()); return krySubReader::SCRIPT_OK; }