Advertisement
jacknpoe

Ajuste Fino para Legendas 0.3B (.srt)

Oct 6th, 2013
231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.95 KB | None | 0 0
  1. //#########################################################################//
  2. //                                                                         //
  3. // Ajuste fino para legendas 0.3B (L) 2013 Ricardo Erick Rebêlo (jacknpoe) //
  4. //                                                                         //
  5. // (para avis com .srt utilizar programa <origem> <destino> 0.9975         //
  6. //                                                                         //
  7. //#########################################################################//
  8.  
  9. #include <iostream>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <fstream>
  14. #include <cctype>
  15. #include <sstream>
  16. #include <locale.h>
  17.  
  18. #define SEPARADOR1 ":"
  19. #define SEPARADOR2 ","
  20. #define MODULO 360000000
  21. #define MAXFILENAME 256
  22. #define MAXTAMLINHA 65536
  23. #define EXTENSAO ".srt"
  24.  
  25. using namespace std;
  26.  
  27. // *** modela tempo, mantém valores e faz conversões de tipos
  28. class cTempo {
  29.    long milisegundos;
  30.    char extenso[ 13], extensoinseguro[ 13];
  31. protected:
  32.    void montar_extenso( void);
  33.    long extenso_to_long( char *);
  34. public:
  35.    cTempo( void) { milisegundos = 0; montar_extenso(); };
  36.    cTempo( char * valor) { milisegundos = extenso_to_long( valor); montar_extenso(); };
  37.    cTempo( long   valor) { milisegundos = valor; montar_extenso(); };
  38.    char * as_char( void) { return extensoinseguro; };
  39.    long   as_long( void) { return milisegundos; };
  40.    void set_valor( long   valor) { milisegundos = valor; montar_extenso(); };
  41.    void set_valor( char * valor) { milisegundos = extenso_to_long( valor); montar_extenso(); };
  42.     cTempo operator=( cTempo valor) { milisegundos = valor.milisegundos; montar_extenso(); return *this; }
  43.     cTempo operator*=( double valor) { milisegundos *= valor; montar_extenso(); return *this; };
  44.     cTempo operator/=( double valor) { milisegundos /= valor; montar_extenso(); return *this; };
  45. } oTempo;
  46.  
  47. // *** monta o valor por extenso a partir de milisegundos (redução de erro com MODULO)
  48. void cTempo::montar_extenso( void) {
  49.     char horas[3], minutos[3], segundos[3], milesimos[4]; int temporario;
  50.     temporario = milisegundos % MODULO;
  51.     snprintf( milesimos, 4, "%03d", temporario % 1000); temporario /= 1000;
  52.     snprintf( segundos, 3, "%02d", temporario % 60); temporario /= 60;
  53.     snprintf( minutos, 3, "%02d", temporario % 60); temporario /= 60;
  54.     snprintf( horas, 3, "%02d", temporario);
  55.  
  56.     strcpy( extenso, horas); strcat( extenso, SEPARADOR1);
  57.     strcat( extenso, minutos); strcat( extenso, SEPARADOR1);
  58.     strcat( extenso, segundos); strcat( extenso, SEPARADOR2);
  59.     strcat( extenso, milesimos);  strcpy( extensoinseguro, extenso);   
  60. }
  61.  
  62. // *** retorna o valor em milisegundos a partir de extenso (ignora erros no formato)
  63. long cTempo::extenso_to_long( char * valor) {
  64.     char horas[3], minutos[3], segundos[3], milesimos[4];
  65.  
  66.     horas[0] = valor[0];  horas[1] = valor[1];  horas[2] = 0;
  67.     minutos[0] = valor[3];  minutos[1] = valor[4];  minutos[2] = 0;
  68.     segundos[0] = valor[6];  segundos[1] = valor[7];  segundos[2] = 0;
  69.     milesimos[0] = valor[9];  milesimos[1] = valor[10];  milesimos[2] = valor[11];  milesimos[3] = 0;
  70.  
  71.     return ( ( atoi( horas) * 60 + atoi( minutos) ) * 60 + atoi( segundos) ) * 1000 + atoi( milesimos) ;
  72. }
  73.  
  74. // *** abre arquivos, lê dados, chama conversor, mantém taxa, salva arquivo
  75. class cAjusteLegenda {
  76.     ifstream oArqLeitura; ofstream oArqEscrita; double multiplicador;
  77.     char sArqLeitura[ MAXFILENAME], sArqEscrita[ MAXFILENAME];
  78.     char sArqLeiturai[ MAXFILENAME], sArqEscritai[ MAXFILENAME];
  79. private:
  80.  
  81. // transforma uma string em maiúscula. TODO: utilizar biblioteca padrão
  82.     void minuscula( char * valor, int maximo){
  83.         int indice = 0;
  84.         while( valor[ indice] != 0 and indice < maximo ){
  85.             valor[ indice] = tolower( valor[ indice]);
  86.             indice++;
  87.         };
  88.     }
  89.  
  90. // normaliza os nomes de arquivos. TODO: possibilitar outras extenções?
  91.     void normalizanome( char * nome){
  92.         int tamanho; char final[5];
  93.         tamanho = strlen( nome);
  94.         if( tamanho > 4)
  95.         {
  96.             strcpy( final, &nome[ tamanho-4]);
  97.             minuscula( final, 4);
  98.             if( strcmp( final, EXTENSAO) == 0) return;
  99.         }
  100.         strcat( nome, EXTENSAO);
  101.     }
  102. public:
  103.  
  104.     cAjusteLegenda() { multiplicador = 1; }
  105.  
  106. // aceita parâmetro para multiplicador (simples)
  107.     bool set_multiplicador( char * valor ) {
  108.         return ( ( istringstream ( valor) >> multiplicador) and multiplicador > 0);
  109.     }
  110.  
  111. // aceita parâmetros para multiplicador composto
  112.     bool set_multiplicador( char * diferenca, char * tempo_base) {
  113.         long i_diferenca, i_tempo_base, tamanho;
  114.         char por_extenso[] = "0000000000000";
  115.         if( ( ! ( istringstream ( diferenca) >> i_diferenca)) or i_diferenca == 0) return false;
  116.         tamanho = strlen( tempo_base);
  117.         if( tamanho < 12) por_extenso[ 12 - tamanho] = 0; else por_extenso[ 0] = 0;
  118.         strcat( por_extenso, tempo_base);
  119.         oTempo.set_valor( por_extenso);
  120.         i_tempo_base = oTempo.as_long();
  121.         if( ( i_tempo_base == 0) or ( i_tempo_base <= abs( i_diferenca) ) ) return false;
  122.         multiplicador = ( double ( i_tempo_base) + double ( i_diferenca) ) / ( double ( i_tempo_base));
  123.         return true;
  124.     }
  125.  
  126. // abre o arquivo de leitura
  127.     bool abrearquivoleitura( char * nome){
  128.         strcpy( sArqLeitura, nome);
  129.         normalizanome( sArqLeitura);
  130.         strcpy( sArqLeiturai, sArqLeitura);
  131.         oArqLeitura.open( sArqLeitura, ios::in);
  132.         return oArqLeitura.is_open();
  133.     }
  134.  
  135. // abre o arquivo para escrita
  136.     bool abrearquivoescrita( char * nome){
  137.         strcpy( sArqEscrita, nome);
  138.         normalizanome( sArqEscrita);
  139.         strcpy( sArqEscritai, sArqEscrita);
  140.         oArqEscrita.open( sArqEscrita, ios::out); //, ios::nocreate
  141.         return oArqEscrita.is_open();
  142.     }
  143.  
  144. // altera o tempo na linha com  -->
  145.     void recalcula( char * cLinha){
  146.         char * cTempo1, * cTempo2, * cEntre;
  147.        
  148.         cTempo1 = strtok( cLinha, " \t" );
  149.         cEntre  = strtok( NULL, " \t" );
  150.         cTempo2 = strtok( NULL, " \t" );
  151.  
  152.         // TODA A MÁGICA DE ALTERAÇÃO DO TEMPO SE DÁ NESSAS QUATRO LINHAS:
  153.         oTempo.set_valor( cTempo1); oTempo *= multiplicador; cTempo1 = oTempo.as_char();
  154.         strcpy( cLinha, cTempo1); strcat( cLinha, " --> ");
  155.         oTempo.set_valor( cTempo2); oTempo *= multiplicador; cTempo2 = oTempo.as_char();
  156.         strcat( cLinha, cTempo2);
  157.     }
  158.    
  159.     char * get_sArqLeitura( void) { return sArqLeiturai; };
  160.  
  161.     char * get_sArqEscrita( void) { return sArqEscritai; };
  162.  
  163. // lê de um arquivo e grava em outro (selecionando as linhas com --> para alteração
  164.     bool processa( void){
  165.         char sTeste[ MAXTAMLINHA];
  166.         while( ! oArqLeitura.eof() ) {
  167.             oArqLeitura.getline( sTeste, MAXTAMLINHA-1);
  168.             if( strstr( sTeste, " --> ") != NULL) recalcula( sTeste);
  169.             oArqEscrita << sTeste << "\n";
  170.             if( oArqEscrita.bad() or oArqEscrita.fail()) return false;
  171.         }
  172.         return true;
  173.     }
  174.  
  175.     ~cAjusteLegenda() {
  176.         if( oArqLeitura.is_open() ) oArqLeitura.close();
  177.         if( oArqEscrita.is_open() ) oArqEscrita.close();
  178.     }
  179.  
  180. } oAjusteLegenda;
  181.  
  182. // *** centraliza todas as mensagens para o usuário e os diálogos (traduzir aqui)
  183. class cMensagem {
  184.     char nomeprograma[ MAXFILENAME];
  185.  
  186. public:
  187.  
  188. // ajuda (quando não tem parâmetros suficientes)
  189.     void ajuda( void) {
  190.         cout << "\nAjuste fino para legendas 0.3B (L) 2013 Ricardo Erick Rebêlo (jacknpoe)";
  191.         cout << "\n\nSintaxes: 1. " << nomeprograma << " <origem> <destino> <diferença> <tempo base>";
  192.         cout << "\n          2. " << nomeprograma << " <origem> <destino> <multiplicador>";
  193.         cout << "\n\norigem: arquivo precisa existir, no formato " << EXTENSAO << ", sem erros.";
  194.         cout << "\ndestino: " << EXTENSAO << ", não pode ser o mesmo que o arquivo de origem. Será sobrescrito.";
  195.         cout << "\ndiferença: milissegundos a serem aplicados ao tempo base (comparativo).";
  196.         cout << "\n           (se negativo adiantará, se positivo atrasará a legenda)";
  197.         cout << "\ntempo base: momento (HH:MM:SS,mmm) em que a diferença se aplica em 100%.";
  198.         cout << "\nmultiplicador: número positivo não inteiro pelo qual o tempo será multiplicado.";
  199.         cout << "\n\nExemplos:";
  200.         cout << "\n\n1. " << nomeprograma << " teste1 teste2 -9750 00:50:30,000";
  201.         cout << "\n   ajusta de forma que, em cinquenta minutos e meio de vídeo a legenda seja";
  202.         cout << "\n   adiantada 9,75 segundos (aproximadamente 99,6782% do tempo)";
  203.         cout << "\n\n2. " << nomeprograma << " teste1 teste2 0.9975     (padrão para alguns .avi)";
  204.         cout << "\n   ajusta as legendas de teste1" << EXTENSAO << " em 99,75% do tempo e grava em teste2" << EXTENSAO << ".\n";
  205.     }
  206.  
  207. // encontra o nome do executável, sem caminho e sem extenção
  208.     void set_nomeprograma( char * executavel){
  209.         int inicio = 0, fim = 0, indice;
  210.         for( indice = strlen( executavel)-1; indice >= 0 and inicio == 0; indice-- ) {
  211.             if( executavel[indice] == '.' and fim == 0) fim = indice - 1;
  212.             if( fim != 0 and inicio == 0 and
  213.                 ( executavel[indice] == '\\' or executavel[indice] == '/' or executavel[indice] == '>' ) )
  214.                     inicio = indice + 1;
  215.         }
  216.         if( fim != 0 and inicio <= fim )    {  
  217.             strcpy( nomeprograma, &executavel[ inicio]);
  218.             nomeprograma[fim-inicio+1] = 0;
  219.         } else if ( fim == 0 and inicio == 0 ) strcpy( nomeprograma, executavel);
  220.           else strcpy( nomeprograma, "indeterminado");
  221.     }
  222.  
  223. // vários tipos de erros e mensagens (auto-explicativas)
  224.     void erro_multiplicador( char * valor) {
  225.         cout << "\nParâmetro '" << valor << "' inválido (precisa ser numérico maior que zero).\n";
  226.     }
  227.  
  228.     void erro_multiplicador( char * diferenca, char * tempo_base) {
  229.         cout << "\nUm ou mais parâmetros '" << diferenca << "' e '"<< tempo_base << "' inválido(s).\n";
  230.     }
  231.  
  232.     void erro_abertura( void){
  233.         cout << "\nArquivo " << oAjusteLegenda.get_sArqLeitura() << " não pode ser aberto.\n";
  234.     }
  235.  
  236.     void erro_escrita( void){
  237.         cout << "\nArquivo " << oAjusteLegenda.get_sArqEscrita() << " não pode ser aberto ou criado.\n";
  238.     }
  239.  
  240.     void erro_processo( void){
  241.         cout << "\nOcorreu um erro no processo de criação do arquivo " << oAjusteLegenda.get_sArqEscrita() << ".\n";
  242.     }
  243.  
  244.     void processando( void){
  245.         cout << "\nProcessando arquivo " << oAjusteLegenda.get_sArqEscrita() << "...\n";
  246.     }
  247.  
  248.     void sucesso( void){
  249.         cout << "\nArquivo " << oAjusteLegenda.get_sArqEscrita() << " gerado com sucesso.\n";
  250.     }
  251. } oMensagem;
  252.  
  253.  
  254. // ***  M A I N  () *******************************************************************
  255.  
  256. int main( int argc, char* argv[]) {
  257.     setlocale( LC_ALL, "");     // para todos os caracteres do Dev aparecerem iguais no prompt
  258.  
  259.     oMensagem.set_nomeprograma( argv[ 0]);
  260.  
  261.     if( argc < 4) { oMensagem.ajuda(); exit( 1); };
  262.  
  263.     if( argc == 4) if( ! oAjusteLegenda.set_multiplicador( argv[ 3]) )
  264.                                             { oMensagem.erro_multiplicador( argv[ 3]); exit( 2); }
  265.  
  266.     if( argc == 5) if( ! oAjusteLegenda.set_multiplicador( argv[ 3], argv[ 4]) )
  267.                                             { oMensagem.erro_multiplicador( argv[ 3], argv[ 4]); exit( 3); }
  268.  
  269.     if( ! oAjusteLegenda.abrearquivoleitura( argv[ 1]) ) { oMensagem.erro_abertura(); exit( 4); }
  270.  
  271.     if( ! oAjusteLegenda.abrearquivoescrita( argv[ 2]) ) { oMensagem.erro_escrita(); exit( 5); }
  272.  
  273.     oMensagem.processando(); if( ! oAjusteLegenda.processa() ) { oMensagem.erro_processo(); exit( 6); }
  274.  
  275.     oMensagem.sucesso();    return EXIT_SUCCESS;
  276. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement