This commit is contained in:
Ruslan Kuchumov 2014-07-09 22:37:16 +00:00
parent 5a09c116f6
commit 947333ea64
6 changed files with 645 additions and 0 deletions

181
src/608.c
View File

@ -250,6 +250,187 @@ void handle_text_attr(const unsigned char c1, const unsigned char c2, struct s_c
}
}
void write_subtitle_file_footer(struct ccx_s_write *out)
{
switch (ccx_options.write_format)
{
case CCX_OF_SAMI:
sprintf ((char *) str,"</BODY></SAMI>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str);
write(out->fh, enc_buffer, enc_buffer_used);
break;
case CCX_OF_SMPTETT:
sprintf ((char *) str,"</div></body></tt>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str);
write (out->fh, enc_buffer,enc_buffer_used);
break;
case CCX_OF_SPUPNG:
write_spumux_footer(out);
break;
default: // Nothing to do, no footer on this format
break;
}
}
void write_subtitle_file_header(struct ccx_s_write *out)
{
switch (ccx_options.write_format)
{
case CCX_OF_SRT: // Subrip subtitles have no header
break;
case CCX_OF_SAMI: // This header brought to you by McPoodle's CCASDI
//fprintf_encoded (wb->fh, sami_header);
REQUEST_BUFFER_CAPACITY(strlen (sami_header)*3);
enc_buffer_used=encode_line (enc_buffer,(unsigned char *) sami_header);
write (out->fh, enc_buffer,enc_buffer_used);
break;
case CCX_OF_SMPTETT: // This header brought to you by McPoodle's CCASDI
//fprintf_encoded (wb->fh, sami_header);
REQUEST_BUFFER_CAPACITY(strlen (smptett_header)*3);
enc_buffer_used=encode_line (enc_buffer,(unsigned char *) smptett_header);
write(out->fh, enc_buffer, enc_buffer_used);
break;
case CCX_OF_RCWT: // Write header
write(out->fh, rcwt_header, sizeof(rcwt_header));
break;
case CCX_OF_SPUPNG:
write_spumux_header(out);
break;
case CCX_OF_TRANSCRIPT: // No header. Fall thru
default:
break;
}
}
void write_cc_line_as_transcript(struct eia608_screen *data, struct s_context_cc608 *context, int line_number)
{
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
if (ccx_options.sentence_cap)
{
capitalize (line_number,data);
correct_case(line_number,data);
}
int length = get_decoder_line_basic (subline, line_number, data);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
}
if (length>0)
{
if (context->ts_start_of_current_line == -1)
{
// CFS: Means that the line has characters but we don't have a timestamp for the first one. Since the timestamp
// is set for example by the write_char function, it possible that we don't have one in empty lines (unclear)
// For now, let's not consider this a bug as before and just return.
// fatal (EXIT_BUG_BUG, "Bug in timedtranscript (ts_start_of_current_line==-1). Please report.");
return;
}
if (ccx_options.transcript_settings.showStartTime){
char buf1[80];
if (ccx_options.transcript_settings.relativeTimestamp){
millis_to_date(context->ts_start_of_current_line + subs_delay, buf1);
fdprintf(context->out->fh, "%s|", buf1);
}
else {
mstotime(context->ts_start_of_current_line + subs_delay, &h1, &m1, &s1, &ms1);
time_t start_time_int = (context->ts_start_of_current_line + subs_delay) / 1000;
int start_time_dec = (context->ts_start_of_current_line + subs_delay) % 1000;
struct tm *start_time_struct = gmtime(&start_time_int);
strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct);
fdprintf(context->out->fh, "%s%c%03d|", buf1,ccx_options.millis_separator,start_time_dec);
}
}
if (ccx_options.transcript_settings.showEndTime){
char buf2[80];
if (ccx_options.transcript_settings.relativeTimestamp){
millis_to_date(get_fts() + subs_delay, buf2);
fdprintf(context->out->fh, "%s|", buf2);
}
else {
mstotime(get_fts() + subs_delay, &h2, &m2, &s2, &ms2);
time_t end_time_int = (get_fts() + subs_delay) / 1000;
int end_time_dec = (get_fts() + subs_delay) % 1000;
struct tm *end_time_struct = gmtime(&end_time_int);
strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct);
fdprintf(context->out->fh, "%s%c%03d|", buf2,ccx_options.millis_separator,end_time_dec);
}
}
if (ccx_options.transcript_settings.showCC){
fdprintf(context->out->fh, "CC%d|", context->my_field == 1 ? context->channel : context->channel + 2); // Data from field 2 is CC3 or 4
}
if (ccx_options.transcript_settings.showMode){
const char *mode = "???";
switch (context->mode)
{
case MODE_POPON:
mode = "POP";
break;
case MODE_FAKE_ROLLUP_1:
mode = "RU1";
break;
case MODE_ROLLUP_2:
mode = "RU2";
break;
case MODE_ROLLUP_3:
mode = "RU3";
break;
case MODE_ROLLUP_4:
mode = "RU4";
break;
case MODE_TEXT:
mode = "TXT";
break;
case MODE_PAINTON:
mode = "PAI";
break;
}
fdprintf(context->out->fh, "%s|", mode);
}
write(context->out->fh, subline, length);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
}
// fprintf (wb->fh,encoded_crlf);
}
int write_cc_buffer_as_transcript(struct eia608_screen *data, struct s_context_cc608 *context)
{
int wrote_something = 0;
context->ts_start_of_current_line = context->current_visible_start_ms;
dbg_print(CCX_DMT_608, "\n- - - TRANSCRIPT caption - - -\n");
for (int i=0;i<15;i++)
{
if (data->row_used[i])
{
write_cc_line_as_transcript (data,context, i);
}
wrote_something=1;
}
dbg_print(CCX_DMT_608, "- - - - - - - - - - - -\r\n");
return wrote_something;
}
>>>>>>> init
struct eia608_screen *get_current_visible_buffer(struct s_context_cc608 *context)
{
struct eia608_screen *data;

View File

@ -177,6 +177,9 @@ void init_options (struct ccx_s_options *options)
/* Networking */
options->udpaddr = 0;
options->udpport=0; // Non-zero => Listen for UDP packets on this port, no files.
options->send_to_srv = 0;
options->srv_addr = NULL;
options->srv_port = NULL;
options->line_terminator_lf=0; // 0 = CRLF
options->noautotimeref=0; // Do NOT set time automatically?
options->input_source=CCX_DS_FILE; // Files, stdin or network
@ -420,6 +423,11 @@ int main(int argc, char *argv[])
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
if (ccx_options.send_to_srv)
{
connect_to_srv(ccx_options.srv_addr, ccx_options.srv_port);
}
if (ccx_options.write_format!=CCX_OF_NULL)
{
/* # DVD format uses one raw file for both fields, while Broadcast requires 2 */

View File

@ -24,6 +24,7 @@ extern int ccblocks_in_avc_lost; // CC blocks found by the AVC code lost due to
#include "bitstream.h"
#include "constants.h"
#include "cc_decoders_common.h"
#include "networking.h"
#define TS_PMT_MAP_SIZE 128
@ -117,6 +118,9 @@ struct ccx_s_options // Options from user parameters
/* Networking */
in_addr_t udpaddr;
unsigned udpport; // Non-zero => Listen for UDP packets on this port, no files.
unsigned send_to_srv;
char *srv_addr;
char *srv_port;
int line_terminator_lf; // 0 = CRLF, 1=LF
int noautotimeref; // Do NOT set time automatically?
enum ccx_datasource input_source; // Files, stdin or network

424
src/networking.c Normal file
View File

@ -0,0 +1,424 @@
#include "ccextractor.h"
#include "networking.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define INT_LEN 10
#define PASSW 10
#define NEW_PRG 12
#define CC 11
#define SERV_ERROR 4
#define WRONG_COMMAND 3
#define WRONG_PASSW 2
#define OK 1
int srv_sd = -1;
/*
* Established connection to speciefied addres.
* Returns socked id
*/
int tcp_connect(const char *addr, const char *port);
/*
* Asks password from stdin, sends it to the server and waits for
* it's response
*/
int ask_passwd(int sd);
#define BUF_SIZE 20480
char *buf;
char *buf_end;
void init_buf();
/*
* Writes data according to protocol to descriptor
* block format:
* command | lenght | data | \r\n
* 1 byte | INT_LEN bytes | lenght bytes | 2 bytes
*/
ssize_t write_block(int fd, char command, const char *buf, size_t buf_len);
/* Reads n bytes from descriptor */
ssize_t readn(int fd, void *vptr, size_t n);
/* Writes n bytes to descriptor */
ssize_t writen(int fd, const void *vptr, size_t n);
/* Convinence functions */
ssize_t write_byte(int fd, char status);
ssize_t read_byte(int fd, char *status);
void connect_to_srv(const char *addr, const char *port)
{
mprint("Connecting to %s:%s\n", addr, port);
if ((srv_sd = tcp_connect(addr, port)) < 0)
fatal(EXIT_FAILURE, "Unable to connect\n");
if (ask_passwd(srv_sd) < 0)
fatal(EXIT_FAILURE, "Unable to connect\n");
mprint("Connected to %s:%s\n", addr, port);
}
void init_buf()
{
buf = (char *) malloc(BUF_SIZE);
if (NULL == buf)
fatal(EXIT_NOT_ENOUGH_MEMORY, "malloc error(): %s", strerror(errno));
buf_end = buf;
}
void net_append_cc(const char *fmt, ...)
{
if (NULL == buf)
init_buf();
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
int rc = vsnprintf(buf_end, BUF_SIZE - (buf_end - buf), fmt, args);
if (rc < 0)
{
mprint("net_append_cc() error: can\'t append ");
mprint(fmt, args);
return;
}
buf_end += rc;
va_end(args);
}
void net_append_cc_n(const char *data, size_t len)
{
assert(data != NULL);
size_t nleft = BUF_SIZE - (buf_end - buf);
if (nleft < len)
{
mprint("net_append_cc_n() warning: buffer overflow, pruning %zd bytes\n",
nleft);
len = nleft;
}
memcpy(buf_end, data, len);
buf_end += len;
}
void net_send_cc()
{
assert(srv_sd > 0);
if (buf_end - buf == 0)
return;
if (write_block(srv_sd, CC, buf, buf_end - buf) < 0)
{
mprint("Can't send subtitle block\n");
return; // XXX: store somewhere
}
buf_end = buf;
char ok;
read_byte(srv_sd, &ok);
switch (ok)
{
case OK:
break;
case SERV_ERROR:
mprint("Error on server side\n"); // lol
break;
/* case PASSW: */
default:
break;
}
return;
}
void net_set_new_program(const char *name, size_t len)
{
assert(name != NULL);
assert(len > 0);
assert(srv_sd > 0);
if (write_block(srv_sd, NEW_PRG, name, len) < 0)
{
mprint("Can't send new program name to the server\n");
return; // XXX: store somewhere
}
}
/*
* command | lenght | data | \r\n
* 1 byte | INT_LEN bytes | lenght bytes | 2 bytes
*/
ssize_t
write_block(int fd, char command, const char *buf, size_t buf_len)
{
assert(buf != NULL);
assert(buf_len > 0);
int rc;
ssize_t nwritten = 0;
if ((rc = write_byte(fd, command)) < 0)
return -1;
else if (rc != 1)
return 0;
nwritten++;
char len_str[INT_LEN] = {0};
snprintf(len_str, INT_LEN, "%d", buf_len);
if ((rc = writen(fd, len_str, INT_LEN)) < 0)
return -1;
else if (rc != INT_LEN)
return 0;
nwritten += rc;
if ((rc = writen(fd, buf, buf_len)) < 0)
return -1;
else if (rc != buf_len)
return 0;
nwritten += rc;
if ((rc = write_byte(fd, '\r')) < 0)
return -1;
else if (rc != 1)
return 0;
nwritten++;
if ((rc = write_byte(fd, '\n')) < 0)
return -1;
else if (rc != 1)
return 0;
nwritten++;
return nwritten;
}
int tcp_connect(const char *host, const char *port)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *ai;
int rc = getaddrinfo(host, port, &hints, &ai);
if (rc != 0) {
mprint("getaddrinfo() error: %s\n", gai_strerror(rc));
return -1;
}
struct addrinfo *p;
int sockfd;
/* Try each address until we sucessfully connect */
for (p = ai; p != NULL; p = p->ai_next) {
sockfd = socket(p->ai_family, SOCK_STREAM, p->ai_protocol);
if (-1 == sockfd) {
mprint("socket() error: %s\n", strerror(errno));
if (p->ai_next != NULL)
mprint("trying next addres ...");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == 0)
break;
mprint("connect() error: %s\n", strerror(errno));
if (p->ai_next != NULL)
mprint("trying next addres ...");
close(sockfd);
}
freeaddrinfo(ai);
if (NULL == p)
return -1;
return sockfd;
}
int ask_passwd(int sd)
{
assert(srv_sd > 0);
struct termios old, new;
int rc;
size_t len = 0;
char len_str[INT_LEN] = {0};
int i;
char *pw = NULL;
char ok;
do {
do {
if (read_byte(sd, &ok) != 1)
{
fatal(EXIT_FAILURE, "read() error: %s", strerror(errno));
}
if (OK == ok)
return 1;
} while(ok != PASSW);
printf("Enter password: ");
fflush(stdout);
if (tcgetattr(STDIN_FILENO, &old) != 0)
{
mprint("tcgetattr() error: %s\n", strerror(errno));
}
new = old;
new.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new) != 0)
{
mprint("tcgetattr() error: %s\n", strerror(errno));
}
rc = getline(&pw, &len, stdin);
rc--; /* -1 for \n */
if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &old) != 0)
{
mprint("tcgetattr() error: %s\n", strerror(errno));
}
printf("\n");
fflush(stdout);
if (write_block(sd, PASSW, pw, rc) < 0)
return -1;
if (read_byte(sd, &ok) != 1)
return -1;
if (WRONG_PASSW == ok)
{
printf("Wrong password\n");
fflush(stdout);
}
} while(OK != ok);
return 1;
}
ssize_t readn(int fd, void *vptr, size_t n)
{
assert(n >= 0);
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0)
{
if (NULL == vptr) {
char c;
nread = read(fd, &c, 1);
}
else
{
nread = read(fd, ptr, nleft);
}
if (nread < 0)
{
if (errno == EINTR)
{
nread = 0;
}
else
{
mprint("read() error: %s\n", strerror(errno));
return -1;
}
}
else if (0 == nread)
{
break; /* EOF */
}
nleft -= nread;
ptr += nread;
}
return n - nleft;
}
ssize_t writen(int fd, const void *vptr, size_t n)
{
assert(vptr != NULL);
assert(n > 0);
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0)
{
if ((nwritten = write(fd, ptr, nleft)) < 0)
{
if (errno == EINTR)
{
nwritten = 0;
}
else
{
mprint("write() error: %s\n", strerror(errno));
return -1;
}
}
else if (0 == nwritten)
{
break;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
ssize_t write_byte(int fd, char ch)
{
return writen(fd, &ch, 1);
}
ssize_t read_byte(int fd, char *ch)
{
assert(ch != 0);
return readn(fd, ch, 1);
}

14
src/networking.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef NETWORKING_H
#define NETWORKING_H
#include <sys/types.h>
void connect_to_srv(const char *addr, const char *port);
void net_append_cc(const char *fmt, ...);
void net_append_cc_n(const char *data, size_t len);
void net_send_cc();
void net_set_new_program(const char *name, size_t len);
#endif /* end of include guard: NETWORKING_H */

View File

@ -1560,6 +1560,20 @@ void parse_parameters (int argc, char *argv[])
i++;
continue;
}
if (strcmp (argv[i],"-sendto")==0 && i<argc-1)
{
ccx_options.send_to_srv = 1;
ccx_options.srv_addr = argv[i + 1];
continue;
}
if (strcmp (argv[i],"-port")==0 && i<argc-1)
{
ccx_options.send_to_srv = 1;
ccx_options.srv_port = argv[i + 1];
continue;
}
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "Error: Parameter %s not understood.\n", argv[i]);
// Unrecognized switches are silently ignored
}