⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subtitle.c

📁 avi player 使用Linux下 GDK,GTK
💻 C
字号:
/***  Sinek (Media Player)**  Copyright (c) 2001-2002 Gurer Ozen****  This code is free software; you can redistribute it and/or**  modify it under the terms of the GNU General Public License.****  subtitles*/#include "common.h"#include <zlib.h>enum{	COL_START,	COL_END,	COL_SUBTITLE,	N_COLS};typedef int (loader_t)(gzFile *fd);static GtkWidget *combo, *delay, *list_view, *text;static GtkListStore *list_store;static subtitle_t *current = NULL, *subtitles = NULL, *last = NULL;static int frame_per_second = 25;static int frame_format = 0;static float delay_time = 0;static char buffer[1024];static loader_t *find_loader(gzFile *fd);static void load_tree(void);int subtitle_load(const char *filename){	gzFile *fd;	loader_t *loader;	int ret;	fd = gzopen(filename, "r");	if(!fd)	{		warning(_("Cannot open subtitle file:\n%s"), filename);		return 0;	}	frame_format = 0;	loader = find_loader(fd);	if(loader)	{		ret = loader(fd);	}	else	{		ret = 0;		warning(_("Unknown subtitle format!"));	}	gzclose(fd);	if(ret && list_view) load_tree();	return ret;}subtitle_t *subtitle_find(unsigned long msec){	if(frame_format) msec = (msec / 100) * frame_per_second;	if(msec < (delay_time * 100)) return(NULL);	msec = msec - (delay_time * 100);	if(current == NULL) current = subtitles;	while(current)	{		if(msec >= current->start && msec < current->end)		{			return current;		}		else if(msec < current->start)		{			if(current->prev && current->prev->end < msec)				return NULL;			current = current->prev;		}		else if(msec >= current->end)		{			if(current->next && current->next->start > msec)				return NULL;			current = current->next;		}	}	return NULL;}void subtitle_delete(void){	current = NULL;	subtitles = NULL;	last = NULL;}static subtitle_t *append(unsigned long start, unsigned long end){	subtitle_t *sub;	sub = malloc(sizeof(subtitle_t));	memset(sub, 0, sizeof(subtitle_t));	sub->start = start;	sub->end = end;	sub->prev = last;	if(!subtitles) subtitles = sub;	if(last) last->next = sub;	last = sub;	if(sub->prev)	{		if(sub->prev->end >= sub->start)			printf("error in %ld - %ld\n", sub->start, sub->end);	}	return sub;}static void append_text(subtitle_t *sub, char *line){	if(sub->lines < 4)	{		sub->text[sub->lines] = g_strdup(line);		sub->lines++;	}}static int parse_microdvd(gzFile *fd){	subtitle_t *sub;	char buf2[1024];	unsigned long start, end;	char *t, *s;	frame_format = 1;	while(1)	{		if(!gzgets(fd, buffer, 1000)) break;		if(sscanf(buffer, "{%ld}{%ld}%[^\r\n]", &start, &end, buf2) < 3) continue;		sub = append(start, end);		t = buf2;		while(1)		{			s = strchr(t, '|');			if(s)			{				*s = '\0';				append_text(sub, t);				t = s + 1;			}			else			{				append_text(sub, t);				break;			}		}	}	return 1;}static int parse_subrip(gzFile *fd){	subtitle_t *sub;	unsigned long start, end;	char *t, *s;	int a1, a2, a3, a4, b1, b2, b3, b4;	while(1)	{		if(!gzgets(fd, buffer, 1000)) break;		if(sscanf(buffer, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue;		start = a1*360000 + a2*6000 + a3*100 + a4;		end   = b1*360000 + b2*6000 + b3*100 + b4;		if(!gzgets(fd, buffer, 1000)) break;		strtok(buffer, "\r\n");		sub = append(start, end);		t = buffer;		while(1)		{			s = strstr(t, "[br]");			if(s)			{				*s = '\0';				append_text(sub, t);				t = s + 4;			}			else			{				append_text(sub, t);				break;			}		}	}	return 1;}static int parse_subrip2(gzFile *fd){	subtitle_t *sub;	unsigned long start, end;	char *t, *s;	int a1, a2, a3, a4, b1, b2, b3, b4;	while(1)	{		if(!gzgets(fd, buffer, 1000)) break;		if(sscanf(buffer, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue;		start = a1*360000 + a2*6000 + a3*100 + a4;		end   = b1*360000 + b2*6000 + b3*100 + b4;		if(!gzgets(fd, buffer, 1000)) break;		strtok(buffer, "\r\n");		sub = append(start, end);		t = buffer;		while(1)		{			s = strstr(t, "[br]");			if(s)			{				*s = '\0';				append_text(sub, t);				t = s + 4;			}			else			{				append_text(sub, t);				break;			}		}	}	return 1;}static int parse_srt(gzFile *fd){	subtitle_t *sub;	unsigned long start, end;	int a1, a2, a3, a4, b1, b2, b3, b4;	while(1)	{		if(!gzgets(fd, buffer, 1000)) break;		if(sscanf(buffer, "%d:%d:%d,%d --> %d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue;		start = a1*360000 + a2*6000 + a3*100 + (a4 / 10);		end   = b1*360000 + b2*6000 + b3*100 + (b4 / 10);		sub = append(start, end);		while(1)		{			if(!gzgets(fd, buffer, 1000)) break;			if(buffer[0] == '\0' || buffer[0] == '\r' || buffer[0] == '\n') break;			strtok(buffer, "\r\n");			append_text(sub, buffer);		}	}	return 1;}static loader_t *find_loader(gzFile *fd){	loader_t *loader = NULL;	int i, j;	for(i = 0; i < 50; i++)	{		if(!gzgets(fd, buffer, 1000)) break;		if(sscanf(buffer, "{%d}{%d}", &j, &j) == 2)		{			loader = parse_microdvd;			break;		}		if(sscanf(buffer, "%d:%d:%d.%d,%d:%d:%d.%d", &j, &j, &j, &j, &j, &j, &j, &j) == 8)		{			loader = parse_subrip;			break;		}		if(sscanf(buffer, "%d:%d:%d,%d,%d:%d:%d,%d", &j, &j, &j, &j, &j, &j, &j, &j) == 8)		{			loader = parse_subrip2;			break;		}		if(sscanf(buffer, "%d:%d:%d,%d --> %d:%d:%d,%d", &j, &j, &j, &j, &j, &j, &j, &j) == 8)		{			loader = parse_srt;			break;		}	}	gzrewind(fd);	return loader;}static void cb_frame_rate(GtkWidget *w, gpointer data){	const gchar *str;	int val;	str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));	if(str)	{		val = atoi(str);		if(val > 0 && val < 80)			frame_per_second = val;	}}void sub_save(char *filename){	FILE *fd;	subtitle_t *tmp;	unsigned long start, end;	int a, b, c, d, e, f;	fd = fopen(filename, "w");	if(fd)	{		tmp = subtitles;		while(tmp)		{			if(frame_format)			{				start = tmp->start / frame_per_second;				end = tmp->end / frame_per_second;			}			else			{				start = tmp->start / 100;				end = tmp->end / 100;			}			if(start >= delay_time)			{				start = start - delay_time;				end = end - delay_time;			}			a = start / 3600;			b = (start % 3600) / 60;			c = start % 60;			d = end / 3600;			e = (end % 3600) / 60;			f = end % 60;			fprintf(fd, "%02d:%02d:%02d.00,%02d:%02d:%02d.00\n", a, b, c, d, e, f);			a = 0;			while(a < tmp->lines)			{				fprintf(fd, "%s", tmp->text[a]);				a++;				if(a < tmp->lines) fprintf(fd, "[br]");			}			fprintf(fd, "\n\n");			tmp = tmp->next;		}		fclose(fd);	}}static void cb_save(GtkWidget *w, gpointer data){	select_file(sub_save, _("Save subtitles as..."));}static void cb_delay(GtkWidget *w, gpointer data){	const gchar *str;	str = gtk_entry_get_text(GTK_ENTRY(delay));	if(str)	{		delay_time = atof(str);	}}static void cb_select_line(GtkTreeSelection *sel, gpointer data){	GtkTreeModel *model;	GtkTreeIter iter;	GtkTextIter iter2;	GtkTextBuffer *tb;	subtitle_t *sub;	int i = 1;	if(gtk_tree_selection_get_selected(sel, &model, &iter))	{		gtk_tree_model_get(model, &iter, COL_START, &sub, -1);		tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));		gtk_text_buffer_set_text(tb, sub->text[0], -1);		gtk_text_buffer_get_end_iter(tb, &iter2);		while(i < sub->lines)		{			gtk_text_buffer_insert(tb, &iter2, "\n", 1);			gtk_text_buffer_insert(tb, &iter2, sub->text[i] , -1);			i++;		}	}}static void cb_render_start(GtkTreeViewColumn *col, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data){	subtitle_t *tmp;	gchar *buf;	unsigned int sec, a, b, c;	gtk_tree_model_get(model, iter, COL_START, &tmp, -1);	if(data) sec = (tmp->end / 100); else sec = (tmp->start / 100);	a = sec / 3600;	b = (sec % 3600) / 60;	c = sec % 60;	buf = g_strdup_printf("%02d:%02d:%02d", a, b, c);	g_object_set(cell, "text", buf, NULL);}static void load_tree(void){	GtkTreeIter iter;	subtitle_t *tmp = subtitles;	gtk_list_store_clear(list_store);	while(tmp)	{		gtk_list_store_append(list_store, &iter);		gtk_list_store_set(list_store, &iter, COL_START, tmp, COL_END, "00:00:00", COL_SUBTITLE, tmp->text[0], -1);		tmp = tmp->next;	}}int subtitle_build(GtkWidget **win){	GtkWidget *w, *vb, *vb2, *hb, *hb2, *b, *sw;	GtkCellRenderer *cell;	GtkTreeViewColumn *col;	GList *items = NULL;	w = gtk_window_new(GTK_WINDOW_TOPLEVEL);	gtk_window_set_title(GTK_WINDOW(w), _("Sinek Subtitle Editor"));	gtk_window_set_wmclass(GTK_WINDOW(w), "subtitles", "sinek");	vb = gtk_vbox_new(FALSE, 5);	gtk_widget_show(vb);	gtk_container_add(GTK_CONTAINER(w), vb);	gtk_container_set_border_width(GTK_CONTAINER(vb), 5);	hb = gtk_hbox_new(FALSE, 5);	gtk_widget_show(hb);	gtk_box_pack_start(GTK_BOX(vb), hb, TRUE, TRUE, 0);	/* subtitle list */	vb2 = gtk_vbox_new(FALSE, 5);	gtk_widget_show(vb2);	gtk_box_pack_start(GTK_BOX(hb), vb2, TRUE, TRUE, 0);	sw = gtk_scrolled_window_new(NULL, NULL);	gtk_widget_show(sw);	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);	gtk_box_pack_start(GTK_BOX(vb2), sw, TRUE, TRUE, 3);	list_store = gtk_list_store_new(N_COLS, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);	list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));	cell = gtk_cell_renderer_text_new();	col = gtk_tree_view_column_new_with_attributes(_("Start"), cell, NULL);	gtk_tree_view_column_set_cell_data_func(col, cell, cb_render_start, NULL, NULL);	gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);	cell = gtk_cell_renderer_text_new();	col = gtk_tree_view_column_new_with_attributes(_("End"), cell, NULL);	gtk_tree_view_column_set_cell_data_func(col, cell, cb_render_start, (gpointer)1, NULL);	gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);	cell = gtk_cell_renderer_text_new();	col = gtk_tree_view_column_new_with_attributes(_("Subtitle"), cell, "text", COL_SUBTITLE, NULL);	gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);	g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view))), "changed", G_CALLBACK(cb_select_line), NULL);	if(subtitles) load_tree();	gtk_widget_show(list_view);	gtk_container_add(GTK_CONTAINER(sw), list_view);	/* edit area */	sw = gtk_scrolled_window_new(NULL, NULL);	gtk_widget_show(sw);	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);	gtk_box_pack_start(GTK_BOX(vb2), sw, FALSE, TRUE, 3);	text = gtk_text_view_new();	gtk_widget_show(text);	gtk_container_add(GTK_CONTAINER(sw), text);	gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);	/* frame rate & delay adjustments */ 	vb2 = gtk_vbox_new(FALSE, 5);	gtk_widget_show(vb2);	gtk_box_pack_start(GTK_BOX(hb), vb2, FALSE, FALSE, 0);	b = gtk_label_new(_("Frame rate:"));	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(vb2), b, FALSE, FALSE, 0);	hb2 = gtk_hbox_new(FALSE, 5);	gtk_widget_show(hb2);	gtk_box_pack_start(GTK_BOX(vb2), hb2, FALSE, FALSE, 0);	combo = gtk_combo_new();	gtk_widget_show(combo);	gtk_box_pack_start(GTK_BOX(hb2), combo, TRUE, TRUE, 0);	items = g_list_append(items, (gpointer) "15");	items = g_list_append(items, (gpointer) "25");	items = g_list_append(items, (gpointer) "29.7");	gtk_combo_set_popdown_strings(GTK_COMBO(combo), items);	g_list_free(items);	b = GTK_COMBO(combo)->entry;	gtk_entry_set_max_length(GTK_ENTRY(b), 6);	gtk_entry_set_width_chars(GTK_ENTRY(b), 6);	gtk_entry_set_text(GTK_ENTRY(b), "25");	b = gtk_label_new(_("fps"));	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(hb2), b, FALSE, FALSE, 0);	b = gtk_button_new_with_label(_("Change"));	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(vb2), b, FALSE, FALSE, 0);	g_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(cb_frame_rate), NULL);	b = gtk_label_new(_("Delay:"));	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(vb2), b, FALSE, FALSE, 0);	hb2 = gtk_hbox_new(FALSE, 5);	gtk_widget_show(hb2);	gtk_box_pack_start(GTK_BOX(vb2), hb2, FALSE, FALSE, 0);	delay = gtk_entry_new();	gtk_widget_show(delay);	gtk_box_pack_start(GTK_BOX(hb2), delay, TRUE, TRUE, 0);	gtk_entry_set_max_length(GTK_ENTRY(delay), 6);	gtk_entry_set_width_chars(GTK_ENTRY(delay), 6);	gtk_entry_set_text(GTK_ENTRY(delay), "0.0");	b = gtk_label_new(_("sec"));	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(hb2), b, FALSE, FALSE, 0);	b = gtk_button_new_with_label(_("Change"));	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(vb2), b, FALSE, FALSE, 0);	g_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(cb_delay), NULL);	/* save & load buttons */	b = gtk_hseparator_new();	gtk_widget_show(b);	gtk_box_pack_start(GTK_BOX(vb), b, FALSE, FALSE, 0);	hb2 = gtk_hbutton_box_new();	gtk_widget_show(hb2);	gtk_box_pack_start(GTK_BOX(vb), hb2, FALSE, FALSE, 0);	gtk_button_box_set_layout(GTK_BUTTON_BOX(hb2), GTK_BUTTONBOX_END);	gtk_container_set_border_width(GTK_CONTAINER(hb2), 5);	gtk_box_set_spacing(GTK_BOX(hb2), 5);/*	b = gtk_button_new_with_label(_("Open..."));	gtk_widget_show(b);	gtk_container_add(GTK_CONTAINER(hb2), b);	b = gtk_button_new_with_label(_("Save"));	gtk_widget_show(b);	gtk_container_add(GTK_CONTAINER(hb2), b);*/	b = gtk_button_new_from_stock(GTK_STOCK_SAVE_AS);	gtk_widget_show(b);	gtk_container_add(GTK_CONTAINER(hb2), b);	g_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(cb_save), NULL);	b = gtk_button_new_from_stock(GTK_STOCK_CLOSE);	gtk_widget_show(b);	gtk_container_add(GTK_CONTAINER(hb2), b);	g_signal_connect_swapped(G_OBJECT(b), "clicked", G_CALLBACK(gtk_widget_hide), GTK_OBJECT(w));	*win = w;	return WM_NORMAL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -